获取 exe 文件的版本,而无需在 .NET Compact Framework 中加载
本文关键字:NET Compact Framework 加载 文件 exe 版本 获取 | 更新日期: 2023-09-27 17:56:31
我有一个在.NET Compact Framework 3.5上运行的移动应用程序和一个在同一平台上运行的更新程序应用程序。当用户点击应用程序快捷方式时,更新程序应用程序将首先运行,并检查主应用程序的新版本是否可用。为此,我使用 Assembly.LoadFrom 方法加载主 exe 程序集并获取当前版本。如果它找到新版本(通过 Web 服务),它会下载新文件并替换。这工作正常。问题是,当它尝试替换主exe文件时,它失败并出现这种"由另一个进程使用"样式异常(可能是因为它之前已经加载过)。如何卸载此程序集,或者如何在不加载的情况下获取其版本?
我已经对程序集类和AppDomain进行了一些研究,但是.NET CF有一些限制,所以我无法弄清楚。
知道吗?
谢谢。
使用
AssemblyName.GetAssemblyName(string)
或 FileVersionInfo
的"传统"方法不起作用,因为它们在 .NET CF 上不受支持。 要在不使用 Assembly.LoadFrom
的情况下执行此操作,您需要使用 P/Invoke 来本机获取文件版本信息。您可以尝试以下代码(未经测试):
[DllImport("coredll", EntryPoint = "GetFileVersionInfo", SetLastError = true)]
private static extern bool GetFileVersionInfo(string filename, int handle, int len, IntPtr buffer);
[DllImport("coredll", EntryPoint = "GetFileVersionInfoSize", SetLastError = true)]
private static extern int GetFileVersionInfoSize(string filename, ref int handle);
[DllImport("coredll", EntryPoint = "VerQueryValue", SetLastError = true)]
private static extern bool VerQueryValue(IntPtr buffer, string subblock, ref IntPtr blockbuffer, ref int len);
public static Version GetFileVersionCe(string fileName)
{
int handle = 0;
int length = GetFileVersionInfoSize(fileName, ref handle);
Version v = null;
if (length > 0)
{
IntPtr buffer = System.Runtime.InteropServices.Marshal.AllocHGlobal(length);
if (GetFileVersionInfo(fileName, handle, length, buffer))
{
IntPtr fixedbuffer = IntPtr.Zero;
int fixedlen = 0;
if (VerQueryValue(buffer, "''", ref fixedbuffer, ref fixedlen))
{
byte[] fixedversioninfo = new byte[fixedlen];
System.Runtime.InteropServices.Marshal.Copy(fixedbuffer, fixedversioninfo, 0, fixedlen);
v = new Version(
BitConverter.ToInt16(fixedversioninfo, 10),
BitConverter.ToInt16(fixedversioninfo, 8),
BitConverter.ToInt16(fixedversioninfo, 14),
BitConverter.ToInt16(fixedversioninfo, 12));
}
}
Marshal.FreeHGlobal(buffer);
}
return v;
}
旧帖子,但以防有人寻找它。我的VB(工作)版本。
Public Declare Function GetFileVersionInfo Lib "Coredll" (ByVal filename As String, ByVal handle As Integer, ByVal len As Integer, ByVal buffer As IntPtr) As Boolean
Public Declare Function GetFileVersionInfoSize Lib "Coredll" (ByVal filename As String, ByRef handle As Integer) As Integer
Public Declare Function VerQueryValue Lib "Coredll" (ByVal buffer As IntPtr, ByVal subblock As String, ByRef blockbuffer As IntPtr, ByRef len As Integer) As Boolean
Public Function GetFileVersionCE(ByVal fileName As String) As Version
Dim handle = 0
Dim length = GetFileVersionInfoSize(fileName, handle)
Dim v As Version = Nothing
If length > 0 Then
Dim buffer As IntPtr = Marshal.AllocHGlobal(length)
If (GetFileVersionInfo(fileName, handle, length, buffer)) Then
Dim fixedbuffer As IntPtr = IntPtr.Zero
Dim fixedlen As Integer = 0
If (VerQueryValue(buffer, "''", fixedbuffer, fixedlen)) Then
Dim fixedversioninfo(fixedlen) As Byte
Marshal.Copy(fixedbuffer, fixedversioninfo, 0, fixedlen)
v = New Version(BitConverter.ToInt16(fixedversioninfo, 10), _
BitConverter.ToInt16(fixedversioninfo, 8), _
BitConverter.ToInt16(fixedversioninfo, 14), _
BitConverter.ToInt16(fixedversioninfo, 12))
End If
End If
Marshal.FreeHGlobal(buffer)
End If
Return v
End Function