Site icon bVisual

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.

Visio Registry Search CRIN


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:

internal const string HKLM_VISIO = @"Software\Microsoft\Office{0}\Visio";
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;
}

Examples of use include:


//The License is either PRO or STD now (Visio 2010 also had PRM - Premium)
var VISIO_LICENSECACHE = GetVisioAppSetting(VISIO_PLATFORM, VISIO_KEYNAME, "LicenseCache");
//StencilPath can be a list of semi-colon separated paths
var VISIO_STENCILPATH = GetVisioAppSetting(VISIO_PLATFORM, VISIO_KEYNAME, "StencilPath");
//TemplatePath can be a list of semi-colon separated paths
var VISIO_TEMPLATEPATH = GetVisioAppSetting(VISIO_PLATFORM, VISIO_KEYNAME, "TemplatePath");
var VISIO_PERSONALTEMPLATES = GetVisioAppSetting(VISIO_PLATFORM, VISIO_KEYNAME, "PersonalTemplates");
var VISIO_MYSHAPESPATH = GetVisioAppSetting(VISIO_PLATFORM, VISIO_KEYNAME, "MyShapesPath");

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 / VariableAreaKey / Value
GetVisioDrawingCurrentVersionHKCRVisio.Drawing\CurVer
VISIO_DWGVERHKCRVisio.Drawing.15
GetVisioClassIDHKCR{VISIO_DWGVER}\CLSID
VISIO_CLASSIDHKCR{00021A15-0000-0000-C000-000000000046}
GetVisioPlatformHKCRCLSID\{VISIO_CLASSID}\LocalServer32
VISIO_PLATFORMHKCRx86
GetVisioExeHKCRCLSID\{VISIO_CLASSID}\LocalServer32
VISIO_EXEPATHHKCRC:\Program Files (x86)\Microsoft Office\Root\Office16\VISIO.EXE
GetVisioVersionFileSys 
VISIO_VERSIONFileSys16.0
GetVisioFullVersionFileSys 
VISIO_FULLVERSIONFileSys16.0.11029.20070
GetVisioKeyNameHKLMSoftware\Microsoft\Office\{VISIO_VERSION}\Visio
VISIO_KEYNAMEHKLMSoftware\Microsoft\Office\16.0\Visio
GetVisioAppSettingHKCU{VISIO_KEYNAME}\Application
VISIO_LICENSECACHEHKCUPRO
GetVisioAppSettingHKCU{VISIO_KEYNAME}\Application
VISIO_STENCILPATHHKCUC:\Users\david\Documents\Visio Stencils
GetVisioAppSettingHKCU{VISIO_KEYNAME}\Application
VISIO_TEMPLATEPATHHKCUC:\Users\david\Documents\Visio Templates
GetVisioAppSettingHKCU{VISIO_KEYNAME}\Application
VISIO_PERSONALTEMPLATESHKCUC:\Users\david\Documents\Custom Office Templates
GetVisioAppSettingHKCU{VISIO_KEYNAME}\Application
VISIO_MYSHAPESPATHHKCUC:\Users\david\Documents\My Shapes
GetOfficeIsC2RHKLMSOFTWARE\Microsoft\Office\ClickToRun\Configuration
OFFICE_ISC2RHKLMTRUE
GetOfficeC2RSettingHKLMSOFTWARE\Microsoft\Office\ClickToRun\Configuration
OFFICE_C2RCULTUREHKLMen-us
Exit mobile version