HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2020
0322
こいるGetFileVersionInfoSize関数の呼び出し方8解決


こいる

リンク

2020/3/22(Sun) 15:39:36|NO.89786

実行ファイルのバージョン情報を取得したくて、
GetFileVersionInfoSize関数などを使うのまでは分かったのですが、呼び出しの仕方が分かりません。

DLLからの呼び出しではないみたいで、
callfunc命令を使うのかなと思いましたが、
p2の「関数アドレス」というものが分かりませんでした。

ご教示ください。



この記事に返信する


沢渡

リンク

2020/3/22(Sun) 19:26:24|NO.89788

「GetFileVersionInfo」関連のAPIは「Api-ms-win-core-version-l1-1-0.dll」という
DLLを使うようです。
以下、「バージョン情報リソース」のみやってみました。
(参考)
http://tokovalue.jp/function/LoadLibrary.htm
http://tokovalue.jp/function/GetFileVersionInfo.htm
http://tokovalue.jp/function/VerQueryValue.htm
https://araramistudio.jimdo.com/2017/05/19/c-%E3%81%A7%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E6%83%85%E5%A0%B1%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B/
https://docs.microsoft.com/en-us/windows/win32/api/winver/nf-winver-verqueryvaluea
(他の「言語識別子」とかは調べても難しそうだったのでパス)

#include "kernel32.as" #uselib "Api-ms-win-core-version-l1-1-0.dll" #cfunc GetFileVersionInfoSize "GetFileVersionInfoSizeA" sptr,int #func GetFileVersionInfo "GetFileVersionInfoA" sptr,int,int,int #func VerQueryValue "VerQueryValueA" int,str,int,int dummy=0 fname="c:\\windows\\notepad.exe" size=GetFileVersionInfoSize(varptr(fname),varptr(dummy)) sdim data,size GetFileVersionInfo varptr(fname),0,size,varptr(data) ptr=0 VerQueryValue varptr(data),"\\",varptr(ptr),varptr(dummy) dupptr fileinfo,ptr,52,4 mes strf("dwSignature:0x%08X",fileinfo(0)) mes strf("dwStrucVersion:0x%08X",fileinfo(1)) mes strf("dwFileVersionMS:0x%08X",fileinfo(2)) mes strf("dwFileVersionLS:0x%08X",fileinfo(3)) mes strf("dwProductVersionMS:0x%08X",fileinfo(4)) mes strf("dwProductVersionLS:0x%08X",fileinfo(5)) mes strf("dwFileFlagsMask:0x%08X",fileinfo(6)) mes strf("dwFileFlags:0x%08X",fileinfo(7)) mes strf("dwFileOS:0x%08X",fileinfo(8)) mes strf("dwFileType:0x%08X",fileinfo(9)) mes strf("dwFileSubtype:0x%08X",fileinfo(10)) mes strf("dwFileDateMS:0x%08X",fileinfo(11)) mes strf("dwFileDateLS:0x%08X",fileinfo(12))



あらや

リンク

2020/3/22(Sun) 19:57:53|NO.89790

>p2の「関数アドレス」というものが分かりませんでした。
GetFileVersionInfoSizeの2つ目は無視して0にしても大丈夫です。

VerQueryValueで取得する値がポインタになってるのと、
言語識別子は上位と下位を逆にするところで引っかかりますね。

>「GetFileVersionInfo」関連のAPIは「Api-ms-win-core-version-l1-1-0.dll」というDLLを使うようです。
version.dllでもいけました。


#define NULL 0 #uselib "version.dll" #cfunc GetFileVersionInfoSize "GetFileVersionInfoSizeA" str, int #func GetFileVersionInfo "GetFileVersionInfoA" str, int, int, var #func VerQueryValue "VerQueryValueA" var, str, var, var file = ""+dir_exe+"\\hsed3.exe"; // HSPエディタのパス res_size = GetFileVersionInfoSize(file, NULL); // サイズの取得 sdim res, res_size; // リソースを取得するバッファを用意 GetFileVersionInfo file, NULL, res_size, res; // リソース取得 // 言語識別子の取得 pLangCode = 0; VerQueryValue res, "\\VarFileInfo\\Translation", pLangCode, ver_size; dupptr LangCode, pLangCode, 4, 4; // バージョン情報等の取得 string_name = {"Comments CompanyName FileDescription FileVersion InternalName LegalCopyright LegalTrademarks OriginalFilename ProductName ProductVersion PrivateBuild SpecialBuild"}; SubBlock = strf("\\StringFileInfo\\%04X%04X\\", wpeek(LangCode, 0), wpeek(LangCode, 2)); notesel string_name repeat notemax code = ""; noteget code, cnt; sdim VerStr, 256; // リソース文字列取得用 VerQueryValue res, SubBlock+code, pVerStr, ver_size; // 各情報取得 // この後は画面に情報を描画するだけの処理 if( ver_size != 0 ) { dupptr VerStr, pVerStr, ver_size, 2; if( code != "OriginalFilename" ) { mes code+"\t\t: "+VerStr; } else { mes code+"\t: "+VerStr; } } else { if( code != "OriginalFilename" ) { mes code+"\t\t: N/A"; } else { mes code+"\t: N/A"; } } loop



こいる

リンク

2020/3/22(Sun) 21:56:14|NO.89791

>沢渡さん
DLLから呼び出すのですね。(逆にそれ以外で呼び出す方法はない?)
実行してみましたが、9行目でエラー38がでて実行できませんでした。


>あらやさん
おおすごい!できました!


APIの説明をみて、なんとなく仕組みは分かったのですが、
17,41行目のdupptr命令はなにをしているのですか?

そのまま変数を指定するのではだめなのでしょうか?


