C# 不复制到本地(软件当前目录)引用程序集;

本文介绍了两种在C#中加载非程序运行目录下的程序集的方法。第一种方法利用AppDomain.CurrentDomain.AssemblyResolve事件来解决程序集依赖问题;第二种方法通过为DLL添加强名称并注册到GAC中实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

方法1:利用AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);事件

转自:http://blog.youkuaiyun.com/dyllove98/article/details/9391325

C#如何加载程序运行目录外的程序集

我们的应用程序部署的时候,目录结构一般不会只有运行程序的目录这一个,我们可能在运行目录下建子目录,也可能使用System32目录,也可能使用其它第三方的程序集。.Net程序集

首先会在GAC中搜索相应的版本,如果未找到则会应用程序配置文件中找(如果配置),最后到应用程序所在的路径搜索。

如何可以将程序集部署的运行目录的子目录, 在app.config添加以下配置,其中probing的privatePath就是配置当前程序搜索的子目录

 <configuration>
  ... ...
 <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="Plugins;Libs"/>
    </assemblyBinding>
  </runtime>
 </configuration>


当然我们也可以更详细的配置,不过似乎一般这么用的很少,这里可以指定程序集名称、公钥、文化,版本重定向等等信息

<configuration>
   <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
         <dependentAssembly>
            <assemblyIdentity name="myAssembly"
                              publicKeyToken="32ab4ba45e0a69a1"
                              culture="neutral" />
            <bindingRedirect oldVersion="1.0.0.0"
                             newVersion="2.0.0.0"/>
            <codeBase version="2.0.0.0"
                      href="http://www.litwareinc.com/myAssembly.dll"/>
         </dependentAssembly>
      </assemblyBinding>
   </runtime>
</configuration>

Msdn地址:http://msdn.microsoft.com/zh-cn/library/twy1dw1e(v=vs.80).aspx

如何加载非运行目录的程序集?也许有的人会想到反射,的确对应单独的一个程序集我们可以直接调用使用 Assembly.LoadFile(@"XXX.dll");加载,再使用反射对其中的方法属性进行调

用,但是如果这个程序集同时引用了其它的,非应用程序运行目录下的程序集,这时就会出错,这个问题该如何解决呢?

我曾尝试用 Assembly.LoadFile(@"XXX.dll");加载那些依赖的程序集,但是没有成功,调用继续出错。使用 AppDomain.CurrentDomain.GetAssemblies()查看,所有的应用程序集都已经加载到了当前应用程序域,但是为什么还是找不到依赖的哪些程序集呢?后来查询未果,希望有高人能回答下。

最后使用了AppDomain.CurrentDomain.AssemblyResolve事件解决了以上问题,希望遇到同样问题的同学们少走弯路,在程序初始化的时候添加监听事件

            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);

在监听的事件中遇到要加载额外的dll的时候,返回 Assembly.LoadFrom(strTempAssmbPath)即可

        Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            var strTempAssmbPath = "";
            if ("qrcsharp" == args.Name.Substring(0, args.Name.IndexOf(",")))
            {
                var systemFolder = Environment.GetFolderPath(Environment.SpecialFolder.System);
                strTempAssmbPath = System.IO.Path.Combine(systemFolder, "qrcsharp.dll");
            }
            return string.IsNullOrWhiteSpace(strTempAssmbPath) ? null : Assembly.LoadFrom(strTempAssmbPath);
        }


方法2:签名+环境变量

转自:http://www.cnblogs.com/yunhuasheng/archive/2008/03/12/1102542.html

http://bbs.youkuaiyun.com/topics/391849269

http://www.doc88.com/p-23574117789.html


.net 注册引用的dll

