公司的业务需要,nodejs要读取文件版本号。
同事要求我用delphi编写dll,以供nodejs调用,结果通过json返回。
delphi代码如下:
1 function GetFileInfo(APath: PAnsiChar): PAnsiChar; 2 var 3 sPath: string; 4 FInfoSize, Temp, Len: Cardinal; 5 InfoBuf: Pointer; 6 TranslationLength: Cardinal; 7 TranslationTable: Pointer; 8 LanguageID, CodePage, LookupString: String; 9 Value: PChar; 10 vJ: ISuperObject; 11 begin 12 sPath := Utf8ToAnsi(strPas(APath)); 13 FInfoSize := GetFileVersionInfoSize(PChar(sPath), Temp); 14 vJ := SO; 15 if FInfoSize > 0 then 16 begin 17 InfoBuf := AllocMem(FInfoSize); 18 try // try 19 GetFileVersionInfo(PChar(sPath), 0, FInfoSize, InfoBuf); 20 21 if VerQueryValue( InfoBuf, 'VarFileInfoTranslation', TranslationTable, TranslationLength ) then 22 begin 23 CodePage := Format( '%.4x', [ HiWord( PLongInt( TranslationTable )^ ) ] ); 24 LanguageID := Format( '%.4x', [ LoWord( PLongInt( TranslationTable )^ ) ] ); 25 end; 26 LookupString := 'StringFileInfo' + LanguageID + CodePage + ''; 27 28 if VerQueryValue( InfoBuf, PChar( LookupString + 'CompanyName' ), Pointer( Value ), Len ) then 29 vJ.S['CompanyName'] := Value; 30 if VerQueryValue( InfoBuf, PChar( LookupString + 'FileDescription' ), Pointer( Value ), Len ) then 31 vJ.S['FileDescription'] := Value; 32 if VerQueryValue( InfoBuf, PChar( LookupString + 'FileVersion' ), Pointer( Value ), Len ) then 33 vJ.S['FileVersion'] := Value; 34 if VerQueryValue( InfoBuf, PChar( LookupString + 'InternalName' ), Pointer( Value ), Len ) then 35 vJ.S['InternalName'] := Value; 36 if VerQueryValue( InfoBuf, PChar( LookupString + 'LegalCopyright' ), Pointer( Value ), Len ) then 37 vJ.S['LegalCopyright'] := Value; 38 if VerQueryValue( InfoBuf, PChar( LookupString + 'LegalTrademarks' ), Pointer( Value ), Len ) then 39 vJ.S['LegalTrademarks'] := Value; 40 if VerQueryValue( InfoBuf, PChar( LookupString + 'OriginalFilename' ), Pointer( Value ), Len ) then 41 vJ.S['OriginalFilename'] := Value; 42 if VerQueryValue( InfoBuf, PChar( LookupString + 'ProductName' ), Pointer( Value ), Len ) then 43 vJ.S['ProductName'] := Value; 44 if VerQueryValue( InfoBuf, PChar( LookupString + 'ProductVersion' ), Pointer( Value ), Len ) then 45 vJ.S['ProductVersion'] := Value; 46 if VerQueryValue( InfoBuf, PChar( LookupString + 'Comments' ), Pointer( Value ), Len ) then 47 vJ.S['Comments'] := Value; 48 finally // wrap up finally 49 FreeMem(InfoBuf, FInfoSize); 50 end; // end try finally 51 end; 52 Result := PAnsiChar(AnsiString(vJ.AsJSon)); 53 end;
PS:
1. 用到的字符串可能较长,注意调用ShareMem
2. 所有的string类型都需要定义成PAnsiChar
3. 此处nodejs使用的编码是utf8,需要转码
4. 返回值,需先通过AnsiString转换,再转换PAnsiChar,不然只能读取到第一个字符
nodejs测试代码如下:
1 var ffi = require('ffi'); 2 3 try { 4 var demo = ffi.Library('./fileInfo', { 5 'GetFileInfo': [ 'string', ['string'] ], 6 }); 7 8 console.log(demo); 9 const info = demo.GetFileInfo('C:\Program Files (x86)\Tencent\WeChat\WeChat.exe');
10 console.log(JSON.parse(info)); 11 console.log('End Test'); 12 } catch(err) { 13 console.log(err); 14 }
测试结果如下: