How to get the Windows SDK folder in MSBuild?

2019-02-01 19:02发布

问题:

What would be the way to retrieve the Windows SDK folder in an MSBuild task?

Using the generateBootstrapper task I'm creating a bootstrapper for my setup to be able to install the pre-requisites. This task needs the path to the folder where the pre-requisite packages are located, i.e. the Windows SDK folder

"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages\"

when using Visual Studio 2008. So far I have been using a hard-coded path but this won't work on any system. Is there a better way to get the path?

This is my build script:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 
         ToolsVersion="3.5">
    <ItemGroup>
        <BootstrapperFile Include="Microsoft.Net.Framework.2.0">
            <ProductName>.NET Framework 2.0</ProductName>
        </BootstrapperFile>
        <BootstrapperFile Include="Microsoft.Windows.Installer.3.1">
            <ProductName>Windows Installer 3.1</ProductName>
        </BootstrapperFile>
    </ItemGroup>

    <Target Name="Bootstrapper">
        <GenerateBootstrapper ApplicationFile="mySetup.msi" 
            Culture="de-DE" 
            ApplicationName="My Application" 
            OutputPath="$(OutDir)\de-DE" 
            BootstrapperItems="@(BootstrapperFile)" 
            Path="C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages\" />

        <GenerateBootstrapper ApplicationFile="mySetup.msi" 
            Culture="en-US" 
            ApplicationName="My Application" 
            OutputPath="$(OutDir)\en-US" 
            BootstrapperItems="@(BootstrapperFile)" 
            Path="C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages\" />
    </Target>
</Project>

回答1:

You can also use the GetFrameworkSdkPath MSBuild task.

<GetFrameworkSdkPath>
  <Output TaskParameter="Path" PropertyName="WindowsSdkPath" />
</GetFrameworkSdkPath>  

For example:

<GenerateBootstrapper 
  ApplicationFile="$(SolutionName).application"
  ApplicationName="$(ClickOnceAppTitle)"
  ApplicationUrl="$(ClickOnceUrl)"
  BootstrapperItems="@(BootstrapperFile)"
  Culture="en"
  FallbackCulture="en-US"
  Path="$(WindowsSDKPath)"
  OutputPath="." /> 


回答2:

thanks John. According to your post I edited the MSBuild script to read the folder from the registry. It was however not necessary to append "Packages" on the end, that was another mistake in my original script.

The following is the working script:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

    <PropertyGroup>
        <WindowsSDKPath>$(registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\GenericBootstrapper\3.5@Path)</WindowsSDKPath>
    </PropertyGroup>

    <ItemGroup>
        <BootstrapperFile Include="Microsoft.Net.Framework.2.0">
                <ProductName>.NET Framework 2.0</ProductName>
        </BootstrapperFile>
        <BootstrapperFile Include="Microsoft.Windows.Installer.3.1">
                <ProductName>Windows Installer 3.1</ProductName>
        </BootstrapperFile>
    </ItemGroup>

    <Target Name="Bootstrapper">
        <GenerateBootstrapper ApplicationFile="mySetup.msi" 
            Culture="de-DE" 
            ApplicationName="My Application" 
            OutputPath="$(OutDir)\de-DE" 
            BootstrapperItems="@(BootstrapperFile)" 
            Path="$(WindowsSDKPath)" />

        <GenerateBootstrapper ApplicationFile="mySetup.msi" 
            Culture="en-US" 
            ApplicationName="My Application" 
            OutputPath="$(OutDir)\en-US" 
            BootstrapperItems="@(BootstrapperFile)" 
            Path="$(WindowsSDKPath)" />
    </Target>
</Project>


回答3:

The install path of the Windows SDK is stored in the CurrentInstallFolder value of the following registry key:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows



回答4:

I followed the answer from Jeremy D, but that gave the error message: error MSB3147: Could not find required file 'setup.bin' in 'C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\Engine'.

The reason is that the path to the bootstrapper (at least with V8.0A of the SDK) is a subdirectory under the path returned by the GetFrameworkSdKPath.

So the MSBuild code that works for me is:

<Target Name="AfterBuild">
  <GetFrameworkSdkPath>
    <Output TaskParameter="Path" PropertyName="WindowsSdkPath"/>
  </GetFrameworkSdkPath>
  <GenerateBootstrapper 
      ApplicationFile="myapp.msi" 
      ApplicationName="MyApplication" 
      BootstrapperItems="@(BootstrapperFile)" 
      OutputPath="$(OutputPath)" 
      Path="$(WindowsSdkPath)\Bootstrapper" />
</Target>

Note the \Bootstrapper suffix to $(WindowsSdkPath)



回答5:

The path to the bootstrapper is stored under the registry key:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\GenericBootstrapper\3.5

To find out the packages folder, open this, read the "Path" registry value, and append "Packages" on the end and that should give you the full path to the folder you want.

For example:

string bootStrapperPackagesFolder = "";

RegistryKey regKey = Registry.LocalMachine.OpenSubKey
   (@"SOFTWARE\Microsoft\GenericBootstrapper\3.5");
if (regKey != null)
{
   bootStrapperPackagesFolder = (string)regKey.GetValue("Path");
   if (bootStrapperPackagesFolder != null)
   {
      bootStrapperPackagesFolder += @"Packages\";
      Console.WriteLine(bootStrapperPackagesFolder);
   }
}