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

时间:2013-03-20 12:55:54

标签: c# .net windows registry controlpanel

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

所以我用过:

  1. WMI Win32_Product课程。它只显示安装了msi的程序。
  2. 注册表项。 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall。同样,某些程序不会显示在控制面板中,某些程序显示在控制面板中而不是此注册表节点中。
  3. 那么,这个世界上是否有人知道哪种算法使用控制面板来显示已安装的程序?

    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); }

4 个答案:

答案 0 :(得分:26)

好的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); } }

答案 1 :(得分: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#开始,所以我不知道如何循环遍历所有四个注册位置,所以我有两个循环(一个用于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
}

答案 2 :(得分:2)

MelnikovI的回答足以满足大多数目的 - 我的列表中有144个项目,而程序和功能中有143个项目。 要进行审核,他的解决方案是点击这些注册表位置:

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

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

  • DisplayName REG_SZ值

并且不得:

  • SystemComponent 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安装,应从显示中排除。

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

答案 3 :(得分:0)

此处在其他几个答案中讨论过的SystemComponent注册表项通常是 REG_DWORD,其可能值为0或1。但是,我看到了几个实例(例如Microsoft Visio 2010和Microsoft Project) 2010),其中SystemComponent是没有数据的REG_SZ。因此,在这种情况下,任何将SystemComponent强制转换为int的解决方案都可能引发异常。