C# 在系统中获取已安装的应用程序

C# 在系统中获取已安装的应用程序,c#,.net,installation,C#,.net,Installation,如何使用c代码在系统中安装应用程序?您最好的选择是使用。特别是类。遍历“HKEY\U LOCAL\U MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall”键并检查其“DisplayName”值。您可以查看。它利用注册表读取已安装应用程序的列表 public void GetInstalledApps() { string uninstallKey = @"SOFTWARE\Microsoft\Windows\Curren

如何使用c代码在系统中安装应用程序?

您最好的选择是使用。特别是类。

遍历“HKEY\U LOCAL\U MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall”键并检查其“DisplayName”值。

您可以查看。它利用注册表读取已安装应用程序的列表

public void GetInstalledApps()
{
    string uninstallKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
    using (RegistryKey rk = Registry.LocalMachine.OpenSubKey(uninstallKey))
    {
        foreach (string skName in rk.GetSubKeyNames())
        {
            using (RegistryKey sk = rk.OpenSubKey(skName))
            {
                try
                {
                    lstInstalled.Items.Add(sk.GetValue("DisplayName"));
                }
                catch (Exception ex)
                { }
            }
        }
    }
}

我建议您看看WMI()。 如果将System.Management引用添加到C#项目中,您将获得对“ManagementObjectSearcher”类的访问权限,您可能会发现该类很有用

有各种各样的WMI类,但是如果它是与Windows Installer一起安装的,那么Win32_产品类可能最适合您

ManagementObjectSearcher s = new ManagementObjectSearcher("SELECT * FROM Win32_Product");

遍历注册表项“SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall”似乎可以提供已安装应用程序的全面列表

public void GetInstalledApps()
{
    string uninstallKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
    using (RegistryKey rk = Registry.LocalMachine.OpenSubKey(uninstallKey))
    {
        foreach (string skName in rk.GetSubKeyNames())
        {
            using (RegistryKey sk = rk.OpenSubKey(skName))
            {
                try
                {
                    lstInstalled.Items.Add(sk.GetValue("DisplayName"));
                }
                catch (Exception ex)
                { }
            }
        }
    }
}
除了下面的例子之外,你可以找到一个与我所做的类似的版本

这是一个粗略的示例,您可能想做一些事情来去掉空行,如提供的第二个链接中所示

string registry_key = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
using(Microsoft.Win32.RegistryKey key = Registry.LocalMachine.OpenSubKey(registry_key))
{
    foreach(string subkey_name in key.GetSubKeyNames())
    {
        using(RegistryKey subkey = key.OpenSubKey(subkey_name))
        {
            Console.WriteLine(subkey.GetValue("DisplayName"));
        }
    }
}
或者,您可以使用WMI,如上所述:

ManagementObjectSearcher mos = new ManagementObjectSearcher("SELECT * FROM Win32_Product");
foreach(ManagementObject mo in mos.Get())
{
    Console.WriteLine(mo["Name"]);
}

但这执行起来相当慢,我听说它可能只列出在“ALLUSERS”下安装的程序,尽管这可能是不正确的。它还会忽略Windows组件和更新,这对您可能很方便。

使用Windows Installer API


它允许对所有程序进行可靠的枚举。注册表不可靠,但WMI是重量级的。

我使用了Nicks方法-我需要检查是否安装了Visual Studio的远程工具,这似乎有点慢,但在单独的线程中,这对我来说是好的。-下面是我的扩展代码:

    private bool isRdInstalled() {
        ManagementObjectSearcher p = new ManagementObjectSearcher("SELECT * FROM Win32_Product");
        foreach (ManagementObject program in p.Get()) {
            if (program != null && program.GetPropertyValue("Name") != null && program.GetPropertyValue("Name").ToString().Contains("Microsoft Visual Studio 2012 Remote Debugger")) {
                return true;
            }
            if (program != null && program.GetPropertyValue("Name") != null) {
                Trace.WriteLine(program.GetPropertyValue("Name"));
            }
        }
        return false;
    }

