简体   繁体   English

获取exe文件的版本而不在.NET Compact Framework中加载

[英]Getting the version of an exe file without loading in .NET Compact Framework

I have a mobile application running on .NET Compact Framework 3.5 and an updater application running on the same platform. 我有一个在.NET Compact Framework 3.5上运行的移动应用程序和在同一平台上运行的更新程序。 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. 为此,我使用Assembly.LoadFrom方法加载主exe程序集并获取当前版本。 If it finds a new version (via web service) it downloads the new files and replaces. 如果找到新版本(通过Web服务),则会下载新文件并替换。 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). 问题是,当它尝试替换主exe文件时,它会因为“另一个进程使用”样式异常而失败(可能是因为它之前已经加载过)。 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. 我已经对Assembly类和AppDomain做了一些研究,但.NET CF有一些局限性,所以我无法弄明白。

Any idea? 任何想法?

Thanks. 谢谢。

The "traditional" ways of using AssemblyName.GetAssemblyName(string) or FileVersionInfo won't work as they aren't supported on .NET CF. 使用AssemblyName.GetAssemblyName(string)FileVersionInfo的“传统”方式不起作用,因为.NET CF不支持它们。 To do this without using Assembly.LoadFrom , you will need to use P/Invoke to natively get the file version information. 要在不使用Assembly.LoadFrom情况下执行此操作,您需要使用P / Invoke本机获取文件版本信息。 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;
}

Old post, but in case anyone looking for it. 老帖子,但万一有人在寻找它。 My VB (working) version. 我的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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM