VerQueryValue を使ってバージョンを取得しますが、
ここで使用する『041103A4』という数字についてですが
『0411』ってのはロケール番号で
『03A4』ってのはシフトJISを表すって
ことがわかったのですが・・・
って、ことは
OSが変わればこの部分も変わるってこと?
それに、OS以外にも地域オプションの設定内容によっても
変わるのでしょうか?
どのような場合でも対応できるようにしようと思ったら
どうすればよいのでしょうか?
ちなみに、メニューは日本語じゃなく英語(世界標準??)にしてます。
これって安易な考えなんでしょうか?
私の場合は、\VarFileInfo\Translation で VerQueryValue が失敗した場合、
OSがサポートするロケール識別子とコードページを組み合わせてサーチしています。
ロケール情報は TLanguages で、
コードページ情報は EnumSystemCodePages(TLanguagesを真似てクラス化)で取得しています。
いろいろ試してみたのですが・・・
これでよいのでしょうか?
日本語OSでは問題ありませんでした。
function LoadVersonInfo: String;
var
ModuleName: array[0..255] of Char;
nSize: DWord;
pBuffer: PChar;
pValue: PDWord;
nValue: DWord;
Str: String;
pRead: PChar;
nRead: DWord;
tsStrings: TStringList;
begin
// パス付きDLLファイル名を取得
GetModuleFilename(HInstance, ModuleName, SizeOf(ModuleName));
// バージョン情報のサイズを取得
nSize := GetFileVersionInfoSize(ModuleName, nSize);
if nSize > 0 then begin
pBuffer := AllocMem(nSize);
try
// バージョン情報を取得する
if GetFileVersionInfo(ModuleName, 0, nSize, pBuffer) then begin
if VerQueryValue(pBuffer, PChar('VarFileInfo\Translation'), Pointer(pValue), nValue) then begin
Str := Format('StringFileInfo\%04.4x%04.4x\FileVersion',
[LoWord(DWord(pValue^)),
HiWord(DWord(pValue^))]);
if VerQueryValue( pBuffer, PChar(Str), Pointer(pRead),
nRead) then begin
tsStrings := TStringList.Create;
try
ExtractStrings(['.'], [], pRead, tsStrings);
Result := pRead;
finally
tsStrings.Free;
end;
end;
end;
end;
finally
FreeMem(pBuffer, nSize);
end;
end;
end;
私も日本語環境でしか確認していませんがPEさんあげられたコードのような場合、
Office97等のDLL(言語がニュートラルとなっている)で言語情報の取得に失敗していました。
その為、先に述べたような処理を何処かで見つけて解決しました。
一部、省かしてもらいますが下記のような感じです。
function GetFileVersionInfoString(const FileName, KeyName: String): String;
var
dwHandle, dwSize, dwLen: DWORD;
pVerInfo, pLocale: Pointer;
dwLCID: LCID;
function GetKeyRecord(LocaleID: LCID): String;
var
Buffer : Pointer;
Mapping: String;
begin
Result := '';
Buffer := nil;
dwLen := 0;
Mapping:= Format('\StringFileInfo\%0.4x%0.4x\%s', [LOWORD(LocaleID), HIWORD(LocaleID), KeyName]);
VerQueryValue(pVerInfo, PChar(Mapping), Buffer, dwLen);
if (dwLen <> 0) then SetString(Result, PChar(Buffer), StrLen(PChar(Buffer)));
end;
function UnknownLCIDAsString: String;
var
I, J: Integer;
Buffer: String;
wLng : TLanguages;
wCP : TCodePages; // 自作クラス 生成時に EnumSystemCodePages を実行しリスト化
begin
Result:= '';
wLng:= TLanguages.Create; // ロケール情報リスト作成
wCP := TCodePages.Create; // コードページ情報リスト作成
try
for I:= 0 to wCP.Count - 1 do
for J:= 0 to wLng.Count - 1 do
begin
Buffer:= GetKeyRecord(wCP.CodePageID[I] shl 16 or wLng.LocaleID[J]);
if (Buffer <> '') then
begin
Result:= Buffer;
Exit;
end;
end;
finally
wCP.Free;
wLng.Free;
end;
end;
begin
//
// バージョン情報リソース取得迄の処理がここに入ります
//
// 言語情報の取得
if VerQueryValue(pVerInfo, '\VarFileInfo\Translation', pLocale, dwLen) then
CopyMemory(@dwLCID, pLocale, dwLen) else
dwLCID:= 0;
// バージョン情報取得処理呼出
if (dwLCID = 0) then
Result:= UnknownLCIDAsString else
Result:= GetKeyRecord(dwLCID);
//
// 確保したメモリの後始末がここに入ります
//
end;
後述ですが、PEさんのソースコードの戻り値の代入部分は間違いではないでしょうか?
コンパイラに怒られそうです。
> tsStrings := TStringList.Create;
> try
> ExtractStrings(['.'], [], pRead, tsStrings);
> Result := pRead; //← ここ
> finally
> tsStrings.Free;
> end;
Basser さん、どもです。
えっと、
pRead は var で PChar にしてます。
Result は String なので
キャスト変換なしで Result := pRead; は
コンパイルは通っちゃいます
もちろん実行後も期待通りのバージョンが取得できています。
ひょっとして、偶然?たまたま?
確信があって作ってるわけじゃなくって、
PChar にしたり @や^つけたり、いろんなこと試して作って
やっとこさコンパイルが通り結果も同じのが出た
ってだけで、実は・・完璧に理解はできていません。
本当ですね。今迄、互換性が無いと思っていました。
私の誤った思い込みでしたスミマセンm(_ _)m
tsStrings にバージョン番号を分解しているように見えるので、
こちらを戻り値にするのかなと解釈してました。
>ExtractStrings(['.'], [], pRead, tsStrings);
この部分は流用してきたプログラムそのままのこってて、
pRead を表示してやると目的のバージョンが得られたので
それを取得したんです。
未熟なものですみませんでした。
Basser さんどうもありがとうございました。
また、よろしくお願いします。
ツイート | ![]() |