C#コードを使用してシステムにアプリケーションをインストールする方法は?
レジストリキー「SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall」を反復処理すると、インストールされているアプリケーションの包括的なリストが得られるようです。
以下の例とは別に、私がやったものと同様のバージョンを見つけることができます here 。
これは大まかな例です。提供された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コンポーネントと更新も無視します。これは便利な場合があります。
この記事 をご覧ください。レジストリを使用して、インストールされているアプリケーションのリストを読み取ります。
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)
{ }
}
}
}
}
レジストリキーを列挙するのが最善の方法であることに同意します。
注ただし、指定されたキー、@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
は、32ビットWindowsインストールのすべてのアプリケーションと、Windows 64ビットインストールの64ビットアプリケーションをリストします。
Windows 64ビットインストールにインストールされた32ビットアプリケーションを表示するには、キー@"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
。
win32_Product WMIクラスは、 Windows Installer によってインストールされる製品を表すことに注意してください。すべてのアプリケーションがWindowsインストーラーを使用するわけではありません
ただし、「SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall」は32ビットのアプリケーションを表します。 64ビットの場合、「HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall」もトラバースする必要があります。すべてのソフトウェアが64ビットバージョンを持っているわけではないため、インストールされるアプリケーションの合計は、「UninstallString」それらとの価値。
しかし、最良のオプションは同じままです。traverseレジストリキーは、すべてのアプリケーションがレジストリ(Windows Installerのものを含む)にエントリを持っているため、より良いアプローチです。ただし、レジストリメソッドは、アプリケーションエントリ。それどころか、HKEY_Classes_ROOT\Installersの変更は、Microsoft Officeや他の製品などのライセンスの問題とリンクしているため、より注意が必要です。より堅牢なソリューションのために、レジストリの代替をWMIといつでも組み合わせることができます。
「HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall」キーを反復処理し、「DisplayName」値を確認します。
Windows Installer APIを使用してください!
すべてのプログラムの信頼できる列挙を行うことができます。レジストリは信頼できませんが、WMIは重量級です。
あなたの最善の策は [〜#〜] wmi [〜#〜] を使用することです。具体的には Win32_Product クラス。
WMI( Windows Management Instrumentation )をご覧になることをお勧めします。 System.Management参照をC#プロジェクトに追加すると、クラス `ManagementObjectSearcher 'にアクセスできるようになります。これはおそらく役立つでしょう。
インストール済みアプリケーション にはさまざまなWMIクラスがありますが、Windowsインストーラーでインストールされた場合、Win32_Productクラスがおそらく最も適しています。
ManagementObjectSearcher s = new ManagementObjectSearcher("SELECT * FROM Win32_Product");
スタートメニューに表示されるとおりにアプリのリストを抽出できるようにしたかったのです。レジストリを使用して、スタートメニューに表示されないエントリを取得していました。
また、exeパスを見つけてアイコンを抽出して、最終的に見栄えの良いランチャーを作成したいと考えました。残念ながら、レジストリ方式では、この情報が確実に利用可能ではないというのが私の観察であるため、これは一種のヒットとミスです。
私の代替手段は、Shell:AppsFolderに基づいています。このフォルダーには、Explorer.exe Shell:appsFolder
を実行してアクセスでき、ストアアプリを含め、現在インストールされ、スタートメニューから利用できるすべてのアプリが一覧表示されます。問題は、これがSystem.IO.Directory
でアクセスできない仮想フォルダーであるということです。代わりに、ネイティブShell32コマンドを使用する必要があります。幸い、MicrosoftはNugetで Microsoft.WindowsAPICodePack-Shell を公開しました。これは、前述のコマンドのラッパーです。コードは次のとおりです。
// GUID taken from https://docs.Microsoft.com/en-us/windows/win32/Shell/knownfolderid
var FODLERID_AppsFolder = new Guid("{1e87508d-89c2-42f0-8a7e-645a0f50ca58}");
ShellObject appsFolder = (ShellObject)KnownFolderHelper.FromKnownFolderId(FODLERID_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 であることを知りたい場合もあります。
私の要件は、特定のソフトウェアがシステムにインストールされているかどうかを確認することです。このソリューションは期待どおりに機能します。役立つかもしれません。 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;
}
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;
}