MSIデータベースのProductVersionをすばやく取得する方法を探して、昨日の高低を検索しました。ほとんどの場合、WindowsInstaller COMラッパーを利用していることがわかりましたが、これは仕事が終わったあと、msi.dllを使用してpinvokeで同じ結果を得たいと思っています。MSIのProductVersionをプログラムで確認する
答えて
ここに私が思いついたのがあります。
C#WindowsインストーラCOMライブラリ:
// Get the type of the Windows Installer object
Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
// Create the Windows Installer object
Installer installer = (Installer)Activator.CreateInstance(installerType);
// Open the MSI database in the input file
Database database = installer.OpenDatabase(od.FileName, MsiOpenDatabaseMode.msiOpenDatabaseModeReadOnly);
// Open a view on the Property table for the version property
WindowsInstaller.View view = database.OpenView("SELECT * FROM Property WHERE Property = 'ProductVersion'");
// Execute the view query
view.Execute(null);
// Get the record from the view
Record record = view.Fetch();
// Get the version from the data
string version = record.get_StringData(2);
C#のPInvoke:
[DllImport("msi.dll", SetLastError = true)]
static extern uint MsiOpenDatabase(string szDatabasePath, IntPtr phPersist, out IntPtr phDatabase);
[DllImport("msi.dll", CharSet = CharSet.Unicode)]
static extern int MsiDatabaseOpenViewW(IntPtr hDatabase, [MarshalAs(UnmanagedType.LPWStr)] string szQuery, out IntPtr phView);
[DllImport("msi.dll", CharSet = CharSet.Unicode)]
static extern int MsiViewExecute(IntPtr hView, IntPtr hRecord);
[DllImport("msi.dll", CharSet = CharSet.Unicode)]
static extern uint MsiViewFetch(IntPtr hView, out IntPtr hRecord);
[DllImport("msi.dll", CharSet = CharSet.Unicode)]
static extern int MsiRecordGetString(IntPtr hRecord, int iField,
[Out] StringBuilder szValueBuf, ref int pcchValueBuf);
[DllImport("msi.dll", ExactSpelling = true)]
static extern IntPtr MsiCreateRecord(uint cParams);
[DllImport("msi.dll", ExactSpelling = true)]
static extern uint MsiCloseHandle(IntPtr hAny);
public string GetVersionInfo(string fileName)
{
string sqlStatement = "SELECT * FROM Property WHERE Property = 'ProductVersion'";
IntPtr phDatabase = IntPtr.Zero;
IntPtr phView = IntPtr.Zero;
IntPtr hRecord = IntPtr.Zero;
StringBuilder szValueBuf = new StringBuilder();
int pcchValueBuf = 255;
// Open the MSI database in the input file
uint val = MsiOpenDatabase(fileName, IntPtr.Zero, out phDatabase);
hRecord = MsiCreateRecord(1);
// Open a view on the Property table for the version property
int viewVal = MsiDatabaseOpenViewW(phDatabase, sqlStatement, out phView);
// Execute the view query
int exeVal = MsiViewExecute(phView, hRecord);
// Get the record from the view
uint fetchVal = MsiViewFetch(phView, out hRecord);
// Get the version from the data
int retVal = MsiRecordGetString(hRecord, 2, szValueBuf, ref pcchValueBuf);
uRetCode = MsiCloseHandle(phDatabase);
uRetCode = MsiCloseHandle(phView);
uRetCode = MsiCloseHandle(hRecord);
return szValueBuf.ToString();
}
これは、簡単にSQLステートメントを変更することにより、MSIデータベースから任意のプロパティまたはフィールドを取得するに推定することができます。私はこれが誰かを助けることを望む。
このP/Invokeコードには2つの主な欠陥があります(このコードを書くのを忘れるまであなたを噛んでしまう可能性は低いです):MSIHANDLEはInt32ではないIntPtrです(これはほとんどのHANDLEタイプと異なり、x64環境のみに関連します)。プロパティーフェッチコードは255より長いプロパティー値を扱うことができません。 –
MSIHANDLEsについて、私は気づきませんでした。それは、そのバグを見つけるために下に行く巨大なウサギの穴だったでしょう。プロパティ値の長さは簡単に変更できます。私はちょうどそれを任意に255に設定しました。 – user529570
エラー静的型 'Microsoft.Deployment.WindowsInstaller.Installer'に変換できません –
MSIで.NET interopを実行する必要がある人は、WiXのDTF SDKにあるMicrosoft.Deployment.WindowsInstallerを使用する必要があります。それは非常にきれいな図書館であり、あなた自身のことを書こうとするより良い方法です。
interopライブラリをメイン実行可能ファイルに埋め込む方法はありますか?私は、アプリケーションに追加の外部DLLに沿ってタグを付けなくても、相互運用する方法を探していました。 – user529570
MicrosoftのILMergeはそのトリックを行うことができます。 –
恐ろしい!ありがとう。 – user529570
- 1. プログラムでMonoランタイムバージョンを確認する
- 2. 設定でiPhoneのパスコードをプログラムで確認する
- 3. マルチタッチ対応Androidデバイスの指数をプログラムで確認する
- 4. C++のデータベース構造をプログラムで確認する
- 5. プログラムでExchangeの添付ファイル制限を確認する
- 6. 連絡先のiMessageサポートをプログラムで確認する
- 7. メモリの使用量をプログラムで確認する(ココア)
- 8. iPod touchの世代をプログラムで確認する
- 9. iPhone:アプリ内購入のステータスをプログラムで確認する
- 10. WCF証明書チェーン、プログラムで確認
- 11. アンドロイドアプリで画面の幅をプログラムで確認できますか?
- 12. プログラムでOutlook電子メールを確認する
- 13. ブートストラップ:MSIのバージョンがインストールされているか確認してください
- 14. ネットワーク状態を確認し、プログラム内のPPPを制御する
- 15. 別のプログラムの作業ディレクトリを確認する
- 16. 実行中のプログラムのステータスを確認する方法
- 17. Cプログラムが3桁の最大Palindrome番号を確認する
- 18. msiをプログラムで実行するとmsi終了コード1625に問題が発生する
- 19. Linuxでの画面の幅と高さをプログラムで確認する(Xinerama、TwinView、BigDesktop)
- 20. WindowsでPerlプログラムのメモリ使用量をプログラムで確認するにはどうすればよいですか?
- 21. サーバー側(Node.js)でFacebookユーザーのアクセストークンをプログラムで確認する方法は?
- 22. RubyでSSL証明書の有効期限をプログラムで確認する
- 23. 私のWiFiがWPA2/WEPであるかどうかを確認するプログラムC++
- 24. mysqlのデータを確認するマルチテーブルを確認する
- 25. 実行中のプログラム内で使用可能なRAMの量を確認する
- 26. dllのFileVersionとProductVersionの違いは何ですか?
- 27. 反復によるK-Means反復を確認するプログラムですか?
- 28. OpenMPがC++プログラムで動作するかどうかを確認する方法
- 29. C#プログラムが.Net v2のみのマシンで実行できることを確認
- 30. どのようにプログラムがクラッシュしたかをアンドロイドで確認するには?
@ user529570ようこそスタックオーバーフロー - これは既にあなたがこれを解決していることは重要ではない、それはまだ有用です。あなたはそれを編集して(質問の下にある「編集」リンクを使用して)これを質問とし、解答の形で回答したいと思うかもしれません。これにより、人々は代替の回答を提供し、あなたの答えに投票することができます。 –
便利です。 Codeprojectはこのようなものを投稿する場所のようです。人々が解決策を投稿できるサイトは非常に便利です。 – Nick
コリンありがとうございます。 – user529570