Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
West Wind WebSurge - Rest Client and Http Load Testing for Windows

Finding the .NET Framework Path


:P
On this page:

Aaargh. In testing my Help Builder install on a fresh XP machine today that has the .NET framework installed, but not ASP.NET I realized that the auto-registration of the .NET COM interop assemblies isn’t working. The reason for this is some code I use to try and detect the .NET framework directory so I can dynamically execute RegAsm and register the wwReflection assembly for COM interop.

 

My previous code was twisted enough – it truly boggles the mind that Microsoft did not see fit to have a couple of simple registry keys, that tell you which version is installed and where each of these versions lives on disk so you can access the various utilities.

 

Oh there are registry keys alright. There are keys that say this version is installed (the latest). One will tell you the detail, another will give you the major version and yet another might at the Windows path for the main .NET directory (thanks – that’s real useful!). Well, there’s one key:

 

HKEY_LOCAL_MACHINE,"Software\Microsoft\ASP.Net

RootVer

 

That tells me exactly what I need which is the last version installed. From there you can look at that entry (with some modification and stripping) and get the framework path.

 

HKEY_LOCAL_MACHINE,"Software\Microsoft\ASP.Net\"+lcVersion,"PATH")

 

Unfortunately I didn’t realize that the RootVer key does not get set unless ASP. Net is actually registered (ASPNET_IISREG.EXE), which means the machine had to have IIS installed when .NET got installed or ASPNET_IISREG.EXE had to be run afterwards to hook up the script maps and client script folders for ASP.NET.

 

So, back to the drawing board - sort of. I took a brute force approach: if the RootVer key is not there by looking for specific versions of the framework explicitly.

 

************************************************************************

* wwUtils :: IsDotNet

****************************************

***  Function: Returns whether .Net is installed

***            Optionally returns the framework path and version

***            of the highest installed version.

************************************************************************

FUNCTION IsDotNet(lcFrameworkPath,lcVersion)

LOCAL loAPI as wwAPI

 

lcVersion = ""

lcFrameworkPath = ""

 

loAPI = CREATEOBJECT("wwAPI")

lcWinDir = loAPI.getSystemdir(.t.)

 

lcVersion = loAPI.Readregistrystring(HKEY_LOCAL_MACHINE,"Software\Microsoft\ASP.Net","RootVer")

 

IF ISNULL(lcVersion)

   *** If ASP.NET is not registered RootVer is not set

   *** we need a different way: probe for specific versions

   lcVersion = "1.1.4322.0"

   lcFrameWorkPath = loAPI.Readregistrystring(HKEY_LOCAL_MACHINE,"SOFTWARE\Microsoft\ASP.NET\1.1.4322.0","Path")

   IF ISNULL(lcFrameworkPath)

      lcVersion = "v1.0.3705.0"

      lcFrameWorkPath = loAPI.Readregistrystring(HKEY_LOCAL_MACHINE,"SOFTWARE\Microsoft\ASP.NET\v1.0.3705.0","Path")

      IF ISNULL(lcFrameworkPath)

         *** December CTP

         lcVersion = "v2.0.40607.0"

         lcFrameWorkPath = loAPI.Readregistrystring(HKEY_LOCAL_MACHINE,"SOFTWARE\Microsoft\ASP.NET\v2.0.40607.0","Path")

      ENDIF

   ENDIF    

   IF ISNULL(lcFrameworkPath)

      lcFrameworkPath = ""

   ELSE

      lcFrameworkPath = ADDBS( lcFrameworkPath )

   ENDIF

   RETURN .T.

ENDIF

 

*** Strip of the build number and replace with 0

lnAt = AT(".",lcVersion,3)

IF lnAt > 0

   lcVersion = SUBSTR(lcVersion,1,lnAt) + "0"

ENDIF

 

