Reading the registry for #Visio settings

I love writing Visio automation code, but I really don’t like writing setup & deployment scripts. There are so many variables : What Visio version, which edition? Which bitness (x86 or x64)? What are the user settings for the paths of stencils or templates?

So, I decided to write myself some C# functions that can be used in custom actions for an installation writing application, such as Advanced Installer. I think of the methods as being in one of three phases, Installation; Functionality and Configuration. The registry has three different areas to search within, Classes Root (HKCR); Local Machine (HKLM) and Current User (HKCU). In addition, the best way to get the true file version of Visio is to use FileInfo on the executable. The following screenshots are from a Cross-Functional Flowchart of the functions that get values for variables, and use them in other functions, until, eventually, the current user settings can be read.

This slideshow requires JavaScript.

Each of the functions I wrote handle the part of the registry that needs to be used. By that I mean that some settings for 64bit Visio on 64bit Windows will be in a different branch than 32bit Visio on 64bit Windows.

The first function gets the current version of the application associated with Visio drawings:

internal const string HKCR_CURVER = @"Visio.Drawing\CurVer";

public string GetVisioDrawingCurrentVersion()
{
  var currentVersion = "";
  RegistryKey targetKey = null;
  try
  {
    targetKey = Registry.ClassesRoot.OpenSubKey(HKCR_CURVER);
    if (targetKey != null)
    {
      currentVersion = targetKey.GetValue("").ToString();
    }
  }
  finally
  {
    if (targetKey != null)
    {
      targetKey.Dispose();
    }
  }
  return currentVersion;
}

The value returned above is assigned to the variable VISIO_CURVER, and used to get the Class ID of the application.

internal const string HKCR_CLASSID = @"{0}\CLSID";

public string GetVisioClassID(string drawingCurrentVersion)
{
  string classID = "";
  RegistryKey targetKey = null;
  try
  {
    targetKey = Registry.ClassesRoot.OpenSubKey(String.Format(HKCR_CLASSID,drawingCurrentVersion));
    if (targetKey != null)
    {
      classID = targetKey.GetValue("").ToString();
    }
  }
  finally
  {
    if (targetKey != null)
    {
      targetKey.Dispose();
    }
  }
  return classID;
}

The returned value is then assigned to the variable VISIO_ClassID, and used to get the platform:

public string GetVisioPlatform(string classID)
{
  var platform = "x64";
  RegistryKey targetKey = null;
  try
  {
    var localServerKey = String.Format(HKCR_LCLSVR,classID);
    if (Environment.Is64BitOperatingSystem)
    {
      using (RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Registry64))
      {
        targetKey = baseKey.OpenSubKey(localServerKey, false);
      }
      if (targetKey == null)
      {
        platform = "x86";
      }
    }
    else
    {
      platform = "x86";
    }
  }
  finally
  {
    if (targetKey != null)
    {
      targetKey.Dispose();
    }
  }
  return platform;
}

It can also be used to get the path of the Visio executable:

internal const string HKCR_LCLSVR = @"CLSID\{0}\LocalServer32";

public string GetVisioExe(string classID)
{
  var exePath = "";
  RegistryKey targetKey = null;
  try
  {
    var localServerKey = String.Format(HKCR_LCLSVR,classID);
    if (Environment.Is64BitOperatingSystem)
    {
      using (RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Registry64))
      {
        targetKey = baseKey.OpenSubKey(localServerKey, false);
      }
      if (targetKey == null)
      {
        using (RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Registry32))
        {
          targetKey = baseKey.OpenSubKey(localServerKey, false);
        }
      }
    }
    else
    {
      using (RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Default))
      {
        targetKey = baseKey.OpenSubKey(localServerKey, false);
      }
    }

    if (targetKey != null)
    {
      exePath = targetKey.GetValue("").ToString();
    }
  }
  finally
  {
    if (targetKey != null)
    {
      targetKey.Dispose();
    }
  }
  return exePath;
}

The return value from this function is assigned to the variable VISIO_EXEPATH, which is then used to get the version of the Visio executable.

public string GetVisioVersion(string exePath)
{
  var version = "";
  if (!string.IsNullOrEmpty(exePath) && File.Exists(exePath))
  {
    var visioFileInfo = FileVersionInfo.GetVersionInfo(exePath);
    version = $"{visioFileInfo.FileMajorPart.ToString()}.{visioFileInfo.FileMinorPart.ToString()}";
  }
  return version;
}

The version is stored in the variable VISIO_VERSION, and this can then be used to extract the value of the Visio registry path:

public string GetVisioKeyName(string platform, string version)
{
  var visioKeyName = "";
  var appPathsKey = "";

  RegistryKey targetKey = null;
  try
  {
    appPathsKey = string.Format(HKLM_VISIO,version);
    if (platform.Equals("x64"))
    {
      using (RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
      {
        targetKey = baseKey.OpenSubKey(appPathsKey, false);
      }
    }
    else
    {
      using (RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
      {
        targetKey = baseKey.OpenSubKey(appPathsKey, false);
      }
    }
    if (targetKey != null)
    {
      visioKeyName = targetKey.Name.Replace("HKEY_LOCAL_MACHINE\\","");
    }

  }
  finally
  {
    if (targetKey != null)
    {
      targetKey.Dispose();
    }
  }
  return visioKeyName;
}

At last, it is possible to get various settings for the Current User’s settings,  using the returned value, VISIO_KEYNAME, from above.

internal const string HKCU_APP = @"{0}\Application";

public string GetVisioAppSetting(string platform, string appPathsKey, string setting)
{
  var value= "";
  RegistryKey targetKey = null;
  try
  {
    var subKeyName = string.Format(HKCU_APP, appPathsKey);
    if (platform.Equals("x64"))
    {
      using (RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64))
      {
        targetKey = baseKey.OpenSubKey(subKeyName, false);
      }
    }
    else
    {
      using (RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry32))
      {
        targetKey = baseKey.OpenSubKey(subKeyName, false);
      }
    }
    if (targetKey != null)
    {
      var subValues = targetKey.GetValueNames();
      if (subValues.Contains(setting))
      { 
      	value = targetKey.GetValue(setting).ToString();
      }
    }
  }
  finally
  {
    if (targetKey != null)
    {
      targetKey.Dispose();
    }
  }
  return value;
}

