I had a lot of linker errors in Visual Studio 2008 Express which I suspected were related to the issues being discussed in this question and this one. After a lot of investigating I managed to fix the problem, and thought it would be useful to share the knowledge.
In summary (I give more detail below):
the linker errors were happening because the value of %WindowsSdkDir%
was not being set correctly, and therefore VS could not find files like kernel32.lib
,
the reason for the incorrect setting was frustratingly simple: a space had crept into the PATH
variable just at the front of the %SystemRoot%\system32
entry,
this meant that the reg query
MSDOS command had effectively been disabled,
this command is used in one of the VS batch files to set variable values; the batch file therefore ended up setting %WindowsSdkDir%
not from the registry (all my registry entries were correct), but instead set it to equal its default value of %VCINSTALLDIR%\PlatformSDK\
which was not correct for my setup.
Obviously, the fix was easy in my case: remove the space! But of course, it is the route to the solution that really is the interesting bit...
As I said, the first symptom of the problem was that VS was giving nasty linker errors. I was able to understand from these that VS was not able to find files like kernel32.lib
.
If you search around this you are likely to find yourself at this SO question. The answer that currently sits with the most votes mentions WindowsSdkDir
, and suggests that the questioner check it is correctly referenced in the VS settings.
It was clear to me that my VS settings were not the problem because I had already been able to get my installation completed error free on another machine. More searching on 'WindowsSdkDir' led me to this here SO question, and I checked all the registry entries that are suggested (here and elsewhere):
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Microsoft SDKs\Windows
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6342Node\Microsoft\Microsoft SDKs\Windows
HKEY_CURRENT_USER\SOFTWARE\Wow6342Node\Microsoft\Microsoft SDKs\Windows
All of these were correctly set: the value in the registry of the CurrentInstallFolder
value was always C:\Program Files\Microsoft SDKs\Windows\v6.0A\
. I was at a loss to understand why the %WindowsSdkDir%
variable was being set with a yet different value.
Yet more searching led me to places like this, and I felt ready to have a go at understanding how the %WindowsSdkDir%
variable gets set.
My best understanding of the process is:
The file C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat
is the one of the first scripts to get run. (BTW you right-click and Edit
to see its contents). It was not difficult to work out that the line call "%~dp0bin\vcvars32.bat"
is executed.
The %~dp0bin\
is interpreted as 'the bin
directory in the current directory`, and therefore the next place to go is there.
In that bin
directory there is the expected vcvars32.bat
, and it contains only one command: "%VS90COMNTOOLS%vsvars32.bat"
.
To see what %VS90COMNTOOLS%
means you can open the Visual Studio command prompt (which you find in the Start Menu in the VS section) and enter echo %VS90COMNTOOLS%
. For me it expands to C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\Tools
.
So I find myself at the file C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\Tools\vcvars32.bat
. This file has some real content, and I was able to recognize that the command @call :GetWindowsSdkDir
is where the action happens.
That function is defined in this same file, a few lines down:
:GetWindowsSdkDir
@call :GetWindowsSdkDirHelper HKLM > nul 2>&1
@if errorlevel 1 call :GetWindowsSdkDirHelper HKCU > nul 2>&1
@if errorlevel 1 set WindowsSdkDir=%VCINSTALLDIR%\PlatformSDK\
@exit /B 0
This function obviously depends on a second function in that same file:
:GetWindowsSdkDirHelper
@for /F "tokens=1,2*" %%i in ('reg query "%1\SOFTWARE\Microsoft\Microsoft SDKs\Windows" /v "CurrentInstallFolder"') DO (
if "%%i"=="CurrentInstallFolder" (
SET "WindowsSdkDir=%%k"
)
)
@if "%WindowsSdkDir%"=="" exit /B 1
@exit /B 0
We are nearly there now. I was able to see how the registry values are actually accessed with the reg query
command, and it was a good guess that the command was returning errors and falling through to the default setting.
When I tried calling reg query
in a vanilla MSDOS cmd
I got a message that it was not recognized.
Naturally you go look in the PATH
variable at this point, and there I came across that nasty little space in the C:\windows\system32\
entry. The space had been put there by accident on a previous edit, fancy that!
Postscript
In the process of writing this answer I stumbled across this SO answer which explains how it is the PATH
variable that is the source of the problem! Just for the record, that SO answer actually points to a blog post here
You can see form the definition of the :GetWindowsSdkDir
function that it looks in the registry at the HKLM
values first, and if it does not find them it looks at the HKCU
values. This suggests to me that Visual Studio 2008 Express does not use the registry entries in the Wow6432Node
branches.