Archive: Determine if the vc8 dlls are installed


Determine if the vc8 dlls are installed
I've been trying to find a way to determine if the vc8 dlls (msvc*80.dll) are installed on a user's system. I've found a few different ways, but they all have their down sides.

http://nsis.sourceforge.net/VC_8.0_Redistributables
Only works if the user used the vc8 redist. If they were installed by some other means, like installing MS Visual Studio.

http://forums.winamp.com/showthread.php?postid=2080081#post2080081
I'm afraid this will be too slow on Vista. The WinSxS folder where the dlls are is too big (~5GB). It would take ages to search through that, wouldn't it?

http://blogs.msdn.com/astebner/archive/2007/01/16/mailbag-how-to-detect-the-presence-of-the-vc-8-0-runtime-redistributable-package.aspx
This looks like it might be the most promising way to do it. The problem is that I don't know how to call that MsiQueryProductState function. Can someone give me a hand with that?

Are there any other ways I haven't mentioned?
Any other thoughts on what I have said?

Thanks in advance for any help


Actually I know very little about vista.
The provided example that you're referring populates the whole system drive, on a typical XP <= system, which is probably useless for you.


I don't know much about Vista either. I just happened to stumble upon that piece of information at http://www.winvistaclub.com/f16.html


I wish I could help, yet, I don't intend to switch to vista.
Certain people down here, already renamed vista to svista, which means "remove them" in greeks. :)


You don't have to have Vista to help me. Just find a way that works in XP that doesn't involve searching for the .dll and it should work in Vista too (hopefully)


Did you try loadlibrary method? Normally microhog dlls are registered and ready to use with loadlibrary.


Thanks a lot! Doing a search for LoadLibrary in the wiki I found this page: http://nsis.sourceforge.net/WinSxS_QueryAssemblyInfo_to_check_if_assembly_is_installed I think that is what I'm looking for. And if it doesn't work as I want it I'm sure I can modify it to my needs (maybe with some help from you guys ;)


You can't use LoadLibrary with Side by Side (SxS) assemblies, so I have to use IAssemblyCache::QueryAssemblyInfo instead (as they do in that function I posted a link to in my last post).

The problem with QueryAssemblyInfo is that it needs the full assembly identity, not just the dll name. Since I don't care about the full version of the dll this complicates things a bit.

Does anyone have any idea how I can use QueryAssemblyInfo to find out if version 8.0.whatever is installed?


that is the whole point of WinSxS, several versions of 8.0.xxx on the same windows install


Yes, I know.

This is the problem:
With this line:
!define CRTCHECKNAME 'Microsoft.VC80.CRT,version="8.0.50727.42",type="win32",processorArchitecture="x86",publicKeyToken="1fc8b3b9a1e18e3b"'
the detection fails.

With this line:
!define CRTCHECKNAME 'Microsoft.VC80.CRT,version="8.0.50727.1433",type="win32",processorArchitecture="x86",publicKeyToken="1fc8b3b9a1e18e3b"'
the detection passes.

The actual program that uses msvcr80.dll works with either version of that dll, so I want the detection to pass in both cases.

Is my only option to run a detection on every possible version of that dll?


This is what I have to do right now, which I think is rather silly:

Push 'msvcr80.dll'
Push 'Microsoft.VC80.CRT,version="8.0.50727.42",type="win32",processorArchitecture="x86",publicKeyToken="1fc8b3b9a1e18e3b"'
Call WinSxS_HasAssembly
Pop $R0

${If} $R0 == 0
; Try another version
Push 'msvcr80.dll'
Push 'Microsoft.VC80.CRT,version="8.0.50727.163",type="win32",processorArchitecture="x86",publicKeyToken="1fc8b3b9a1e18e3b"'
Call WinSxS_HasAssembly
Pop $R0

${If} $R0 == 0
; Try yet another version
Push 'msvcr80.dll'
Push 'Microsoft.VC80.CRT,version="8.0.50727.762",type="win32",processorArchitecture="x86",publicKeyToken="1fc8b3b9a1e18e3b"'
Call WinSxS_HasAssembly
Pop $R0