lcFrameworkPath = loAPI.Readregistrystring(HKEY_LOCAL_MACHINE,"Software\Microsoft\ASP.Net\"+lcVersion,"PATH")

IF ISNULL(lcFrameworkPath)

   lcFrameworkPath = ""

ELSE

   lcFrameworkPath = ADDBS(lcFrameworkPath)

ENDIF  

 

RETURN .T.

ENDFUNC

*  wwUtils :: IsDotNet

 

This is not what I would call an ideal situation but it appears to work well. Now I only have to remember to update the version number once new versions of .NET ship. Obviously all the intermediate CTP versions are probably not required here, but when 2.0 ships that definitely would need to go in there probably as the primary check.

 

The brute force approach has some problems – namely you won’t really know if the version is the primary version installed. I’m not 100% sure, but I think that if you uninstall a .NET version it doesn’t completely wipe out registry keys so that may be a problem as well.

 

Another alternative I was thinking about was to look in the Windows\Microsoft.NET directory. All versions are listed in there in a specific format, but that gets tricky too as well because again you have to worry about uninstalls not completely clearing the dirs (and then you have to look for specific files) and no way of knowing which is the last installed version.

 

This all seems pretty silly – a couple of simple registry keys from Microsoft would have solved this problem nicely.


The Voices of Reason


 

Mattias Sjögren
March 07, 2005

# re: Finding the .NET Framework Path

All that to run RegAsm? Can't you do it programmatically with the System.Runtime.InteropServices.RegistrationServices class instead?

Rick Strahl
March 07, 2005

# re: Finding the .NET Framework Path

Mattias,

I wish! And yup my thinking exactly - all that <g>...

Problem is if you have NON-MANAGED code you can't call into the runtime to find out what version you're running unless you register the COM Interop component first.


Mark Duncan
May 09, 2005

# re: Finding the .NET Framework Path

I don't think Microsoft gives you the option of specifying a directory to install the framework in so all of your versions should be under %WINDIR%\Microsoft.Net\Framework.

Damal Dichkey
May 13, 2005

# re: Finding the .NET Framework Path

System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()

this will do the trick

nopie
September 04, 2005

# re: Finding the .NET Framework Path

"System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory() "

That's silly. This assumes the presence of what you are checking the presence off.

LOL.

Alan Kaplan
February 27, 2006

# re: Finding the .NET Framework Path

Wouldn't it be better to enumerate the keys under HKEY_LOCAL_MACHINE,"Software\Microsoft\ASP.Net, skip MACHINEACCOUNTS, then take the highest of cint(left,1))? That will give you the highest installed version of ASP.NET, then you can get the path from there.

Thomas
June 06, 2006

# re: Finding the .NET Framework Path

System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory()

This is not too silly, I think. In fact, this will not check the presence but retrieve the location.

If you know you have .NET installed but you are looking for RegAsm.exe, this is what you need.

Colin
September 28, 2006

# re: Finding the .NET Framework Path

Why doesn't MSFT just set an environment variable? Anyone remember those? Sigh... this is definitely harder than it needs to be.

Rick Strahl
September 28, 2006

# re: Finding the .NET Framework Path

Well the problem with that is there can be multiple versions and you probably don't want a bunch of environment variables for each version. In recent versions there are registry keys, but they weren't there in 1.x. In 1.x the only registry were for ASP.NET and that might not install if IIS isn't on the machine.

Rick Strahl
January 15, 2007

# re: Finding the .NET Framework Path

One more note here: This code doesn;'t take into account the screwy .NET 3.0 versioning - since 3.0 is not really a full version of the .NET Runtime if 3.0 is installed you have to back up to the 2.0 version to find RegAsm.

There's an updated version of the above code here:

http://west-wind.com/WebLog/posts/7152.aspx

Jake Heidt
October 31, 2007

# re: Finding the .NET Framework Path

Rick,

The official unmanaged way to determine the framework installation directory is to call the GetCORSystemDirectory of mscoree.dll. It's a very straightforward method declaration, should be a snap.

Rick Strahl
October 31, 2007

# re: Finding the .NET Framework Path

@Jake - yup missed that and it looks like that would work although the docs are a bit misleading since they say of the .NET Runtime loaded into the process. In my case there's nothing loaded. However it looks like it's returning the highest 'active' version installed - ie. it correctly returns .NET 2.0 when 1.1, 2.0, 3.0 and 3.5 are installed. Cool! This I can work with. Wonder if that's been there though all the way back to 1.0?

Rick Strahl
October 31, 2007

# re: Finding the .NET Framework Path

For completeness sake here's the FoxPro code:

************************************************************************
*  GetDotNetFrameworkPath
****************************************
***  Function: Returns the highest active .NET version path
***            Note returns 2.0 version for 3.0 or 3.5 since
***            those versions are not full frameowrk versions.
***      Pass: nothing
***    Return: Path with trailing backslash or "" on failure
************************************************************************
FUNCTION GetDotNetFrameworkPath()
LOCAL lcString, lnSize, lnResult, llError

llError = .F.
TRY
    DECLARE INTEGER GetCORSystemDirectory IN MSCorEE.dll ;
        string @, integer, integer@        

    lcString = SPACE(512)
    lnSize = LEN(lcString)
        
    lnResult = GetCorSystemDirectory(@lcString,lnSize,@lnSize)
    IF lnResult # 0
       RETURN ""
    ENDIF   
CATCH
   
ENDTRY

IF llError
    RETURN ""
ENDIF

RETURN LEFT( STRCONV(lcString,6),lnSize-1)
ENDFUNC
*   GetDotNetFrameworkPath

Jake Heidt
June 21, 2008

# re: Finding the .NET Framework Path

@Rick,
I read west-wind regularly and I am just glad that I could. I was in the same boat, and even after reading the docs I didn't assume this method would return the information I wanted. Lo-and-behold it did, just hope that others read this in their search for the best way to get the current framework version installed on a computer.


.jfh

Kevin
January 12, 2009

# re: Finding the .NET Framework Path

I'm in the same boat too. This is so very helpful thankyou Rick.

I have MFC code if you'd like...

Mayur
July 19, 2009

# re: Finding the .NET Framework Path

Here is code to find the path.

I have tested and it works fine.

#region Private Functions

/// <summary>
/// Function that return .net framnework installation path.
/// </summary>
const int MAX_PATH = 256;

[DllImport("mscoree.dll",
CharSet = CharSet.Unicode,
ExactSpelling = true)]
public static extern int GetCORSystemDirectory(
StringBuilder buf,
int cchBuf,
ref int cchRequired);


public string GetNetFrameworkDirectory()
{
StringBuilder buf = new StringBuilder(
MAX_PATH, MAX_PATH);
int cch = MAX_PATH;
int hr = GetCORSystemDirectory(
buf, MAX_PATH, ref cch);
if (hr < 0) Marshal.ThrowExceptionForHR(hr);
return buf.ToString();
}
#endregion

GetNetFrameworkDirectory Function will return path like "C:\Windows\Microsoft.NET\Framework\v2.0.50727\"


Thanks

Schalk
December 22, 2010

# re: Finding the .NET Framework Path

What about:
typeof(Object).Assembly.Location

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024