Nhận các ứng dụng đã cài đặt trong hệ thống


83

Làm cách nào để cài đặt các ứng dụng trong hệ thống bằng mã c #?

Câu trả lời:


115

Lặp lại thông qua khóa đăng ký "SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall" dường như cung cấp một danh sách đầy đủ các ứng dụng đã cài đặt.

Ngoài ví dụ bên dưới, bạn có thể tìm thấy một phiên bản tương tự như những gì tôi đã làm ở đây .

Đây là một ví dụ sơ bộ, bạn sẽ muốn làm gì đó để loại bỏ các hàng trống như trong liên kết thứ 2 được cung cấp.

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

Ngoài ra, bạn có thể sử dụng WMI như đã được đề cập:

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

Nhưng điều này khá chậm hơn để thực thi và tôi đã nghe nói rằng nó có thể chỉ liệt kê các chương trình được cài đặt trong "ALLUSERS", mặc dù điều đó có thể không chính xác. Nó cũng bỏ qua các thành phần và cập nhật Windows, có thể hữu ích cho bạn.


27
Cần lưu ý rằng sử dụng lớp WMI Win32_Product là một ý tưởng tồi nếu bạn định chạy truy vấn này nhiều lần. Xem bài viết Microsoft KB này: support.microsoft.com/kb/974524/EN-US Vấn đề cốt lõi là (a) Win32_Product thực sự chậm và (b) nó tạo ra "Windows Installer đã cấu hình lại sản phẩm." thông báo nhật ký sự kiện cho mọi sản phẩm được cài đặt trên hệ thống của bạn ... mỗi khi bạn chạy truy vấn. Doh! Bài viết này khuyến nghị sử dụng lớp Win32reg_AddRemovePrograms ... lớp này không có trừ khi bạn đã cài đặt SMS. Doh! Vì vậy, có lẽ tốt hơn nên gắn bó với truy vấn đăng ký.
Simon Gillbee

Nhận xét của Simon Gillbee nên là câu trả lời được chấp nhận, hoặc Kirtans! WMI WIN32_Sản phẩm không phải là cách để đi đến đây, hãy tin tôi!
bdd

13
Er, đó là lý do tại sao ví dụ đăng ký đầu tiên trong câu trả lời của tôi. WMI được trình bày đơn giản như một giải pháp thay thế, và thậm chí ở đó tôi nói rằng "điều này khá chậm hơn để thực thi" và các nhược điểm khác. Đọc câu trả lời từ đầu. ;)
Xiaofu

1
Kinda lạ nhưng nếu bạn gỡ bỏ cài đặt một chương trình và cài đặt nó trở lại sau đó cố gắng tìm nó bằng cách sử dụng các khóa registry bạn không thể trừ khi bạn khởi động lại máy tính của bạn
Yar

3
Để trả lời câu hỏi của riêng tôi: stackoverflow.com/questions/27838798/… Mặc dù khó chịu rằng bạn có thể phải truy vấn cả 64bit và 32bit.
Robert Koernke,

9

Bạn có thể xem qua bài viết này . Nó sử dụng registry để đọc danh sách các ứng dụng đã cài đặt.

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

Tôi không muốn toàn bộ danh sách, tôi chỉ cần một số chương trình cài đặt được chọn để tôi có thể làm gì cho điều đó. Cảm ơn bạn
Dhru 'soni

8

Tôi đồng ý rằng liệt kê thông qua khóa đăng ký là cách tốt nhất.

Tuy nhiên, lưu ý rằng khóa được cung cấp, @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"sẽ liệt kê tất cả các ứng dụng trong cài đặt Windows 32 bit và các ứng dụng 64 bit trong cài đặt Windows 64 bit.

Để xem các ứng dụng 32-bit được cài đặt trên bản cài đặt Windows 64-bit, bạn cũng cần phải liệt kê khóa @"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall".


Bạn có chắc về điều này? Trên Windows 10 Enterprise 64bit của tôi, hai danh sách trông giống nhau và các ứng dụng x86 hiển thị trong cả hai.
Florian Straub

