C#:如何在控制面板程序和功能中完全安装程序?

Mel*_*ovI 17 .net c# windows registry controlpanel

我读了很多关于获取程序的信息.算法没有做我想做的事.我需要完全像控制面板中那样安装程序.

所以我用过:

  1. WMI Win32_Product类.它只显示msi安装的程序.
  2. 注册表项.HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall.同样,某些程序不会显示在控制面板中,某些程序显示在控制面板中而不是此注册表节点中.

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

UPD1:是的,我使用64位,我知道64位已安装的程序"HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"还有另一个节点,但以下代码列举了twise HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion \卸载部分,很奇怪......

var programs = new List();
    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))
            {
                var name = (string)subkey.GetValue("DisplayName");
                if(!string.IsNullOrEmpty(name))
                {
                    programs.Add(name);
                }
            }
        }
    }

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); }
Run Code Online (Sandbox Code Playgroud)

Mel*_*ovI 28

好的gyus,我写的类可以从注册表安装程序没有修补程序和更新.它仍然是不完全一样的控制面板,但几乎.我希望这有助于其他任何人.

public static class InstalledPrograms
{
    const string registry_key = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";

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); } }
Run Code Online (Sandbox Code Playgroud)

  • 我发现如果我将方法IsProgramVisible(RegistryKey子键)的最后一行从:&&(systemComponent == null)更改为:&&(systemComponent == null ||(int)systemComponent == 0); 然后它与我在功能程序中看到的完全匹配,也就是说,我现在可以看到NVIDIA驱动程序和功能条目. (3认同)

小智 5

MelnikovI 的答案足以满足大多数目的 - 我的列表中有 144 项,而程序和功能中有 143 项。 为了进行审查,他的解决方案是访问这些注册表位置:

  • HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall
  • HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall
  • HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall

为了符合资格,每个子项必须具有:

  • DisplayName REG_SZ 值

并且不得有:

  • 系统组件 REG_DWORD(非零)
  • ParentKeyName 或 ParentDisplayName REG_SZ 值
  • ReleaseType REG_SZ 值

我发现的一项附加增强功能是针对 Windows Installer 条目,定义为

  • 键名是标准 GUID 字符串
  • WindowsInstaller REG_DWORD 存在(且非零)

对于此类条目,您可以采取额外的步骤,使用msi.dll中的Win32 函数MsiGetProductInfoW,并请求密钥表示的 GUID 的“VersionString”属性。

如果此函数返回1605: ERROR_UNKNOWN_PRODUCT,则意味着该条目未根据 Windows Installer 安装,应从显示中排除。

实施这个小调整后,我的列表现在与程序和功能相同。