下面是我从在线资源获得的代码示例,但它假设使用fullframework,但是当我尝试使用C#智能设备构建它时,它会抛出异常,说它内存不足。有谁知道如何修复它在紧凑型上使用?当我第二次调用最后一个VerQueryValue时出现内存不足的异常。
感谢,
[DllImport("coredll.dll")]
public static extern bool VerQueryValue(byte[] buffer, string subblock, out IntPtr blockbuffer, out uint len);
[DllImport("coredll.dll")]
public static extern bool VerQueryValue(byte[] pBlock, string pSubBlock, out string pValue, out uint len);
//
private static void GetAssemblyVersion()
{
string filename = @"\Windows\MyLibrary.dll";
if (File.Exists(filename))
{
try {
int handle = 0;
Int32 size = 0;
size = GetFileVersionInfoSize(filename, out handle);
if (size > 0)
{
bool retValue;
byte[] buffer = new byte[size];
retValue = GetFileVersionInfo(filename, handle, size, buffer);
if (retValue == true)
{
bool success = false;
IntPtr blockbuffer = IntPtr.Zero;
uint len = 0;
//success = VerQueryValue(buffer, "\\", out blockbuffer, out len);
success = VerQueryValue(buffer, @"\VarFileInfo\Translation", out blockbuffer, out len);
if(success)
{
int p = (int)blockbuffer;
//Reads a 16-bit signed integer from unmanaged memory
int j = Marshal.ReadInt16((IntPtr)p);
p += 2;
//Reads a 16-bit signed integer from unmanaged memory
int k = Marshal.ReadInt16((IntPtr)p);
string sb = string.Format("{0:X4}{1:X4}", j, k);
string spv = @"\StringFileInfo\" + sb + @"\ProductVersion";
string versionInfo;
VerQueryValue(buffer, spv, out versionInfo, out len);
}
}
}
}
catch (Exception err)
{
string error = err.Message;
}
}
}
答案 0 :(得分:0)
添加这两个陈述后:
Int32 dwVerMinor = j & 0xffff;
Int32 dwVerBuild = k & 0xffff;
它能够检索DLL版本。
答案 1 :(得分:0)
这是一个实现:
using DWORD = System.UInt32;
public static class NativeFile
{
public struct NativeFileInfo
{
public Version Version;
public NameValueCollection StringTable;
}
public unsafe static NativeFileInfo GetFileInfo(string path)
{
if (!File.Exists(path))
{
throw new FileNotFoundException();
}
IntPtr handle;
var size = GetFileVersionInfoSize(path, out handle);
var buffer = Marshal.AllocHGlobal(size);
try
{
if (!GetFileVersionInfo(path, handle, size, buffer))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
IntPtr pVersion;
int versionLength;
VerQueryValue(buffer, “\”, out pVersion, out versionLength);
var versionInfo = (VS_FIXEDFILEINFO)Marshal.PtrToStructure(pVersion, typeof(VS_FIXEDFILEINFO));
var version = new Version((int)versionInfo.dwFileVersionMS >> 16,
(int)versionInfo.dwFileVersionMS & 0xFFFF,
(int)versionInfo.dwFileVersionLS >> 16,
(int)versionInfo.dwFileVersionLS & 0xFFFF);
// move to the string table and parse
var pStringTable = ((byte*)pVersion.ToPointer()) + versionLength;
var strings = ParseStringTable(pStringTable, size – versionLength);
return new NativeFileInfo
{
Version = version,
StringTable = strings
};
}
finally
{
Marshal.FreeHGlobal(buffer);
}
}
private unsafe static NameValueCollection ParseStringTable(byte* pStringTable, int length)
{
NameValueCollection nvc = new NameValueCollection();
byte* p = pStringTable;
short stringFileInfoLength = (short)*p;
byte* end = pStringTable + length;
p += (2 + 2 + 2); // length + valuelength + type
// verify key
var key = Marshal.PtrToStringUni(new IntPtr(p), 14);
if (key != "StringFileInfo") throw new ArgumentException();
// move past the key to the first string table
p += 30;
short stringTableLength = (short)*p;
p += (2 + 2 + 2); // length + valuelength + type
// get locale info
key = Marshal.PtrToStringUni(new IntPtr(p), 8);
// move to the first string
p += 18;
while (p < end)
{
short stringLength = (short)*p;
p += 2;
short valueChars = (short)*p;
p += 2;
short type = (short)*p;
p += 2;
if (stringLength == 0) break;
if ((valueChars == 0) || (type != 1))
{
p += stringLength;
continue;
}
var keyLength = stringLength – (valueChars * 2) – 6;
key = Marshal.PtrToStringUni(new IntPtr(p), keyLength / 2).TrimEnd(”);
p += keyLength;
var value = Marshal.PtrToStringUni(new IntPtr(p), valueChars).TrimEnd(”);
p += valueChars * 2;
if ((int)p % 4 != 0) p += 2;
nvc.Add(key, value);
}
return nvc;
}
private const string COREDLL = "coredll.dll";
[DllImport(COREDLL, SetLastError = true)]
private static extern int GetFileVersionInfoSize(string lptstrFilename, out IntPtr lpdwHandle);
[DllImport(COREDLL, SetLastError = true)]
private static extern bool GetFileVersionInfo(string lptstrFilename, IntPtr dwHandle, int dwLen, IntPtr lpData);
[DllImport(COREDLL, SetLastError = true)]
private static extern bool VerQueryValue(IntPtr pBlock, string lpSubBlock, out IntPtr lplpBuffer, out int puLen);
[StructLayout(LayoutKind.Sequential)]
private struct VS_FIXEDFILEINFO
{
public DWORD dwSignature;
public DWORD dwStrucVersion;
public DWORD dwFileVersionMS;
public DWORD dwFileVersionLS;
public DWORD dwProductVersionMS;
public DWORD dwProductVersionLS;
public DWORD dwFileFlagsMask;
public DWORD dwFileFlags;
public FileOS dwFileOS;
public FileType dwFileType;
public DWORD dwFileSubtype;
public DWORD dwFileDateMS;
public DWORD dwFileDateLS;
};
public enum FileOS : uint
{
Unknown = 0x00000000,
DOS = 0x00010000,
OS2_16 = 0x00020000,
OS2_32 = 0x00030000,
NT = 0x00040000,
WindowsCE = 0x00050000,
}
public enum FileType : uint
{
Unknown = 0x00,
Application = 0x01,
DLL = 0x02,
Driver = 0x03,
Font = 0x04,
VXD = 0x05,
StaticLib = 0x07
}
}
使用示例:
class Program
{
static void Main(string[] args)
{
string target = “\FlashFX Disk\ARMv4i\conmanclient2.exe”;
var version = NativeFile.GetFileInfo(target);
Console.WriteLine(string.Format(“File: { 0}”, Path.GetFileName(target)));
Console.WriteLine(string.Format(“Version: { 0}”, version.Version.ToString(4)));
foreach (var key in version.StringTable.AllKeys)
{
Console.WriteLine(string.Format(“{ 0}: { 1}”, key, version.StringTable[key]));
}
Console.ReadLine();
}