Cảm ơn bạn, điều này phù hợp với tôi, tôi đã tìm thấy chương trình mà tôi đã tìm kiếm.
Xtian11

Trong regeditđó có vẻ như vậy. Tuy nhiên, trong chương trình 32 bit (trên Windows 64 bit), cả hai danh sách đều giống với danh sách WOW6432Nodetừ regedit.
Meow Cat 2012

5

Tôi muốn có thể trích xuất danh sách ứng dụng ngay khi chúng xuất hiện trong menu bắt đầu. Sử dụng sổ đăng ký, tôi nhận được các mục nhập không hiển thị trong menu bắt đầu.

Tôi cũng muốn tìm đường dẫn exe và trích xuất một biểu tượng để cuối cùng tạo ra một launcher đẹp mắt. Thật không may, với phương pháp đăng ký, đây là một sự cố và bỏ lỡ vì quan sát của tôi là thông tin này không có sẵn một cách đáng tin cậy.

Giải pháp thay thế của tôi dựa trên shell: AppsFolder mà bạn có thể truy cập bằng cách chạy explorer.exe shell:appsFoldervà liệt kê tất cả các ứng dụng, bao gồm các ứng dụng cửa hàng, hiện đã được cài đặt và có sẵn thông qua menu bắt đầu. Vấn đề là đây là một thư mục ảo không thể truy cập được System.IO.Directory. Thay vào đó, bạn sẽ phải sử dụng các lệnh shell32 bản địa. May mắn thay, Microsoft đã xuất bản Microsoft.WindowsAPICodePack-Shell trên Nuget, một trình bao bọc cho các lệnh nói trên. Nói đủ rồi, đây là mã:

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

Và đó là tất cả những gì cần làm. Bạn cũng có thể khởi động các ứng dụng bằng

System.Diagnostics.Process.Start("explorer.exe", @" shell:appsFolder\" + appModelUserID);

Điều này hoạt động cho các ứng dụng Win32 thông thường và các ứng dụng cửa hàng UWP. Làm thế nào về họ táo.

Vì bạn quan tâm đến việc liệt kê tất cả các ứng dụng đã cài đặt, điều hợp lý là bạn có thể muốn theo dõi các ứng dụng mới hoặc ứng dụng đã gỡ cài đặt, bạn có thể thực hiện bằng cách sử dụng ShellObjectWatcher:

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

Chỉnh sửa: Một người cũng có thể quan tâm đến việc biết rằng AppUserMoedlID được đề cập ở trên là ID duy nhất mà Windows sử dụng để nhóm các cửa sổ trong thanh tác vụ .


Cảm ơn bạn rất nhiều, một cách thực sự tốt để đạt được điều này. Bạn có biết liệu có cách nào để lấy tên, phân tích cú pháp tên hoặc cách khác trực tiếp từ ShellObjectWatcher không?
forlayo

Ngoài ra còn có các loại sự kiện khác AllEventsnhư ItemCreatedhoặc loại sự kiện ItemRenamedmà tôi đã thử sử dụng để theo dõi các ứng dụng khi chúng được cài đặt hoặc gỡ bỏ. Các chuỗi sự kiện của các sự kiện này chứa một thuộc Pathtính nhưng thuộc tính này luôn là null, ít nhất là trong các thử nghiệm của tôi. Tôi không bận tâm khi cố gắng tìm cách lấy tên phân tích cú pháp từ nó vì nó luôn rỗng. Thay vào đó, tôi chỉ cần giữ một danh sách các ứng dụng mà tôi đồng bộ hóa bất cứ khi nào một mục được nâng lên bằng cách lặp lại các ứng dụng trong thư mục. Không lý tưởng nhưng hoàn thành công việc.
user1969903

1
Cảm ơn! Tôi thực sự đang làm như vậy; điều này cũng đã giúp tôi trên quesion khác về "cách khám phá tệp thực thi chính của một ứng dụng vừa được cài đặt" -> stackoverflow.com/questions/60440044/… Sau đó, cảm ơn vì điều đó! :)
forlayo

