Reputation: 167
I have a mobile application running on .NET Compact Framework 3.5 and an updater application running on the same platform. When user taps on the app shortcut, updater application runs first and checks if a new version of the main app. is available. To do this, I load the main exe assembly using Assembly.LoadFrom method and get the current version. If it finds a new version (via web service) it downloads the new files and replaces. This works fine. The problem is, when it tries the replace main exe file, it fails with this "used by another process" style exception (probably because it's already loaded before). How can I unload this assembly or how can I get its version without loading it?
I've done some research about Assembly class and AppDomain, but .NET CF has some limitations, so I couldn't figure it out.
Any idea?
Thanks.
Upvotes: 3
Views: 1595
Reputation: 328
Old post, but in case anyone looking for it. My VB (working) version.
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
Upvotes: 0
Reputation: 42516
The "traditional" ways of using AssemblyName.GetAssemblyName(string)
or FileVersionInfo
won't work as they aren't supported on .NET CF. To do this without using Assembly.LoadFrom
, you will need to use P/Invoke to natively get the file version information. You can try this code (untested):
[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;
}
Upvotes: 2