Why is Visual Studio 2013 using the wrong SdkTools

2020-02-11 05:26发布

问题:

I am using Visual Studio 2013 with an asp.net project. One of the projects gives the error below. Why is it looking for LC.exe in the wrong path? My Windows 8.1 SDK is installed and I have an lc.exe at

C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools

and a 64bit version and I have a registry key at

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.1A

I am looking at Microsoft.Common.targets under C:\Windows\Microsoft.NET\Framework\v4.0.30319 and this key exists: SdkToolsPath="$(TargetFrameworkSDKToolsDirectory)". Then looked at Microsoft.NetFramework.CurrentVersion.props under

C:\Program Files (x86)\MSBuild\12.0\Bin

and TargetFrameworkSDKToolsDirectory is defined at $SDK40ToolsPath. According to MSBuild /v:diag,

SDK40ToolsPath = C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools 

which looks good. The project's target in VS in .NET 4.0.

So why is it still looking at the wrong folder or registry key? The interesting thing is when I rebuild the project after getting the error message, the project builds fine.

Error   5   
Task could not find "LC.exe" using the SdkToolsPath 
    "C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 Tools\" 
or the registry key 
    "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.0A\WinSDK-NetFx40Tools-x86".
Make sure the SdkToolsPath is set and the tool exists in the correct processor 
specific location under the SdkToolsPath and that the Microsoft Windows SDK is 
installed   
    C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets  2428    5   SuperReports

回答1:

It turns out you can specify the path to the SDK directly in the .csproj file:

<TargetFrameworkSDKToolsDirectory>C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6 Tools</TargetFrameworkSDKToolsDirectory>

and the build found lc.exe that way.

I previously expected to set this using <SdkToolsPath>, but that didn't work. In Microsoft.Common.targets, SdkToolsPath gets set from TargetFrameworkSDKToolsDirectory, so I tried that and it worked. This is on Visual Studio 2015, and msbuild being called from ant.

Solution found via MSBuild Using Incorrect Version of sgen.exe to Generate XmlSerializer dlls?



回答2:

Do you have a PlatformToolset property defined in your project before the imports? I think it uses that and maybe the ToolsVersion attribute on the Project XML element to choose between multiple installed SDKs. I think, from similar path funny business, that the IDE sets paths to find things based on the PlatformToolset which it looks for in a specific place in the project (while building from MSBuild command line it works no matter how it was set).

Here is an example from a vcxproj file:

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" 
    ToolsVersion="4.0" 
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <!-- NB: see ToolsVersion in above -->

⋮

<PropertyGroup Label="Globals">
  <ProjectGuid>{⋯⋯⋯}</ProjectGuid>
  <RootNamespace>blahblahblah</RootNamespace>
  <ConfigurationType>StaticLibrary</ConfigurationType>
  <PlatformToolset>Windows7.1SDK</PlatformToolset>
  <!-- NB: PlatformToolset must be repeated in each top-level project file -->
  <Keyword>Win32Proj</Keyword>
</PropertyGroup>

I think there are two reasons why this gives funny results if placed in a common property page: First, it needs to be set before the standard built-in logic is imported (e.g. Microsoft.Cpp.Default.props), and second the IDE somehow sets paths itself or does something with the generated solution file, and it looks for that property in the main file. I learned this when I was getting wrong paths (wrong version of an EXE was being used) when built by pressing F7 when it worked fine invoking MSBuild from a command line.

In the IDE, check the Platform Toolset in the properties editor for the project. Make sure it is shown in boldface; that is, set directly there rather than inherited even if it has the correct version showing.



回答3:

I went with a slightly different hack than the one suggested by Hans Passant above. My scenario is my builds are executed via Jenkins (a CI tool), using MSBuild 2015, in a Windows 2008 server.

Microsoft SDK 10 does not support Windows 2008, according to the docs. I tried playing with both SdkToolsPath and FrameworkOverride msbuild command line parameters but without success (did not try them together, have just realized while typing).

In any case, something that worked, was that yes - I was not able to force msbuild to use the newer SDK version instead of the one from Windows 7 (it insists in taking LC.exe from C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\NETFX 4.0 Tools) - so my hack was to overwrite the LC.exe with the one from SDK 10 (I have installed in my local machine, not in the build server, running Windows 2008).

My build finally succeeded.