【问题标题】:Programmatically retrieve Visual Studio install directory以编程方式检索 Visual Studio 安装目录
【发布时间】:2010-09-07 00:39:38
【问题描述】:

我知道有一个指示安装目录的注册表项,但我不记得它是什么。

我目前对 Visual Studio 2008 安装目录感兴趣,但列出其他目录以供将来参考也无妨。

【问题讨论】:

    标签: visual-studio


    【解决方案1】:

    我用这个方法找到Visual Studio 2010的安装路径:

        private string GetVisualStudioInstallationPath()
        {
            string installationPath = null;
            if (Environment.Is64BitOperatingSystem)
            {
                installationPath = (string)Registry.GetValue(
                   "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\VisualStudio\\10.0\\",
                    "InstallDir",
                    null);
            }
            else
            {
                installationPath = (string)Registry.GetValue(
           "HKEY_LOCAL_MACHINE\\SOFTWARE  \\Microsoft\\VisualStudio\\10.0\\",
                  "InstallDir",
                  null);
            }
            return installationPath;
    
        }
    

    【讨论】:

    • 如果应用程序没有管理员权限,这将不起作用。
    • 这里也一样,Visual Studio Community 2017 15.8.7 中也没有填充。
    【解决方案2】:

    我确定也有一个注册表项,但我无法轻松找到它。您也可以使用 VS90COMNTOOLS 环境变量。

    【讨论】:

    • 此方法不适用于 Visual Studio 的快速版本,因为未设置环境变量。注册表方法适用于所有版本的软件。
    • 查看我对注册表项的回答
    • 也不适用于 VS2017,因为没有定义变量
    • 对于 VS2017,路径可以在 HKLM\SOFTWARE\Wow6432Node\Microsoft\Visual Studio\SxS\VS17 找到
    • @ApostolisBekiaris 不幸的是,并非在所有系统上。我有两个安装了 VS2017 的独立系统(x86 和 x64),并且 SxS 目录不包含任何这些系统上的任何 VS2017 痕迹。
    【解决方案3】:

    注册方法

    我建议查询注册表以获取此信息。这提供了实际安装目录,无需组合路径,它也适用于快速版本。这可能是一个重要的区别,具体取决于您需要做什么(例如,模板安装到不同的目录,具体取决于 Visual Studio 的版本)。注册表位置如下(注意 Visual Studio 是一个 32 位程序,将安装到 x64 机器上注册表的 32 位部分):

    • Visual Studio:HKLM\SOFTWARE\Microsoft\Visual Studio\Major.Minor:InstallDir
    • Visual C# Express:HKLM\SOFTWARE\Microsoft\VCSExpress\Major.Minor:InstallDir
    • Visual Basic Express:HKLM\SOFTWARE\Microsoft\VBExpress\Major.Minor:InstallDir
    • Visual C++ Express: HKLM\SOFTWARE\Microsoft\VCExpress\Major.Minor:InstallDir

    其中 Major 是主要版本号,Minor 是次要版本号,冒号后面的文本是注册表值的名称。例如,Visual Studio 2008 Professional 的安装目录将位于 HKLM\SOFTWARE\Microsoft\Visual Studio\9.0 键的 InstallDir 值中。

    这是一个打印几个版本的 Visual Studio 和 Visual C# Express 的安装目录的代码示例:

    string visualStudioRegistryKeyPath = @"SOFTWARE\Microsoft\VisualStudio";
    string visualCSharpExpressRegistryKeyPath = @"SOFTWARE\Microsoft\VCSExpress";
    
    List<Version> vsVersions = new List<Version>() { new Version("10.0"), new Version("9.0"), new Version("8.0") };
    foreach (var version in vsVersions)
    {
        foreach (var isExpress in new bool[] { false, true })
        {
            RegistryKey registryBase32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);
            RegistryKey vsVersionRegistryKey = registryBase32.OpenSubKey(
                string.Format(@"{0}\{1}.{2}", (isExpress) ? visualCSharpExpressRegistryKeyPath : visualStudioRegistryKeyPath, version.Major, version.Minor));
            if (vsVersionRegistryKey == null) { continue; }
            Console.WriteLine(vsVersionRegistryKey.GetValue("InstallDir", string.Empty).ToString());
        }
    

    环境变量法

    Visual Studio 的非 express 版本也写了一个环境变量,你可以检查,但它给出了公共工具目录的位置,而不是安装目录,所以你必须做一些路径组合。环境变量的格式是 VS*COMNTOOLS 其中 * 是主要和次要版本号。例如,Visual Studio 2010 的环境变量是 VS100COMNTOOLS 并包含类似 C:\Program Files\Microsoft Visual Studio 10.0\Common7\Tools 的值。

    下面是一些示例代码,用于打印多个 Visual Studio 版本的环境变量:

    List<Version> vsVersions = new List<Version>() { new Version("10.0"), new Version("9.0"), new Version("8.0") };
    foreach (var version in vsVersions)
    {
        Console.WriteLine(Path.Combine(Environment.GetEnvironmentVariable(string.Format("VS{0}{1}COMNTOOLS", version.Major, version.Minor)), @"..\IDE"));
    }
    

    【讨论】:

    • 在我的机器上,Visual Studio Community 2017 (15.0) 没有 InstallDir 值。
    • 我认为从 Visual Studio 2017 开始,他们停止使用 VSxxxCOMNTOOLS 变量。我想知道没有注册表是否还有另一种方法。
    【解决方案4】:

    环境:感谢 Zeb 和 Sam 对 VS*COMNTOOLS 环境变量的建议。在 PowerShell 中访问 IDE:

    $vs = Join-Path $env:VS90COMNTOOLS '..\IDE\devenv.exe'
    

    注册表: 看起来注册表位置是HKLM\Software\Microsoft\VisualStudio,每次安装都有特定于版本的子项。在 PowerShell 中:

    $vsRegPath = 'HKLM:\Software\Microsoft\VisualStudio\9.0'
    $vs = (Get-ItemProperty $vsRegPath).InstallDir + 'devenv.exe'
    

    [改编自here]

    【讨论】:

      【解决方案5】:

      对于 Visual Studio 2017 和 Visual Studio 2019,有 Microsoft 的 Setup API。

      在C#中,只需添加NuGet包“Microsoft.VisualStudio.Setup.Configuration.Interop”,这样使用即可:

          try {
              var query = new SetupConfiguration();
              var query2 = (ISetupConfiguration2)query;
              var e = query2.EnumAllInstances();
      
              var helper = (ISetupHelper)query;
      
              int fetched;
              var instances = new ISetupInstance[1];
              do {
                  e.Next(1, instances, out fetched);
                  if (fetched > 0)
                      Console.WriteLine(instances[0].GetInstallationPath());
              }
              while (fetched > 0);
              return 0;
          }
          catch (COMException ex) when (ex.HResult == REGDB_E_CLASSNOTREG) {
              Console.WriteLine("The query API is not registered. Assuming no instances are installed.");
              return 0;
          }
      

      您可以找到更多适用于 VC、C# 和 VB 的示例here

      【讨论】:

        【解决方案6】:

        @Dim-Ka 有一个很好的答案。如果您对如何在批处理脚本中实现这一点感到好奇,这就是方法。

        @echo off
        :: BATCH doesn't have logical or, otherwise I'd use it
        SET platform=
        IF /I [%PROCESSOR_ARCHITECTURE%]==[amd64] set platform=true
        IF /I [%PROCESSOR_ARCHITEW6432%]==[amd64] set platform=true
        
        :: default to VS2012 = 11.0
        :: the Environment variable VisualStudioVersion is set by devenv.exe
        :: if this batch is a child of devenv.exe external tools, we know which version to look at
        if not defined VisualStudioVersion SET VisualStudioVersion=11.0
        
        if defined platform (
        set VSREGKEY=HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\%VisualStudioVersion%
        )  ELSE (
        set VSREGKEY=HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\%VisualStudioVersion%
        )
        for /f "skip=2 tokens=2,*" %%A in ('reg query "%VSREGKEY%" /v InstallDir') do SET VSINSTALLDIR=%%B
        
        echo %VSINSTALLDIR%
        

        【讨论】:

          【解决方案7】:

          真正的问题是所有 Visual Studio 版本都有自己的位置。所以这里提出的解决方案不是通用的。然而,微软已经免费提供了一个实用程序(包括源代码)来解决这个问题(即烦恼)。它被称为vswhere.exe,您可以从here 下载它。我对它非常满意,希望它也适用于未来的版本。它使此页面上的整个讨论变得多余。

          【讨论】:

            【解决方案8】:

            啊,64 位机器部分是问题所在。事实证明,我需要确保在 syswow64 目录下运行 PowerShell.exe 才能获取 x86 注册表项。

            现在这不是很有趣。

            【讨论】:

            • RegEdit 相同:如果您不从 %WINDIR%\SysWOW64 运行 RegEdit,则不会显示密钥
            【解决方案9】:

            使用Environment.GetEnvironmentVariable("VS90COMNTOOLS");

            在 64 位环境中,它也适用于我。

            【讨论】:

              【解决方案10】:

              您可以读取 VSINSTALLDIR 环境变量。

              【讨论】:

                【解决方案11】:

                这是始终获取最新版本路径的解决方案:

                $vsEnvVars = (dir Env:).Name -match "VS[0-9]{1,3}COMNTOOLS"
                $latestVs = $vsEnvVars | Sort-Object | Select -Last 1
                $vsPath = Get-Content Env:\$latestVs
                

                【讨论】:

                  【解决方案12】:

                  现在,我使用以下 PowerShell 命令获取 Visual Studio 2017/2019 路径(此处带有 Common7\IDE 后缀,因此它模仿了 DevEnvDir 属性):

                  Get-ChildItem HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall | foreach { Get-ItemProperty $_.PsPath } | where { $_.DisplayName -like '*Visual Studio*' -and $_.InstallLocation.Length -gt 0 } | sort InstallDate -Descending | foreach { (Join-Path $_.InstallLocation 'Common7\IDE') } | where { Test-Path $_ } | select -First 1

                  如果你想从 cmd.exe 执行它,命令应该是这样的:

                  powershell.exe -ExecutionPolicy Bypass -Command "Get-ChildItem HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall | foreach { Get-ItemProperty $_.PsPath } | where { $_.DisplayName -like '*Visual Studio*' -and $_.InstallLocation.Length -gt 0 } | sort InstallDate -Descending | foreach { (Join-Path $_.InstallLocation 'Common7\IDE') } | where { Test-Path $_ } | select -First 1"

                  我在一个 C# 项目中使用它,我使用 Rider 而不是 Visual Studio 作为我的 IDE(当然我也可以在 Rider 的设置中手动设置 DevEnvDir 属性):

                  <Target Name="MyTarget" BeforeTargets="Build">
                    <Exec Condition="'$(DevEnvDir)' == '' Or '$(DevEnvDir)' == '*Undefined*' Or !Exists('$(DevEnvDir)')"
                          Command="powershell.exe -ExecutionPolicy Bypass -Command &quot;Get-ChildItem HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall | foreach { Get-ItemProperty $_.PsPath } | where { $_.DisplayName -like '*Visual Studio*' -and $_.InstallLocation.Length -gt 0 } | sort InstallDate -Descending | foreach { (Join-Path $_.InstallLocation 'Common7\IDE') } | where { Test-Path $_ } | select -First 1&quot;"
                          ConsoleToMSBuild="true">
                      <Output TaskParameter="ConsoleOutput" PropertyName="DevEnvDir" />
                    </Exec>
                  </Target>
                  

                  我使用它来获取 VS 命令提示符批处理文件的路径(例如 vcvars64.batvcvarsall.bat),因此我可以在调用 MIDL.exe 之前调用它们来为我的 IDL 文件生成类型库,所以我的当通过regsvr32.exe 注册comhost.dll 时,.NET 5 COM 类可以为自己注册一个类型库。

                  【讨论】:

                    【解决方案13】:

                    请注意,如果您使用的是 Visual Studio Express 或 Visual C++ Express,则键名分别包含 WDExpress 或 VCExpress,而不是 VisualStudio。

                    【讨论】:

                    • 如果您没有回答实际问题,这可能更适合作为评论。
                    • 同意,但是关于使用注册表有 3 个不同的答案;你建议我对哪个添加评论?
                    • 您可以将其添加到所有 3 个中,但如果超过 3 个,我个人只会选择得分最高的 3 个答案。如果您被允许编辑答案,您甚至可以将其添加进去。您也可以将其作为评论添加到原始问题中,但答案是最好的位置。
                    【解决方案14】:

                    没有环境设置吗?

                    我有 VCToolkitInstallDirVS71COMNTOOLS 虽然我使用的是 Visual Studio 2003,但我不知道以后的版本是否会改变。在命令行输入“set V”,看看有没有。

                    【讨论】:

                      【解决方案15】:

                      这是我多年来一直在更新的内容...(用于 CudaPAD)

                      用法示例:

                      var vsPath = VS_Tools.GetVSPath(avoidPrereleases:true, requiredWorkload:"NativeDesktop");
                      var vsPath = VS_Tools.GetVSPath();
                      var vsPath = VS_Tools.GetVSPath(specificVersion:"15");
                      

                      插件功能:

                      using System;
                      using System.Collections.Generic;
                      using System.Linq;
                      using Microsoft.VisualStudio.Setup.Configuration;
                      using System.IO;
                      using Microsoft.Win32;
                      
                      static class VS_Tools
                      {
                          public static string GetVSPath(string specificVersion = "", bool avoidPrereleases = true, string requiredWorkload = "")
                          {
                              string vsPath = "";
                              // Method 1 - use "Microsoft.VisualStudio.Setup.Configuration.SetupConfiguration" method.
                      
                              // Note: This code has is a heavily modified version of Heath Stewart's code.
                              // original source: (Heath Stewart, May 2016) https://github.com/microsoft/vs-setup-samples/blob/80426ad4ba10b7901c69ac0fc914317eb65deabf/Setup.Configuration.CS/Program.cs
                              try
                              {
                                  var e = new SetupConfiguration().EnumAllInstances();
                      
                                  int fetched;
                                  var instances = new ISetupInstance[1];
                                  do
                                  {
                                      e.Next(1, instances, out fetched);
                                      if (fetched > 0)
                                      {
                                          var instance2 = (ISetupInstance2)instances[0];
                                          var state = instance2.GetState();
                      
                                          // Let's make sure this install is complete.
                                          if (state != InstanceState.Complete)
                                              continue;
                      
                                          // If we have a version to match lets make sure to match it.
                                          if (!string.IsNullOrWhiteSpace(specificVersion))
                                              if (!instances[0].GetInstallationVersion().StartsWith(specificVersion))
                                                  continue;
                      
                                          // If instances[0] is null then skip
                                          var catalog = instances[0] as ISetupInstanceCatalog;
                                          if (catalog == null)
                                              continue;
                      
                                          // If there is not installation path lets skip
                                          if ((state & InstanceState.Local) != InstanceState.Local)
                                              continue;
                      
                                          // Let's make sure it has the required workload - if one was given.
                                          if (!string.IsNullOrWhiteSpace(requiredWorkload))
                                          {
                                              if ((state & InstanceState.Registered) == InstanceState.Registered)
                                              {
                                                  if (!(from package in instance2.GetPackages()
                                                          where string.Equals(package.GetType(), "Workload", StringComparison.OrdinalIgnoreCase)
                                                          where package.GetId().Contains(requiredWorkload)
                                                          orderby package.GetId()
                                                          select package).Any())
                                                  {
                                                      continue;
                                                  }
                                              }
                                              else
                                              {
                                                  continue;
                                              }
                                          }
                      
                                          // Let's save the installation path and make sure it has a value.
                                          vsPath = instance2.GetInstallationPath();
                                          if (string.IsNullOrWhiteSpace(vsPath))
                                              continue;
                      
                                          // If specified, avoid Pre-release if possible
                                          if (avoidPrereleases && catalog.IsPrerelease())
                                              continue;
                      
                                          // We found the one we need - lets get out of here
                                          return vsPath;
                                      }
                                  }
                                  while (fetched > 0);
                              }
                              catch (Exception){ }
                      
                              if (string.IsNullOrWhiteSpace(vsPath))
                                  return vsPath;
                      
                              // Fall-back Method: Find the location of visual studio (%VS90COMNTOOLS%\..\..\vc\vcvarsall.bat)
                              // Note: This code has is a heavily modified version of Kevin Kibler's code.
                              // source: (Kevin Kibler, 2014) http://stackoverflow.com/questions/30504/programmatically-retrieve-visual-studio-install-directory
                              List<Version> vsVersions = new List<Version>() { new Version("15.0"), new Version("14.0"),
                                  new Version("13.0"), new Version("12.0"), new Version("11.0") };
                              foreach (var version in vsVersions)
                              {
                                  foreach (var isExpress in new bool[] { false, true })
                                  {
                                      RegistryKey registryBase32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);
                                      RegistryKey vsVersionRegistryKey = registryBase32.OpenSubKey(
                                          string.Format(@"{0}\{1}.{2}",
                                          (isExpress) ? @"SOFTWARE\Microsoft\VCSExpress" : @"SOFTWARE\Microsoft\VisualStudio",
                                          version.Major, version.Minor));
                                      if (vsVersionRegistryKey == null) { continue; }
                                      string path = vsVersionRegistryKey.GetValue("InstallDir", string.Empty).ToString();
                                      if (!string.IsNullOrEmpty(path))
                                      {
                                          path = Directory.GetParent(path).Parent.Parent.FullName;
                                          if (File.Exists(path + @"\VC\bin\cl.exe") && File.Exists(path + @"\VC\vcvarsall.bat"))
                                          {
                                              vsPath = path;
                                              break;
                                          }
                                      }
                                  }
                                  if (!string.IsNullOrWhiteSpace(vsPath))
                                      break;
                              }
                              return vsPath;
                          }
                      }
                      

                      【讨论】:

                        【解决方案16】:

                        这是我提供的最简单的解决方案。它适用于 x86 和 x64,无论 VS 版本如何: 采用 Environment.GetEnvironmentVariable("VSAPPIDDIR") 获取IDE文件夹,如: "C:\Program Files\Microsoft Visual Studio\2019\Community\Common7\IDE\" 在 x86 机器上。

                        您可以使用它转到您想要的任何其他目录,例如:

                        Dim x = Environment.GetEnvironmentVariable("VSAPPIDDIR").Trim("\"c, "/"c)
                        x = System.IO.Path.GetDirectoryName(x)
                        Dim XsdFile = IO.Path.Combine(x, "Packages\Schemas\html\html_5.xsd")
                        

                        在 x64 机器中 XsdFile 将引用: "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Packages\Schemas\html\html_5.xsd"

                        注意:这似乎仅适用于社区版!

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 1970-01-01
                          • 2017-04-27
                          • 2011-09-28
                          • 1970-01-01
                          • 2011-07-02
                          • 2023-04-07
                          • 2012-02-06
                          • 1970-01-01
                          相关资源
                          最近更新 更多