文章出處

一,普通的一段代碼

之前寫了兩個軟件, 一個是阿里云客戶端,一個是淘寶刷單軟件,都用到了IOC技術。

我的做法是在引導程序中,把程序需要用到的DLL文件加載到IOC容器中,如下代碼:

    foreach (var file in System.IO.Directory.GetFiles(System.IO.Directory.GetCurrentDirectory(), "Trade.*.dll"))
    {
        AssemblySource.Instance.Add(Assembly.LoadFile(file));
    }

然后通過IOC的方式創建實例

    object obj = IoC.Get<IRetrievePwd>();
    IoC.Get<IWindowManager>().ShowDialog(obj);

這樣的好處在于:

1,項目之間不用互相添加 DLL 文件的引用,做到了松耦合。

2,通過接口創建對象,實現了程序的多態性。

3,項目中基本上不會出現new關鍵字,避免了亂創建對象產生的性能損失。對象都給IOC容器管理了。

二,普通的代碼引出的問題

在開發環境中,我的軟件運行的很順利,在測試環境里,也沒有發現不能運行的情況。

當軟件打包,發布到公網的時候,很多用戶反應軟件打不開。

幸運的是在監控日志中得到了相關錯誤信息:

An attempt was made to load an assembly from a network location which would have caused the assembly to be sandboxed in previous versions of the .NET Framework. This release of the .NET Framework does not enable CAS policy by default, so this load may be dangerous. If this load is not intended to sandbox the assembly, please enable the loadFromRemoteSources switch. See http://go.microsoft.com/fwlink/?LinkId=155569 for more information.

這個錯誤說的大致意思就是,.net的安全機制阻止了加載一個dll文件。

三,解決方案:

隨后,我在網絡上找到了很多方法,現在匯總一下分享給大家:

方法一:

可以通過配置文件進行處理

  <runtime>
    <loadFromRemoteSources enabled="true" />
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
        <bindingRedirect oldVersion="0.0.0.0-2.6.8.0" newVersion="2.6.8.0"/>
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Threading.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
        <bindingRedirect oldVersion="0.0.0.0-2.6.8.0" newVersion="2.6.8.0"/>
      </dependentAssembly>
    </assemblyBinding>
  </runtime>

至關重要的就是這句:

<loadFromRemoteSources enabled="true" /> 

方法二:
也可以通過C#代碼,進行處理

    //以前
    foreach (var file in System.IO.Directory.GetFiles(System.IO.Directory.GetCurrentDirectory(), "FileTransfer.*.dll"))
    {
        AssemblySource.Instance.Add(Assembly.LoadFile(file));
    }
    //替換為
    foreach (var file in System.IO.Directory.GetFiles(System.IO.Directory.GetCurrentDirectory(), "FileTransfer.*.dll"))
    {
        AssemblySource.Instance.Add(Assembly.LoadFrom(file));
    }

把 Assembly.LoadFile(file)  替換為   Assembly.LoadFrom(file)

方法三:

還是通過C#代碼處理,以字節的方式加載DLL

    //以前
    foreach (var file in System.IO.Directory.GetFiles(System.IO.Directory.GetCurrentDirectory(), "FileTransfer.*.dll"))
    {
        AssemblySource.Instance.Add(Assembly.LoadFile(file));
    }
    //替換為
    foreach (var file in System.IO.Directory.GetFiles(System.IO.Directory.GetCurrentDirectory(), "FileTransfer.*.dll"))
    {
        byte[] assemblyBuffer = System.IO. File.ReadAllBytes(file);
        AssemblySource.Instance.Add(Assembly.Load(assemblyBuffer));
    }


四:疑問

我的項目一直用  Assembly.LoadFile(file)  加載DLL,在本機上折騰是不會出現問題的。

一旦:

程序以DLL的方式發布到外網(比如上傳到外網服務器,上傳到阿里云)

然后:

Download到本地計算機運行,就會報錯,具體錯誤信息,就是我第二大點提到的錯誤信息。

我也仔細對比了上傳前的 DLL 與 通過上傳再下載的DLL,沒有任何區別。包括DLL的屬性設置,讀寫狀態等都沒區別

但是異常就這樣出現了,求原因,同仁們,你們遇上過這種問題嗎?

 


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()