【问题标题】:DLLImport works in VS but not in IISDLLImport 在 VS 中有效,但在 IIS 中无效
【发布时间】:2014-10-10 12:08:16
【问题描述】:

我们有使用第三方 DLL 的 Soap Webservice 项目。在 Visual Studio 中,当我运行该程序时,它运行良好。它可以找到dll。但是当我将项目放入 IIS 时,webservice 找不到 dll。这是下面的 DLLImport 部分。

[DllImport(@"/dll/y1d431_mit.dll",
        EntryPoint = "Y1DPackG", SetLastError = false, ExactSpelling = true)]
    private static extern void Y1DPackG(ref int ErrorNumb, ref int ErrorMsgs,
        string RegCustomer, int RegPassword, int CostOptim, int IgnoreLast,
        int EffortLev, int ReduceLays, int PrefShort, int DiffStocks,
        int DiffPieces, int ReusLength, int GapItIt, int GapItEnd,
        int GapGripEnd, int OptimTime, int IterMult, int LayByMark,
        int RunMsgMode, int ReservInp2, ref int StockGrLth, ref int StockGrCst,
        ref short StockGrQty, ref int PartGrLth, ref int PartGrMrkID, ref short PartGrQty,
        ref int Critsum, ref int Effsum, ref int StockSum, ref int PartSum,
        ref int LengthSum, ref int WasteSum, ref int CostSum, ref int LastStockNo,
        ref int LastParts, ref int LastLength, ref int LastWaste, ref int LastCost,
        ref int PatternSum, ref int LayoutSum, ref int LayoutCuts, ref int ReservOut1,
        ref int ReservOut2, ref short StockGrNo, ref short PartGrNo, ref short PartStockNo,
        ref short StockLayNo, ref short StockPatNo, ref short StockParts, ref int StockWaste);

IIS根据DLLImport语句在哪里查找dll文件?我应该根据DLLIMPORT语句将dll文件放在哪里以便IIS找到它?

【问题讨论】:

    标签: c# asp.net web-services iis dll


    【解决方案1】:

    加载 Sysinternal 的免费 process monitor。在运行执行 dllimport 的代码之前启动它,并在出错后停止事件收集。这个工具会告诉你正在发生的每一件事,包括 IIS 从哪里开始搜索它。它还会告诉您是否遇到权限错误。

    如果它是 64 位系统上的 32 位 dll,则可能会出现权限错误,因为 dll 将通过 WOW64 运行,并可能复制到 WOW64 目录中执行。默认情况下,这不是任何匿名 Internet 用户帐户都可以访问的目录。

    【讨论】:

      【解决方案2】:

      谢谢马克。 Process Monitor 向我展示了 Windows 在哪里寻找我的 DLLImport 非托管/本机 DLL,以及它的所有依赖项/导入项。我找到了 2 种方法来找到我的 DLL:

      方法#1:SetDllDirectory()

      using System.Web;
      
      public myClass
      {
          private static bool dllIsLoaded = false;
      
          [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
          [return: MarshalAs(UnmanagedType.Bool)]
          static extern bool SetDllDirectory(string lpPathName);
      
          public void myDllLoader()
          {
              if (!dllIsLoaded)
              {
      #if DEBUG
                  string dllDir = Path.Combine(HttpRuntime.AppDomainAppPath, @"Lib\Debug\");
      #else
                  string dllDir = Path.Combine(HttpRuntime.AppDomainAppPath, @"Lib\Release\");
      #endif
                  SetDllDirectory(dllDir);
                   // Call any function in your DLL to load it.  Stays loaded for the duration of the app.
                  string ver = myDllGetVersion();
                  SetDllDirectory("");    // Reset path to original
      
                  dllIsLoaded = true;
              }
          }
      }
      

      方法 #2:在我的应用程序的 DLL 目录前附加 PATH 环境变量:

      using System.Web;
      
      string dllDir = Path.Combine(HttpRuntime.AppDomainAppPath, @"myAppDLLDirectory\");
      string currentPath = Environment.GetEnvironmentVariable("path");
      Environment.SetEnvironmentVariable("path", $"{dllDir};{currentPath}");
      

      对 PATH 的这种修改只影响当前进程。

      附言如果您的错误消息说它找不到您的 DLL,但您的 DLL 在 DLL 搜索路径上,这实际上可能意味着您的 DLL 正在导入的 DLL 之一找不到。例如,我的 DLL 依赖于我的开发机器上的“vcruntime140d.dll”和“ucrtbased.dll”,但不在我部署到的服务器上。使用“dumpbin.exe /imports my.dll”列出依赖项。 Dumpbin 可从 Visual Studio“x64 本机工具命令提示符”获得。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-30
        • 1970-01-01
        相关资源
        最近更新 更多