2010-02-08 14 views
5

मैं win32-api library का उपयोग कर फ़ाइल संस्करण जानकारी प्राप्त करने के लिए मानक Win32 API फ़ंक्शंस को कॉल करने का प्रयास कर रहा हूं।रूबी win32api और structs (VerQueryValue)

3 version.dll फ़ंक्शन GetFileVersionInfoSize, GetFileVersionInfo, और VerQueryValue हैं। फिर मैं VS_FIXEDFILEINFO संरचना की एक प्रति प्राप्त करने के लिए kernel32.dll में RtlMoveMemory को कॉल करता हूं (माइक्रोसॉफ्ट प्रलेखन देखें: http://msdn.microsoft.com/en-us/library/ms646997%28VS.85%29.aspx)।

मैंने एक उदाहरण से आकर्षित किया जिसे मैंने वीबी: http://support.microsoft.com/kb/139491 का उपयोग करके देखा था।

मेरी समस्या यह है कि अंततः लौटाया जाने वाला डेटा अपेक्षित संरचना से मेल नहीं खाता है, वास्तव में यह एक स्थिर मूल्य भी नहीं लौटाता है। मुझे संदेह है कि डेटा किसी बिंदु पर उलझ रहा है, शायद VerQueryValue या RtlMoveMemory में।

GetFileVersionInfoSize = Win32::API.new('GetFileVersionInfoSize','PP','I','version.dll') 
GetFileVersionInfo = Win32::API.new('GetFileVersionInfo','PIIP','I', 'version.dll') 
VerQueryValue = Win32::API.new('VerQueryValue','PPPP','I', 'version.dll') 
RtlMoveMemory = Win32::API.new('RtlMoveMemory', 'PPI', 'V', 'kernel32.dll') 

buf = [0].pack('L') 
version_size = GetFileVersionInfoSize.call(myfile + "\0", buf) 
raise Exception.new if version_size == 0 #TODO 

version_info = 0.chr * version_size 
version_ok = GetFileVersionInfo.call(file, 0, version_size, version_info) 
raise Exception.new if version_ok == 0 #TODO 

addr = [0].pack('L') 
size = [0].pack('L') 
query_ok = VerQueryValue.call(version_info, "\\\0", addr, size) 
raise Exception.new if query_ok == 0  #TODO 

# note that at this point, size == 4 -- is that right? 

fixed_info = Array.new(13,0).pack('L*') 
RtlMoveMemory.call(fixed_info, addr, fixed_info.length) 

# fixed_info.unpack('L*') #=> seemingly random data, usually only the first two dwords' worth and the rest 0. 
+1

मुझे लगता है कि मैं इसे समझ से बाहर .. मूल रूप से VerQueryValue एक सूचक (चर addr ऊपर) के लिए सूचक देता है, जबकि RtlMoveMemory एक सूचक चाहता है लंबे समय तक कि addr यानी, संदर्भ। RtlMoveMemory = Win32 :: API.new ('RtlMoveMemory', 'पीएलआई', 'वी', 'kernel32.dll') और फिर इसे बुला: RtlMoveMemory.call ( इसलिए मैं घोषणा बदल fixed_info, addr.unpack ('एल') [0], fixed_info.length) –

उत्तर

3

यह पूर्ण कोड मैं काम करने के लिए, मामला दूसरों में इस तरह के एक समारोह के लिए देख रहे हैं मिल गया है:

यहाँ कोड है।

def file_version ref, options = {} 
    options = {:path => LIBDIR, :extension => 'dll'}.merge(options) 
    begin 
     file = File.join(ROOT, options[:path],"#{ref}.#{options[:extension]}").gsub(/\//,"\\") 
     buf = [0].pack('L') 
     version_size = GetFileVersionInfoSize.call(file + "\0", buf) 
     raise Exception.new if version_size == 0 #TODO 

     version_info = 0.chr * version_size 
     version_ok = GetFileVersionInfo.call(file, 0, version_size, version_info) 
     raise Exception.new if version_ok == 0  #TODO 

     addr = [0].pack('L') 
     size = [0].pack('L') 
     query_ok = VerQueryValue.call(version_info, "\\\0", addr, size) 
     raise Exception.new if query_ok == 0  #TODO 

     fixed_info = Array.new(18,0).pack('LSSSSSSSSSSLLLLLLL') 
     RtlMoveMemory.call(fixed_info, addr.unpack('L')[0], fixed_info.length) 

     fixed_info.unpack('LSSSSSSSSSSLLLLLLL')[5..8].reverse 

    rescue 
     [] 
    end 
end 
1

https://stackoverflow.com/a/2224681/3730446 में जवाब सख्ती से सही नहीं है:

उत्पाद/फ़ाइल संस्करण संख्या (यानी, क्या "संस्करण फ़ाइल" एक dll फ़ाइल गुण विंडो में कहा जाता है) के चार भागों के साथ एक सरणी देता है : VS_FIXEDFILEINFO संरचना में अलग FileVersion और ProductVersion शामिल हैं। वह कोड ProductVersion के दो और महत्वपूर्ण घटकों और FileVersion के दो कम महत्वपूर्ण घटकों वाला एक संस्करण संख्या देता है। मैंने देखा है कि ज्यादातर बार, इससे कोई फर्क नहीं पड़ता क्योंकि Product- और FileVersion दोनों समान मूल्य रखते हैं, लेकिन आप कभी नहीं जानते कि आपको जंगली में क्या सामना करना पड़ सकता है।

हम http://msdn.microsoft.com/en-us/library/windows/desktop/ms646997(v=vs.85).aspx से VS_FIXEDFILEINFO struct और प्रारूप स्ट्रिंग हम पैक और बफर अनपैक करने के लिए प्रयोग कर रहे हैं की तुलना द्वारा इस देख सकते हैं:

typedef struct tagVS_FIXEDFILEINFO { 
    DWORD dwSignature;  // 0: L 
    DWORD dwStrucVersion;  // 1: S 
           // 2: S 
    DWORD dwFileVersionMS; // 3: S 
           // 4: S 
    DWORD dwFileVersionLS; // 5: S 
           // 6: S 
    DWORD dwProductVersionMS; // 7: S 
           // 8: S 
    DWORD dwProductVersionLS; // 9: S 
           // 10: S 
    DWORD dwFileFlagsMask; // 11: L 
    DWORD dwFileFlags;  // 12: L 
    DWORD dwFileOS;   // 13: L 
    DWORD dwFileType;   // 14: L 
    DWORD dwFileSubtype;  // 15: L 
    DWORD dwFileDateMS;  // 16: L 
    DWORD dwFileDateLS;  // 17: L 
} VS_FIXEDFILEINFO; 

सबस्क्रिप्ट 5 से 8, फिर, dwFileVersionLS और dwProductVersionMS के होते हैं। FileVersion और ProductVersion सही ढंग से हो रही इस प्रकार दिखाई देगा:

info = fixed_info.unpack('LSSSSSSSSSSLLLLLLL') 
file_version = [ info[4], info[3], info[6], info[5] ] 
product_version = [ info[8], info[7], info[10], info[9] ] 
संबंधित मुद्दे