製品をインストールすることによって生じる結果とは、それほど意外なものではありません。それらはあくまでフィーチャをインストールことによって生じる結果です。コンポーネントはフィーチャがインストールすることで初めてインストールされると述べました。コンパイル済みHTMLヘルプファイルなどが含まれることになるでしょう。ユーザーは自分にとって必要なファイルのみをインストールすることができるようになります。全てのコンポーネントが関連付けられることになります。結果としてユーザーも開発者もフィーチャの存在を意識することはなくなるでしょう。その製品が持てる機能を知れることになり、非常に有用といえます。次に示すMsiEnumFeaturesは、指定した製品に含まれるフィーチャを列挙します。lpParentBuf);szProductは、フィーチャを列挙したい製品の製品コードを指定します。iFeatureIndexは、ゼロベースでフィーチャのインデックスを指定します。lpFeatureBufは、フィーチャのIDとなる文字列を受け取るバッファのアドレスを指定します。lpParentBufは、取得したフィーチャの親のフィーチャIDが返りますが、NULLで問題ありません。フィーチャIDからフィーチャの情報を取得するには、少しばかりの手順を踏むことになります。フィーチャに関して記述する文字列が格納されているのは、あくまでMSIファイルだからです。データベースへのアクセスを簡略化するハンドルを取得するということを意味しています。このハンドルの事を製品ハンドルと呼び、MsiOpenProductで取得することになります。*hProduct);szProductは、ハンドルを取得したい製品の製品コードを指定します。hProductは、製品ハンドルを受け取るための変数のアドレスを指定します。このハンドルが、製品に関連するMSIファイルのデータベースを指すことになります。製品ハンドルを取得すれば、それを使用してMsiGetFeatureInfoを呼び出すことができます。*pcchHelpBuf);hProductは、製品ハンドルを指定します。szFeatureは、情報を取得したいフィーチャのIDを指定します。lpAttributesは、フィーチャの属性フラグが返ります。lpTitleBufは、フィーチャのタイトルを受け取るバッファのアドレスを指定します。この値は、FeatureテーブルのTitleカラムに相当します。pcchTitleBufは、lpTitleBufのサイズを格納した変数のアドレスを指定します。lpHelpBufは、フィーチャについて記述した文字列を受け取るバッファのアドレスを指定します。この値は、FeatureテーブルのDescriptionカラムに相当します。pcchHelpBufは、lpHelpBufのサイズを格納した変数のアドレスを指定します。選択したフィーチャの情報を右側のリストボックスに追加します。WindowProcにて静的に宣言されているszProductCodeに、適切な製品コードを指定してください。前節で列挙した製品コードのいずれかを指定してもよいでしょう。WM_CREATEで予め取得しておくことにしています。-1;MsiOpenProductの呼び出しは、見て分かるように単純です。その前に呼び出しているMsiSetInternalUIという関数については後の節で説明します。次に、MsiEnumFeaturesの呼び出しを確認します。(LPARAM)szFeature);}これについても、特に問題はないと思われます。インデックスをカウントしつつ、指定していきます。WM_COMMANDでは、選択されたフィーチャIDを取得し、MsiGetFeatureInfoを呼び出します。あるということは常に意識しておいてください。この情報からは、現在のインストール状態というのは特定することはできません。ローカルのディスクにインストールされたのかが分からないわけです。このような場合は、MsiQueryFeatureStateでインストール状態を確認します。このMSIファイルのパスは一体どのように取得しているのでしょうか。このような問題にはどのように対処しているのでしょうか。その名前を含めたフルパスをレジストリに書き込むことになっています。MsiOpenDatabaseに指定すれば、データベースをオープンすることができるでしょう。指定して取得することもできます。MsiGetFeatureInfoの他にMsiGetProductPropertyという関数があります。それを取得するだけであれば、MsiGetProductInfoを呼び出したほうがよいと思われます。無意味なダイアログが表示される点を考えると、決して使いやすいとは言い難いものがあります。