Revit Install Location

Quite a while back, we discussed the

Revit install path and product GUIDs
.
Last week, Jim Bish of

Inlet Technology
wrote me a nice message making use of that and including VB code demonstrating how to use the install path and also how to determine the product GUID from the registry without having to manually type it in or copy and paste it from a table.

Jim says: It has always been my policy to give back to others as they have given to me.
Here are two functions that will retrieve the ProductCode and subsequently, the InstallLocation of Revit Structure 2010. It can be modified for any install of Revit, and is primarily used to get a path to the revit.ini file for Appends, and Repairs, and Uninstalls of my External Commands and External Applications.


Public Function GetRevitProductCode()
  Dim key As String _
    = "SOFTWAREAutodeskRevitAutodesk Revit Structure 2010"
  Using rgk1 As RegistryKey _
    = Registry.LocalMachine.OpenSubKey(key)
    For Each sSubkeyName As String In _
      rgk1.GetSubKeyNames()
      Using rgk2 As RegistryKey _
        = rgk1.OpenSubKey(sSubkeyName)
        Try
          Return rgk2.GetValue("ProductCode")
        Catch generatedExceptionName As Exception
          Console.WriteLine("Error Occured")
        End Try
      End Using
    Next
  End Using
End Function
Public Function GetRevitInstallLocation( _
  ByVal sProdCode As String)
  Dim key As String _
    = "SOFTWAREMicrosoftWindowsCurrentVersionUninstall"
  Using rgk1 As RegistryKey _
    = Registry.LocalMachine.OpenSubKey(key)
    Using rgk2 As RegistryKey _
      = rgk1.OpenSubKey(sProdCode)
      Try
        Return rgk2.GetValue("InstallLocation")
      Catch generatedExceptionName As Exception
        Console.WriteLine("Error Occured")
      End Try
    End Using
  End Using
End Function

I used these two functions as a basis for implementing a new Building Coder sample command CmdInstallLocation to ensure that this useful functionality is easily found and available.
It determines and lists the product code and the install location for the currently executing Revit application and also tries to do so for all three flavours, Architecture, MEP and Structure.
On my system, the result of running it looks like this:

Revit install locations

I factored out various useful bits of functionality from Jim’s code as follows:

Define the Revit product and Windows uninstall registry paths:


const string _reg_path_uninstall
  = @"SOFTWAREMicrosoftWindowsCurrentVersionUninstall";
 
const string _reg_path_for_flavour
  = @"SOFTWAREAutodeskRevitAutodesk Revit {0} 2010";

Note that the registry path for the Revit product is actually a format string which still needs to be populated with the Revit product flavour.
The correct string to specify the flavour can be obtained directly from the ProductType enumeration.
We use it in the following function which returns the final Revit product registry path:


string RegPathForFlavour( ProductType flavour )
{
  return string.Format( _reg_path_for_flavour, flavour );
}

We also need methods to extract data from the registry.
In one case, we use the Revit product registry path to determine the product key, which is located in the value named ProductCode in the subkey named Components.
In the other case, we determine the Revit install location from the value named InstallLocation in the subkey specified by the product code in the Windows uninstall key.
Both of these values’ data type is string.
Due to these two similar access paths, I can implement one single function to read the data:


string GetSubkeyValue(
  string reg_path_key,
  string subkey_name,
  string value_name )
{
  using( RegistryKey key
    = Registry.LocalMachine.OpenSubKey( reg_path_key ) )
  {
    using( RegistryKey subkey
      = key.OpenSubKey( subkey_name ) )
    {
      return subkey.GetValue( value_name ) as string;
    }
  }
}

Defined like this, making use of the method for the two cases described above is extremely simple:


string GetRevitProductCode( string reg_path_product )
{
  return GetSubkeyValue( reg_path_product,
    "Components", "ProductCode" );
}
 
string GetRevitInstallLocation( string product_code )
{
  return GetSubkeyValue( _reg_path_uninstall,
    product_code, "InstallLocation" );
}

