gz13802424 发表于 2019-1-15 20:06:39

文件 详细信息

本帖最后由 gz13802424 于 2019-1-15 20:13 编辑

今天太闲了,翻出些旧代码进行优化,在优化字体安装这一部分时,发现Au3自带的FileGetVersion只能查询到文件的部分信息    $FV_COMMENTS ("Comments") - 注释
    $FV_COMPANYNAME ("CompanyName") - 公司名称
    $FV_FILEDESCRIPTION ("FileDescription") - 文件说明
    $FV_FILEVERSION ("FileVersion") - 文件版本
    $FV_INTERNALNAME ("InternalName") - 内部名称
    $FV_LEGALCOPYRIGHT ("LegalCopyright") - 法律版权
    $FV_LEGALTRADEMARKS ("LegalTrademarks") - 法律商标
    $FV_ORIGINALFILENAME ("OriginalFilename") - 原始文件名
    $FV_PRODUCTNAME ("ProductName") - 产品名称
    $FV_PRODUCTVERSION ("ProductVersion") - 产品版本
    $FV_PRIVATEBUILD ("PrivateBuild") - 专用编译
    $FV_SPECIALBUILD ("SpecialBuild") - 特别编译

如果需要比较齐全的文件信息,看样子只能自己折腾,首先找出自己写的VBS脚本

ExplorerVer = GetProductVersion(SysWOW64Drive & "\Windows", "explorer.exe", "文件版本")

'********************************
'**      
'**      读取文件扩展信息
'**      
'********************************
Function GetProductVersion(Folder, FiLename, DetailsOf)
set objShell = CreateObject("shell.application")
set objFolder = objShell.NameSpace(lcase(Folder))
GetProductVersion = ""
ArrDetailsOf = Split(DetailsOf, "|")
Max_j = UBound(ArrDetailsOf)
For i = 0 to 300
      For j=0 to Max_j
                If objFolder.GetDetailsOf(objFolder.Items, i) = ArrDetailsOf(j) then
                        set objFolderItem = objFolder.ParseName(FiLename)
                        GetProductVersion = GetProductVersion & objFolder.GetDetailsOf(objFolderItem, i) & chr(13)
                        ArrDetailsOf(j) = ArrDetailsOf(Max_j)
                        Max_j = Max_j - 1
                End If
      Next
      if Max_j < 0 then Exit For
Next
if GetProductVersion <> "" then GetProductVersion= Left(GetProductVersion, Len(GetProductVersion)-1)
End Function      'Function GetProductVersion


这个VBS脚本是利用信息类型获取文件对应信息

在转变为Au3代码时,硬是没把objFolder.GetDetailsOf(objFolder.Items, i) 写出来Au3对应的代码(真心脸红,我是个靠google来写代码的门外汉),幸好Au3交流群的一位大神(风过影相随)伸出援助之手
$sSourceFile = "U:\Au3\Patch\DFPHaiBaoW12-GB.TTF"
$sIndex = _GetFileDetailIndexByType($sSourceFile, "标题")
$sFileInfo = _GetFileDetailInfoByIndex($sSourceFile,$sIndex)


;// 利用信息类型获取文件对应信息的索引值
Func _GetFileDetailIndexByType($sFile, $sDetailType)
      If FileExists($sFile) Then
                Dim $f, $shell, $oParentShell, $oFile, $sInfoType
                Local $sIndex = 0 ;//起始索引
                $oFile = ObjCreate("Scripting.FileSystemObject")
                $f = $oFile.GetFile($sFile) ;//返回文件对应的文件对象
                $oParentShell = ObjCreate("Shell.Application")
                $shell = $oParentShell.Namespace($f.ParentFolder.Path);ParentFolder......返回该文件夹
                While 1
                        $sInfoType = $shell.GetDetailsOf(0, $sIndex) ;//文件的信息类型
                        If $sInfoType = '' Then ExitLoop ;//信息类型为空,跳出循环
                        If String($sInfoType) = String($sDetailType) Then
                              ;//成功得到对应的索引值
                              $shell = 0
                              $oFile = 0
                              $oParentShell = 0
                              $f = 0
                              Return $sIndex
                        EndIf
                        $sIndex += 1 ;//索引值加1
                WEnd
               
                ;//未获取对应的索引值
                $shell = 0
                $oFile = 0
                $oParentShell = 0
                $f = 0
                Return SetError(2) ;//未获取对应的索引值
      Else
                ;// 文件不存在
                SetError(1)
      EndIf
EndFunc   ;==>_GetFileDetailIndexByType

