.net 如何在不加载程序集的情况下获取程序集的版本?

.net 如何在不加载程序集的情况下获取程序集的版本?,.net,assemblies,versions,.net,Assemblies,Versions,大型程序的一个小功能是检查文件夹中的程序集,并用最新版本替换过期的程序集。要实现这一点,它需要读取现有程序集文件的版本号,而不实际将这些程序集加载到执行过程中。使用AssemblyName.GetAssemblyName(“assembly.dll”),然后解析名称。根据: 只有当文件 包含程序集清单。这 方法导致打开该文件 和已关闭,但程序集未关闭 已添加到此域 我发现了以下几点 使用系统反射; 使用System.IO; ... //获取当前和更新的程序集 AssemblyName curre

大型程序的一个小功能是检查文件夹中的程序集,并用最新版本替换过期的程序集。要实现这一点,它需要读取现有程序集文件的版本号,而不实际将这些程序集加载到执行过程中。

使用
AssemblyName.GetAssemblyName(“assembly.dll”),然后解析名称。根据:

只有当文件 包含程序集清单。这 方法导致打开该文件 和已关闭,但程序集未关闭 已添加到此域

我发现了以下几点

使用系统反射;
使用System.IO;
...
//获取当前和更新的程序集
AssemblyName currentAssemblyName=AssemblyName.GetAssemblyName(currentAssemblyPath);
AssemblyName UpdateAssemblyName=AssemblyName.GetAssemblyName(UpdateAssemblyPath);
//比较两个版本

如果(updatedAssemblyName.Version.CompareTo(currentAssemblyName.Version)取决于文件,则一个选项可能是
FileVersionInfo
——即

FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(path)
string ver = fvi.FileVersion;
问题在于,这取决于具有
[AssemblyFileVersion]
属性的代码,并且它与
[AssemblyVersion]
属性匹配


不过,我想我应该先看看其他人建议的AssemblyName选项。

仅供记录:以下是如何在C#.NET Compact Framework中获取文件版本。它基本上来自OpenNETCF,但非常简短,可以通过复制粘贴来实现。希望对您有所帮助

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;
}

[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);

A
.netcore
更新Joel的答案,使用:

使用System.IO;
运用系统反思;
使用System.Runtime.Loader;
...
//获取当前和更新的程序集
AssemblyName currentAssemblyName=AssemblyLoadContext.GetAssemblyName(currentAssemblyPath);
AssemblyName UpdateAssemblyName=AssemblyLoadContext.GetAssemblyName(UpdateAssemblyPath);
//比较两个版本

if(updatedAssemblyName.Version.CompareTo(currentAssemblyName.Version)你用什么语言编写代码?@RB:语言不重要,因为人们会使用相同的类来获取信息。你需要让jop或Joel的答案正确。如果可以的话,我会投票给他们100万。多年来我一直想知道如何做到这一点。我尽量不去想我为g所实施的所有黑客在不加载文件.Yeesh.Crap的情况下设置版本号。对我来说,这在Compact框架上总是不起作用。AssemblyName在那里,但AssemblyName.GetAssemblyName不在。我以前使用的一个老技巧(用于扫描插件程序集)是创建一个沙盒AppDomain,在其中加载它们,然后在我完成后关闭AppDomain。但不确定是否使用CF。此处不适用。但它依赖于在新AppDomain中创建的对象来加载assebly,这意味着使用AppDomain.CreateInstance(),这在CF中似乎不受支持。您应该提出一个新问题,链接到此问题,并指定Compact Framework.+1,但有一个警告-如果您使用这样的代码,并且您将DLL更新为以新CLR为目标(即从Framework 3.5升级到Framework 4.0时),这将产生“此程序集由比当前加载的运行时更新的运行时生成,无法加载"错误…这样比较FileVersionInfo可能也很有用。对修复错误但不更改API的库的更新可能具有相同的程序集版本,但应具有不同的文件版本。因此,在许多情况下,您可能需要检查AssemblyFileVersion。提示:使用FileVersionInfo存在于系统中。Diagnostics名称空间,您需要导入该名称空间。@虽然为了公平起见,您只需按ctrl+(将焦点放在未解析的类型上),IDE就会找到它并为您添加它……然后您就不需要记住namespacesTrue,@MarcGravel,但我是通过rdp在一个测试区域部署它的,那里只有记事本:)非常好,确实有用。
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;
}

[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);