有没有办法在我自己的应用程序中使用visual studio的“添加程序集引用对话框”(或类似的东西)?我需要它来进行动态代码生成和编译。
这不仅仅是一个OpenFileDialog,因为它还会调查GAC等等,所以我认为自己这样做会非常复杂。
如果无法做到这一点,我如何从GAC获取所有程序集的列表?
答案 0 :(得分:2)
有一个undocumented API,允许您枚举GAC中的程序集。
答案 1 :(得分:2)
从GAC获取所有程序集的最佳方法是使用Fusion
第一个approch :以下代码段显示了如何实现目标:
internal class GacApi
{
[DllImport("fusion.dll")]
internal static extern IntPtr CreateAssemblyCache(
out IAssemblyCache ppAsmCache,
int reserved);
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("e707dcde-d1cd-11d2-bab9-00c04f8eceae")]
internal interface IAssemblyCache
{
int Dummy1();
[PreserveSig()]
IntPtr QueryAssemblyInfo(int flags, [MarshalAs(UnmanagedType.LPWStr)] String assemblyName, ref ASSEMBLY_INFO assemblyInfo); int Dummy2(); int Dummy3(); int Dummy4();
}
[StructLayout(LayoutKind.Sequential)]
internal struct ASSEMBLY_INFO
{
public int cbAssemblyInfo;
public int assemblyFlags;
public long assemblySizeInKB;
[MarshalAs(UnmanagedType.LPWStr)]
public String currentAssemblyPath;
public int cchBuf;
}
class Program
{
static void Main()
{
try
{
Console.WriteLine(QueryAssemblyInfo("System"));
}
catch(System.IO.FileNotFoundException e)
{
Console.WriteLine(e.Message);
}
}
public static String QueryAssemblyInfo(String assemblyName)
{
ASSEMBLY_INFO assembyInfo = new ASSEMBLY_INFO ();
assembyInfo.cchBuf = 512;
assembyInfo.currentAssemblyPath = new String('\0', assembyInfo.cchBuf) ;
IAssemblyCache assemblyCache = null;
IntPtr hr = GacApi.CreateAssemblyCache(out assemblyCache, 0);
if (hr == IntPtr.Zero)
{
hr = assemblyCache.QueryAssemblyInfo(1, assemblyName, ref assembyInfo);
if(hr != IntPtr.Zero)
Marshal.ThrowExceptionForHR(hr.ToInt32());
}
else
Marshal.ThrowExceptionForHR(hr.ToInt32());
return assembyInfo.currentAssemblyPath;
}
}
第二种方法:GAC目录(默认安装的%systemroot%\ assembly)是一个标准目录,就像任何其他目录一样,您应该能够遍历目录,加载程序集并检索在程序集中键入所有类型的信息。
编辑:最简单方法的代码:
List<string> dirs = new List<string>() {
"GAC", "GAC_32", "GAC_64", "GAC_MSIL",
"NativeImages_v2.0.50727_32",
"NativeImages_v2.0.50727_64",
"NativeImages_v4.0.50727_32",
"NativeImages_v4.0.50727_64"
};
string baseDir = @"c:\windows\assembly";
int i = 0;
foreach (string dir in dirs)
if (Directory.Exists(Path.Combine(baseDir, dir)))
foreach (string assemblyDir in Directory.GetFiles(Path.Combine(baseDir, dir), "*.dll", SearchOption.AllDirectories))
Console.WriteLine(assemblyDir);
有关Fusion.dll的更多信息,请访问:
http://support.microsoft.com/kb/317540
如果您有其他问题,请告诉我
取值
答案 2 :(得分:1)
你不希望你的应用那个慢,你呢:P
来源可用于CR_QuickAddReference。