;//利用索引值 获取文件对应索引下的 信息
Func _GetFileDetailInfoByIndex($sFile, $sIndex)
      If FileExists($sFile) Then
                Dim $f, $shell, $oParentShell, $oFile, $sDetailInfo
                $oFile = ObjCreate("Scripting.FileSystemObject")
                $f = $oFile.GetFile($sFile) ;//返回文件对应的文件对象
                $oParentShell = ObjCreate("Shell.Application")
                $shell = $oParentShell.Namespace($f.ParentFolder.Path);ParentFolder......返回该文件夹
                $sDetailInfo = $shell.GetDetailsOf($shell.Items.Item($f.Name), $sIndex) ;//获取对应的信息

                $shell = 0
                $oFile = 0
                $oParentShell = 0
                $f = 0
                Return $sDetailInfo
      Else
                ;// 文件不存在
                SetError(1)
      EndIf
EndFunc   ;==>_GetFileDetailInfoByIndex


最后在(风过影相随)代码基础上,重新写出了我自己需要的代码
$sSourceFile = "U:\Au3\Patch\DFPHaiBaoW12-GB.TTF"
$sFileInfo = _GetProductVersion($sSourceFile, "标题|类型")
$sFileInfo = _GetProductVersion($sSourceFile, "标题")


Func _GetProductVersion($sFile, $sDetailType)
      Local $sDetailInfo = ""
      If FileExists($sFile) Then
                Dim $Path_, $Name_, $shell, $oParentShell, $sInfoType
                Local $sIndex = 0
                $Path_ = StringRegExpReplace($sFile, '(^.*)(\\.*$)', '$1')
                $Name_ = StringRegExpReplace($sFile, '^.*\\', '')
                $oParentShell = ObjCreate("Shell.Application")
                $shell = $oParentShell.Namespace($Path_)
                While 1
                        $sInfoType = $shell.GetDetailsOf(0, $sIndex)
                        If @error Then ExitLoop
                        If StringRegExp($sInfoType, $sDetailType) Then
                              $sDetailType = StringReplace($sDetailType, $sInfoType, "")
                              If @extended = 1 Then
                                        $sDetailInfo = $sDetailInfo & $shell.GetDetailsOf($shell.Items.Item($Name_), $sIndex) & "|"
                                        $sDetailType = StringTrimLeft($sDetailType, 1)
                              EndIf
                        EndIf
                        If $sDetailType = "" Then ExitLoop
                        $sIndex += 1
                        If $sIndex = 1000 Then ExitLoop
                WEnd
      EndIf
      Return SetError(($sDetailInfo = "" ? 1 : 0), $sIndex, StringTrimRight($sDetailInfo, 1))
EndFunc   ;==>_GetProductVersion


gz13802424 发表于 2019-1-15 20:35:14

补正几点

一、需要查找的文件信息可以通过 | 分隔同时查找多个信息
$sFileInfo = _GetProductVersion($sSourceFile, "标题|类型")

二、我使用了二个正则来分离 目录 和 文件名
$Path_ = StringRegExpReplace($sFile, '(^.*)(\\.*$)', '$1')
$Name_ = StringRegExpReplace($sFile, '^.*\\', '')

三、由于设定了查询信息可以有多个,一般来说都会用二个循环来查询,一个循环枚举出所有信息,再套一个循环逐一检查是否匹配枚举出来的信息
由于设定了入口参数使用 | 分隔,这正好符合正则的代达方式,所以我干脆在这里换成了用正则的方法
If StringRegExp($sInfoType, $sDetailType) Then
StringRegExp($sInfoType, $sDetailType) ----> StringRegExp("程序标题", "标题|类型")
这样就简便了编程,不需要套用二个循环

但是由于这里使用的正则没有严谨匹配,如果查询到的信息是 "程序标题" "程序类型",那么也会匹配成功
为了纠正这种误判,接下来使用了
$sDetailType = StringReplace($sDetailType, $sInfoType, "")
If @extended = 1 Then


通过 StringReplace($sDetailType, $sInfoType, "") 可以把已经精确匹配到的条件过滤掉(注意一下这条语句和上面那条正则,二个参数的位置是互换了)
StringReplace($sDetailType, $sInfoType, "") ----> StringReplace( "标题|类型","程序标题","")
这样如果不是完全匹配的信息,@extended 将会是0,那么就可以防止误判了

整个程序写下来还有一个地方不满意,那么就循环的退出机制
If @error Then ExitLoop,事实上这句是没用的
全靠If $sIndex = 1000 Then ExitLoop来退出循环

有请路过的各位帮忙完善一下这里的循环退出机制

haijie1223 发表于 2019-1-15 21:22:47

字体这个东西比较特殊,和dll,exe又不一样。如果你仅仅是想获取字体的名字,有现成的api:GetFontResourceInfo
#Include <WinAPIEx.au3>
Local $sFontFile = @ScriptDir & "\DFPHaiBaoW12-GB.TTF"
Local $sFontName = _WinAPI_GetFontResourceInfo($sFontFile, True)
ConsoleWrite($sFontName & @CRLF)

haijie1223 发表于 2019-1-15 21:38:08

如果只是为了记录自己的学习心得,发到中文资料区更合适。
页: [1]
查看完整版本: 文件 详细信息