また、31行目のstrf命令は、
%04xを16進数に変換しているのは分かるのですが、
その %04x の「04」はなにを表しているのですか?

桁数みたいなものなのでしょうか?
それならなぜ4桁(4yte)を指定しているのに
wpeekで2byteしか取得しないのでしょうか?

それとも、この認識自体が間違っているのでしょうか?



あらや

リンク

2020/3/22(Sun) 23:05:24|NO.89792

>17,41行目のdupptr命令はなにをしているのですか?
VerQueryValueで取得される値がポインタなので
dupptrを使って変数として扱えるようにしているだけです。

そのまま使うと下記のようにポインタが表示されるだけになります。

i = 123; mes i; // 通常の変数 mes varptr(i); // 変数のポインタ



>また、31行目のstrf命令は、
>%04xを16進数に変換しているのは分かるのですが、
>その %04x の「04」はなにを表しているのですか?
>桁数みたいなものなのでしょうか?
>それならなぜ4桁(4yte)を指定しているのに
>wpeekで2byteしか取得しないのでしょうか?
『dupptr LangCode, pLangCode, 4, 4;』
このdupptrの最後に4を指定しているので
LangCodeは整数型(32ビット=4バイト)の変数になります。

丁寧に書くと下記が分かりやすいでしょうか。

dupptr LangCode, pLangCode, 4, 4; High = (LangCode >> 16) & 0xFFFF; // 上位16ビット(2バイト)を取得 Low = LangCode & 0xFFFF; // 下位16ビット(2バイト)を取得 LangCode = (Low << 16) & High; // 上位と下位の入れ替え // 〜省略〜 SubBlock = strf("\\StringFileInfo\\%08X\\", LangCode );

これが面倒だったのでwpeekで省略させていただきました。

また、VerQueryValueの仕様で16進数で8桁の文字列と決まっているので
桁を揃えるために%04Xとしています。

整数型と文字列型が混在しているのでわかりにくくなっていますが、
16進数で『FF』は文字としては2文字(バイト)ですが、
整数型変数では1バイトです。

つまり、整数型の変数で2バイト分取得して
16進の文字列に変換すると4バイトになります。



%04xの桁などは下記のソースを参考にしてみて下さい。

i = 0x0123ABCD; iHigh = (i >> 16) & 0xFFFF; // 上位16ビット(2バイト)を取得 iLow = i & 0xFFFF; // 下位16ビット(2バイト)を取得 mes "上位16ビットと下位16ビットを分割して表示\n"; mes strf("元の数値:\t%04X,%04X", iHigh, iLow); // 元の数値(16進数) mes strf("入れ替えた数値:%04X,%04X", iLow, iHigh); // 上位と下位の入れ替え mes strf("wpeek使用(桁無し )%X,%X", wpeek(i, 0), wpeek(i,2)); // 桁無し mes strf("wpeek使用(桁有り1)%4X,%4X", wpeek(i, 0), wpeek(i,2)); // 桁有り(上の0はスペースで代用される) mes strf("wpeek使用(桁有り2)%04X,%04X", wpeek(i, 0), wpeek(i,2)); // 桁有り(0も反映される)
ちなみにXを大文字にすると16進の文字も『FFFF』と大文字になりますし、
小文字のxにすると16進の文字も『ffff』のように小文字になります。



あらや

リンク

2020/3/22(Sun) 23:28:23|NO.89793

dupptrの説明が足りない気がするので追記します。

ポインタとは変数のアドレス(場所)を意味しているだけです。

例え話ですが、
電話に登録している人の番号を調べようと名前で検索したら

[『こ』の項目で3番目です]

とか返ってきたようなものだと考えてください。

当然そのままでは電話番号が分からないので、
dupptrで[『こ』の項目で3番目]という場所に登録されている
電話番号を取得するために必要な手続きをしている感じです。



沢渡

リンク

2020/3/23(Mon) 08:13:09|NO.89794

>実行してみましたが、9行目でエラー38がでて実行できませんでした。
私の環境ではできたのですが、これ↓が原因かもしれません。
https://www.softantenna.com/wp/windows/api-ms-win-crt-runtime-l1-1-0-dll/
あらやさんの言うversion.dllに置き換えれば上手くいくと思います。
(まあ、あらやさんの方が完全上位互換ですから今更実行する必要もないですが)



あらや

リンク

2020/3/23(Mon) 12:14:23|NO.89797

すみません。
説明用のソースにミスがありました。

このソースですが

dupptr LangCode, pLangCode, 4, 4; High = (LangCode >> 16) & 0xFFFF; // 上位16ビット(2バイト)を取得 Low = LangCode & 0xFFFF; // 下位16ビット(2バイト)を取得 LangCode = (Low << 16) & High; // 上位と下位の入れ替え // 〜省略〜 SubBlock = strf("\\StringFileInfo\\%08X\\", LangCode );


>LangCode = (Low << 16) & High; // 上位と下位の入れ替え
ここは[&]ではなく[|]でした。

下記に訂正させていただきます。

dupptr LangCode, pLangCode, 4, 4; High = (LangCode >> 16) & 0xFFFF; // 上位16ビット(2バイト)を取得 Low = LangCode & 0xFFFF; // 下位16ビット(2バイト)を取得 LangCode = (Low << 16) | High; // 上位と下位の入れ替え // 〜省略〜 SubBlock = strf("\\StringFileInfo\\%08X\\", LangCode );


失礼いたしました。



こいる

リンク

2020/3/23(Mon) 14:38:54|NO.89799

>あらやさん
なるほど。丁寧にありがとうございます。
なんとなくですが理解できました。


>沢渡さん
おっしゃる通り、version.dllに置き換えると実行ができました。


沢渡さん、あらやさん、お二人ともありがとうございました!



ONION software Copyright 1997-2023(c) All rights reserved.