We define a little helper method to format the data obtained for presentation in the message box:


string FormatData(
  string description,
  string version_name,
  string product_code,
  string install_location )
{
  return string.Format
    ( "{0}: {1}"
    + "nProduct code: {2}"
    + "nInstall location: {3}",
    description,
    version_name,
    product_code,
    install_location );
}

Finally we can put it all together into the mainline code of our external command’s Execute function.
First, we look at the currently executing Revit application.
The application Product property provides the ProductType, which can be used to obtain the registry path for this flavour of Revit, determine its product code and from that the install location.
Next we loop through all three ProductType enumeration values and check for other installed flavours of Revit as well.
The final result is displayed in the message box shown above:


Application app = commandData.Application;
 
string reg_path_product
  = RegPathForFlavour( app.Product );
 
string product_code
  = GetRevitProductCode( reg_path_product );
 
string install_location
  = GetRevitInstallLocation( product_code );
 
string msg = FormatData(
  "Running application",
  app.VersionName,
  product_code,
  install_location );
 
foreach( ProductType p in
  Enum.GetValues( typeof( ProductType ) ) )
{
  try
  {
    reg_path_product = RegPathForFlavour( p );
 
    product_code = GetRevitProductCode(
      reg_path_product );
 
    install_location = GetRevitInstallLocation(
      product_code );
 
    msg += FormatData(
      "nnInstalled product",
      p.ToString(),
      product_code,
      install_location );
  }
  catch( Exception ex )
  {
  }
}
 
Util.InfoMsg( msg );
 
return CmdResult.Failed;

Here is
version 1.1.0.48
of the complete Building Coder sample source code and Visual Studio solution including the new command.

Many thanks to Jim for providing the original VB code snippets and the idea for this post!


Comments

8 responses to “Revit Install Location”

  1. Coding just looks prettier in C#… Thanks Jeremy, for taking a simple code stream and making it better!

  2. Dear Jim,
    Thank you very much for submitting it in the first place!
    I enjoyed dissecting it so systematically, hoping that this makes it even easier to understand and reuse.
    Cheers, Jeremy.

  3. Jeremy,
    Now that you know where Revit is located, maybe you could use the System.Diagnostics.FileVersionInfo to determine what build you have. Then hook it up to some (perhaps non-existent) Autodesk web service that lets us know if it’s the latest. Tossing out ideas…
    Thanks!

  4. Dear Danny,
    That would be one possibility. Doesn’t the product already check to see if updates are available during start-up (if enabled by customer)? I noticed that such a check is performed to get the most recent update during installation.
    If I understand the mechanism correctly, this is should be even better than what you suggest, because Revit will always get the latest service pack or user release, ensuring that customers can always be current.
    Cheers, Jeremy.

  5. Unless we’ve turned that functionality off, yes, the update mechanism works as expected. Our users aren’t allowed to install their own updates however, so we’ve disabled that.

  6. Dear Danny,
    Oh, I see. You are an ADN member, aren’t you? Would you like to submit a DevHelp Online request and explain the exact functionality that you require? It will also be very helpful if you can add a business case to that, so we can file a request for this functionality and explain the motivation for it. Thank you!
    Cheers, Jeremy.

  7. kevin vandecar Avatar
    kevin vandecar

    Hi Danny, I work in Revit SWD on the API, so this update stuff was a bit new to me, too. However, a quick look shows that it is working through the communication center. My production copy of Revit shows in the communication center that an update is available, but has not tried to automatically install it… That’s what you are after, right? Just knowing about the update rather than getting it forced on you…. This can be toggled on/off easily the commjunication center settings dialog. Hope it helps, Kevin

  8. Hi Jeremy,
    Thanks. I wasn’t suggesting the build info as a need, but merely as an example of expanding this code sample with some more useful information, and an illustration of tapping into a useful portion of the framework that people may not be aware of. No need for anything further.
    Thanks again,
    -Danny

Leave a Reply to kevin vandecarCancel reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading