必要なバージョンのTWindowsMediaPlayerがインストールされているかを確認しようというページ。
参考サイト
リソースにあるバージョン情報を取得したい。
http://www2.big.or.jp/~osamu/Delphi/Tips/key.cgi?key=13#0226.txt
リンク先のサンプルだとResultの最後に#0がくっついてくるので対策が必要になることも。
VerQueryValue 関数
http://msdn.microsoft.com/ja-jp/library/cc364858.aspx
サンプルコードがありがたい。
TWindowsMediaPlayerはVer 9以降がOSにインストールされていないとプログラムに取り込んで使うことはできません。
Ver 9以降がインストールされているOSでTWindowsMediaPlayerを取り込みコンパイルしたプログラムを、Ver
9以降がインストールされていないOSで動かそうとすると起動時にエラーが起きプログラムが異常終了してしまいます。
最近のOS(XPのSP3にはVer 9がインストールされていました)ではVer 9以降がインストール済みなので問題になることはありませんが、2000や古いXPでは問題になり得ます。
ということでTWindowsMediaPlayerのversionInfoプロパティに頼らずTWindowsMediaPlayerのバージョンを知る方法を探り、起動時に必要なバージョンのTWindowsMediaPlayerがあるか判定しましょうということです。
interface
function gfnbAppReadyWMP(iVer: Integer; sTitle:
String): Boolean;
implementation
uses
Forms,
Windows,
SysUtils;
//------------------------------------------------------------------------------
function gfnsSystem32DirGet:
WideString;
//System32ディレクトリを返す
var
li_Size: UINT;
lp_Buff: PWideChar;
begin
Result := '';
li_Size := GetSystemDirectoryW(
nil, 0);
if (li_Size > 0)
then begin
lp_Buff := AllocMem(li_Size * 2);
try
li_Size := GetSystemDirectoryW(lp_Buff, li_Size);
if (li_Size > 0)
then begin
Result :=
WideString(lp_Buff);
end;
finally
FreeMem(lp_Buff);
end;
end;
end;
function gfnsFileVersionGet(sFile:
WideString):
WideString;
//ファイルのバージョン情報を返す
//http://www2.big.or.jp/~osamu/Delphi/Tips/key.cgi?key=13#0226.txt
type
TLangAndCodePage =
record
iLanguage: WORD;
iCodePage: WORD;
end;
PLangAndCodePage = ^TLangAndCodePage;
var
li_Size, li_Reserved, li_Len: DWORD;
lp_Buff, lp_Dat: Pointer;
lp_LangPage: PLangAndCodePage;
ls_FileInfo:
WideString;
begin
Result := '';
// 必要なバッファのサイズを取得
li_Size := GetFileVersionInfoSizeW(PWideChar(sFile), li_Reserved);
if (li_Size > 0)
then begin
//メモリ確保
lp_Buff := AllocMem((li_Size +1) * 2);
try
if (GetFileVersionInfoW(PWideChar(sFile), 0, li_Size, lp_Buff))
then begin
//変数情報ブロック内の変換テーブルを指定
if (VerQueryValueW(lp_Buff, '\VarFileInfo\Translation', Pointer(lp_LangPage), li_Len)
and (li_Len > 0))
then begin
//'\StringFileInfo\040904B0\'というような文字列
ls_FileInfo :=
WideString(Format('\StringFileInfo\%.4x%.4x\', [lp_LangPage^.iLanguage, lp_LangPage^.iCodePage]));
//ファイルバージョン
if (VerQueryValueW(lp_Buff, PWideChar(ls_FileInfo + 'FileVersion'), lp_Dat, li_Len)
and (li_Len > 0))
then begin
Result :=
WideString(PWideChar(lp_Dat));
end;
end;
end;
finally
// 解放
FreeMem(lp_Buff);
end;
end;
end;
//------------------------------------------------------------------------------
function gfnbAppReadyWMP(iVer: Integer; sTitle:
String): Boolean;
//WindowsMediaPlayerのiVer以上がインストールされていればTrueを返す。
//そうでなければエラーメッセージを出しFalseを返す。
const
lcs_WMPDLL = 'wmp.dll';
var
li_Num, li_Code: Integer;
ls_Wmpdll, ls_Ver:
WideString;
begin
Result := True;
ls_Wmpdll := gfnsSystem32DirGet + '\' + lcs_WMPDLL;
if not(FileExists(ls_Wmpdll))
then begin
Application.MessageBox(PChar(Format('システムに必要なコンポーネントがインストールされていません。'#13'WindowsMediaPlayerのVer %d 以上がインストールされている必要があります', [iVer])), PChar(sTitle), MB_OK);
Result := False;
end else begin
ls_Ver := gfnsFileVersionGet(ls_Wmpdll);
Val(ls_Ver, li_Num, li_Code);
if (li_Num < iVer)
then begin
Application.MessageBox(PChar(Format('システムにWindowsMediaPlayerのVer %d 以上がインストールされている必要があります'#13'現在インストールされているWindowsMediaPlayerのバージョンは %s です', [iVer, ls_Ver])), PChar(sTitle), MB_OK);
Result := False;
end;
end;
end;
要はTWindowsMediaPlayerがインストールされていればシステムディレクトリにwmp.dllというファイルが存在するはずなので、そのファイルがあるかどうか、あればそのバージョン情報を取得して比較するというだけのことです。
システムディレクトリはGetSystemDirectoryW APIを使って取得します。
(GetSystemDirectoryWではなくGetSystemDirectoryでも良いのですが、一応念のため)
ファイルのバージョン情報はGetFileVersionInfoSizeWとGetFileVersionInfoWとVerQueryValueWという三つのAPIを使います。
(これまたGetFileVersionInfoSizeとGetFileVersionInfoとVerQueryValueでも良いのですが、一応念のため)
ちょっとややこしいです。
if (VerQueryValueW(lp_Buff, '\VarFileInfo\Translation', Pointer(lp_LangPage), li_Len) and (li_Len > 0)) then begin
//'\StringFileInfo\040904B0\'というような文字列
ls_FileInfo := WideString(Format('\StringFileInfo\%.4x%.4x\', [lp_LangPage^.iLanguage, lp_LangPage^.iCodePage]));
最初のVerQueryValueWの呼び出しで第二引数に'\VarFileInfo\Translation'をセットすることでlp_LangPageに「言語識別子」と「文字セット識別子」の二つの情報がセットされます。
この「言語識別子」と「文字セット識別子」を16進数の文字列に変換して二度目のVerQueryValueWの第二引数に、取り出したいバージョン情報のキーと組み合わせて指定することで希望する値が得られます。
一口にバージョン情報と言っても、よくある「バージョン3.1」などのおなじみのものだけでなく、エクスプローラで.exeファイルや.dllファイルを選択、右クリックして「プロパティ」を選んでバージョン情報タブを選択すると現れる一連の情報を含めたものになります。
これらの一連の情報の中から下の図で言えば'9.0.0.4503'という「ファイルバージョン」を得ようということです。
この色々ある情報を取り出すのに上で述べたようにVerQueryValueWの第二引数に、'Comments'や'InternalName'や'ProductName'などのキーを「言語識別子」と「文字セット識別子」につけて渡すわけです。
これらのキーの中で、ファイルバージョンは'FileVersion'を使います。
//ファイルバージョン
if (VerQueryValueW(lp_Buff, PWideChar(ls_FileInfo + 'FileVersion'), lp_Dat, li_Len) and (li_Len > 0)) then begin
Result := WideString(PWideChar(lp_Dat));
end;
第二引数に希望するキーを「言語識別子」と「文字セット識別子」と組み合わせて指定すると三引数のlp_Datに希望する値がセットされるのでPWideCharとWideStringでキャストして取り出します。
あとはこの取り出したファイルバージョンのメジャーバージョンのみを数値として取り出し、必要とするメディアプレーヤーのバージョンと比較するだけです。
ls_Ver := gfnsFileVersionGet(ls_Wmpdll);
Val(ls_Ver, li_Num, li_Code);
if (li_Num < iVer) then begin
Application.MessageBox(PChar(Format('システムにWindowsMediaPlayerのVer %d 以上がインストールされている必要があります'#13'現在インストールされているWindowsMediaPlayerのバージョンは %s です', [iVer, ls_Ver])), PChar(sTitle), MB_OK);
Result := False;
end;
2009-08-09