[リストへもどる]   [VBレスキュー(花ちゃん)]
一括表示

投稿時間:2006/09/18(Mon) 18:37
投稿者名:Nemo
Eメール:
URL :
タイトル:
バージョン情報の取得
環境:WindowsXP SP2, VB6.0 SP6

外部のDLLやEXEファイルのバージョン情報を取得したいのですが、
WinAPIのGetFileVersionInfo等を使っても変な数値しか取得出来ません。
ちなみに、参照したページは
http://www.kit.co.jp/vbit/QAndA04.htm#ファイルのバージョン情報
ここです。
他にも一つくらいあったのですが、要領はほぼ同じ感じでした。
気になるところと言えば、APIビュアーで読み込む WinApi32.txt
の中に、MoveMemory の関数が無かった点でしょうか・・・。
一応デバッガは起動せずに、おかしな数値のバージョン(しかも毎度違う)が表示されるだけです

どうか助言いただけませんでしょうか?よろしくお願いします。

投稿時間:2006/09/18(Mon) 23:59
投稿者名:Blue
Eメール:
URL :
タイトル:
Re: バージョン情報の取得
実際どんなコードになっていますか?

> WinApi32.txt の中に、MoveMemory の関数が無かった点でしょうか・・・。
たぶんCopyMemoryのことだと思う。

Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

# 以前この手のAPIの質問を解答した記憶があるんだけど、どこでしたんだけかな。
## ↑
## たぶん今、過去ログも見れない状態の「VB初心者友の会」にしたと思う。

投稿時間:2006/09/19(Tue) 00:40
投稿者名:Nemo
Eメール:
URL :
タイトル:
Re^2: バージョン情報の取得
レスありがとうございます。
CopyMemory関数ならApiにありました。
、、、が、結果は同じでした。一応コードを載せますね。
---------------------------------------------------------------
Type VS_FIXEDFILEINFO
    dwSignature As Long
    dwStrucVersionl As Integer
    dwStrucVersionh As Integer
    dwFileVersionMSl As Integer
    dwFileVersionMSh As Integer
    dwFileVersionLSl As Integer
    dwFileVersionLSh As Integer
    dwProductVersionMSl As Integer
    dwProductVersionMSh As Integer
    dwProductVersionLSl As Integer
    dwProductVersionLSh As Integer
    dwFileFlagsMask As Long
    dwFileFlags As Long
    dwFileOS As Long
    dwFileType As Long
    dwFileSubtype As Long
    dwFileDateMS As Long
    dwFileDateLS As Long
End Type
Type CODEPAGE
    lngLOW As Integer
    lngHIGH As Integer
End Type
Declare Function GetFileVersionInfo Lib "Version.dll" Alias "GetFileVersio
nInfoA" ( _
    ByVal lptstrFilename As String, _
    ByVal dwHandle As Long, _
    ByVal dwLen As Long, _
    lpData As Any) As Long
Declare Function GetFileVersionInfoSize Lib "Version.dll" Alias "GetFileVe
rsionInfoSizeA" ( _
    ByVal lptstrFilename As String, _
    lpdwHandle As Long) As Long
Declare Function VerQueryValue Lib "Version.dll" Alias "VerQueryValueA&quo
t; ( _
    pBlock As Any, _
    ByVal lpSubBlock As String, _
    lplpBuffer As Any, _
    puLen As Long) As Long
Declare Function MoveMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
    ByRef Dest As Any, ByRef Src As Any, ByVal Size As Long) As Long
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
    Destination As Any, Source As Any, ByVal Length As Long)

Public Sub GetFileVersion(Path As String)

Dim LngRet As Long
Dim lngDummy As Long
Dim bBuffer() As Byte
Dim lngLen As Long
Dim lpBuffer As Long
Dim ffi As VS_FIXEDFILEINFO

If Dir$(Path) = "" Then
    Exit Sub
End If

' strFileName に取得したいファイル名をセット
strFileName = Path

' サイズを取得
lngLen = GetFileVersionInfoSize(strFileName, lngDummy)
If lngLen < 1 Then
    Exit Sub
End If

' バイトの配列の領域取得
ReDim bBuffer(lngLen)

