我知道如何从文件名和全局程序集缓存中加载程序集。 由于我的.msi文件将一个dll项目放入全局程序集缓存中,所以我想知道是否可能从全局程序集缓存中加载它而不知道完整名称(我的意思是只使用程序集名称,甚至是dll文件名),因为我需要从另一个项目中加载此程序集。
我知道如何从文件名和全局程序集缓存中加载程序集。 由于我的.msi文件将一个dll项目放入全局程序集缓存中,所以我想知道是否可能从全局程序集缓存中加载它而不知道完整名称(我的意思是只使用程序集名称,甚至是dll文件名),因为我需要从另一个项目中加载此程序集。
这里有一段代码可以实现这个功能,还有一个例子:
string path = GetAssemblyPath("System.DirectoryServices");
Assembly.LoadFrom(path);
请注意,如果您需要特定的处理器架构,由于它支持部分名称,您可以编写这样的内容:
// load from the 32-bit GAC
string path = GetAssemblyPath("Microsoft.Transactions.Bridge.Dtc, ProcessorArchitecture=X86");
// load from the 64-bit GAC
string path = GetAssemblyPath("Microsoft.Transactions.Bridge.Dtc, ProcessorArchitecture=AMD64");
这是实现:
/// <summary>
/// Gets an assembly path from the GAC given a partial name.
/// </summary>
/// <param name="name">An assembly partial name. May not be null.</param>
/// <returns>
/// The assembly path if found; otherwise null;
/// </returns>
public static string GetAssemblyPath(string name)
{
if (name == null)
throw new ArgumentNullException("name");
string finalName = name;
AssemblyInfo aInfo = new AssemblyInfo();
aInfo.cchBuf = 1024; // should be fine...
aInfo.currentAssemblyPath = new String('\0', aInfo.cchBuf);
IAssemblyCache ac;
int hr = CreateAssemblyCache(out ac, 0);
if (hr >= 0)
{
hr = ac.QueryAssemblyInfo(0, finalName, ref aInfo);
if (hr < 0)
return null;
}
return aInfo.currentAssemblyPath;
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("e707dcde-d1cd-11d2-bab9-00c04f8eceae")]
private interface IAssemblyCache
{
void Reserved0();
[PreserveSig]
int QueryAssemblyInfo(int flags, [MarshalAs(UnmanagedType.LPWStr)] string assemblyName, ref AssemblyInfo assemblyInfo);
}
[StructLayout(LayoutKind.Sequential)]
private struct AssemblyInfo
{
public int cbAssemblyInfo;
public int assemblyFlags;
public long assemblySizeInKB;
[MarshalAs(UnmanagedType.LPWStr)]
public string currentAssemblyPath;
public int cchBuf; // size of path buf.
}
[DllImport("fusion.dll")]
private static extern int CreateAssemblyCache(out IAssemblyCache ppAsmCache, int reserved);
是的,这就是GAC的全部意义。运行时会首先查找GAC,而不是当前目录。
Assembly.Load("myAssembly")
而不是Assembly.Load("myAssembly, Version=xxxxx, PublicKeyToken=xxxxxx")
。在我看来,这似乎是不可能的,但现在我正在寻找了解我的MSI中主要输出的程序集名称,并将其放入app.config中,以便在代码中动态获取程序集名称。 - metalcam