システムにインストールされたアプリケーションを取得する


83

C#コードを使用してシステムにアプリケーションをインストールする方法は?

回答:


115

レジストリキー「SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall」を繰り返すと、インストールされているアプリケーションの包括的なリストが表示されるようです。

以下の例とは別に、私がここで行っことと同様のバージョンを見つけることができます。

これは大まかな例です。提供されている2番目のリンクのように、空白行を取り除くために何かをしたいと思うでしょう。

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

または、前述のようにWMIを使用することもできます。

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

しかし、これは実行にかなり時間がかかり、「ALLUSERS」の下にインストールされたプログラムのみがリストされる可能性があると聞きましたが、それは正しくない可能性があります。また、Windowsのコンポーネントとアップデートも無視されます。これは便利な場合があります。


27
このクエリを繰り返し実行する場合は、WMIWin32_Productクラスを使用することはお勧めできません。次のMicrosoftKB記事を参照してください:support.microsoft.com/kb/974524/EN-US 主要な問題は、(a)Win32_Productが非常に遅いこと、および(b)「Windowsインストーラーが製品を再構成した」ことを生成することです。システムにインストールされているすべての製品のイベントログメッセージ...クエリを実行するたび。ドー!この記事では、SMSをインストールしない限り存在しないWin32reg_AddRemoveProgramsクラスの使用を推奨しています。ドー!したがって、おそらくレジストリクエリに固執する方が良いでしょう。
Simon Gillbee 2010年

Simon Gillbeeのコメントは、受け入れられた答え、またはKirtansでなければなりません!WMI WIN32_Productは、ここに移動する方法ではありません。信頼してください。
bdd 2010年

13
えーと、それが私の答えの最初にレジストリの例がある理由です。WMIは単に代替ソリューションとして提示されたものであり、そこでも「これは実行にかなり時間がかかる」などの欠点があると述べています。最初から答えを読んでください。;)
Xiaofu 2010年

1
ちょっと奇妙ですが、プログラムをアンインストールして再度インストールした場合は、マシンを再起動しない限り、レジストリキーを使用して見つけようとします
Yar

3
私自身の質問に答えるには:stackoverflow.com/questions/27838798/…64 ビットと32ビットの両方をクエリする必要があるかもしれないのは面倒ですが。
Robert Koernke 2017

9

あなたはこの記事を見ることができます。レジストリを利用して、インストールされているアプリケーションのリストを読み取ります。

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

リスト全体は必要ありません。選択したインストールプログラムが必要なだけなので、そのために何ができますか。ありがとう
Dhru'soni 2015

8

レジストリキーを介して列挙することが最善の方法であることに同意します。

ただし、指定されたキー@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"は、32ビットのWindowsインストールではすべてのアプリケーションを一覧表示し、Windows64ビットのインストールでは64ビットのアプリケーションを一覧表示することに注意してください

Windows 64ビットインストールにインストールされている32ビットアプリケーションも表示するには、キーを列挙する必要もあります@"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"


あなたはこれについて確信を持っていますか?私のWindows10 Enterprise 64ビットでは、2つのリストは同じように見え、x86アプリケーションは両方に表示されます。
Florian Straub 2017年

ありがとう、これは私のために働きます、私は私が探していたプログラムを見つけました。
xtian 1119年

regedit、それはそう思えます。ただし、32ビットプログラム(64ビットWindows)では、両方のリストはからのWOW6432Nodeものと同じです regedit
ニャーキャット

5

スタートメニューに表示されるとおりにアプリのリストを抽出できるようにしたかったのです。レジストリを使用して、スタートメニューに表示されないエントリを取得していました。

また、exeパスを見つけてアイコンを抽出し、最終的に見栄えの良いランチャーを作成したいと思いました。残念ながら、レジストリ方式では、この情報が確実に利用可能ではないという私の観察から、これは一種のヒットとミスです。

私の代替案は、実行explorer.exe shell:appsFolderしてアクセスできるshell:AppsFolderに基づいており、ストアアプリを含む、現在インストールされており、スタートメニューから利用できるすべてのアプリが一覧表示されます。問題は、これがでアクセスできない仮想フォルダであるということSystem.IO.Directoryです。代わりに、ネイティブのshell32コマンドを使用する必要があります。幸い、MicrosoftはMicrosoft.WindowsAPICodePack-ShellをNugetで公開しました。これは、前述のコマンドのラッパーです。十分に言った、ここにコードがあります:

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

そして、それがすべてです。を使用してアプリを起動することもできます

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

これは、通常のWin32アプリとUWPストアアプリで機能します。りんごはどうですか。

インストールされているすべてのアプリを一覧表示することに関心があるため、新しいアプリやアンインストールされたアプリも監視することをお勧めします。これは、ShellObjectWatcher次を使用して実行できます。

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

編集:上記のAppUserMoedlIDは、Windowsがタスクバーのウィンドウをグループ化するために使用する一意のIDであることを知りたいと思うかもしれません。


どうもありがとう、これを達成するための本当に良い方法。ShellObjectWatcherから直接名前を取得したり、名前を解析したりする方法があるかどうか知っていましたか?
forlayo

