Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# excel在注册表中的安装位置_C# - Fatal编程技术网

C# excel在注册表中的安装位置

C# excel在注册表中的安装位置,c#,C#,我需要检测注册表中的excel安装位置并打开excel文件。我找到了一个示例代码。 我有两个问题:首先,代码中给定的注册表路径中没有InstallRoot directorty RegistryKey rootdir=excelKey.OpenSubKey(当前版本+ @“.0\Excel\InstallRoot”) 但它确实存在于此路径下(SOFTWARE\Wow6432Node\MicroSoft\Office) 另一个问题是,我收到的信息是“无法在excel中打开” 因为excel没有安装

我需要检测注册表中的excel安装位置并打开excel文件。我找到了一个示例代码。 我有两个问题:首先,代码中给定的注册表路径中没有InstallRoot directorty

RegistryKey rootdir=excelKey.OpenSubKey(当前版本+ @“.0\Excel\InstallRoot”)

但它确实存在于此路径下(SOFTWARE\Wow6432Node\MicroSoft\Office) 另一个问题是,我收到的信息是“无法在excel中打开” 因为excel没有安装。”所以我认为CurrentVersion返回worng值 在我的例子中(自2007年以来),它返回120.0而不是12.0

public void OpenInExcel(string filename)
        {
            string dir = "";
            RegistryKey key = Registry.LocalMachine;
            RegistryKey excelKey = key.OpenSubKey(@"SOFTWARE\MicroSoft\Office");
            if (excelKey != null)
            {
                foreach (string valuename in excelKey.GetSubKeyNames())
                {
                    int version = 9;
                    double currentVersion=0;
                    if (Double.TryParse(valuename, out currentVersion) && currentVersion >= version)
                    {
                        RegistryKey rootdir = excelKey.OpenSubKey(currentVersion + @".0\Excel\InstallRoot");
                        if (rootdir != null)
                        {
                            dir = rootdir.GetValue(rootdir.GetValueNames()[0]).ToString();
                            break;
                        }
                    }
                }                
            }
            if (dir != "")
            {
                ProcessStartInfo startInfo = new ProcessStartInfo();

                startInfo.FileName = dir + @"Excel.exe";
                startInfo.Arguments = "\"" + fileName + "\"";
                startInfo.UseShellExecute = false;

                using (Process process = new Process())
                {
                    process.StartInfo = startInfo;
                    try
                    {
                        process.Start();
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("\n\nCould not start Excel process.");
                        Console.WriteLine(ex);
                    }
                }
            }
            else
            {
                MessageBox.Show("Can't Open in excel because excel is not installed.");
            }
        }     
@编辑:我认为这行出现了一些错误,返回了错误的值,因为它是这样工作的

RegistryKey rootdir=excelKey.OpenSubKey( @“12.0\Excel\InstallRoot”)


我不知道为什么TryParse返回120.0这不是对您的问题的回答,但它可能会帮助您获得正确的版本号,我不能在评论中发布所有这些代码

  public const string CProgIdOutlook = "Outlook.Application";

  /// <summary>
  /// Method to get the Outlook version number, which will presumably be 11 (2003), 12 (2007), 
  /// 14 (2010) or 15 (2013). (I wonder what happened to version 13?) An exception is thrown if 
  /// this method is unable to provide an answer.
  /// 
  /// The technique used to get the version number of the "current" installed version of Outlook 
  /// is one of many possible methods that are described in various Internet sources, and is 
  /// hopefully the most likely to provide the correct answer with the least side-effects. 
  /// Problems with some of the alternative registry-based methods typically show up when 
  /// multiple versions of Outlook are installed or have been installed. The registry values can 
  /// also depend on x86 vs. x64 systems and whether Outlook was installed for one user or for 
  /// all users. Techniques involving querying the Outlook automation object have the 
  /// disadvantage of an instance of the Outlook program getting created - this can be seen in 
  /// Task Manager.
  /// 
  /// The idea for this code came from here: http://support.microsoft.com/kb/240794
  /// </summary>
  /// <returns>11 (2003), 12 (2007), 14 (2010) or 15 (2013)</returns>
  private static int GetOutlookVersion()
  {
     const string CRegistryKey = @"SOFTWARE\Classes\" + GroupwareProgIds.CProgIdOutlook;
     int outlookVersion;

     using (RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(CRegistryKey))
     {
        outlookVersion = GetOutlookVersion(registryKey);
        if (outlookVersion != -1)
           return outlookVersion;
     }

     using (RegistryKey registryKey = Registry.CurrentUser.OpenSubKey(CRegistryKey))
     {
        outlookVersion = GetOutlookVersion(registryKey);
        if (outlookVersion != -1)
           return outlookVersion;
     }

     throw new MerliniaException(0x2d4a67fu, "No registry entry for " + CRegistryKey);
  }


  /// <summary>
  /// Sub-method of above method to do the work for either HKLM or HKCU.
  /// </summary>
  /// <returns>11 (2003), 12 (2007), 14 (2010) or 15 (2013), or -1 for error</returns>
  private static int GetOutlookVersion(RegistryKey registryKey1)
  {
     const string CCurVer = "CurVer";

     if (registryKey1 == null)
        return -1;

     using (RegistryKey registryKey2 = registryKey1.OpenSubKey(CCurVer))
     {
        if (registryKey2 == null)
           throw new MerliniaException(0x2d43e5au, 
                                      "No registry entry for " + registryKey1 + "\\" + CCurVer);

        string currentOutlookAppName = registryKey2.GetValue(null) as string;
        if (currentOutlookAppName != null)
        {
           string[] sa = currentOutlookAppName.Split('.');
           if (sa.Length == 3)
           {
              int outlookVersion;
              if (int.TryParse(sa[2], NumberStyles.Integer, 
                               CultureInfo.InvariantCulture, out outlookVersion))
                 return outlookVersion;
           }
        }

        throw new MerliniaException(0x2d4b29du, 
                               "Invalid registry content for " + registryKey1 + "\\" + CCurVer);
     }
  }