值得注意的是,Win32_Product WMI类表示由安装的产品。并非所有应用程序都使用windows installer

但是,“SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall”表示32位的应用程序。对于64位,您还需要遍历“HKEY\U LOCAL\U MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall”,并且由于并非每个软件都有64位版本,因此安装的所有应用程序都是两个位置上具有“UninstallString”值的键的并集

但最好的选择仍然是一样的。遍历注册表项是一种更好的方法,因为每个应用程序在注册表中都有一个条目[包括Windows Installer中的条目]。但是,注册表方法是不安全的,因为如果有人删除了相应的项,则您将不知道应用程序项。相反,更改HKEY_Classes_ROOT\Installer更为棘手,因为它与许可问题(如Microsoft office或其他产品)有关。
要获得更健壮的解决方案,您可以始终将注册表替代方案与WMI结合起来。

我同意通过注册表项枚举是最好的方法

注意,但是,给定的键“SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall”将列出32位Windows安装中的所有应用程序,以及64位Windows安装中的64位应用程序


为了查看Windows 64位安装上安装的32位应用程序,您还需要枚举键“SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall”

我的要求是检查我的系统中是否安装了特定的软件。此解决方案按预期工作。这可能对你有帮助。我在visual studio 2015中使用了c#中的windows应用程序

 private void Form1_Load(object sender, EventArgs e)
        {

            object line;
            string softwareinstallpath = string.Empty;
            string registry_key = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
            using (var baseKey = Microsoft.Win32.RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
            {
                using (var key = baseKey.OpenSubKey(registry_key))
                {
                    foreach (string subkey_name in key.GetSubKeyNames())
                    {
                        using (var subKey = key.OpenSubKey(subkey_name))
                        {
                            line = subKey.GetValue("DisplayName");
                            if (line != null && (line.ToString().ToUpper().Contains("SPARK")))
                            {

                                softwareinstallpath = subKey.GetValue("InstallLocation").ToString();
                                listBox1.Items.Add(subKey.GetValue("InstallLocation"));
                                break;
                            }
                        }
                    }
                }
            }

            if(softwareinstallpath.Equals(string.Empty))
            {
                MessageBox.Show("The Mirth connect software not installed in this system.")
            }



            string targetPath = softwareinstallpath + @"\custom-lib\";
            string[] files = System.IO.Directory.GetFiles(@"D:\BaseFiles");

            // Copy the files and overwrite destination files if they already exist. 
            foreach (var item in files)
            {
                string srcfilepath = item;
                string fileName = System.IO.Path.GetFileName(item);
                System.IO.File.Copy(srcfilepath, targetPath + fileName, true);
            }
            return;

        }

我希望能够提取应用程序列表,就像它们出现在“开始”菜单中一样。使用注册表,我得到的条目不会显示在“开始”菜单中

我还想找到exe路径并提取一个图标,最终制作一个漂亮的启动器。不幸的是,对于registry方法,这是一种偶然的结果,因为根据我的观察,这些信息不可靠

我的备选方案是基于shell:AppsFolder,您可以通过运行
explorer.exe来访问该shell:AppsFolder
,它列出了当前安装并通过“开始”菜单可用的所有应用程序,包括商店应用程序。问题是这是一个虚拟文件夹,无法使用
System.IO.Directory
访问。相反,您必须使用本机shell32命令。幸运的是,微软发布了Nuget,它是上述命令的包装器。说得够多了,下面是代码:

// GUID taken from https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid
var FOLDERID_AppsFolder = new Guid("{1e87508d-89c2-42f0-8a7e-645a0f50ca58}");
ShellObject appsFolder = (ShellObject)KnownFolderHelper.FromKnownFolderId(FOLDERID_AppsFolder);

foreach (var app in (IKnownFolder)appsFolder)
{
    // The friendly app name
    string name = app.Name;
    // The ParsingName property is the AppUserModelID
    string appUserModelID = app.ParsingName; // or app.Properties.System.AppUserModel.ID
    // You can even get the Jumbo icon in one shot
    ImageSource icon =  app.Thumbnail.ExtraLargeBitmapSource;
}
List<string> installs = new List<string>();
List<string> keys = new List<string>() {
  @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
  @"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
};

// The RegistryView.Registry64 forces the application to open the registry as x64 even if the application is compiled as x86 
FindInstalls(RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64), keys, installs);
FindInstalls(RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64), keys, installs);