アプリがインストールまたは削除されたときにアプリを追跡するために使用しようとしたAllEventsItemCreatedまたはItemRenamedそれ以外のイベントタイプがあります。これらのイベントのイベント引数にはPathプロパティが含まれていますが、少なくとも私のテストでは、このプロパティは常にnullです。常にnullであるため、解析名を取得する方法をわざわざ理解しようとはしていません。代わりに、フォルダー内のアプリを反復処理してアイテムが発生するたびに同期するアプリのリストを保持するだけです。理想的ではありませんが、仕事を成し遂げます。
user1969903

1
ありがとう!私は実際に同じことをしています。また、これは「インストールされたばかりのアプリケーションのメイン実行可能ファイルを見つける方法」に関する他の質問にも役立ちました-> stackoverflow.com/questions/60440044/… それでは、ありがとうございます!:)
forlayo

4

Win32_Product WMIクラスは、Windowsインストーラーによってインストールされる製品を表すことに注意してください。すべてのアプリケーションがWindowsインストーラーを使用するわけではありません

ただし、「SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall」は、32ビットのアプリケーションを表します。64ビットの場合は、「HKEY_LOCAL_MACHINE \ SOFTWARE \ Wow6432Node \ Microsoft \ Windows \ CurrentVersion \ Uninstall」もトラバースする必要があります。すべてのソフトウェアに64ビットバージョンがあるわけではないため、インストールされるアプリケーションの総数は、「UninstallString」がある両方の場所のキーの和集合です。それらとの価値。

しかし、最良のオプションは同じままです。すべてのアプリケーションがレジストリにエントリを持っているので、レジストリキーをトラバースする方が良いアプローチです[Windowsインストーラーのエントリを含む]。ただし、レジストリメソッドは、誰かが対応するキーを削除するかのように安全ではありません。アプリケーションエントリ。逆に、HKEY_Classes_ROOT \ Installersの変更は、Microsoft Officeやその他の製品などのライセンスの問題に関連しているため、より注意が必要です。より堅牢なソリューションを実現するには、レジストリの代替手段をWMIといつでも組み合わせることができます。


3

受け入れられたソリューションは機能しますが、完全ではありません。はるかに。

すべてのキーを取得する場合は、さらに2つのことを考慮する必要があります。

x86およびx64アプリケーションは、同じレジストリにアクセスできません。基本的に、x86は通常x64レジストリにアクセスできません。また、一部のアプリケーションはx64レジストリにのみ登録します。

そして

一部のアプリケーションは、LocalMachineではなくCurrentUserレジストリに実際にインストールされます

このことを念頭に置いて、私は、ALLは、次のコードを使用してアプリケーションをインストールし得ることをどうにかなしWMIを使用して

コードは次のとおりです。

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

これは、他のソリューションよりも正確に機能しました。
Vilas Joshi

1

「HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall」キーを繰り返し処理し、それらの「DisplayName」値を確認します。


1

WindowsインストーラAPIを使用してください!

これにより、すべてのプログラムの信頼できる列挙を行うことができます。レジストリは信頼できませんが、WMIは重要です。


確かに重いです-繰り返し実行すると、重いもののようにパフォーマンスが低下します。私のアプリの機能が別のアプリに依存していて、正しくインストールされているかどうかがわかっている場合は、アプリが64ビットでも利用できる場合にのみ32または64のアンインストールレジストリキーが必要です)一方、wmiを使用する必要がある場合は、スマートプロパティトリックを介して、アプリケーション中に1回だけ使用するように制限されます。
gg89 2015年


1

リストのオブジェクト:

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

リストを作成するための呼び出し:

    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

他の人が指摘しているように、受け入れられた回答はx86とx64の両方のインストールを返しません。以下はそのための私の解決策です。を作成しStringBuilder、それにレジストリ値を(フォーマットを使用して)追加し、その出力をテキストファイルに書き込みます。

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

WMI(Windows Management Instrumentation)をご覧になることをお勧めします。System.Management参照をC#プロジェクトに追加すると、クラス `ManagementObjectSearcher 'にアクセスできるようになります。これは、おそらく便利です。

インストールされているアプリケーションにはさまざまなWMIクラスがありますが、Windowsインストーラーを使用してインストールされている場合は、Win32_Productクラスがおそらく最適です。

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

0

Nicksのアプローチを使用しました-VisualStudioのリモートツールがインストールされているかどうかを確認する必要がありました。少し遅いようですが、別のスレッドではこれで問題ありません。-ここに私の拡張コード:

    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

私の要件は、特定のソフトウェアがシステムにインストールされているかどうかを確認することです。このソリューションは期待どおりに機能します。それはあなたを助けるかもしれません。Visual Studio 2015でC#のWindowsアプリケーションを使用しました。

 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(key.GetSubKeyNames()の文字列subkey_name)<-nullの場合はここでチェックしません。
Burgo855 2018年

この理由から、反対票を投じる価値はありません。重複していますが。
ニャーキャット2012年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.