C#:如何让安装程序完全像在控制面板程序和功能?(C#: How to get installing

2019-07-22 03:42发布

我读了很多的获取程序的信息。 算法并没有做我想做的。 我需要安装的程序完全一样的控制面板。

所以我用:

  1. WMI Win32_Product类。 这表明只有MSI安装程序。
  2. 注册表项。 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall 。 此外,某些程序不能在控制面板中显示,有些程序在此注册表节点显示在控制面板中没有。

那么,有没有人在这个世界上,谁知道哪种算法使用控制面板显示已安装的程序?

UPD1:是的,我用64位的,我知道有64位安装的程序 “HKLM \ SOFTWARE \ Wow6432Node \微软\的Windows \ CurrentVersion \卸载” 的另一个节点,但下面的代码枚举twise HKLM \ SOFTWARE \ Wow6432Node \微软\的Windows \ CURRENTVERSION \卸载部分,奇怪...

  VAR程序=新名单();      串registry_key = @ “SOFTWARE \微软\的Windows \ CurrentVersion \卸载”;      使用(Microsoft.Win32.RegistryKey键= Registry.LocalMachine.OpenSubKey(registry_key))      {          的foreach(在key.GetSubKeyNames串subkey_name())          {              使用(的RegistryKey子项= key.OpenSubKey(subkey_name))              {                  变种名称=(字符串)subkey.GetValue( “显示名称”);                  如果(!string.IsNullOrEmpty(名称))                  {                      programs.Add(名称);                  }              }          }      } 

registry_key = @"SOFTWARE\Wow6432Node\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)) { var name = (string)subkey.GetValue("DisplayName"); if (!string.IsNullOrEmpty(name)) { programs.Add(name); } } } } foreach (var program in programs.OrderBy(x => x)) { Console.WriteLine(program); }

Answer 1:

