Finding the .NET Framework Path
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.
************************************************************************
* 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.
Other Posts you might also like
The Voices of Reason
# re: Finding the .NET Framework Path
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.
# re: Finding the .NET Framework Path
# re: Finding the .NET Framework Path
this will do the trick
# re: Finding the .NET Framework Path
That's silly. This assumes the presence of what you are checking the presence off.
LOL.
# re: Finding the .NET Framework Path
# re: Finding the .NET Framework Path
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.
# re: Finding the .NET Framework Path
# re: Finding the .NET Framework Path
# re: Finding the .NET Framework Path
There's an updated version of the above code here:
http://west-wind.com/WebLog/posts/7152.aspx
# re: Finding the .NET Framework Path
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.
# re: Finding the .NET Framework Path
# re: Finding the .NET Framework Path
************************************************************************
* 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# re: Finding the .NET Framework Path
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
# re: Finding the .NET Framework Path
I have MFC code if you'd like...
# re: Finding the .NET Framework 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
# re: Finding the .NET Framework Path
typeof(Object).Assembly.Location
# re: Finding the .NET Framework Path