installs = installs.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().ToList();
installs.Sort(); // The list of ALL installed applications



private void FindInstalls(RegistryKey regKey, List<string> keys, List<string> installed)
{
  foreach (string key in keys)
  {
    using (RegistryKey rk = regKey.OpenSubKey(key))
    {
      if (rk == null)
      {
        continue;
      }
      foreach (string skName in rk.GetSubKeyNames())
      {
        using (RegistryKey sk = rk.OpenSubKey(skName))
        {
          try
          {
            installed.Add(Convert.ToString(sk.GetValue("DisplayName")));
          }
          catch (Exception ex)
          { }
        }
      }
    }
  }
}
这就是全部。您还可以使用启动应用程序

System.Diagnostics.Process.Start("explorer.exe", @" shell:appsFolder\" + appModelUserID);
这适用于常规Win32应用程序和UWP应用商店应用程序。苹果怎么样

由于您对列出所有已安装的应用程序感兴趣,因此有理由认为您可能希望监视新的应用程序或已卸载的应用程序,您可以使用
ShellObjectWatcher

ShellObjectWatcher sow = new ShellObjectWatcher(appsFolder, false);
sow.AllEvents += (s, e) => DoWhatever();
sow.Start();

编辑:您可能还想知道上面提到的AppUserMoedId是。

虽然接受的解决方案有效,但它并不完整。到目前为止

如果您想获得所有钥匙,还需要考虑两件事:

x86和x64应用程序无权访问同一注册表。 基本上x86无法正常访问x64注册表。还有一些 应用程序仅注册到x64注册表

有些应用程序实际上安装到CurrentUser注册表中,而不是本地计算机

考虑到这一点,我设法使用以下代码获取所有已安装的应用程序,而不使用WMI

代码如下:

// GUID taken from https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid
var FOLDERID_AppsFolder = new Guid("{1e87508d-89c2-42f0-8a7e-645a0f50ca58}");
ShellObject appsFolder = (ShellObject)KnownFolderHelper.FromKnownFolderId(FOLDERID_AppsFolder);

foreach (var app in (IKnownFolder)appsFolder)
{
    // The friendly app name
    string name = app.Name;
    // The ParsingName property is the AppUserModelID
    string appUserModelID = app.ParsingName; // or app.Properties.System.AppUserModel.ID
    // You can even get the Jumbo icon in one shot
    ImageSource icon =  app.Thumbnail.ExtraLargeBitmapSource;
}
List<string> installs = new List<string>();
List<string> keys = new List<string>() {
  @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
  @"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
};

// The RegistryView.Registry64 forces the application to open the registry as x64 even if the application is compiled as x86 
FindInstalls(RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64), keys, installs);
FindInstalls(RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64), keys, installs);

installs = installs.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().ToList();
installs.Sort(); // The list of ALL installed applications



private void FindInstalls(RegistryKey regKey, List<string> keys, List<string> installed)
{
  foreach (string key in keys)
  {
    using (RegistryKey rk = regKey.OpenSubKey(key))
    {
      if (rk == null)
      {
        continue;
      }
      foreach (string skName in rk.GetSubKeyNames())
      {
        using (RegistryKey sk = rk.OpenSubKey(skName))
        {
          try
          {
            installed.Add(Convert.ToString(sk.GetValue("DisplayName")));
          }
          catch (Exception ex)
          { }
        }
      }
    }
  }
}
List installs=newlist();
列表键=新列表(){
@“软件\Microsoft\Windows\CurrentVersion\Uninstall”,
@“软件\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall”
};
//RegistryView.Registry64强制应用程序以x64的形式打开注册表,即使应用程序编译为x86
FindInstalls(RegistryKey.OpenBaseKey