Determine Revit Demo Mode Revisited

Almost a year back, we talked about how to determine whether the current running Revit application is a

demo version
or not.

The initial suggestion was to test this by trying to execute real functionality modifying the model and then save it.
That obviously incurs significant overhead and may cause other problems as well.

Rudolf Honke suggested simply reading and evaluating the Revit main window title text instead.

Now Madmed created and

posted
an
implementation of Rudolf’s idea.
I took the opportunity of both adding that as a new command CmdDemoCheck to The Building Coder samples and simultaneously incrementing all the year number references in the source code comments from 2012 to 2013, so that that trivial yearly update step is over and done with.

Another obvious step to be performed is the elimination of all warning messages when compiling the code, since they indicate obsolete API usage that needs to be cleaned up.
Stay tuned for that anon.

Rudolf suggested checking whether the main window caption contains the words “VIEWER” and “MODE”.
This is language dependent, of course, and would be “MODUS” in the German Revit, for instance.
He provided a link to

C# and VB GetWindowText implementations
and
pointed out that this approach works in a zero-document scenario and will fail if the current document is named something like “VIEWER-MODE”.
That problem could be worked around by more intelligent parsing of the string to extract the document name, for instance, before searching for the demo mode trigger string.

To begin with, here is Madmed’s implementation:


  [DllImport( "user32.dll", SetLastError = true,
    CharSet = CharSet.Auto )]
  static extern int GetWindowText(
    IntPtr hWnd,
    StringBuilder lpString,
    int nMaxCount );
 
  [DllImport( "user32.dll", SetLastError = true,
    CharSet = CharSet.Auto )]
  static extern int GetWindowTextLength(
    IntPtr hWnd );
 
  static StringBuilder GetStatusTextMadmed(
    IntPtr mainWindow )
  {
    StringBuilder s = new StringBuilder();
    if( mainWindow != IntPtr.Zero )
    {
      int length = GetWindowTextLength( mainWindow );
      StringBuilder sb = new StringBuilder( length + 1 );
      GetWindowText( mainWindow, sb, sb.Capacity );
      sb.Replace( "Autodesk Revit Architecture 2013 - ", "" );
      return sb;
    }
    return s;
  }

He suggests using it like this:


  IntPtr revitHandle = System.Diagnostics.Process
    .GetCurrentProcess().MainWindowHandle;
 
  StringBuilder sb = GetStatusText(revitHandle);
 
  bool isDemo = sb.ToString()[0] != '['

When trying that out on my system, I noticed that I my Revit window title does not include the “Architecture” sub-string, since I am running the one-box version.

I also thought that it might be handy and cleaner to start off by implementing a method which simply returns the entire Revit main window caption string unmodified, for the caller to use freely in any desired fashion.
I ended up with the following implementation:


  static string GetWindowText( IntPtr mainWindow )
  {
    if( IntPtr.Zero == mainWindow )
    {
      throw new ArgumentException(
        "Expected valid window handle." );
    }
    int len = GetWindowTextLength( mainWindow );
    StringBuilder sb = new StringBuilder( len + 1 );
    GetWindowText( mainWindow, sb, sb.Capacity );
    return sb.ToString();
  }

That returns “Autodesk Revit 2013 – Not For Resale Version – [Floor Plan: Level 1 – rac_empty.rvt]” on my system.

The sample command making use of this currently looks like this:


  public Result Execute(
    ExternalCommandData commandData,
    ref string message,
    ElementSet elements )
  {
    IntPtr revitHandle = System.Diagnostics.Process
      .GetCurrentProcess().MainWindowHandle;
 
    string s = GetWindowText( revitHandle );
 
    // My system returns:
    // "Autodesk Revit 2013 - Not For Resale Version 
    // - [Floor Plan: Level 1 - rac_empty.rvt]"
 
    bool isDemo = s.Contains( "VIEWER" );
 
    TaskDialog.Show( "Demo Version Check",
      ( isDemo ? "Demo" : "Production")
      + " version." );
 
    return Result.Succeeded;
  }

Here is
version 2013.0.100.0 of
The Building Coder samples with incremented year numbers throughout and including the new CmdDemoCheck command.

Many thanks to Rudolf for his helpful ideas and to Madmed for prompting me to pick this up again.

Retain or Update External Command GUID

Here are some thoughts by my colleague Joe Ye on whether to retain or update an external command GUID:

It is acceptable to keep the GUID unchanged for different versions of your Revit add-in.
If you release several different versions for the same Revit version, e.g. 2013, you obviously have to make sure that only one add-in manifest file to load it is found.

