2013-03-20 19 views
15

Tôi đọc rất nhiều thông tin về việc nhận các chương trình. Không có thuật toán nào làm được những gì tôi muốn. Tôi cần cài đặt các chương trình chính xác như trong bảng điều khiển.C#: Làm cách nào để cài đặt chương trình giống hệt như chương trình và tính năng của bảng điều khiển?

Vì vậy, tôi đã sử dụng:

  1. WMI Win32_Product lớp. Nó chỉ hiển thị các chương trình được cài đặt msi.
  2. Khóa đăng ký. HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall. Một lần nữa, một số chương trình không được hiển thị trong bảng điều khiển, một số chương trình được hiển thị trong bảng điều khiển không có trong nút đăng ký này.

Vậy, có ai trong thế giới này, ai biết thuật toán nào sử dụng bảng điều khiển để hiển thị các chương trình đã cài đặt?

UPD1: vâng, tôi sử dụng 64 bit, tôi biết có một nút khác cho các chương trình được cài đặt 64 bit "HKLM \ SOFTWARE \ Wow6432Node \ Microsoft \ Windows \ CurrentVersion \ Uninstall" nhưng mã sau liệt kê twLM HKLM \ SOFTWARE \ Wow6432Node \ Microsoft \ Windows \ CurrentVersion \ Uninstall phần, kỳ lạ ...

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

+1

'HKLM \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall' nên thực hiện. Bạn có thể đưa ra một ví dụ về một chương trình xuất hiện trong Control Panel nhưng không xuất hiện trong khóa reg này? – Jonathan

+0

bạn có đang sử dụng máy 64 bit không? –

+0

tôi cập nhật chủ đề, mã sau đây không hiển thị cho tôi chương trình winrar mà nằm trong nút SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall – MelnikovI

Trả lời

25

gyus Ok, tôi đã viết lớp đó có thể nhận được các chương trình từ đăng ký cài đặt mà không hotfix và cập nhật. Nó vẫn là không chính xác như trong bảng điều khiển nhưng gần như. Tôi hy vọng điều này sẽ giúp bất cứ ai khác.

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

+0

Cảm ơn bạn! rất hữu ích! – elady

+0

lớp rất thanh lịch. Đối với tôi nó đã cho một mục nhập autodesk thêm và bỏ lỡ 6 trong số 8 mục nvidia cho thấy trong Chương trình và tính năng. Nếu tôi tìm hiểu lý do tôi sẽ đăng lại tại đây. – sdjuan

+2

Tôi thấy rằng nếu tôi thay đổi dòng cuối cùng của phương pháp IsProgramVisible (RegistryKey subkey) từ: && (systemComponent == null) thành: && (systemComponent == null || (int) systemComponent == 0); sau đó nó phù hợp hoàn hảo với những gì tôi thấy trong các chương trình trong các tính năng, đó là, bây giờ tôi có thể nhìn thấy các chương trình trình điều khiển NVIDIA và các tính năng mục. – sdjuan

2

Tôi mất mã mà MelnikovI viết (mà là siêu hữu ích) và bổ sung thêm một vài điều. Đầu tiên, nó tìm kiếm bốn nơi trong registry:

HKLM \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall

HKLM \ SOFTWARE \ Wow6432Node \ Microsoft \ Windows \ CurrentVersion \ Uninstall

HKCU \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall

HKCU \ SOFTWARE \ Wow6432Node \ Microsoft \ Windows \ CurrentVersion \ Uninstall

nó cũng kiểm tra để xem nếu có bất kỳ khóa con - nếu không muốn nói nó bỏ qua mà một.

Cuối cùng, nó thực hiện một regex để chỉ cho phép một nhóm ký tự nhất định [^ a-zA-Z0-9.() + -].

Tôi chỉ bắt đầu từ C#, vì vậy tôi không biết cách lặp qua tất cả bốn vị trí reg, vì vậy tôi có hai vòng lặp (một cho HKLM và một cho 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; 
     } 

Nếu có ai quan tâm, tôi đã so sánh kết quả với PowerShell mà tôi đang sử dụng và chúng giống nhau.

##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 
} 
+0

Bạn đang trên đường đua cứng nhắc nhưng bạn nên lok vào RegistryView như sử dụng đường dẫn wow6432Node trên một hệ thống 64-bit không trả lại những gì bạn nghĩ rằng nó có thể. Tôi thấy rằng nếu bạn sử dụng một đường dẫn như SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall với Registry32 sẽ trả về PHẦN MỀM \ Wowo6432Node \ Microsoft \ Windows \ CurrentVersion \ Uninstall và khi bạn sử dụng cùng một đường dẫn chính xác với Registry64, nó trả vềSOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall – sdjuan

2

Câu trả lời của MelnikovI đủ cho hầu hết các mục đích - Tôi có 144 mục trong danh sách của tôi so với 143 trong Chương trình và tính năng.Đối với xét, giải pháp của ông là để đạt các địa điểm đăng ký:

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

Để hội đủ điều kiện, mỗi khóa pHẢI có:

    012 giá trị
  • Các DisplayName REG_SZ

Và PHẢI KHÔNG có:

  • Các SystemComponent REG_DWORD (non-zero)
  • Các ParentKeyName hoặc ParentDisplayName REG_SZ giá trị
  • Giá trị ReleaseType REG_SZ

một phụ kiện nâng cao tôi đã tìm thấy là dành cho mục Windows Installer, định nghĩa là:

  • Tên khoá là một GUID chuỗi tiêu chuẩn
  • Các WindowsInstaller REG_DWORD có mặt (và non-zero)

Đối với mục như vậy , bạn có thể thực hiện thêm bước sử dụng hàm Win32 MsiGetProductInfoW từ msi.dll và yêu cầu thuộc tính "VersionString" cho GUID được biểu thị bằng khóa.

Nếu hàm này trả về 1605: ERROR_UNKNOWN_PRODUCT, điều đó có nghĩa là mục nhập không được cài đặt theo Trình cài đặt Windows và phải được loại trừ khỏi màn hình.

Sau khi triển khai tinh chỉnh nhỏ này, danh sách của tôi giờ đã giống với Chương trình và Tính năng.

Các vấn đề liên quan