質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

VBScript

VBScript(Visual Basic Scripting Edition)はMicrosftが開発したスクリプト言語であり、Visual Basicのサブセットです。

Q&A

解決済

2回答

1972閲覧

Installer.ProductsExの戻り値をC#で取得したい。

trons

総合スコア20

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

VBScript

VBScript(Visual Basic Scripting Edition)はMicrosftが開発したスクリプト言語であり、Visual Basicのサブセットです。

0グッド

0クリップ

投稿2018/11/08 06:24

編集2018/11/12 00:38

イタリックテキスト

前提・実現したいこと

ここに質問の内容を詳しく書いてください。
お世話になります。
パソコンにインストールされている製品情報をC#からWindows Installerを通じて取得しようと
しております。
そこでNETで見つけた下記コードを元にC#に置換を行っています。
https://social.msdn.microsoft.com/Forums/windows/en-US/e5225e8e-6830-4ece-8897-f22117f92d1c/how-to-uninstall-an-msi-programmatically-if-productcode-is-not-provided

https://docs.microsoft.com/en-us/windows/desktop/Msi/installer-productsex
によると「ProductsEx」の戻り値は「RecordList」となっておりますが、
上記サイト同じように値を取得する方法が分かりません。

RecordList、Recordオブジェクトのサイトにも情報が記載されておらず取得方法が分かりません。
よろしければどなたか教えていただけますでしょうか。
宜しくお願い致します。

該当のソースコード

■VBS

Option Explicit Public installer, fullmsg, comp, prod, a, fso, pname, ploc, pid,contxt, sid, psorce, pcache, pvers Set fso = CreateObject("Scripting.FileSystemObject") Set a = fso.CreateTextFile("prodex.txt", True) ' Connect to Windows Installer object Set installer = CreateObject("WindowsInstaller.Installer") a.writeline ("Products") 'on error resume next For Each prod In installer.ProductsEx("", "", 7) pid = prod.ProductCode '**C#での値取得方法が知りたい** contxt = prod.Context sid=prod.usersid pname = prod.InstallProperty("InstalledProductName")'**C#での値取得方法が知りたい** psorce=prod.InstallProperty( "InstallSource") ploc =prod.InstallProperty( "InstallLocation") pcache = prod.InstallProperty("LocalPackage") pvers=prod.InstallProperty("VersionString") a.writeline (pid & " " & pname & " " & pvers & " installed at <" & ploc & "> from " & psorce & " Context " & contxt) Next ```■C# ```ここに言語を入力 Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer"); Object installerObj = Activator.CreateInstance(installerType); Installer oMsi = installerObj as Installer; RecordList rl= oMsi.ProductsEx["", "", 7]; foreach (Record data in rl)//**Record型にすると例外(キャストNG)** { } foreach (var data in rl)//**varにすると例外は発生しませんが値の取得方法が分かりません。 **{ } ```### 補足情報(FW/ツールのバージョンなど) VS2017 .Net3.5 OS Win7以上 ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2018/11/09 04:07

お使いのWindowsのバージョンは10でしょうか。それとも.NET Framework 3.5ということなので、Windows 7 以前とか。あと、コードはマークアップの為に’’'でくくり、見易くしてもらえると助かります。
guest

回答2

0

ベストアンサー

WindowsInstaller.Installer.ProductsExはC#(.NET Framework)では使えないと考えた方が良いようです。

WindowsInstaller.Installer.ProductsExの戻り値の扱いを求めたご質問ですが、手段を変える必要がありそうです。ProductsExの戻り値RecordListのプロパティItemsから更に要素を列挙すると確かにRecordが取れるはずなのですが、そうはなりません。

オブジェクトブラウザーで確認1: ProductsExの戻り値はRecordList
ProductsExの戻り値はRecordList

オブジェクトブラウザーで確認2: RecordListのItemsプロパティはRecordのコレクション(のはず)
RecordListのItemsプロパティはRecordのコレクション