我们在做.Net Class Library项目时常常会遇到这样的问题,我想生成一个dll供其它程序使用,但在我的项目里,又需要引用一些其它的reference,像ActiveX控件或其它dll,而这些控件或dll又没有strong name,不能写入到GAC(Global Assembly Cache)中,因而,在注册使用你的dll时,就必须带上这些引用的控件或dll,才能完成注册。然而,这并不是我们需要的,我们只想提供一个dll给人家用就行了,为什么还要带上一堆的控件或dll呢?别人也不愿意这样。那么,有什么办法解决这个问题呢?

  正好现在做的这个项目就是这种情况,看了一下网上的资料也不多,于是将自己的解决方法share一下,有什么不好的地方,恳请指正。

  大家都知道,在.Net中,如果你试图将一个dll写入到GAC中,那么除了你的dll项目要使用strong name以外,你的项目中用到的其它的控件或dll都需要有strong name,否则,当你注册你的dll时,会提示缺少dependency。这一点让人很烦,但应该有它的好处,利于版本控制。既然是这样,我们只有将引用到的控件或dll都加上strong name,并写入到GAC中,这样在注册你的dll时,就会到GAC中去找它所用到的控件或dll了。那么,如何做呢?大致分两步:

  1、给需要引用的控件或dll加strong name

  这是必须要做的,否则你无法把他们写到GAC中。.Net的SDK提供一个给程序集生成强名的工具,其实不只是生成,还有管理及签名的验证等,只是根据不同的option来的。详细说明请参考MSDN。下面是通过sn创建一个key pair,存储在keyfile.snk中:

sn -k keyfile.snk

  这样就生成了一个密钥对。如果你的项目中没有引用其它的不带强名的控件或dll的话,只是想把自己的dll写入GAC,那么在你项目的AssemblyInfo.cs中,把AssemblyKeyFile加上,就是你刚才生成的keyfile.snk文件。

[assembly: AssemblyKeyFile("..\\..\\keyfile.snk")]

  这里的路径是指编译后项目输出的相对路径,所以,如果这里写成这样的话(当然你也可以修改),就应该把刚才生成的keyfile.snk拷贝到项目的跟目录下,以确保在编译的时候能找到snk文件。这样,编译后的dll就可以写到GAC中了:

gacutil -i yourdll.dll

  如果你的项目中引用了其它的不带有强名的控件或dll的话,就需要再做下一步。

  2、给不带有强名的控件或dll加上强名

  这里要用到两个工具,也是.Net自带的,tlbimp和aximp。tlbimp是将COM类型库中的类型定义转换为CLR程序集的等效定义,aximp是将COM类型库中的类型定义转换为windows窗体控件,详细说明请参考MSDN。
  假设你要给tom.dll和MSFlxGrd.ocx加上强名:
  
tlbimp tom.dll keyfile:tom.dll.snk out:tom.dll

aximp MSFlxGrd.ocx keyfile:MSFlxGrd.ocx.snk AxMSFlxGrd.ocx.snk

  这里,tom.dll.snk、MSFLlxGrd.ocx.snk和AxMsFlxGrd.ocx.snk是根据第一步产生的,每一个dll都要对应一个snk。tom.dll为转换过的dll的名字,没有什么其它含义。另外需要说明的是MSFlxGrd.ocx会产生两个dll,分别是MSFlexGridLib.dll和AxMSFlexGridLib.dll。个人理解为在窗体初始化时会产生一个AxMSFlexGridLib,不知谁有更好的解释?

  这样就把tom.dll和MSFlxGrd.ocx控件加上了强名称并转换为相应的dll了,再把它们写入到GAC中:

gacutil -i tom.dll
gacutil -i MSFlexGridLib.dll
gacutil -i AxMSFlexGridLib.dll

  剩下的工作就是将它们重新引用到你的项目中,重新编译,这样生成的dll在注册时就不需要任何dependency了,因为它们已经在GAC中了,打开c:\winnt\assembly即可看到。

  如果要将它们从GAC中删除,则:

gacutil -u tom
gacutil -u MSFlexGrid
gacutil -u AxMSFlexGrid

  tom、MSFlexGrid和AxMSFlexGrid为GAC中的名字,这里不需要加任何路径

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值