公共常量字符串CProgIdOutlook=“Outlook.Application”; /// ///方法获取Outlook版本号,大概是11(2003)、12(2007), ///第14条(2010年)或第15条(2013年)。(我想知道版本13发生了什么?)如果 ///此方法无法提供答案。 /// ///用于获取Outlook“当前”安装版本的版本号的技术 ///是各种Internet来源中描述的许多可能方法之一,并且 ///希望最有可能以最少的副作用提供正确答案。 ///一些基于注册表的替代方法的问题通常在 ///已安装或已安装多个版本的Outlook。注册表值可以 ///还取决于x86和x64系统,以及Outlook是为一个用户安装的还是为其他用户安装的 ///所有用户。涉及查询Outlook自动化对象的技术具有以下特点: ///创建Outlook程序实例的缺点-可以在中看到 ///任务管理器。 /// ///此代码的想法来自于此:http://support.microsoft.com/kb/240794 /// ///11(2003)、12(2007)、14(2010)或15(2013) 私有静态int GetOutlookVersion() { const string CRegistryKey=@“软件\类\”+GroupwareProgIds.CProgIdOutlook; 国际展望版; 使用(RegistryKey RegistryKey=Registry.LocalMachine.OpenSubKey(CRegistryKey)) { outlookVersion=GetOutlookVersion(registryKey); 如果(了望版本!=-1) 返回了望版本; } 使用(RegistryKey RegistryKey=Registry.CurrentUser.OpenSubKey(CRegistryKey)) { outlookVersion=GetOutlookVersion(registryKey); 如果(了望版本!=-1) 返回了望版本; } 抛出新的MerliniaException(0x2d4a67fu,“没有“+CRegistryKey”的注册表项); } /// ///为HKLM或HKCU开展工作的上述方法的子方法。 /// ///11(2003)、12(2007)、14(2010)或15(2013)或-1表示错误 私有静态int GetOutlookVersion(RegistryKey registryKey1) { 常量字符串ccerver=“CurVer”; 如果(registryKey1==null) 返回-1; 使用(RegistryKey registryKey2=registryKey1.OpenSubKey(CCServer)) { 如果(registryKey2==null) 抛出新的MerliniaException(0x2d43e5au, “没有“+registryKey1+”\\“+CCServer”的注册表项); 字符串currentOutlookAppName=registryKey2.GetValue(null)作为字符串; 如果(currentOutlookAppName!=null) { 字符串[]sa=currentOutlookAppName.Split('.'); 如果(sa.Length==3) { 国际展望版; if(int.TryParse(sa[2],numberstyle.Integer, CultureInfo.InvariantCulture,outlookVersion) 返回了望版本; } } 抛出新的MerliniaException(0x2d4b29du, “+registryKey1+”\\“+CCServer”的注册表内容无效); } }
问题在于双重类型和文化

我试着解释:

您将获得
12.0

ToString
美国文化中转换为12.0,在文化中转换为120.0(十进制分隔符不相同)

问题是将版本解析为双精度

由于计算机文化的考虑,作为小数点分隔符和。作为千分之一

您可以这样更改代码(当您尝试
Double.TryParse
时):


if(Double.TryParse(valuename,System.Globalization.NumberStyles.Any,System.Globalization.CultureInfo.InvariantCulture,out-currentVersion)&¤tVersion>=version)

您有什么特别的原因不想设置
startInfo.UseShellExecute=true
startInfo.FileName=@“document.xls”
剩下的就让操作系统来做吧?你标记了RenniePet答案<代码>这不是对您的问题的回答