views:

3858

answers:

13

This question is not so much programming related as it is deployment related.

I find myself conversing a lot with the group in my company whose job it is to maintain our production Windows servers and deploy our code on them. For legal and compliance reasons, I do not have direct visibility or any control over the servers so the only way I can tell which version(s) of .NET are installed on any of them is through directions I give to that group.

So far, all of the methods I can think of to tell which version(s) are installed (check for Administrative Tools matching 1.1 or 2.0, check for the entries in the "Add/Remove Programs" list, check for the existence of the directories under c:\Windows\Microsoft.NET) are flawed (I've seen at least one machine with 2.0 but no 2.0 entries under Administrative Tools - and that method tells you nothing about 3.0+, the "Add/Remove Programs" list can get out of sync with reality, and the existence of the directories doesn't necessarily mean anything).

Given that I generally need to know these things are in place in advance (discovering that "oops, this one doesn't have all the versions and service packs you need" doesn't really work well with short maintenance windows) and I have to do the checking "by proxy" since I can't get on the servers directly, what's the foolproof way to tell which version(s) of .NET are installed on a production Windows Server? Preferably some intrinsic way to do so using what the framework installs since it will be quicker and not need some sort of utility to be loaded and also a method which will definitely fail if the frameworks are not properly installed but still have files in place (i.e., there's a directory and gacutil.exe is inded there but that version of the framework is not really "installed")

EDIT: In the absence of a good foolproof intrinsic way to do this built into the Framework(s), does anyone know of a good, lightweight, no-install-required program that can find this out? I can imagine someone could easily write one but if one already exists, that would be even better.

+2  A: 

OneTouch deployment will do all the detection and installation of pre-requisites. It's probably best to go with a pre-made solution than trying to roll your own. Trying to roll your own may lead to problems because whatever thing you key on may change with a hotfix or service pack. Likely Microsoft has some heuristic for determining what version is running.

Orion Adrian
A: 

It is probably a nasty way to find vewrsions out but I was always under the impression that all version got installed to :\WINDOWS\Microsoft.NET\Framework

This provides folders with names such as v2.0.50727 which I believe give detailed version information

Dean
And that might be the right way but the "what if?" in my head says "what if the files are there but the Framework isn't really 'installed' and some clueless admin thought copying the files over was the way to do it?"
Schnapple
+6  A: 

You can programmatically check the registry and a few other things as per this blog entry.

The registry key to look at is

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\...]
Ed Guiness
I can't tell - does this also cover 1.1?
Schnapple
A: 

You should open up IE on the server for which you are looking for this info, and go to this site: http://www.hanselman.com/smallestdotnet/

That's all it takes.

Vaibhav
- if it's a production server, he might not even have access to it - browsing random sites on prod server is a big no-no - that site gives only the highest .Net version; he wants all of them
Franci Penov
Problem, looks like, with that approach is that it only tells you what the latest version you have is. I deploy code in 2.0, 3.0, 3.5 and (sadly) even 1.1. Although the goal is to get everything upgraded eventually, the sad fact for now is that I need all the different parallel versions.
Schnapple
+3  A: 

Well, this is the official Microsoft answer on how to do this....

KB article 318785

Code Trawler
+3  A: 

The Microsoft way is this:

http://support.microsoft.com/kb/318785

If you want foolproof that's another thing. I wouldn't worry about an xcopy of the framework folder. If someone did that I would consider the computer broken.

The most foolproof way would be to write a small program that uses each version of .NET and the libraries that you care about and run them.

For a no install method, PowerBasic is an excellent tool. It creates small no runtime required exe's. It could automate the checks described in the MS KB article above.

bruceatk
+1  A: 

The official way to detect .NET 3.0 is described here

http://msdn.microsoft.com/en-us/library/aa480198.aspx

Flawed, because it requires the caller to have registry access permissions.

MSDN also mentions a technique for detecting .NET 3.5 by checking the User Agent string:

http://msdn.microsoft.com/en-us/library/bb909885.aspx

I think Microsoft should have done a better job than this.

Joe
+1  A: 

If the machine that you want to check has the .net SDK installed, you can use a SDK cmd prompt and run the program CLRVer.exe

