Aaron Stebner's WebLog

Thoughts about setup and deployment issues, WiX, XNA, the .NET Framework and Visual Studio

November, 2008

  • Aaron Stebner's WebLog

    Creating an installer that includes a Visual Studio bootstrapper package and an MSI built with WiX 3.0

    • 16 Comments

    A few days ago, I wrote a blog post describing how to create an MSI-based installer for a Windows game created with XNA Game Studio 3.0.  In that post, I described how to create custom actions in the MSI to check for system-level prerequisites (the .NET Framework and the XNA Framework Redistributable) and block the MSI from installing if they are not installed on the user's system.

    Adding a bootstrapper to your game installer

    The next thing I want to demonstrate is how to expand on the steps in that blog post to create an installer that will do all of the following:

    • Check for the presence of prerequisite components for the game on a user's system.
    • Download and install any prerequisites that are missing.
    • After prerequisites are installed, trigger the installation of the game MSI.

    Visual Studio includes a bootstrapper that can do all of the above, and XNA Game Studio 3.0 includes a prerequisite package for the XNA Framework Redistributable 3.0 that integrates with the Visual Studio bootstrapper.  As a result, you can use the Visual Studio 2008 or Visual C# 2008 Express Edition IDE to create an installer for your game for both ClickOnce packages and VS setup/deployment projects, and I have previously posted steps for doing this in this blog post.

    If you want to create an installer that uses the Visual Studio bootstrapper along with an MSI built with WiX instead of an MSI build with a VS setup/deployment project, you need to perform a couple of additional steps:

    1. Create an MSBuild project that contains information about the prerequisites you want to include for your game and also contains a GenerateBootstrapper task with the settings that you want to use for your installer.
    2. Build your MSI with WiX using the steps from my previous blog post.
    3. Build the bootstrapper for your game by running MSBuild for the project you create in step 1.

    Updated sample that builds an MSI and a bootstrapper

    I have posted a sample at http://cid-27e6a35d1a492af7.skydrive.live.com/self.aspx/Blog%7C_Tools/WiX%20Samples/wix%7C_sample%7C_xgs30%7C_game%7C_with%7C_bootstrapper.zip that extends my previous sample so you can use it to create a bootstrapper in addition to an MSI.  It includes the following additions/changes from the previous sample:

    • The file wix_sample_xgs30_game_bootstrapper_netfx35.proj is an MSBuild project file that will create a bootstrapper for a game that will install the .NET Framework 3.5 and the XNA Framework Redistributable 3.0 as prerequisites.
    • The file wix_sample_xgs30_game_bootstrapper_netfx20.proj is an MSBuild project file that will create a bootstrapper for a game that will install the .NET Framework 2.0 and the XNA Framework Redistributable 3.0 as prerequisites.
    • The file build_wix_sample_xgs30_game.bat has been updated to compile the MSI using WiX v3.0 and then run MSBuild for wix_sample_xgs30_game_bootstrapper_netfx35.proj to create a VS bootstrapper setup.exe package.

    How to use the updated sample

    To try out this updated sample, you can use the following steps:

    1. Install Visual Studio 2008 or Visual C# 2008 Express Edition and XNA Game Studio 3.0.
    2. Install the latest build of WiX v3.0 from http://wix.sourceforge.net/releases/.
    3. Open Visual Studio and create a project using the Platformer Starter Kit (3.0) project template that is included as a part of XNA Game Studio 3.0.
    4. Build the x86 release version of the project.
    5. Download the sample from http://cid-27e6a35d1a492af7.skydrive.live.com/self.aspx/Blog%7C_Tools/WiX%20Samples/wix%7C_sample%7C_xgs30%7C_game%7C_with%7C_bootstrapper.zip.
    6. Create a sub-folder named Setup in the Platformer game project that you created above.
    7. Extract the contents of wix_sample_xgs30_game_with_bootstrapper.zip to the Setup folder.  You should end up with a folder structure like c:\Users\myusername\Documents\Visual Studio 2008\Projects\Platformer1\Platformer1\Setup with the contents of the .zip file in there.
    8. Run the script named build_wix_sample_xgs30_game.bat from the Setup folder to invoke the WiX toolset and build an MSI for the game and then invoke MSBuild to build the bootstrapper setup.exe.

    After doing the above, you can copy setup.exe and wix_sample_xgs30_game.msi from the Setup sub-directory to a server and run setup.exe to install your game and its prerequisites on another computer.

    Advanced scenario - building an MSI with WiX by using a .wixproj file

    Note - it is also possible to create an MSBuild project file to build an MSI using WiX instead of using a batch file that calls the WiX tools directly.  I have included a sample MSBuild project file named wix_sample_xgs30_game.wixproj in the new sample that I have posted.  It was created by using the Votive Visual Studio package that is a part of the WiX toolset, and it can be built by invoking msbuild.exe directly or by opening the .wixproj file in Visual Studio 2005 or 2008 standard edition or higher on a system that also has WiX v3.0 installed.  Keep in mind that Votive is a Visual Studio add-in package, so it can only be installed for use in Visual Studio standard edition or higher.  You cannot use it if you only have Visual C# 2008 Express Edition.  You can create and build .wixproj files by hand outside of Visual Studio if you only have an Express Edition installed though.

    <update date="3/21/2009"> Fixed broken link to sample installer files. </update>

     

  • Aaron Stebner's WebLog

    How to target the .NET Framework 2.0 instead of 3.5 in a Windows game created with XNA Game Studio 3.0

    • 4 Comments

    By default, when you create a new Windows game project in XNA Game Studio 3.0, it will target the .NET Framework 3.5.  This means that the project will be configured to include references to assemblies that are a part of the .NET Framework 3.5 but are not a part of the .NET Framework 2.0 or 3.0, and it will also be configured to include the .NET Framework 3.5 as a prerequisite if you choose to deploy your game using ClickOnce or a Visual Studio setup/deployment project.

    The Visual Studio 2008 product family includes a multi-targeting feature that allows you to select what version of the .NET Framework is required for your application.  You can use multi-targeting to create a Windows game using XNA Game Studio 3.0 that only requires the .NET Framework 2.0 instead of 3.0 or 3.5.  This can be particularly useful in reducing your installer footprint and to enable your game to run on Windows Vista after installing only the XNA Framework Redistributable Package 3.0 and your game payload.

    There are some specific steps you need to take to change the project defaults and choose to target the .NET Framework 2.0 instead of 3.5 in your Windows game.  The exact steps you need to take depend on what edition of Visual Studio 2008 you have installed.

    Changing the .NET Framework version to target in Visual Studio 2008 Standard Edition or higher

    In Visual Studio 2008 Standard Edition and higher, there is a drop-down menu in the New Project dialog that allows you to select the .NET Framework version you want to target in your XNA Game Studio 3.0 game project.  The New Project dialog looks like the following, and the drop-down menu is in the top right corner of this dialog:

    Note - if you change the drop-down menu from the default .NET Framework 3.5 value to .NET Framework 2.0, you will notice that the Content Pipeline Extension Library and Platformer Starter Kit project templates are no longer available.  This is because those 2 project templates use features that rely on the .NET Framework 3.5.

    After changing the .NET Framework version in the New Project dialog, you can create your project and it will automatically configure the assembly references, using statements in the source code and prerequisite packages for ClickOnce and setup projects appropriately.

    Changing the .NET Framework version to target in Visual C# 2008 Express Edition

    In Visual C# 2008 Express Edition, the New Project dialog does not offer an option to change the .NET Framework version you will target for your project.  Instead, it will always create projects that target the .NET Framework 3.5.  You can change the .NET Framework version you want to target after the project is created, but it requires some additional steps.

    To change the .NET Framework version that your Windows game will target from the default .NET Framework 3.5 value to the .NET Framework 2.0, you can right-click on the project in the Visual Studio solution explorer and choose Properties.  Then, in the Application properties tab, you can change the Target Framework drop-down.  The UI for the Application properties tab looks like the following, and the Target Framework drop-down is directly below the Assembly Name text box:

    Note - You can only target the .NET Framework 3.5 for Xbox 360 and Zune projects because there is only one available version of the .NET Compact Framework for these platforms in XNA Game Studio 3.0.  As a result, the Target Framework drop-down will be blank and grayed out in the Application properties page for an Xbox 360 or Zune project.

    After making a change to the Target Framework drop-down, you will be prompted to save, close and re-open the project.  After clicking Yes to make the change, you will have to make the following additional manual changes to complete the .NET Framework re-targeting process:

    1. Remove the reference to System.Xml.Linq from your project.
    2. Remove the using statement that refers to System.Linq from the Game1.cs source file.
    3. Update the deployment prerequisites to include .NET Framework 2.0 instead of .NET Framework 3.5 - you can access the prerequisites dialog by right-clicking on your project, selecting Properties, selecting the Publish tab, then clicking on the Prerequisites... button.

    You can also use the above steps in Visual Studio 2008 Standard Edition and higher to change the .NET Framework version that your game project will target if you do not want to keep the default value selected when you first created the project.

    Possible deployment error messages related to .NET Framework version targeting issues

    Skipping steps 1 and 2 above will result in build errors, so they will be easy to catch.  Skipping step 3 can lead to more subtle error messages when users attempt to install your game.

    There are a couple of installation errors your users might encounter that are related to .NET Framework version mismatches.  If you create a game that targets the .NET Framework 3.0 or 3.5 and a user tries to run the ClickOnce .application file for the game on a system that has the .NET Framework 2.0 installed (but not 3.0 or 3.5), they will see an error with the following text:

    Unable to install or run the application. The application requires that assembly WindowsBase Version 3.0.0.0 be installed in the Global Assembly Cache (GAC) first. Please contact your system administrator.

    It looks like the following: 

    If you create a game that targets the .NET Framework 3.5 and a user tries to run the ClickOnce deployment manifest (named <game>.application) for the game on a system that has the .NET Framework 2.0 and 3.0 (but not 3.5) installed, they will see an error with the following text:

    Unable to install or run the application. The application requires that assembly System.Core Version 3.5.0.0 be installed in the Global Assembly Cache (GAC) first. Please contact your system administrator.

    It looks like the following: 

    In both of the above cases, you will need to double-check that you have selected the appropriate .NET Framework version as a prerequisite for your game.  I have most commonly run into this type of error when creating a game that targets the .NET Framework 2.0 and then deciding to change it to target the .NET Framework 3.5 afterwards, but forgetting to update the deployment prerequisites for the game after making the targeting change (step 3 described above).

    This type of error can also occur when creating a ClickOnce-based game installer, but then running the ClickOnce deployment manifest (<game>.application) instead of setup.exe on the system to deploy the game.  The prerequisite checking logic for ClickOnce-based games exists in setup.exe, not in the deployment manifest.  This can lead to cases where a user has a version of the .NET Framework (which will enable the .application file extension to be invoked), but do not have the version of the .NET Framework that your game is targeting.

    A key thing to keep in mind here is that even if your Windows game does not use any .NET Framework 3.0 or 3.5 features, if you configure your project to target the .NET Framework 3.0 or 3.5, your users can run into this kind of error when they try to deploy your game to their system.

    <update date="11/13/2008"> Added text that lists the deployment error messages to make this post easier to find in search engines. </update>

    <update date="6/17/2009"> Fixed broken image links. </update>

     

  • Aaron Stebner's WebLog

    Mailbag: How to detect the .NET Framework 2.0 SP2 or greater in an MSI-based installer

    • 2 Comments

    Question:

    I have an application that requires the .NET Framework 2.0 SP2.  I would like to author a condition in my MSI-based installer to check for SP2 or higher so that the application will continue to install even if future service packs are released for the .NET Framework 2.0.

    What is the correct way to check for the .NET Framework 2.0 SP2 or greater in an MSI-based installer?

    Answer:

    The following registry value that can be used to detect the service pack level for the .NET Framework 2.0 on a system:

    [HKEY_LOCAL_MACHINE\Software\Microsoft\NET Framework Setup\NDP\v2.0.50727]
    SP

    This SP registry value is a DWORD registry value.  That means you can author a Windows Installer registry locator to retrieve the SP registry value during your application's installer.  In WiX v3.0, the syntax looks like the following:

    <Property Id="NETFRAMEWORK20_SP_LEVEL" Secure="yes">
        <RegistrySearch Id="NetFramework20SP" Root="HKLM" Key="Software\Microsoft\NET Framework Setup\NDP\v2.0.50727" Name="SP" Type="raw" />
    </Property>

    Note - instead of defining the above registry locator in your setup authoring, you can include the following PropertyRef that is a part of the WixNetFxExtension in WiX v3.0:

    <PropertyRef Id="NETFRAMEWORK20_SP_LEVEL" />

    When querying this registry value in your MSI, the property value NETFRAMEWORK20_SP_LEVEL will be set to blank if the registry value does not exist on the system.  It will be set to a value like "#0" or "#1" or "#2" depending on the exact service pack level on the system.

    It will be tempting to simply check that NETFRAMEWORK20_SP_LEVEL >= "#2" in your MSI in order to verify that the .NET Framework 2.0 SP2 or later is installed.   However, it is very important to note that this property value will be set to a string value and not a numerical value.  That means that when you do comparisons in an MSI launch condition or custom action, you must use string comparison logic or else you run the risk of incorrectly detecting the service pack level on a user's system.  The place where this causes the most problems is when the value goes from a single digit to double digits.  For example, service pack 10 is greater than service pack 2, but the string value "#10" is less than the string value "#2".  This means you cannot just check to make sure that the NETFRAMEWORK20_SP_LEVEL property is greater than or equal to "#2" to correctly detect service pack 2 or greater.

    Because a string comparison can lead to incorrect results, I suggest that your MSI instead check individual values to narrow down the service pack level.  For example, to verify that the system has service pack 2 or greater, you can make sure that the SP registry value exists and that it does not equal 0 or 1.

    Implementing a launch condition to perform the check

    The following WiX v3.0 syntax can be used to implement a Windows Installer launch condition that checks for the .NET Framework 2.0 SP2 or greater:

    <PropertyRef Id="NETFRAMEWORK20_SP_LEVEL" />

    <Condition Message="[ProductName] requires .NET Framework 2.0 SP2 or higher (Launch Condition). Setup will now exit.">
      <![CDATA[(NETFRAMEWORK20_SP_LEVEL AND NOT NETFRAMEWORK20_SP_LEVEL = "#0" AND NOT NETFRAMEWORK20_SP_LEVEL = "#1") OR Installed]]>
    </Condition>

    Implementing a type 19 custom action to perform the check

    When I create MSI-based installers, I prefer to use type 19 custom actions instead of launch conditions for this type of prerequisite checking because you can control the order in which the prerequisite checks are performed when using custom actions, but you cannot control the order when using launch conditions.  The following WiX v3.0 syntax can be used to implement the same check for the .NET Framework 2.0 SP2 or greater as shown above with a custom action instead of a launch condition:

    <PropertyRef Id="NETFRAMEWORK20_SP_LEVEL" />

    <CustomAction Id="CA_CheckForNetfx20Sp2OrGreater" Error="[ProductName] requires .NET Framework 2.0 SP2 or higher. Setup will now exit." />

    <InstallExecuteSequence>
      <LaunchConditions After="AppSearch"/>
      <Custom Action="CA_CheckForNetfx20Sp2OrGreater" After="LaunchConditions">(NOT NETFRAMEWORK20_SP_LEVEL OR NETFRAMEWORK20_SP_LEVEL = "#0" OR NETFRAMEWORK20_SP_LEVEL = "#1") AND NOT Installed</Custom>
    </InstallExecuteSequence>

    <InstallUISequence>
      <LaunchConditions After="AppSearch"/>
      <Custom Action="CA_CheckForNetfx20Sp2OrGreater" After="LaunchConditions">(NOT NETFRAMEWORK20_SP_LEVEL OR NETFRAMEWORK20_SP_LEVEL = "#0" OR NETFRAMEWORK20_SP_LEVEL = "#1") AND NOT Installed</Custom>
    </InstallUISequence>

    I have also created a full set of sample files that can be used to build an MSI using WiX v3.0 that includes a custom action to check for the .NET Framework 2.0 SP2 or later and block installation if it is not present.  You can find the sample files at http://astebner.sts.winisp.net/Tools/WiX%20Samples/wix_sample_detect_netfx_sp_level.zip.  To build this sample, you need to do the following:

    1. Install the latest build of WiX v3.0 from the SourceForge releases page and choose to install it to the default location offered by the installer
    2. Download the sample .zip file from http://astebner.sts.winisp.net/Tools/WiX%20Samples/wix_sample_detect_netfx_sp_level.zip and extract the contents to your hard drive
    3. Run the file build_wix_sample_detect_netfx_sp_level.bat from the extracted .zip file in order to invoke the WiX v3.0 toolset to build the sample MSI

    Additional notes:

    • The conditions listed above include the clause "OR Installed" (for the launch condition implementation) and "AND NOT Installed" (for the custom action implementation).  These clauses ensure that the user will not be blocked from running the uninstall process for this MSI if the condition is not met.  I recommend adding these clauses to any prerequisite checks that you include in your MSI that will block the user from running the MSI.  Without the clauses, the user would be forced to re-install the prerequisite package in order to uninstall your product, which can be a frustrating user experience.
    • The above logic explains how to implement a specific check for the .NET Framework 2.0 SP2 or later.  However, the same underlying principles apply to any type of prerequisite checking within a Windows Installer package that requires checking for a range of values that are retrieved from REG_DWORD values in the registry.  The key thing to remember is that a registry locator in an MSI will end up setting the property value to a string, so you need to keep in mind that you will need to account for string comparison logic and not the more simple numerical comparison logic when checking the property value in your MSI.
  • Aaron Stebner's WebLog

    .NET Framework 3.0 and 3.5 ServiceModelReg.exe custom action failure related to files in the temporary directory

    • 5 Comments

    I have run into a few reports of .NET Framework 3.0 and 3.5 installation failures recently that have exhibited the same set of symptoms.  I wanted to describe this issue in more detail so that folks who have followed the steps in my previous post about diagnosing .NET Framework 3.0 and 3.5 installation failures related to the ServiceModelReg.exe custom action will recognize this pattern and have some additional workarounds to try to get the .NET Framework to install successfully on their systems.

    Diagnosing the issue

    When the .NET Framework 3.0 or 3.5 setup fails, I recommend using steps like the ones listed at http://blogs.msdn.com/astebner/archive/2008/03/28/8342307.aspx to narrow down the root cause.  Recently, I have heard from a few customers who have used these steps, and when they get to step 4 and look in the event logs on their system, they see errors like the following:

    An error occurred while creating the MSI-style log file at 'C:\Documents and Settings\myusername\Local Settings\Temp\':
    System.IO.IOException: Unknown error "-1".
       at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
       at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
       at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
       at System.ServiceModel.Install.MsiStyleLogWriter..ctor(String logEntryPrefix).

    System.IO.IOException: Unknown error "-1".
       at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
       at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
       at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access)
       at System.CodeDom.Compiler.TempFileCollection.EnsureTempNameCreated()
       at System.CodeDom.Compiler.TempFileCollection.AddExtension(String fileExtension, Boolean keepFile)
       at System.CodeDom.Compiler.TempFileCollection.AddExtension(String fileExtension)
       at Microsoft.CSharp.CSharpCodeGenerator.FromSourceBatch(CompilerParameters options, String[] sources)
       at Microsoft.CSharp.CSharpCodeGenerator.System.CodeDom.Compiler.ICodeCompiler.CompileAssemblyFromSourceBatch(CompilerParameters options, String[] sources)
       at System.CodeDom.Compiler.CodeDomProvider.CompileAssemblyFromSource(CompilerParameters options, String[] sources)
       at System.Xml.Serialization.Compiler.Compile(Assembly parent, String ns, CompilerParameters parameters, Evidence evidence)
       at System.Xml.Serialization.TempAssembly.GenerateAssembly(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, Evidence evidence, CompilerParameters parameters, Assembly assembly, Hashtable assemblies)
       at System.Xml.Serialization.TempAssembly..ctor(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, String location, Evidence evidence)
       at System.Xml.Serialization.XmlSerializer.GenerateTempAssembly(XmlMapping xmlMapping, Type type, String defaultNamespace)
       at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace)
       at System.Xml.Serialization.XmlSerializer..ctor(Type type)
       at System.ServiceModel.Install.Configuration.ConfigurationHandlersInstallComponent..ctor(ConfigurationLoader configLoader)
       at System.ServiceModel.Install.Configuration.ConfigurationHandlersInstallComponent.CreateNativeConfigurationHandlersInstallComponent()
       at Microsoft.Tools.ServiceModel.ServiceModelReg.BuildActionQueue()
       at Microsoft.Tools.ServiceModel.ServiceModelReg.Run(String[] args)
       at Microsoft.Tools.ServiceModel.ServiceModelReg.TryRun(String[] args).

    Possible root cause of the issue

    These call stacks mean that the installation process is running into errors while attempting to create a new file in the temporary directory on the computer.  In many of the cases I've seen of this type of error in the past, there was an anti-virus or anti-spyware program running on the system that was preventing applications from creating files in the temporary directory.

    Options to work around the issue

    When I see this type of error in the event logs during .NET Framework 3.0 or 3.5 installation, I typically suggest trying the following workaround:

    1. Temporarily disable anti-virus and anti-spyware software on the system
    2. Try to install the .NET Framework 3.0 or 3.5 again
    3. Re-enable the anti-virus and anti-spyware software that was disabled in step 1

    If those steps are not helpful, then I typically suggest installing the .NET Framework 3.5 SP1 instead of the .NET Framework 3.0 or 3.5.

    The reason I suggest this is because the .NET Framework 3.5 SP1 installs the .NET Framework 3.0 SP2 behind the scenes as a prerequisite.  The underlying issue described above occurs while running a specific custom action during the .NET Framework 3.0 installation process.  In the .NET Framework 3.0 SP2 installer, a logic change was made so that if this particular custom action fails, setup will continue to install instead of failing and rolling back.  The end result is that if this action fails in 3.0 SP2, installation will complete and report success, but some specific functionality related to the System.ServiceModel namespace will not work correctly.  However, if this scenario arises, it is possible to manually run the ServiceModelReg.exe tool after the fact if this functionality is needed and it isn't working as expected.

  • Aaron Stebner's WebLog

    Creating an MSI-based installer for the XNA Game Studio 3.0 platformer starter kit

    • 5 Comments

    I previously wrote an introductory post describing Windows game deployment features that are a part of XNA Game Studio 3.0.  That post focuses mostly on ClickOnce publishing and the Visual Studio bootstrapper that can be used to create an installer to chain the .NET Framework and XNA Framework prerequisites along with Windows-based games.

    I most commonly use WiX v3.0 when creating installers, so I wanted to also devote some time to explaining how to use the WiX toolset to create an MSI-based installer for a Windows game created with XNA Game Studio 3.0.

    In order to write this blog post, I created a working sample that can be used to create an MSI-based installer for the platformer game that is included as a starter kit in XNA Game Studio 3.0.  In this blog post, I'll walk through how to download and build the sample, then explain the details about how I created the sample so that you can use similar techniques for the installers for your games if you choose to.

    You can download the sample from http://cid-27e6a35d1a492af7.skydrive.live.com/self.aspx/Blog%7C_Tools/WiX%20Samples/wix%7C_sample%7C_xgs30%7C_game.zip.

    Using the sample - preparing your system

    Before being able to build an installer using the sample I created, you will need to configure your system as follows:

    1. Install Visual Studio 2008 or Visual C# 2008 Express Edition and XNA Game Studio 3.0.
    2. Install the latest build of WiX v3.0 from http://wix.sourceforge.net/releases/.
    3. Open Visual Studio and create a project using the Platformer Starter Kit (3.0) project template that is included as a part of XNA Game Studio 3.0.
    4. Build the x86 release version of the project.

    Using the sample - downloading the source files and building the installer

    Now that you have compiled the game, you are ready to download the sample and build an installer for the game.  You can use the following steps to do this:

    1. Download the sample from http://cid-27e6a35d1a492af7.skydrive.live.com/self.aspx/Blog%7C_Tools/WiX%20Samples/wix%7C_sample%7C_xgs30%7C_game.zip.
    2. Create a sub-folder named Setup in the Platformer game project that you created above.
    3. Extract the contents of wix_sample_xgs30_game.zip to the Setup folder.  You should end up with a folder structure like c:\Users\myusername\Documents\Visual Studio 2008\Projects\Platformer1\Platformer1\Setup with the contents of the .zip file in there.
    4. Run the script named build_wix_sample_xgs30_game.bat from the Setup folder to invoke the WiX toolset and build an MSI for the game.

      Note: If you choose to, you could add a post-build step to your game project to invoke build_wix_sample_xgs30_game.bat instead of running it manually.  This would cause your MSI to be rebuilt each time you rebuild your game.
    5. After the build completes, you will have a file named wix_sample_xgs30_game.msi.  You can double-click on it to run it and test installing a copy of the Platformer game to your system.

    This sample makes a couple of key assumptions that you will need to keep in mind:

    • It expects the files that it will include into the MSI are located in a relative path of ..\bin\x86\Release.  That means that you must unzip the sample files to a sub-folder that is at the same level as the bin directory for your project.  You must also build the release (and not debug) version of the game for the installer to build correctly using this sample.
    • It expects the game executable to be named Platformer1.exe.  If you created the game with a different name, you will need to update the information in the file Platformer.wxs that is included with the sample.

    Creating your own installer - Step 1: using Heat to harvest the game project output

    Now that I have explained how to build the sample, I want to explain some of the behind-the-scenes details about how I created it so that hopefully you can apply similar techniques in order to use WiX v3.0 to create MSI-based installers for your own games.

    The first step I took was to create a WiX source (.wxs) file to describe the files and directory structure that I want to use when installing the game.  The installer needs to essentially mimic the output from the game project's build process (the \bin\x86\release\ directory for example), but there are a lot of files in that folder, and I didn't want to author all of these files into WiX syntax manually.  Fortunately, the WiX toolset contains a tool named Heat that allows you to harvest resources and automatically create WiX setup authoring for you.

    In this case, I ran Heat with command line switches to cause it to recursively harvest all of the files in the \bin\x86\release\ directory and generate a .wxs file from it.  To do that, I used the the following steps:

    1. Click on the Start menu, choose Run, type cmd and click OK
    2. Change the cmd prompt directory to my game project's root directory by running a command like the following:  cd /d c:\users\myusername\Documents\Visual Studio 2008\Projects\Platformer1\Platformer1
    3. Run this command to invoke Heat and harvest the \bin\x86\release\ directory for the game:  "%ProgramFiles%\Windows Installer XML v3\bin\heat.exe" dir -gg -sfrag bin\x86\release -out Platformer.wxs

    After creating Platformer.wxs, I had to make a couple of changes to the setup authoring information that was created:

    1. Change the Directory element to a DirectoryRef so that it can be included in my main .wxs file.  To do that, I found this line:

      <Directory Id="release" Name="release">

      and changed it to this (the exact ID value is important here - I will explain that in more detail below):

      <DirectoryRef Id="APPLICATIONFOLDER">
    2. Change each of the Source values to be relative paths instead of absolute paths - this isn't strictly necessary, but it makes the .wxs file more portable so it will work on other systems that don't have the exact same folder structure.  You can do a find-and-replace to update all of the Source values at once.
    3. Add an icon that will be displayed for the game in Add/Remove Programs.  I chose the icon that is a part of the Platformer game starter kit for this purpose.  To do that, I added the following lines to Platformer.wxs inside the Fragment but outside of the DirectoryRef:

      <Icon Id="ProductIcon" SourceFile="..\Game.ico" />
      <Property Id="ARPPRODUCTICON" Value="ProductIcon" />
    4. Remove the Component, File and ComponentRef elements for the file Platformer1.pdb so it will not be included in my installer.

    Creating your own installer - Step 2: creating a main .wxs file that references the Heat output

    After generating the setup authoring for the game project output, I created a main .wxs file to represent my MSI and to reference the contents of the Platformer.wxs file that I created above.  The file wix_sample_xgs30_game.wxs is the main .wxs file for the sample I created, and most of its contents are boilerplate WiX syntax.  There are a few specific items that I added to the .wxs file in order to cause the WiX build process to include the game payload that was created by Heat in Platformer.wxs:

    1. I defined the following Directory structure, which is used as the default install path for the game in the setup UI:

      <Directory Id="TARGETDIR" Name="SourceDir">
        <Directory Id="ProgramFilesFolder" Name="Program Files">
          <Directory Id="APPLICATIONFOLDER" Name="Sample XNA Framework 3.0 Game" />
        </Directory>
      </Directory>

      Note - the Id value of the game's root directory needs to be set to APPLICATIONFOLDER just like the Id value of the DirectoryRef that we added to Platformer.wxs above.  This is how WiX will know to include all of the files and sub-folders under this directory into your MSI at build time.
    2. I defined the following Feature, and included a reference to the ComponentGroup1 item that was created by Heat in Platformer.wxs:

      <Feature Id="Payload" Title="!(loc.Feature_Title)" Level="1">
        <ComponentGroupRef Id="ComponentGroup1" />
      </Feature>

      Note - the Id value of the ComponentGroupRef listed here must match the Id of the ComponentGroup in Platformer.wxs in order to cause WiX to include all of the files and sub-folders into your MSI at build time.

    Creating your own installer - Step 3: adding prerequisite checking

    After adding the payload for the game to the installer, my next step was to add some prerequisite checks to make sure that users will not be allowed to install the game if system components needed to run the game are missing.  In a future blog post, I will explain how to build a VS bootstrapper package to automatically install the prerequisites if they are missing, but for now, I am just going to demonstrate how to check for the .NET Framework 2.0 and the XNA Framework Redistributable 3.0 and block installation if they are missing.  Note that even if you add logic later on to automatically install these prerequisites, it is a good idea to have these blocks in the MSI in case a user tries to skip running the bootstrapper and installs the MSI directly.

    The following logic allows you to set property values that identify the .NET Framework 2.0 and XNA Framework Redistributable 3.0 install state:

    <PropertyRef Id="NETFRAMEWORK20" />

    <Property Id="XNAFRAMEWORK30" Secure="yes">
      <RegistrySearch Id="XnaFramework30RegLocator" Root="HKLM" Key="SOFTWARE\Microsoft\XNA\Framework\v3.0" Name="Installed" Type="raw" />
    </Property>

    Note - the NETFRAMEWORK20 property is included as a part of the WixNetfxExtension in WiX v3.0, so I am including it as a PropertyRef instead of defining it myself.

    After defining the detection properties, we next need to create type 19 custom actions to block the user from installing the game if the prerequisites are not found on the system.  That requires adding the following authoring:

    <CustomAction Id="CA_CheckForNetfx20" Error="!(loc.LaunchCondition_Netfx20)" />

    <CustomAction Id="CA_CheckForXnafx30" Error="!(loc.LaunchCondition_Xnafx30)" />

    Note: The exact error messages are defined in a separate WiX localization (.wxl) file in order to make it easier to create localized versions of the installer in the future if we choose to.

    After creating the custom actions, we now need to schedule them so they will run at the appropriate times during setup.  That is accomplished by adding the following information to the sequence tables:

    <InstallExecuteSequence>
      <LaunchConditions After="AppSearch"/>
      <Custom Action="CA_CheckForNetfx20" After="LaunchConditions">NOT NETFRAMEWORK20 AND NOT Installed</Custom>
      <Custom Action="CA_CheckForXnafx30" After="CA_CheckForNetfx20">(NOT XNAFRAMEWORK30 = "#1") AND NOT Installed</Custom>
    </InstallExecuteSequence>

    <InstallUISequence>
      <LaunchConditions After="AppSearch"/>
      <Custom Action="CA_CheckForNetfx20" After="LaunchConditions">NOT NETFRAMEWORK20 AND NOT Installed</Custom>
      <Custom Action="CA_CheckForXnafx30" After="CA_CheckForNetfx20">(NOT XNAFRAMEWORK30 = "#1") AND NOT Installed</Custom>
    </InstallUISequence>

    Creating your own installer - Step 4: finishing touches

    After creating the main .wxs file and adding the necessary references to the game payload and the custom actions to check for prerequisites, I also added the following items to provide the user experience that I wanted to support for this game installer:

    1. I wanted to build a self-contained MSI that includes all of the game payload.  To accomplish that, I added the following Media entry that tells WiX to embed the payload as a cabinet file inside of the MSI instead of packaging the payload as loose files next to the MSI:

      <Media Id="1" Cabinet="wix_sample_xgs30_game.cab" EmbedCab="yes" />
    2. I chose the built-in WixUI_InstallDir dialog set for the setup UI so that I would not have to create any custom setup UI pages.  This dialog set includes a welcome page, a license agreement page, an installation directory selection page, a confirmation page, a progress page and a completion page (plus relevant error dialogs for failure cases).  I added the following information to the .wxs file to accomplish this:

      <UIRef Id="WixUI_InstallDir"/>
      <Property Id="WIXUI_INSTALLDIR" Value="APPLICATIONFOLDER" />
      <WixVariable Id="WixUILicenseRtf" Value="License.rtf" />

      Notes - The Property named WIXUI_INSTALLDIR must have a Value of APPLICATIONFOLDER to match the value used above - this is how the default install path is set for the setup UI.

      Also, the sample I posted includes a default license.rtf file to display in the license agreement text box.  You can replace that file with your own license terms when creating your own games by updating the Value of the WixVariable named WixUILicenseRtf to point to your own license file.
    3. I added logic to this MSI to enable Windows Installer major upgrades - this allows me to build a new version of the MSI that will automatically uninstall older versions if they are installed on the user's system.  This is an optional step, but I typically include it when I create any installer in order to give myself more options for updating the application in the future.  I added the following information to accomplish this:

      <Upgrade Id="!(loc.Property_UpgradeCode)">
        <UpgradeVersion Minimum="$(var.ProductVersion)" OnlyDetect="yes" Property="NEWERVERSIONDETECTED" />
        <UpgradeVersion Minimum="1.0.0" IncludeMinimum="yes" Maximum="$(var.ProductVersion)" IncludeMaximum="no" Property="OLDERVERSIONBEINGUPGRADED" />
      </Upgrade>

      <InstallExecuteSequence>
        <Custom Action="CA_BlockOlderVersionInstall" After="FindRelatedProducts">
          <![CDATA[NEWERVERSIONDETECTED]]>
        </Custom>
        <RemoveExistingProducts After="InstallInitialize" />
      </InstallExecuteSequence>
    4. <InstallUISequence>
        <Custom Action="CA_BlockOlderVersionInstall" After="FindRelatedProducts">
          <![CDATA[NEWERVERSIONDETECTED]]>
        </Custom>
      </InstallUISequence>

    Creating your own installer - Advanced scenario 1: per-user installer

    The sample that I posted creates a per-machine MSI that requires administrative privileges (and UAC elevation on Windows Vista).  Many XNA Framework-based Windows games can install and run as per-user applications.  It is possible to convert this sample from a per-machine MSI into a per-user MSI.  There is a set of general steps that need to be taken to create a per-user MSI in WiX v3.0 in this blog post.

    Creating your own installer - Advanced scenario 2: Windows Vista Game Explorer integration

    WiX v3.0 includes built-in logic to allow you to integrate your game with the Windows Vista Game Explorer.  There is an introduction to this WiX v3.0 feature in this blog post.  In addition, Bob Arnson recently enhanced the WixGamingExtension to support using separate files for the game executable and the GDF resource file.  This fix is available in WiX builds starting with 3.0.4707.0.

    <update date="3/21/2009"> Fixed broken link to sample installer files. </update>

     

  • Aaron Stebner's WebLog

    Updated XNA Game Studio 3.0 starter kits are now available for download

    • 1 Comments

    To go along with the recent release of the final version of XNA Game Studio 3.0, we have posted a set of updated starter kits that will work with Visual Studio 2008 or Visual C# 2008 Express Edition and XNA Game Studio 3.0.

    You can find the download pages for the starter kits on the Creators Club site at http://creators.xna.com/en-US/education/starterkits/.

    Each of the starter kits has download links for both XNA Game Studio 2.0 and XNA Game Studio 3.0 versions.  When visiting the download pages, make sure that you download the MSIs that match the version of XNA Game Studio that you plan to use.

    The installers for the 3.0 starter kits will check your system and verify that you have a Visual Studio 2008 edition installed and have XNA Game Studio 3.0 installed.  After installing, the starter kits will appear in the My Templates section of Visual Studio new project dialog under the Visual C# node in the XNA Game Studio 3.0 sub-node.

  • Aaron Stebner's WebLog

    Configuring XNA Game Studio 3.0 projects with custom content processors to work with ClickOnce deployment

    • 3 Comments

    Since we released XNA Game Studio 3.0, I've heard of a few problems from customers via my blog and the Creators Club forums related to deployment of Windows game projects that include custom content processors.  Most of the problems I've heard of so far involve using ClickOnce to deploy a game, then receiving the following error message when attempting to run the game on another computer that doesn't have XNA Game Studio 3.0 installed:

    Unable to install or run the application. The application requires that assembly Microsoft.Xna.Framework.Content.Pipeline be installed in the Global Assembly Cache (GAC) first.

    This error is typically caused by including a reference to the custom content processor in the Windows game project even though the processor is only needed at build time.  If the processor is only needed at build time, you only need to include a reference to it in your content project.  Doing this will prevent any dependencies on content pipeline assemblies while running your game.  This is important because the XNA Framework Redistributable 3.0 does not contain content pipeline assemblies, which means that the only way to run a game that requires content pipeline assemblies at runtime (and not just at build time) is to install XNA Game Studio 3.0 on the target system.

    I have also heard of one issue where someone fixed the content pipeline assembly reference issue described above, but then ran into an exception stating that the type ContentTypeReader cannot be found when deploying their their game to another computer.  Custom content processors can include several parts - an importer, a processor, a type writer and a type reader.  Of these, the type reader and any types used by your game need to be deployed to the target system along with your game binaries and content.  The importers, processors and type writers are only needed at build time and do not need to be deployed to the target system.

    In order to avoid deployment issues, if you have a custom content processor that includes both build time and runtime components, you can split your custom content processor into the following:

    • A content pipeline extension project that includes the importers, processors and type writers.  This project will be used at build time, and needs to be included as a reference in your content project(s) but not your game project(s)
    • A game library project or code files that are included in your game project and includes the type readers and any types used by the game.  If you use a game library project, you need to include it as a reference in your game project(s)

    To better understand the content pipeline and the split between build time and runtime components, I'd suggest reading the recent post that Shawn Hargreaves wrote at http://blogs.msdn.com/shawnhar/archive/2008/11/24/content-pipeline-assemblies.aspx.  The post includes the following information:

    • Content pipeline data flow
    • What parts of the content pipeline run at build time on the development PC versus running at game run time on the target device
    • Details about creating custom content processors based on real world scenarios from samples currently available on the Creators Club site
  • Aaron Stebner's WebLog

    New samples available for XNA Game Studio 3.0 and how to upgrade existing XNA Game Studio 2.0 samples

    • 0 Comments

    Earlier this week, we released updated versions of the existing XNA Game Studio starter kits on the Creators Club web site that will install and work with XNA Game Studio 3.0.  To go along with that, we have also released some new and updated samples and a standalone version of the Spacewar starter kit for XNA Game Studio 3.0.

    New XNA Game Studio 3.0 samples

    We released 3 new samples that were created by Shawn Hargreaves to demonstrate new features in XNA Game Studio 3.0 and to better illustrate some of the best practices that will help you add polish to your games for publication on Xbox LIVE Community Games.  Here is some info about the new samples:

    1. Invites - this sample builds on the peer-to-peer networking sample to demonstrate how to use the new invites feature in a game created with XNA Game Studio 3.0
    2. Safe Area - this sample demonstrates how to make your game display correctly on a wide range of televisions; this is important so your game will look good on standard and wide-screen TVs of various sizes
    3. Localization - this sample demonstrates how to create a multi-lingual game that uses .NET resource files to store locale-specific information and dynamically load the appropriate resources at runtime depending on the user's system settings

    Updated samples

    We also released updated versions of the following samples to better illustrate community game best practices and new XNA Game Studio 3.0 features:

    Spacewar starter kit

    In addition, we released a standalone XNA Game Studio 3.0 version of the Spacewar starter kit (previously available as a part of the XNA Game Studio installation process, but replaced in 3.0 by the Platformer starter kit).

    Converting existing 2.0 samples to 3.0

    Most of the samples currently available on the Creators Club site are still only available in XNA Game Studio 2.0 versions.  However, they can easily be converted to work with XNA Game Studio 3.0 (and you do not need to have VS 2005 or XNA Game Studio 2.0 installed to convert the samples).  Here are steps you can use to accomplish this conversion:

    1. Download the sample .zip file and extract the contents to a folder on your computer
    2. Open Visual Studio 2008 or Visual C# 2008 Express Edition
    3. Click on the File menu and choose Open | Project/Solution... (in VS 2008) or Open Project... (in VC# 2008 Express)
    4. Browse to the .csproj for the sample that you downloaded - this will cause the Visual Studio Conversion Wizard to appear
    5. Step through the wizard UI to upgrade the project - as long as you have XNA Game Studio 3.0 installed along with VS 2008, the conversion wizard will upgrade the XNA Framework-specific information in the project files in addition to performing the general C# project upgrade steps provided by Visual Studio
    6. After the conversion process completes, save the project, then build and run it in VS 2008 + XNA Game Studio 3.0

    There is also a set of unofficial XNA Game Studio 3.0 samples that a member of the community converted from 2.0 to 3.0 using steps like the ones listed above and then re-zipped and posted for download.  You can find link to these unofficial samples in this blog post.  This link mentions the XNA Game Studio 3.0 beta, but there are not any differences in the Visual Studio project file format between the beta and the final release of XNA Game Studio 3.0, so these samples should also work in the final release of 3.0 and not just in the beta.

    <update date="11/15/2008"> Added a link to a download location for unofficial 3.0 versions of the XNA Game Studio samples. </update>

     

  • Aaron Stebner's WebLog

    Online documentation is now available for XNA Game Studio 3.0

    • 0 Comments

    Yesterday, the publishing process was completed for the online version of the XNA Game Studio 3.0 documentation.  You can access this documentation at http://msdn.microsoft.com/library/bb200104.aspx.

    The documentation is also installed as a part of the XNA Game Studio 3.0 product if you would like to use the documentation on your computer without requiring access to the Internet.  You can launch the documentation by clicking on the Windows start menu, choosing All Programs, then XNA Game Studio 3.0, then XNA Game Studio Documentation.

  • Aaron Stebner's WebLog

    Possible issue with ClickOnce publishing using a project created with the XNA Game Studio 3.0 CTP

    • 0 Comments

    If you are using ClickOnce to deploy a Windows game created with XNA Game Studio 3.0, you might run into an issue that causes the game to not run correctly after being deployed to a user's computer.  If your Windows game project was originally created with the XNA Game Studio 3.0 CTP, it will not be configured to include the XNA Framework Redistributable 3.0 as a prerequisite by default (because that feature was not added until the 3.0 beta).

    In this scenario, you can use the following steps to manually add the XNA Framework Redistributable 3.0 as a prerequisite for your Windows game, and then re-publish your game to get the changes to take effect:

    1. Right-click on your Windows game project in the Visual Studio 2008 or Visual C# 2008 Express Edition solution explorer and choose Properties
    2. Choose the Publish tab
    3. Click the Prerequisites... button
    4. Check the item at the bottom of the list that is named Microsoft XNA Framework Redistributable 3.0
    5. Click OK to dismiss the Prerequisites dialog
    6. Save your project
    7. Publish your project

    New Windows game projects created in the final release of XNA Game Studio 3.0 will automatically include the XNA Framework Redistributable 3.0 as a prerequisite by default, so these steps are only needed for Windows game projects originally created with the 3.0 CTP.

Page 1 of 1 (10 items)