开源第52波-通过注册表信息判断Excel位数的方法

2021-08-18 11:16:16 浏览数 (5)

在开发EasyShu的过程中,因为用户体验的倒逼,不得不认真再去学习下如何更好地解决Excel位数的问题。

以下说一下使用代码去获取当前电脑上Excel的位数。

方法一:通过Application.HinstancePtr属性

这个方法弊端是需要拿到Excel的Application对象,安装过wps的电脑,可能会破坏正常调用Excel的能力。

方法二:通过VBA代码的的Win64方法

如果有办法在VBA环境下使用,那就好简单,上面的方法也行,下面的Win64方法也行。

代码语言:javascript复制
Public Function IsOffice64() As Boolean
    #If Win64 Then
        IsOffice64 = True
    #Else
        IsOffice64 = False
    #End If
End Function

方法三:通过Application.RegisterXLL来加载不同位数的xll文件

这个方法,笔者在EasyShu里短暂用过一段时间,但弊端也是要拿到Excel的Application对象。如果加载对应位数的xll文件后返回结果为true,就证明是这个位数的版本。当然比方法一要折腾了,方法一今天才发现,没用得上,就被方法四给替换了。

方法四:使用注册表信息判断

这个也是今天的主角,这个方法好处是快速,不用调用Excel程序,读写注册表非常快。准确性还有待EasyShu的用户反馈检验。特别是对一些非默认安装OFFICE路径的,有可能识别不到。

详细核心代码如下:原理为通过注册表位置找到Excel程序的路径,再通过注册表卸载信息里找到OFFICE的GUIDS信息。

最后,正如微软官方定义的GUIDS规则,第四段是存放位数信息。

https://docs.microsoft.com/en-us/office/troubleshoot/office-suite-issues/numbering-scheme-product-code-guids

代码语言:javascript复制
internal static  bool IsExcel64Bit()
        {
            var uninstallNode = Registry.LocalMachine.OpenSubKey(@"SOFTWAREMicrosoftWindowsCurrentVersionUninstall", RegistryKeyPermissionCheck.ReadSubTree, System.Security.AccessControl.RegistryRights.ReadKey);
            var excelAppNode = Registry.LocalMachine.OpenSubKey(@"SOFTWAREMicrosoftWindowsCurrentVersionApp Pathsexcel.exe", RegistryKeyPermissionCheck.ReadSubTree, System.Security.AccessControl.RegistryRights.ReadKey);
            var uninstallNode32 = Registry.LocalMachine.OpenSubKey(@"SOFTWAREWOW6432NodeMicrosoftWindowsCurrentVersionUninstall", RegistryKeyPermissionCheck.ReadSubTree, System.Security.AccessControl.RegistryRights.ReadKey);
            var excelAppNode32 = Registry.LocalMachine.OpenSubKey(@"SOFTWAREWOW6432NodeMicrosoftWindowsCurrentVersionApp Pathsexcel.exe", RegistryKeyPermissionCheck.ReadSubTree, System.Security.AccessControl.RegistryRights.ReadKey);
            string excelAppPath;
            if (!Environment.Is64BitProcess && excelAppNode32 != null)
            {
                excelAppPath = excelAppNode32.GetValue("Path").ToString();
            }
            else
            {
                excelAppPath = excelAppNode.GetValue("Path").ToString();
            }
            if (uninstallNode32 != null)
            {
                var guids = GetGuidsOfOffice(uninstallNode32, excelAppPath);
                if (string.IsNullOrEmpty(guids))
                {
                    guids = GetGuidsOfOffice(uninstallNode, excelAppPath);
                }
                return guids.Split('-')[3].Substring(0, 1) == "1" ? true : false;
            }
            else
            {
                var guids = GetGuidsOfOffice(uninstallNode, excelAppPath);
                return guids.Split('-')[3].Substring(0, 1) == "1" ? true : false;
            }
        }
        private static string GetGuidsOfOffice(RegistryKey registryKey, string excelAppPath)
        {
            foreach (string subKeyName in registryKey.GetSubKeyNames())
            {
                RegistryKey subKey = registryKey.OpenSubKey(subKeyName);
                //Console.WriteLine(subKey.GetValue("DisplayName")  "|"  subKey.GetValue("Publisher")  "|"  subKey.GetValue("InstallSource"));
                if (
                    subKey.GetValue("DisplayName") != null &&
                    subKey.GetValue("DisplayName").ToString().ToLower().Contains("office") &&
                   subKey.GetValue("Publisher") != null &&
                   subKey.GetValue("Publisher").ToString() == "Microsoft Corporation" &&
                   subKey.GetValue("InstallSource") != null &&
                  Path.GetDirectoryName(subKey.GetValue("InstallSource").ToString().TrimEnd('\')).ToLower() == Path.GetDirectoryName(excelAppPath.TrimEnd('\')).ToLower()
                    )
                {
                    return Path.GetFileName(subKey.Name);
                }
            }
            return string.Empty;
        }

结语

Excel催化剂开发运营至今3年多,说实话,对用户体验的改善度没有太强烈,相反EasyShu因其定位为付费产品,用户体验倒逼不断地找寻更优解决方案。

0 人点赞