James Deville
Are there any (licensing) issues with deploying just that executable? It doesn't have any dependencies to speak of.
uncle brad
A: 

Take a look at this thread, which gives you the full details of the registry keys you need to evaluate.

Scott Dorman
A: 

Well, like Dean said you can look at registry and do what he did. To check if he really has CLR .NET Framework installed, you should look for MSCorEE.dll file in %SystemRoot%\System32 directory.

Bruno Costa
A: 

As per CodeTrawler's answer, the solution is to enter the following into an explorer window:

%systemroot%\Microsoft.NET\Framework

Then search for:

Mscorlib.dll

...and right-click / go to the version tab for each result.

Jon Cage
+1  A: 

Strangely enough, I wrote some code to do this back when 1.1 came out (what was that, seven years ago?) and tweaked it a little when 2.0 came out. I haven't looked at it in years as we no longer manage our servers.

It's not foolproof, but I'm posting it anyway because I find it humorous; in that it's easier to do in .NET and easier still in power shell.

bool GetFileVersion(LPCTSTR filename,WORD *majorPart,WORD *minorPart,WORD *buildPart,WORD *privatePart)
{
    DWORD dwHandle;
    DWORD dwLen = GetFileVersionInfoSize(filename,&dwHandle);
    if (dwLen) {
        LPBYTE lpData = new BYTE[dwLen];
        if (lpData) {
            if (GetFileVersionInfo(filename,0,dwLen,lpData)) {
                UINT uLen;  
                VS_FIXEDFILEINFO *lpBuffer;  
                VerQueryValue(lpData,_T("\\"),(LPVOID*)&lpBuffer,&uLen);  
                *majorPart = HIWORD(lpBuffer->dwFileVersionMS);
                *minorPart = LOWORD(lpBuffer->dwFileVersionMS);
                *buildPart = HIWORD(lpBuffer->dwFileVersionLS);
                *privatePart = LOWORD(lpBuffer->dwFileVersionLS);
                delete[] lpData;
                return true;
            }
        }
    }
    return false;
}

int _tmain(int argc,_TCHAR* argv[])
{
    _TCHAR filename[MAX_PATH];
    _TCHAR frameworkroot[MAX_PATH];
    if (!GetEnvironmentVariable(_T("systemroot"),frameworkroot,MAX_PATH))
        return 1;
    _tcscat_s(frameworkroot,_T("\\Microsoft.NET\\Framework\\*"));
    WIN32_FIND_DATA FindFileData;
    HANDLE hFind = FindFirstFile(frameworkroot,&FindFileData);
    if (hFind == INVALID_HANDLE_VALUE)
        return 2;
    do {
        if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
            _tcslen(FindFileData.cAlternateFileName) != 0) {
            _tcsncpy_s(filename,frameworkroot,_tcslen(frameworkroot)-1);
            filename[_tcslen(frameworkroot)] = 0;
            _tcscat_s(filename,FindFileData.cFileName);
            _tcscat_s(filename,_T("\\mscorlib.dll"));
            WORD majorPart,minorPart,buildPart,privatePart;
            if (GetFileVersion(filename,&majorPart,&minorPart,&buildPart,&privatePart )) {
                _tprintf(_T("%d.%d.%d.%d\r\n"),majorPart,minorPart,buildPart,privatePart);
            }
        }
    } while (FindNextFile(hFind,&FindFileData) != 0);
    FindClose(hFind);
    return 0;
}
uncle brad
A: 

Also see this question:

How to detect what .NET Framework versions and service packs are installed? http://stackoverflow.com/questions/199080/how-to-detect-what-net-framework-versions-and-service-packs-are-installed/3087128#3087128

Which also mentions:

There is an official Microsoft answer to this question at the following knowledge base article:

http://support.microsoft.com/kb/318785/en-us

Article ID: 318785 - Last Review: November 7, 2008 - Revision: 20.1 How to determine which versions of the .NET Framework are installed and whether service packs have been applied

Unfortunately, it doesn't appear to work, because the mscorlib.dll version in the 2.0 directory has a 2.0 version, and there is no mscorlib.dll version in either the 3.0 or 3.5 directories even though 3.5 SP1 is installed ... why would the official Microsoft answer be so misinformed?

anon