Thoughts about setup and deployment issues, WiX, XNA, the .NET Framework and Visual Studio
All postings are provided AS IS
with no warranties, and confer no rights. Additionally, views expressed
herein are my own and not those of my employer, Microsoft.
Many installers and applications require that one or more versions of the .NET Framework be installed on the system in order to be able to install and function correctly. This article provides sample C++ code that can be used in a setup program or in an application's code to detect the install state and service pack level of various versions of the .NET Framework.
Note - when used in a setup program, this sample code is intended to be used in a setup EXE bootstrapper. It is not intended for use within an MSI. If your setup program is a single MSI, you can use Windows Installer AppSearch and RegLocator tables to detect the install state. If you use WiX to create your MSI, you can use the information provided in the WixNetFxExtension instead of implementing this logic yourself. Refer to How To: Check for .NET Framework Versions in the WiX documentation for more details.
.NET Framework versions that can be detected by the sample code
The sample code available via this article supports detecting the install state and service pack level for the following versions of the .NET Framework:
Registry-based detection code
The simple version of the sample code queries the officially documented registry values that are intended to be used to detect the presence of each version of the .NET Framework.
This sample code can be downloaded from the following location:
Registry-based detection code and more in-depth checking that loads mscoree.dll
The more thorough version of the sample code queries the officially documented registry values like in the previous sample. In addition, it performs an additional check that loads mscoree.dll and uses some of its APIs to query for the presence of specific versions of the .NET Framework. The algorithm to perform the additional check was originally introduced in this blog post.
Creating a Visual Studio project to compile the sample code
The sample code available for download via the links above is in the form of a single C++ source (.cpp) file. If you are having trouble getting this code to compile on your system, you can refer to the instructions in this blog post to create a Visual C++ project that can be used to compile the sample code into a sample executable file.
For anyone reading this in the future, here is a link to a starting point you can use to convert this sample code to C# - http://geekswithblogs.net/lorint/archive/2006/01/30/67654.aspx.
One note of caution here - if you write this detection code in C#, then if the computer you run it on doesn't have any version of the .NET Framework installed on it, the code won't be able to run. If you know for sure that at least one version of the .NET Framework will always be present on the computers that you run it on, it should probably be OK to write the detection code in C# though.
Also, if you need to detect the .NET Framework version or service pack level within an MSI, you should not use this detection code or a custom action. You can instead use the AppSearch, RegLocator and LaunchCondition tables. There are built-in detection properties in WiX that you can use for this if you use WiX to create your MSI. You can find more information about these detection properties at http://wix.sourceforge.net/manual-wix3/wixnetfxextension.htm.
When compiling the "more thorough" version in VS2008Express, I get
.\detectfx40.cpp(634) : error C2373: 'wWinMain' : redefinition; different type modifiers
C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\winbase.h(2573) : see declaration of 'wWinMain'
Any ideas? Thanks.
Hi BosReg - I'm not sure what would cause that error. I tested both of the samples that I posted in VS 2008 Professional, but not VC++ 2008 Express, but I don't know of any reason why it wouldn't work there too. Did you make any changes to the code before trying to compile it?
Hi. Thanks for the answer. I did a cut/paste from what is displayed in the browser of both sets of code. I also "Save As..."'d both and loaded them into different new projects. I made no changes. All combinations give the same error. I looked at the winbase.h refered to in the error, and the wWinMain declaration looks just like the _tWinMain in your code. This has all the earmarks of being something other than WinMain, but I'm not a cpp programmer, so I don't know tha usual suspects.
Hi BosReg - Just to confirm, are you also using the instructions at http://blogs.msdn.com/astebner/archive/2009/01/31/9387659.aspx when you create the Visual Studio project to build this code?
Yes, those instructions.
Hi BosReg - I'm sorry, but I'm not sure what is causing that compilation error. I tried again to make sure, and the steps at http://blogs.msdn.com/astebner/archive/2009/01/31/9387659.aspx worked fine for me on multiple computers. After I created the new VC++ project in Visual Studio and followed the steps to turn off pre-compiled headers, I selected all of the text in the .cpp file that is created with the same name as the project, then copied and pasted all of the code from http://public.blu.livefilestore.com/y1pn7xJa-v5xknXclEy7vYuB-sEU42_6c5giI0xc5bslWTPScZqavABO-WhcXAGuEECzBtnpzuXH8_jir47d2kFkg/detectfx_new.cpp.txt into that .cpp file, saved it, and pressed F5 to build and run it and it worked fine.
hi, i've successfully compiled your "detectfx_new" samplecode with "VC++ 2008 Express Ed SP1". no problems.
thx for your work.
hi, I'm interest to install dotnetframework silently when dotnetframework not exist, then launch my c# app. If dotnetframework exist just launch my c# app immediately instead launch a message box. How to modify your code since i'm totally new to c++? Thanks astebner.
Hi Jimmychan - Your best option in this scenario is to use a setup chainer to install the .NET Framework (if it doesn't exist) and then install your application. You can use the Visual Studio bootstrapper for this type of scenario, you can use other setup chainers that are available, or you could write something yourself to do this. You can look at msdn.microsoft.com/.../h4k032e1.aspx for some information about using the Visual Studio bootstrapper.
Hi. Thanks for your response. But my purpose is create a portable app with .NETFramework inside the folder. Run smooth without notify user anything. I see your code is best to suit my needs with some modification of course. But the problem is i'm new to c++ and want to launch my app instead launch messagebox. Any ideas? jimmychan: micadyelite at gmail dot com.
Hi Jimmychan - In order to accomplish this, you will need to update the sample code to call CreateProcess or some other Windows API to launch your program if it detects the .NET Framework. You can find documentation about these APIs on MSDN – for example, msdn.microsoft.com/.../ms682425.aspx.
Your code works great. But the problem is it only works on the computer it was compiled on. That has little value for me since I want to run this program on a target computer as part of the application setup process. I tested the program on Virtual PC running Windows XP SP2 just recently installed ( no .NET Framework set up yet ), and it doesn't execute. Instead it gives an error message. I have a feeling it still depends on the availability of .NET on the target machine in order to execute properly. What would you recommend ? Is there a way for me to build your code in Visual Studio so that the resulting program contains no dependecies on .NET Framework or anything else that causes this program to fail on old Windows OS ( such as XP, for example )? Thanks !
Hi Alex - I haven't had any problems building the sample code on one computer and running it on another computer. It is written in Visual C++ and it doesn't have any dependencies on the .NET Framework, so it doesn't require the .NET Framework to be on the computer in order to run correctly. What is the exact error message that you're seeing in this scenario on your computer?
The message I get is
"The application has failed to start because the application configuration is incorrect. Reinstalling the application may fix the problem".
I believe it has nothing to do with .NET. Something with CRT dll ?