4

cần lưu ý rằng lớp WMI Win32_Product đại diện cho các sản phẩm khi chúng được cài đặt bởi Windows Installer . không phải mọi ứng dụng đều sử dụng trình cài đặt windows

tuy nhiên "SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall" đại diện cho các ứng dụng cho 32 bit. Đối với 64 bit, bạn cũng cần xem qua "HKEY_LOCAL_MACHINE \ SOFTWARE \ Wow6432Node \ Microsoft \ Windows \ CurrentVersion \ Uninstall" và vì không phải mọi phần mềm đều có phiên bản 64 bit nên tổng số ứng dụng được cài đặt là một tổ hợp khóa trên cả hai vị trí có "UninstallString" Giá trị với họ.

nhưng các tùy chọn tốt nhất vẫn giống nhau. khóa đăng ký chuyển đổi là một cách tiếp cận tốt hơn vì mọi ứng dụng đều có mục nhập trong sổ đăng ký [bao gồm cả những mục trong Windows Installer]. dù phương pháp đăng ký không an toàn vì nếu ai xóa khóa tương ứng thì bạn sẽ không biết Ngược lại, việc thay đổi HKEY_Classes_ROOT \ Installers phức tạp hơn vì nó được liên kết với các vấn đề cấp phép như Microsoft office hoặc các sản phẩm khác. để có giải pháp mạnh mẽ hơn, bạn luôn có thể kết hợp thay thế sổ đăng ký với WMI.


3

Trong khi giải pháp được chấp nhận hoạt động, nó không hoàn chỉnh. Cho đến nay.

Nếu muốn lấy hết chìa khóa, bạn cần lưu ý thêm 2 điều:

Các ứng dụng x86 & x64 không có quyền truy cập vào cùng một sổ đăng ký. Về cơ bản x86 thường không thể truy cập sổ đăng ký x64. Và một số ứng dụng chỉ đăng ký vào sổ đăng ký x64.

một số ứng dụng thực sự cài đặt vào sổ đăng ký CurrentUser thay vì LocalMachine

Với ý nghĩ đó, tôi đã quản lý để tải TẤT CẢ các ứng dụng được cài đặt bằng mã sau đây, KHÔNG sử dụng WMI

Đây là mã:

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

điều này hoạt động chính xác hơn các giải pháp khác.
Vilas Joshi

1

Lặp lại các khóa "HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall" và kiểm tra các giá trị "DisplayName" của chúng.


1

Sử dụng API của trình cài đặt Windows!

Nó cho phép liệt kê đáng tin cậy tất cả các chương trình. Registry không đáng tin cậy, nhưng WMI là nặng.


chắc chắn là trọng lượng nặng - nếu chạy liên tục, người ta sẽ thấy hiệu suất giảm xuống như một trọng lượng nặng. nếu một tính năng của ứng dụng của tôi phụ thuộc vào một ứng dụng khác và biết nếu được cài đặt đúng cách, tôi chỉ cần gỡ cài đặt khóa đăng ký cho 32 hoặc 64 chỉ khi ứng dụng đó cũng có sẵn ở 64 bit) mặt khác nếu tôi phải sử dụng wmi, tôi sẽ giới hạn chỉ sử dụng một lần trong một ứng dụng thông qua một thủ thuật thuộc tính thông minh.
gg89


1

Đối tượng cho danh sách:

public class InstalledProgram
{
    public string DisplayName { get; set; }
    public string Version { get; set; }
    public string InstalledDate { get; set; }
    public string Publisher { get; set; }
    public string UnninstallCommand { get; set; }
    public string ModifyPath { get; set; }
}