' ファイル バージョン情報を取得
LngRet = GetFileVersionInfo(strFileName, 0&, lngLen, bBuffer(0))
LngRet = VerQueryValue(bBuffer(0), "\", lpBuffer, lngLen)

' バイトの処理
CopyMemory ffi, lpBuffer, Len(ffi)

' ファイル バージョン
Debug.Print "FileViersion = " & _
Format$(ffi.dwFileVersionMSh) & "." & _
Format$(ffi.dwFileVersionMSl) & "." & _
Format$(ffi.dwFileVersionLSh) & "." & _
Format$(ffi.dwFileVersionLSl)

End Sub
---------------------------------------------------------------
長くなりましたが、こんな感じです。
指定したexe,dllファイルのフルパスを渡してdebug出力させるようにしただけです。

投稿時間:2006/09/19(Tue) 02:05
投稿者名:Blue
Eメール:
URL :
タイトル:
Re^3: バージョン情報の取得
Option Explicit

Type CODEPAGE
    lngLOW As Integer
    lngHIGH As Integer
End Type

Private Declare Function GetFileVersionInfoSize Lib "version" Alias "GetFileVersionInfoSizeA" ( _
    ByVal lptstrFilename As String, ByRef lpdwHandle As Long) As Long
Private Declare Function GetFileVersionInfo Lib "version" Alias "GetFileVersionInfoA" ( _
    ByVal lptstrFilename As String, ByVal dwHandle As Long, _
    ByVal dwLen As Long, ByRef lpData As Byte) As Long
Private Declare Function VerQueryValue Lib "version" Alias "VerQueryValueA" ( _
    ByRef pBlock As Byte, ByVal lpSubBlock As String, _
    ByRef lplpBuffer As Long, ByRef puLen As Long) As Long
Private Declare Function MoveMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
    ByRef Dest As Any, ByRef Src As Any, ByVal size As Long) As Long
    Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
    Destination As Any, Source As Any, ByVal Length As Long)

Public Sub GetFileVersion(ByVal path As String)
    Dim size     As Long
    Dim dummy    As Long
    Dim vi()     As Byte
    Dim subblock As String
    Dim pointa   As Long
    Dim cp       As CODEPAGE
    Dim buff()   As Byte
    Dim verstr   As String
    
    ' バージョンリソースのサイズを取得
    size = GetFileVersionInfoSize(path, dummy)
    If size < 1 Then
        Exit Sub
    End If
    ' バージョンリソースを取得
    ReDim vi(size)
    If GetFileVersionInfo(path, 0&, size, vi(0)) = 0 Then
        Exit Sub
    End If
    ' バージョンリソースの言語情報を取得
    subblock = "\VarFileInfo\Translation"
    If VerQueryValue(vi(0), subblock, pointa, size) = 0 Then
        Exit Sub
    End If
    CopyMemory cp, ByVal pointa, size
    ' 製品バージョンを取得
    subblock = "\StringFileInfo\" & Right$("0000" & Hex(cp.lngLOW), 4) & Right$("0000" & Hex(cp.lngHIGH), 4) & "\ProductVersion"
    If VerQueryValue(vi(0), subblock, pointa, size) = 0 Then
        Exit Sub
    End If
    ReDim buff(size)
    CopyMemory buff(0), ByVal pointa, size ' Shift_JIS文字列
    verstr = StrConv(buff, vbUnicode)      ' Unicode変換
    verstr = Left(verstr, InStr(verstr, vbNullChar) - 1)  ' 末尾のNULL文字削除
    
    MsgBox verstr
    
End Sub

参考:ファイルのバージョン情報を取得する(VC++)
http://katsura-kotonoha.sakura.ne.jp/prog/win/tip00019.shtml

投稿時間:2006/09/19(Tue) 02:48
投稿者名:Blue
Eメール:
URL :
タイトル:
Re^3: バージョン情報の取得
> ' バイトの処理
> CopyMemory ffi, lpBuffer, Len(ffi)
ココが不味かっただけのようです。

' バイトの処理
CopyMemory ffi, ByVal lpBuffer, Len(ffi)

投稿時間:2006/09/19(Tue) 05:36
投稿者名:Nemo
Eメール:
URL :
タイトル:
解決
> > ' バイトの処理
> > CopyMemory ffi, lpBuffer, Len(ffi)
> ココが不味かっただけのようです。
>
> ' バイトの処理
> CopyMemory ffi, ByVal lpBuffer, Len(ffi)

上手く行きました!
どうもメモリ関連はC++に慣れてるのでByvalとか忘れがちのようです。^^;
とにかく細かい部分までの指摘ありがとうございました。

投稿時間:2006/09/19(Tue) 09:16
投稿者名:Blue
Eメール:
URL :
タイトル:
Re: 解決
というか、参考しにしたサイトの後ろの方にちゃんとAPI宣言がのってるやんけ。
http://www.kit.co.jp/vbit/QAndA04.htm#

> 以下は、宣言部です。標準モジュールに入れてください。

>  Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
>     dest As Any, _
>     ByVal Source As Long, _
>     ByVal length As Long)
おそらく、第2引数をデフォルトで ByVal にしてあるので、 CopyMemory と別の名前にしているのでしょう。

# 7267のヤツものっていた。orz    ちょっと苦労したんだけどな。