How to escape quotes in the command line for .NET Framework setup

I heard from a setup developer here at Microsoft last week who was working on updating his team's setup chainer to install the .NET Framework 2.0 instead of .NET Framework 1.1, but he was running into some issues while working on the implementation.

Their team's setup is doing something creative that I hadn't heard of anyone trying before. They want to be able to display reasonably accurate progress during the installation of the .NET Framework. Since the .NET Framework setup does not offer any kind of hook to let a calling setup package register to receive messages, they added logic to their setup chainer to parse the .NET Framework verbose MSI log file and display granular progress UI based on that. For reference, you can compare this algorithm to the "fake" progress algorithm used by Visual Studio setup when it installs the .NET Framework if you're interested.

Their setup wrapper installs the .NET Framework 1.1 with the command line dotnetfx.exe /q:a /c:"install.exe /l /q" In the .NET Framework 1.1 setup wrapper, passing the /l switch with no arguments following it causes setup to create a verbose MSI log file named netfx.log in the %temp% directory during setup.

A similar command line will allow you to install the .NET Framework 2.0, but the behavior of setup is slightly different. Verbose logging is enabled by default, so you do not need to pass the /l switch. By default, the verbose MSI log file will be named %temp%\dd_netfx20msi*.txt (where * is a randomly generated ending) instead of %temp%\netfx.log.

In order to minimize the churn to their setup code, the team that contacted me wanted to be able to force the log file to be named netfx.log so they would not have to dynamically determine the log file name each time their setup package launched .NET Framework 2.0 setup. I tried the following command line from a cmd prompt and it worked great for me - dotnetfx.exe /q:a /c:"install.exe /l %temp%\netfx.log /q".

However, the setup wrapper that this team wrote calls CreateProcess to launch .NET Framework 2.0 setup, and passing the %temp% string to CreateProcess throws an error because the environment variable is not automatically expanded via CreateProcess like it is via a cmd prompt, and the .NET Framework is not able to create a log file with the literal name %temp%\netfx.log. So they added code to their setup wrapper to programatically expand the %temp% variable (using an API call such as GetTempPath) and then call .NET Framework 2.0 setup with the expanded path passed in via the /l command line parameter.

This introduced one additional problem because the %temp% environment variable expands in a cmd prompt into 8x3 format (meaning there are no spaces in the path), but the GetTempPath API call expands into standard format (which typically has spaces in it). The .NET Framework 2.0 setup wrapper (install.exe) parses command line parameters using spaces as a delimiter unless the parameter is enclosed with quotes.

That means that if you want to install the .NET Framework 2.0 and create a log file in a path with spaces you need to use a command line like the following: dotnetfx.exe /q:a /c:"install.exe /l ""c:\Documents and Settings\myusername\Local Settings\Temp\netfx.log"" /q"

The key thing to note in this command line is that you have to double-quote any quotation marks that appear inside the quotes for the /c command line parameter. Double-quoting is the way that you have to escape quotation marks when passing command line parameters to an IExpress self-extracting executable package.

<update date="7/12/2006"> Updated instructions for .NET Framework 2.0 command line switches because the exact same command line from .NET 1.1 will not work in .NET 2.0 </update>