好吧gyus,我写道,可以获取安装从注册表程序,而无需修补程序和更新类。 它仍然是不完全一样的控制面板,但差不多 。 我希望这可以帮助别人。

  公共静态类InstalledPrograms  {      常量字符串registry_key = @ “SOFTWARE \微软\的Windows \ CurrentVersion \卸载”; 

public static List<string> GetInstalledPrograms() { var result = new List<string>(); result.AddRange(GetInstalledProgramsFromRegistry(RegistryView.Registry32)); result.AddRange(GetInstalledProgramsFromRegistry(RegistryView.Registry64)); return result; } private static IEnumerable<string> GetInstalledProgramsFromRegistry(RegistryView registryView) { var result = new List<string>(); using (RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, registryView).OpenSubKey(registry_key)) { foreach (string subkey_name in key.GetSubKeyNames()) { using (RegistryKey subkey = key.OpenSubKey(subkey_name)) { if(IsProgramVisible(subkey)) { result.Add((string)subkey.GetValue("DisplayName")); } } } } return result; } private static bool IsProgramVisible(RegistryKey subkey) { var name = (string)subkey.GetValue("DisplayName"); var releaseType = (string)subkey.GetValue("ReleaseType"); //var unistallString = (string)subkey.GetValue("UninstallString"); var systemComponent = subkey.GetValue("SystemComponent"); var parentName = (string)subkey.GetValue("ParentDisplayName"); return !string.IsNullOrEmpty(name) && string.IsNullOrEmpty(releaseType) && string.IsNullOrEmpty(parentName) && (systemComponent == null); } }



Answer 2:

我把那MelnikovI写道(这是超级有用),并增加了两件事情的代码。 首先,它搜索注册表中的四个地方:

HKLM \ SOFTWARE \微软\的Windows \ CurrentVersion \卸载

HKLM \ SOFTWARE \ Wow6432Node \微软\的Windows \ CurrentVersion \卸载

HKCU \ SOFTWARE \微软\的Windows \ CurrentVersion \卸载

HKCU \ SOFTWARE \ Wow6432Node \微软\的Windows \ CurrentVersion \卸载

它还检查,看看是否有任何子项 - 如果不是它跳过一个。

最后,它正则表达式,仅允许一组特定的字符[^ A-ZA-Z0-9()+ - 。]。

我只是从C开始#,所以我不知道的方式通过所有四个REG位置环,所以我有两个循环(一个用于HKLM,一个用于HKCU)。

public static class InstalledPrograms
    {
      public static List<string> GetInstalledPrograms()
        {
            var result = new List<string>();
            result.AddRange(GetInstalledProgramsFromRegistry(RegistryView.Registry32));
            result.AddRange(GetInstalledProgramsFromRegistry(RegistryView.Registry64));
            result.Sort();
            return result;
        }
        private static string cleanText(string dirtyText)
        {
            Regex rgx = new Regex("[^a-zA-Z0-9 .()+-]");
            string result = rgx.Replace(dirtyText, "");
            return result;
        }
        private static IEnumerable<string> GetInstalledProgramsFromRegistry(RegistryView registryView)
        {
            var result = new List<string>();
            List<string> uninstall = new List<string>();
            uninstall.Add(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
            uninstall.Add(@"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall");
            foreach (string registry_key in uninstall)
            {
               using (RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, registryView).OpenSubKey(registry_key))
               {
                    foreach (string subkey_name in key.GetSubKeyNames())
                    {
                        using (RegistryKey subkey = key.OpenSubKey(subkey_name))
                        {
                            if (IsProgramVisible(subkey))
                            {
                                result.Add(cleanText(subkey.GetValue("DisplayName").ToString()).ToString());
                            }
                        }
                    }
                }
                using (RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, registryView).OpenSubKey(registry_key))
                {
                    if (key != null)
                    {
                        foreach (string subkey_name in key.GetSubKeyNames())
                        {
                            using (RegistryKey subkey = key.OpenSubKey(subkey_name))
                            {
                                if (IsProgramVisible(subkey))
                                {
                                    result.Add(cleanText(subkey.GetValue("DisplayName").ToString()).ToString());
                                }
                            }
                        }
                    }
                }
            }

            return result;
        }

如果有人有兴趣,我比我一直在使用的结果到PowerShell和他们是一样的。

##Get list of Add/Remove programs
if (!([Diagnostics.Process]::GetCurrentProcess().Path -match '\\syswow64\\'))
{
$uninstallPath = "\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"
$uninstallWow6432Path = "\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\"
@(
if (Test-Path "HKLM:$uninstallWow6432Path" ) { Get-ChildItem "HKLM:$uninstallWow6432Path"}
if (Test-Path "HKLM:$uninstallPath" ) { Get-ChildItem "HKLM:$uninstallPath" }
if (Test-Path "HKCU:$uninstallWow6432Path") { Get-ChildItem "HKCU:$uninstallWow6432Path"}
if (Test-Path "HKCU:$uninstallPath" ) { Get-ChildItem "HKCU:$uninstallPath" }
) |
ForEach-Object { Get-ItemProperty $_.PSPath } |
Where-Object {
$_.DisplayName -and !$_.SystemComponent -and !$_.ReleaseType -and !$_.ParentKeyName -and ($_.UninstallString -or $_.NoRemove)
} |
Sort-Object DisplayName |
Select-Object DisplayName
}
else
{
"You are running 32-bit Powershell on 64-bit system. Please run 64-bit Powershell instead." | Write-Host -ForegroundColor Red
}


Answer 3:

MelnikovI的答案是足以满足大多数的目的 - 我在我的名单VS在程序和功能143有144项。 审查 ,他的解决办法是打这些注册表位置:

  • HKLM \ SOFTWARE \微软\的Windows \ CurrentVersion \卸载
  • HKCU \软件\微软\的Windows \ CurrentVersion \卸载
  • HKLM \ SOFTWARE \ Wow6432Node \微软\的Windows \ CurrentVersion \卸载

要获得资格,每个子项必须具备:

  • 显示名称REG_SZ值

且不得有:

  • 所述SystemComponent REG_DWORD(非零)
  • 该ParentKeyName或ParentDisplayName REG_SZ值
  • 该ReleaseType REG_SZ值

一个addtional增强我发现是Windows安装程序项,定义为:

  • 键名是一个标准的GUID字符串
  • 该WindowsInstaller REG_DWORD存在(和非零)

对于这样的项目,您可以使用从MSI.DLL Win32函数MsiGetProductInfoW,并要求由键所代表的GUID的“VERSIONSTRING”属性的额外步骤。

如果这个函数返回1605:ERROR_UNKNOWN_PRODUCT,这意味着该条目不按照Windows安装程序安装,并应显示被排除在外。

实施这一小调整之后,我的名单现在相同的程序和功能。



Answer 4:

在其他几个答案在这里讨论的SystemComponent注册表项通常是0或1。然而可能值的REG_DWORD,我看到一对夫妇的实例(如微软的Visio 2010和Microsoft Project 2010),其中SystemComponent是REG_SZ没有数据。 这蒙上SystemComponent为int的任何解决方案因此容易抛出一个异常,在这些情况下。



文章来源: C#: How to get installing programs exactly like in control panel programs and features?