Lời kêu gọi tạo danh sách:

    List<InstalledProgram> installedprograms = new List<InstalledProgram>();
    string registry_key = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
    using (RegistryKey key = Registry.LocalMachine.OpenSubKey(registry_key))
    {
        foreach (string subkey_name in key.GetSubKeyNames())
        {
            using (RegistryKey subkey = key.OpenSubKey(subkey_name))
            {
                if (subkey.GetValue("DisplayName") != null)
                {
                    installedprograms.Add(new InstalledProgram
                    {
                        DisplayName = (string)subkey.GetValue("DisplayName"),
                        Version = (string)subkey.GetValue("DisplayVersion"),
                        InstalledDate = (string)subkey.GetValue("InstallDate"),
                        Publisher = (string)subkey.GetValue("Publisher"),
                        UnninstallCommand = (string)subkey.GetValue("UninstallString"),
                        ModifyPath = (string)subkey.GetValue("ModifyPath")
                    });
                }
            }
        }
    }

1

Như những người khác đã chỉ ra, câu trả lời được chấp nhận không trả về cả cài đặt x86 và x64. Dưới đây là giải pháp của tôi cho điều đó. Nó tạo một StringBuilder, nối các giá trị đăng ký vào nó (với định dạng) và ghi đầu ra của nó vào một tệp văn bản:

const string FORMAT = "{0,-100} {1,-20} {2,-30} {3,-8}\n";

private void LogInstalledSoftware()
{
    var line = string.Format(FORMAT, "DisplayName", "Version", "Publisher", "InstallDate");
    line += string.Format(FORMAT, "-----------", "-------", "---------", "-----------");
    var sb = new StringBuilder(line, 100000);
    ReadRegistryUninstall(ref sb, RegistryView.Registry32);
    sb.Append($"\n[64 bit section]\n\n{line}");
    ReadRegistryUninstall(ref sb, RegistryView.Registry64);
    File.WriteAllText(@"c:\temp\log.txt", sb.ToString());
}

   private static void ReadRegistryUninstall(ref StringBuilder sb, RegistryView view)
    {
        const string REGISTRY_KEY = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
        using var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, view);
        using var subKey = baseKey.OpenSubKey(REGISTRY_KEY);
        foreach (string subkey_name in subKey.GetSubKeyNames())
        {
            using RegistryKey key = subKey.OpenSubKey(subkey_name);
            if (!string.IsNullOrEmpty(key.GetValue("DisplayName") as string))
            {
                var line = string.Format(FORMAT,
                    key.GetValue("DisplayName"),
                    key.GetValue("DisplayVersion"),
                    key.GetValue("Publisher"),
                    key.GetValue("InstallDate"));
                sb.Append(line);
            }
            key.Close();
        }
        subKey.Close();
        baseKey.Close();
    }


0

Có thể tôi khuyên bạn nên xem qua WMI ( Công cụ quản lý Windows ). Nếu bạn thêm tham chiếu System.Management vào dự án C # của mình, bạn sẽ có quyền truy cập vào lớp ManagementObjectSearcher, lớp mà bạn có thể sẽ thấy hữu ích.

Có nhiều lớp WMI khác nhau cho các ứng dụng đã cài đặt , nhưng nếu nó được cài đặt bằng Windows Installer, thì lớp Win32_Product có lẽ phù hợp nhất với bạn.

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

0

Tôi đã sử dụng phương pháp tiếp cận Nicks - Tôi cần kiểm tra xem Công cụ Từ xa cho Visual Studio đã được cài đặt hay chưa, nó có vẻ hơi chậm, nhưng trong một chuỗi riêng biệt, điều này là tốt cho tôi. - đây là mã mở rộng của tôi:

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

0

Yêu cầu của tôi là kiểm tra xem phần mềm cụ thể đã được cài đặt trong hệ thống của tôi chưa. Giải pháp này hoạt động như mong đợi. Nó có thể giúp bạn. Tôi đã sử dụng một ứng dụng windows trong c # với visual studio 2015.

 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;

        }

foreach (string subkey_name trong key.GetSubKeyNames ()) <- Không kiểm tra ở đây nếu null.
Burgo855

Nó không đáng bị bỏ phiếu vì lý do NÀY. Mặc dù nó được sao chép.
Meow Cat 2012
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.