こちらでも試してみたのですが、Record型のみならず、最も基本であるSystem.Object型の変数で受けようとしてもInvalidCastException例外がthrowされ、使うことができません。これはWindows.InstallerのCOMと.NET Framework間の問題のようです。Windowsのバージョン間の差異もあるかと思い、Windows XP + Visual Studio 2008 環境下でも試しましたが、メソッドやプロパティ名の違いが少しあったものの、
エラーの本質は同じでした。

Stackoverflowに関連する投稿がありましたのでご案内します。こちらでもInstaller.ProductsExを使用した場合の問題が挙げられています。
Stackoverflow - Getting List Of Installed Products c#
ここで、Windows Installerに関するCOMは、.NET でのサポートが未完成であることが示唆されていて、WindowsInstaller.Installer.ProductsExをC#で使うのであれば、代わりにWindows InstallerのベースとなるAPIであるMsiEnumProductsExを使うことが提案されてます。


では結局どうしたらいいのか

質問者さんの最終的な目的は「パソコンにインストールされている製品情報をC#からWindows Installerを通じて取得する」ことですので、マイクロソフトから例として提供されているVBScriptを参考にできます。
Windows Installer Scripting Examples
の WiLstPrd.vbs と言うVBScriptのサンプルでは WindowsInstaller.Installer.ProductsExを使うのではなく、Productsプロパティからインストールされている製品のProductCode(製品コード)を列挙し、Installer.ProductInfoでそれぞれの製品名やバージョン情報をたぐる方法が示されています。

WiLstPrd.vbsの一部を引用します。

VB

1' If Product name supplied, need to search for product code 2... 3For Each product In products 4 version = DecodeVersion(installer.ProductInfo(product, "Version")) : CheckError 5 info = product & " = " & installer.ProductInfo(product, "ProductName") & " " & version : CheckError 6 If productList <> Empty Then productList = productList & vbNewLine & info Else productList = info 7Next

ちなみにこの部分をC#に移植するとだいたい以下のようになります。("Version"は除いています)

C#

1Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer"); 2WindowsInstaller.Installer installerObj = Activator.CreateInstance(installerType) as Installer; 3 4// Product Code(製品コード)を列挙して各製品情報を出力 5foreach (string productCode in installerObj.Products) 6{ 7 string productName= installerObj.ProductInfo[productCode, "ProductName"]; 8 System.Diagnostics.Debug.WriteLine("製品コード:" + productCode + " 製品名:" + productName); 9} 10 11Marshal.FinalReleaseComObject(installerObj);

このコードで、以下のようにデバッグ端末に出力されます。

Plain

1製品コード:{0D6B41AF-D117-8944-A059-3F9346A896C5} 製品名:Universal CRT Headers Libraries and Sources 2製品コード:{B315ACAF-F444-40B4-B361-8E6B9A2C084B} 製品名:PreEmptive Analytics Client Japanese Language Pack 3製品コード:{F99F24BF-0B90-463E-9658-3FD2EFC3C992} 製品名:Microsoft Identity Extensions 4...

このように、改めてマイクロソフトのWiLstPrd.vbsを参考にして取り組まれることをお勧めします。

上記のコードとは違いますが、確認を兼ねて簡単なコンソールアプリとして造ったものをgithubに挙げましたので、よろしければ参考にしてみてください。https://github.com/dodox86/WICmdUtl

投稿2018/11/12 03:40

dodox86

総合スコア9183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

trons

2018/11/12 04:46

ご回答ありがとうございます。 提示いただいた方法で確認したいと思います。 ありがとうございました。
guest

0

RecordList がわからないので、大雑把な回答になりますが、まずは var で受けてブレイクポイントを張れば、各要素の型はわかるはずです。

どうしてもだめなら dynamic 型をつかえばなんとかなるかもしれません。

投稿2018/11/11 07:38

gaya-K

総合スコア449

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問