none
Have C# check what version of Excel is installed

    Question

  • I have users who are using Excel 2000, Excel 2007, Excel 2010.  I was wondering if there was a way to have C# 1st check to see what version of Excel is installed (I am assuming there would be a registry key to check) and then based off of what version of Excel is installed auto-add the correct COM reference to that version of Excel.

    This may not be possible, as some users may have multiple versions of Excel installed, but thought I would ask rather than constantly pointing users in the direction of how to add a COM reference, when they are NOT tech savy.

    Thursday, June 20, 2013 11:31 PM

Answers

  • Hi,

        Welcome to MSDN Forum Support.

      You can use the MSI (Windows Installer) APIs to find out if the relevant product/package/component codes are present on the machine. These are fairly simple to use via P/Invoke.

    Alternatively, you can look in the registry. Word 2007, for example, puts its install location at HKLM\SOFTWARE\Microsoft\Office\12.0\Word\InstallRoot.

    This doesn't help you if you're planning on using the interop components, but it does tell you, with reasonable certainty, whether the various things are installed. Its detailed implementation you can follow these two links:

      C#: How to know whether certain Office 2003 or 2007 application is installed?

     


    Jason Wang [MSFT]
    MSDN Community Support | Feedback to us

    Friday, June 21, 2013 2:44 AM
  • Hi Indigo,

    As you can check from Microsoft documentation, the right way to check that is from the default value of the registry key:

    HKEY_CLASSES_ROOT\Excel.Application\CurVer

    The default value of that key should have something like "Excel.Application.14", that indicates the version installed. In this case was Microsoft Excel 2010.

    I think the corresponding values are:

    Excel.Application.10 = Excel 2000
    Excel.Application.11 = Excel 2003
    Excel.Application.12 = Excel 2007
    Excel.Application.13 = Excel for Mac
    Excel.Application.14 = Excel 2010

    I hope this helps.


    Best regards,

    Fernando Rocha

    Friday, June 21, 2013 2:48 AM
  • Hi again,


    Well... I've read many interesting information on the internet, for instance, this one and the official Microsoft documentation on the subject. It states that you can access an Excel COM object with something like this:

    dynamic excel = System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");

    Unfortunately I was unable to make it work, because this will only work if you already have one instance of that application running and accessible, they say it must be in the Running Object Table (ROT). To instantiate the application means doing something like this:

    var excelApp = new Microsoft.Office.Interop.Excel.Application();

    And you can only do this if you already have added a concrete reference to the correct "Microsoft.Office.Interop.Excel.dll" file.

    One thing you can be sure of: you can't unload assemblies (DLL references) once they are loaded  into the same AppDomain. This means that once the application loads one version of the Interop DLL, it can't unload that DLL and load another one.

    Maybe you be able to replace the Interop DLL before the application starts, depending on the check of what version of Excel is installed. Try to compile the application with the reference to the 2007 and then, replace the DLL with the 2010 version and check if that works well. Please, tell me if that works.

    If that doesn't work, I think you would need to compile part of the code (the whole part that is manipulating the Excel) for each Excel assembly version you would like to support, and then dynamically load, at run-time, the one that you want to use. This is something hard to do, you're making the code that manipulates the Excel to load dynamically at run-time, just like a plugin.

    Best regards,

    Fernando Rocha

    Friday, June 21, 2013 5:30 AM
  • I think I found a way.

    Try this:

    var excelClsid = new Guid("00024500-0000-0000-C000-000000000046");
    Type excelType = Type.GetTypeFromCLSID(excelGuid);
    dynamic excelApplication = Activator.CreateInstance(excelType);

    I think the GUID for the Excel never changes (it's the same on all versions), but it's very easy to get that GUID from the registry anyway. To do this, you don't even need to add a reference to the Interop assemblies!!! One disadvantage is that you won't get IntelliSense, but you can add the Reference just to have IntelliSense, and cast that object to Excel.Application, and then remove the Reference and the cast when you deploy.

    Try it and tell me if that works.


    Best regards,

    Fernando Rocha


    Friday, June 21, 2013 5:42 AM

All replies

  • Hi,

        Welcome to MSDN Forum Support.

      You can use the MSI (Windows Installer) APIs to find out if the relevant product/package/component codes are present on the machine. These are fairly simple to use via P/Invoke.

    Alternatively, you can look in the registry. Word 2007, for example, puts its install location at HKLM\SOFTWARE\Microsoft\Office\12.0\Word\InstallRoot.

    This doesn't help you if you're planning on using the interop components, but it does tell you, with reasonable certainty, whether the various things are installed. Its detailed implementation you can follow these two links:

      C#: How to know whether certain Office 2003 or 2007 application is installed?

     


    Jason Wang [MSFT]
    MSDN Community Support | Feedback to us

    Friday, June 21, 2013 2:44 AM
  • Hi Indigo,

    As you can check from Microsoft documentation, the right way to check that is from the default value of the registry key:

    HKEY_CLASSES_ROOT\Excel.Application\CurVer

    The default value of that key should have something like "Excel.Application.14", that indicates the version installed. In this case was Microsoft Excel 2010.

    I think the corresponding values are:

    Excel.Application.10 = Excel 2000
    Excel.Application.11 = Excel 2003
    Excel.Application.12 = Excel 2007
    Excel.Application.13 = Excel for Mac
    Excel.Application.14 = Excel 2010

    I hope this helps.


    Best regards,

    Fernando Rocha

    Friday, June 21, 2013 2:48 AM
  • Is it possible to once the installed version is determined then add the proper COM reference?
    Friday, June 21, 2013 3:12 AM
  • Hi again,


    Well... I've read many interesting information on the internet, for instance, this one and the official Microsoft documentation on the subject. It states that you can access an Excel COM object with something like this:

    dynamic excel = System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");

    Unfortunately I was unable to make it work, because this will only work if you already have one instance of that application running and accessible, they say it must be in the Running Object Table (ROT). To instantiate the application means doing something like this:

    var excelApp = new Microsoft.Office.Interop.Excel.Application();

    And you can only do this if you already have added a concrete reference to the correct "Microsoft.Office.Interop.Excel.dll" file.

    One thing you can be sure of: you can't unload assemblies (DLL references) once they are loaded  into the same AppDomain. This means that once the application loads one version of the Interop DLL, it can't unload that DLL and load another one.

    Maybe you be able to replace the Interop DLL before the application starts, depending on the check of what version of Excel is installed. Try to compile the application with the reference to the 2007 and then, replace the DLL with the 2010 version and check if that works well. Please, tell me if that works.

    If that doesn't work, I think you would need to compile part of the code (the whole part that is manipulating the Excel) for each Excel assembly version you would like to support, and then dynamically load, at run-time, the one that you want to use. This is something hard to do, you're making the code that manipulates the Excel to load dynamically at run-time, just like a plugin.

    Best regards,

    Fernando Rocha

    Friday, June 21, 2013 5:30 AM
  • I think I found a way.

    Try this:

    var excelClsid = new Guid("00024500-0000-0000-C000-000000000046");
    Type excelType = Type.GetTypeFromCLSID(excelGuid);
    dynamic excelApplication = Activator.CreateInstance(excelType);

    I think the GUID for the Excel never changes (it's the same on all versions), but it's very easy to get that GUID from the registry anyway. To do this, you don't even need to add a reference to the Interop assemblies!!! One disadvantage is that you won't get IntelliSense, but you can add the Reference just to have IntelliSense, and cast that object to Excel.Application, and then remove the Reference and the cast when you deploy.

    Try it and tell me if that works.


    Best regards,

    Fernando Rocha


    Friday, June 21, 2013 5:42 AM