${If} $R0 == 0
; Try another version again
Push 'msvcr80.dll'
Push 'Microsoft.VC80.CRT,version="8.0.50727.1433",type="win32",processorArchitecture="x86",publicKeyToken="1fc8b3b9a1e18e3b"'
Call WinSxS_HasAssembly
Pop $R0

${If} $R0 == 0
StrCpy $R3 "false"
${EndIf}
${EndIf}
${EndIf}
${EndIf}

you can just change the wiki sample to check more than one identity at the time

the

System::Call `$R0->4(i 0,w '$8',i $R1)i.r0` ;IAssemblyCache::QueryAssemblyInfo
${If} $0 == 0
System::Call '*$R1(i,i.r0)'
IntOp $0 $0 & 1 ;ASSEMBLYINFO_FLAG_INSTALLED=1
${IfThen} $0 <> 0 ${|} StrCpy $9 1 ${|}
${EndIf}

code could be called in a loop


Yes, but I would still have to call it once for every version of the .dll

And whenever microsoft releases a new version of the dll I need to update that script :/

Don't get me wrong here. I'm not trying to blame nsis or the function in the wiki. And I'm not trying to be ungrateful, I was just hoping there would be an easier way to do this.


well, there is, just use the findfile nsis stuff in $windir\winsxs and look for your dll (this method is not supported by MS ofcourse)


yeah, that would work if it weren't for Vista's 5GB winsxs dir...


Look at the folder names inside WinSxS for *VC80.CRT* , can't be that slow


Well, I needed to verify if those libraries are installed on every windows version and I found that:

- Windows 2000 sp4 not installed (obvious)
- Windows xp sp3 not installed (surprise)
- Windows server 2003 no sp not installed
- Vista home premium fresh install without any update. The libraries are installed v8.0.50727.312 assigned to none hence if your application has not dependency on a specific version you don't have to perform any search.

Therefore I've implemented Anders' code for search and Koby's code for install in xp/2003 which takes a couple of seconds to proceed along with policy manifest/cat who also need to install. For older windows just copy them into $SYSDIR.

So far, everything works as expected from win 2000 up to vista.


Originally posted by Red Wine
Windows xp sp3 not installed (surprise)
Not really a surprise to me, the CRT for anything after VC6 is not really a part of windows (Microsoft does not follow the guideline here, they have their own internal version, new CRT code, but it still is in msvcrt.dll so they don't have to ship this stupid runtime with windows)

I'm slightly confused by all of the above...

From:
http://blogs.msdn.com/astebner/archi...-2005-sp1.aspx
Linking to:
http://msdn.microsoft.com/en-gb/library/aa370363.aspx ( MsiQueryProductState Function )

Which describes a windows installer function to check if a particular product has been installed, one of the possible return codes is "INSTALLSTATE_ABSENT - The product is installed for a different user.".

Is it at all possible that the redistributables are installed under a 'current user' only, thus resulting in the above state? If so, wouldn't that invalidate the file searching method?

Alternatively, regardless of whether it might be installed for 'current users' only, wouldn't checking the registry work? The class ID passed to that MsiQueryProductState function is certainly the same as used for the uninstall class ID's; though one post found on here seems to reference an older (non-SP1, perhaps?) class ID (starting with A4).

I understand that the actual DLLs *may* have been installed via different means; either the extremely scary code as described by Koby or via a Visual Studio install, but then checking for those specific DLLs leads to the variat on DLL Hell (just when Microsoft intended SxS to do away with DLL Hell.. hum) that is checking version upon version and for each file you actually use; seeing as the existence of -one- file out of the redistributable wouldn't guarantee the existence of every single other?

Dependencies are always a mess, but this one is headache-worthy. ( A wiki page would be nice.. this one is outdated (and not very clearly titled; happened upon it via Google) : http://nsis.sourceforge.net/VC_8.0_Redistributables )

Thanks in advance for any insights.. an hour of reading about didn't give me much :/