If you prefer, it is also okay to define a different GUID for each version of your add-in.
In that case, please note that an external command with the same name from two different versions can be loaded simultaneously.

If the add-in creates its own Ribbon items, trying to create the same items twice over will also cause an error, since ribbon item names are unique.

Thank you, Joe, for these hints.


Comments

10 responses to “Determine Revit Demo Mode Revisited”

  1. Hi Jeremy,
    some additional observations:
    File extension may be cut off, depending on OS settings, so “.rvt” may be omitted.
    If Revit window is resized to a small width, the title will appear abbreviated, this may result in another GetWindowText result which does not even contain “VIEWER” string (haven’t tested this yet).
    Best regards,
    Rudolf/Revitalizer

  2. Dear Rudolf,
    Thank you again for all your ideas, including this new important observation.
    Cheers, Jeremy.

  3. how can I make it valid for all languages?

  4. Hi Rudolf, hi Jeremy.
    WinAPI? Why?? To get Revit title is much easier. System.Diagnostics.Process.GetCurrentProcess().MainWindowTitle; :)
    And in my opinion to determine whether Revit run in Demo mode or not using title is not a good idea. In different localization DEMO string may have different values. For me the approach with transaction is better.
    BTW, don’t forget use ComponentManager.ApplicationWindow instead System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
    Have a nice day,
    Victor.

  5. Hello again.
    I’m trying to suggest my own version how to determine is Revit run on Demo mode or not.
    Just reference UIFrameworkServices.dll assembly, read the Revit serial number with Static method ProductSerialNumber of InfoCenterService class. If Revit run in demo mode the serial number is 000-00000000
    Here is the full source code.
    Simply, isn’t it?
    Regards,
    Victor.

  6. Hi Victor,
    of course you are right.
    A few weeks ago, I posted the same approach in the Revit API forum:
    http://forums.autodesk.com/t5/Autodesk-Revit-API/Active-window-name/td-p/3659274
    I’m Revitalizer ;-)
    Cheers,
    Rudolf

  7. Hi Victor,
    as far as I know, referencing UIFramework.dll is not supported by Autodesk, meaning “do not use that in code that is meant for production”. As far as I know from my “Pimp my Revit” stuff, it is not recommended to do so:
    http://thebuildingcoder.typepad.com/blog/2011/02/pimp-my-autocad-or-revit-ribbon.html
    Haven’t read the code yet, but reading the serial number sounds good for me.
    Best regards,
    Rudolf

  8. Hi Rudolf.
    I referenced UIFrameworkServices.dll, not UIFramework.dll.
    If it is not supported by Autodesk it doesn’t mean that you cannot use it:) As you know these unsupported assemblies contains many interesting classes and I don’t see any reason not to use it if it help to solve your problem.
    Of course you should keep in mind that in the next release the classes and methods could change.
    Regards, Victor

  9. Hi Victor,
    yes, I see that you use a different dll.
    I fully agree that there are much classes in these unsupported dlls which may provide many of these methods the RevitAPI.dll is missing yet.
    But what if you would provide a plug-in based on unsupported dlls, saying an app in the exchange store.
    Imagine if there would be a problem caused by an unsupported method, nobody on the Autodesk side would consider to fix this because it was always declared as “not recommended”: and no way to fix it on your own side…
    But after all, I really like finding new ways to perform something new which cannot be done by the Revit API itself.
    I do that a lot on myself, too ;-)
    Cheers,
    Rudolf

  10. Hi Rudolf.
    As developer you should decide yourself use unsupported dlls or not for your own risk.
    In my opinion these dlls are provided by Autodesk. Despite of they are for internal use they has public classes. I don’t think they make drastically changes.
    If you publish your app in Exchange store you must test your apps carefully and you specify Revit versions where your application works. So, you don’t guarantee that your app should works in other versions.
    There is no any insurance that any serious problem is not caused by RevitAPI.dll and even serious bug fixed very slow (I’ve encountered with Extensible storage bug where Revit crashes in 2012 Revit but it was fixed only in 2013 UR1) but it is not the reason doesn’t use RevitAPI.dll :)
    In the worst case if in one of the release Autodesk remove methods from unsupported dll which you used in your applications you must find alternative way to achieve that you need. E.g. instead ComponentManager.ApplicationWindow you can use MainWindow handl etc.
    BTW, I like that you like my serial-number method. If you don’t want unsupported dlls, you can read serial number from Registry :)
    And at the conclusion: nothing venture nothing have )
    The programming is the thing where always everything is changed ;)
    Regards,
    Victor.

Leave a Reply to Jeremy TammikCancel reply

Discover more from Autodesk Developer Blog

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

Continue reading