Checking if Office, and therefore Visio, is Click2Run or not, proved to be a little easier. The following function will return True or False:

internal const string HKLM_C2RCONFIG = @"SOFTWARE\Microsoft\Office\ClickToRun\Configuration";

public bool GetOfficeIsC2R()
{
  RegistryKey targetKey = null;
  string platform = "";
  try
  {
    if (Environment.Is64BitOperatingSystem)
    {
      using (RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
      {
        targetKey = baseKey.OpenSubKey(HKLM_C2RCONFIG, false);
      }
      if (targetKey == null)
      {
        using (RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
        {
          targetKey = baseKey.OpenSubKey(HKLM_C2RCONFIG, false);
        }
      }
    }
    else
    {
      targetKey = Registry.LocalMachine.OpenSubKey(HKLM_C2RCONFIG, false);
    }
    if (targetKey != null)
    {
       platform = targetKey.GetValue("Platform").ToString();
    }
  }
  finally
  {
    if (targetKey != null)
    {
      targetKey.Dispose();
    }
  }
  return platform.Length > 0;
}

The following is an extract from synchronised Data Visualizer Excel workbook created from my Visio Cross-Functional Flowchart, showing the functions, variables, and registry keys in my current PC:

Function / Variable Area Key / Value
GetVisioDrawingCurrentVersion HKCR Visio.Drawing\CurVer
VISIO_DWGVER HKCR Visio.Drawing.15
GetVisioClassID HKCR {VISIO_DWGVER}\CLSID
VISIO_CLASSID HKCR {00021A15-0000-0000-C000-000000000046}
GetVisioPlatform HKCR CLSID\{VISIO_CLASSID}\LocalServer32
VISIO_PLATFORM HKCR x86
GetVisioExe HKCR CLSID\{VISIO_CLASSID}\LocalServer32
VISIO_EXEPATH HKCR C:\Program Files (x86)\Microsoft Office\Root\Office16\VISIO.EXE
GetVisioVersion FileSys
VISIO_VERSION FileSys 16.0
GetVisioFullVersion FileSys
VISIO_FULLVERSION FileSys 16.0.11029.20070
GetVisioKeyName HKLM Software\Microsoft\Office\{VISIO_VERSION}\Visio
VISIO_KEYNAME HKLM Software\Microsoft\Office\16.0\Visio
GetVisioAppSetting HKCU {VISIO_KEYNAME}\Application
VISIO_LICENSECACHE HKCU PRO
GetVisioAppSetting HKCU {VISIO_KEYNAME}\Application
VISIO_STENCILPATH HKCU C:\Users\david\Documents\Visio Stencils
GetVisioAppSetting HKCU {VISIO_KEYNAME}\Application
VISIO_TEMPLATEPATH HKCU C:\Users\david\Documents\Visio Templates
GetVisioAppSetting HKCU {VISIO_KEYNAME}\Application
VISIO_PERSONALTEMPLATES HKCU C:\Users\david\Documents\Custom Office Templates
GetVisioAppSetting HKCU {VISIO_KEYNAME}\Application
VISIO_MYSHAPESPATH HKCU C:\Users\david\Documents\My Shapes
GetOfficeIsC2R HKLM SOFTWARE\Microsoft\Office\ClickToRun\Configuration
OFFICE_ISC2R HKLM TRUE
GetOfficeC2RSetting HKLM SOFTWARE\Microsoft\Office\ClickToRun\Configuration
OFFICE_C2RCULTURE HKLM en-us
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Simplify Tasks

Want to learn the simple way?

Paul Turley's SQL Server BI Blog

sharing my experiences with the Microsoft data platform, SQL Server BI, Data Modeling, SSAS Design, Power Pivot, Power BI, SSRS Advanced Design, Power BI, Dashboards & Visualization since 2009

John Goldsmith's visLog

be smart, be clear, be visual ...

Mo's blog

Personal views on Dynamics 365 for Operations and Technical Architecture.

Chris Webb's BI Blog

Microsoft Power BI, Analysis Services, MDX, DAX, M, Power Pivot and Power Query

davecra.wordpress.com/

Microsoft Office 365 Development, and more...

PowerShell.Amsterdam

Automate, Accelerate, Accurate

johnvisiomvp

Life with Visio and other Microsoft Toys!

Title (Required)

Windows Server Essentials Tips & Tricks

Nilsandrey's Weblog

Just another WordPress.com weblog

Things that Should be Easy

Every so often (too often in the IT industry) I encounter things that should have been very easy to do but turned out to be far too complicated. My favorite topics include SharePoint, .Net development, and software architecture, especially distributed systems.

Visio Guy

Smart graphics for visual people

Pluralsight blog

be smart, be clear, be visual ...

%d bloggers like this: