Finding the .NET Framework folder from Visual FoxPro

How to programmatically locate the latest version of the .NET Framework directory.

By Dan Macleod

A colleague recently asked for my help with three related problems:

And he needed to do all this programmatically, from within a Visual FoxPro (VFP) application.

Where is the Framework folder?

It turns out that all three problems have a similar solution.

If .NET is installed, there will be a directory on the user's system with this path:


If you were to type that path into the address bar in Windows Explorer, you would see the contents of the .NET Framework folder. If the folder was not present, you would know that .NET was not installed.

In case you're wondering, %WINDIR% is an environment variable that points to the Windows directory. That directory is usually C:\Windows, but you can never be sure of that. It might be named, say, WinNT rather than Windows, and it might not reside on the C drive. Hence the need for the environment variable.

Within the Framework directory, there will be a sub-folder for each installed version of the framework. Each of these sub-folders has a name in the form vN, where N is a two- or three-part version number. In the example shown in Figure 1, there are five versions installed: 1.0.3705, 1.1.4322, 2.0.50727, 3.0 and 3.5.

Figure 1

Figure 1: Five versions of the .NET Framework are installed on this system.

The latest version of the framework is the highest of those version numbers (not necessarily the one belonging to the directory with the latest timestamp, as it's possible that a later version was installed after an earlier one).

Framework folders on 64-bit systems

Just to confuse the issue slightly, on a 64-bit system, the path to the framework directory will be %WINDIR%\Microsoft.NET\Framework64. But %WINDIR%\Microsoft.NET\Framework might also be present, and this might or might not contain a higher version of the framework. To do the job properly, you need to look at both framework folders and choose the sub-folder with the highest overall version number.

Using ADIR() to find the directories

So we now know how to find the .NET Framework folder, and how to identify the highest version of the framework within it. The next task is to do that programmatically.

To do so, we can use Visual FoxPro's ADIR() function. This takes the name of an array as its first parameter, a file skeleton as its second parameter, and an attribute string as its third parameter. The function then fills the array with details of the files that match the skeleton. By passing "D" in the attribute string, you stipulate that the array will hold sub-directories as well as files.

So the code that calls ADIR() should look something like this:

lcSkeleton = "%WINDIR%\Microsoft.NET\Framework\*.*"
ADIR(laFolders, lcSkeleton, "D")

Unfortunately, that's not quite right. ADIR() does not recognize environment variables in its second parameter, so the above call will have no effect. But there's an easy workaround: call VFP's GETENV() function to determine the contents of %WINDIR%:

lcWinDir = GETENV("windir")
lcSkeleton = ADDBS(lcWindir) + "Microsoft.NET\Framework\*.*"
ADIR(laFolders, lcSkeleton, "D")

After calling ADIR() in this way, we can loop through the array (laFolders), looking for the entries that match the installed framework folders. These are the folders whose names are in the form vN (where N is the two- or three-part version number). The relevant array rows will have "D" in the fifth column, indicating that they are directories rather than files. Remember, we need to repeat the whole thing for the 64-bit version of the framework, if it is present.

Here then is a complete function that does the job. It takes no parameters. It returns the full path to whichever folder contains the highest version of the .NET Framework.

FUNCTION DotNetFramework
* Returns the path to the .NET Framework directory 
* on the user's system.

* Where more than one version of .NET is installed, 
* returns the highest. If both 32- and 64-bit versions 
* are present, returns the highest overall version. 
* If no version of .NET is installed, returns an empty 
* string.

LOCAL lcWinDir, lcFr32, lcVer32, lcFr64, lcVer64

* Path to Windows directory
lcWinDir = GETENV("windir")

* Path to 32-bit parent framework directory
lcFr32 = ADDBS(lcWinDir) + "Microsoft.NET\Framework"

* Path to highest 32-bit framework version
lcVer32 = HighestDir(lcFr32)

* Path to 64-bit parent framework directory
lcFr64 = lcFr32 + "64"

* Path to highest 64-bit framework version
lcVer64 = HighestDir(lcFr64)

* Return whichever of the two (32-bit or 
* 64-bit path) has the higher verion (for this
* purpose, disregard anything after the second dot)
   VAL(SUBSTR(JUSTFNAME(lcVer64),2)), ;
    lcVer32, lcVer64)

* Given the path to the Microsoft.NET\Framework directory,
* return the path to the directory below it which contains
* the highest Framework version number, or an empty string 
* if none present.

LOCAL lnCount, lcHighestDir, lnHighestVer
LOCAL lcName, lnVer, lnI
LOCAL ARRAY laFolders(1)

* Get contents of the passed-in directory 
* (including sub-directories) into an array
lnCount = ADIR(laFolders, ADDBS(tcPath) + "*.*", "D")

lcHighestDir = ""
lnHighestVer = 0

FOR lnI = 1 TO lnCount
  IF AT("D", laFolders(lnI, 5)) > 0
    * Array element is a directory name

      * Look for directories whose name starts with "v" 
      * followed by a digit and contains at least one dot
      lcName = LOWER(laFolders(lnI, 1))
      IF LEFT(lcName, 1) = "v" AND ;
        ISDIGIT(SUBSTR(lcName,2,1)) AND AT(".", lcName) > 0
        * Extract its version number (for this purpose, 
        * disregard anything after the second dot)
        lnVer = VAL(SUBSTR(lcName, 2))
        IF lnVer > lnHighestVer
          lnHighestVer = lnVer
          lcHighestDir = lcName

  IIF(lnHighestVer=0, "", FORCEPATH(lcHighestDir, tcPath))

If you only want to know the version number, you can parse it out from the value returned from the function, like so:

lcFrameworkFolder = DotNetFramework()
lcVersion = SUBSTR(JUSTFNAME(lcFrameworkFolder), 2)

December 2011

Please note: The information given on this site has been carefully checked and is believed to be correct, but no legal liability can be accepted for its use. Do not use code, components or techniques unless you are satisfied that they will work correctly with your sites or applications.

If you found this article useful, please tell your friends: