从.NET Windows服务调用本机DLL失败

时间:2012-02-14 10:18:40

标签: .net windows windows-services pinvoke unmanaged

我有一个本地dll形式的第三方API,我使用DllImport从C#调用。此本机dll取决于正在打开的第三方应用程序。

当我正常运行代码时,API会执行预期的操作并驱动应用程序。但是,当我运行与Windows服务相同的代码时,即使是我自己,API也会返回与应用程序关闭时相同的(未记录的)错误代码;进程资源管理器确认从应用程序目录正确加载了本机dll。

可能导致此问题的原因以及我如何解决此问题?

3 个答案:

答案 0 :(得分:1)

很难说,但我可以想到三种可能性:

  • 您的服务具有需要“与桌面交互”选项的UI组件选项
  • Windows服务的工作目录是%WinDir%\ system32(例如C:\ windows \ system32),你的dll代码使用相对路径引用无法找到的其他资源
  • 您的服务使用netpipe通信与在两个不同会话中运行的应用程序

答案 1 :(得分:1)

有点旧,但它成为搜索中的最佳结果之一。所以我认为我的数据仍然有用。

  

我有一个本地dll形式的第三方API,我使用DllImport从C#调用。此本机dll取决于正在打开的第三方应用程序。

(t)生锈的Office Interop DLL也是一样的。您实际上正在启动相关Office程序的后台实例。 后台实例需要一个交互式会话,即使它没有显示任何内容(工作中的设计假设/错误)。 服务不在interactive session since Vista中运行。建议不要使用覆盖。 这是不再使用Office Interop的(3?)原因之一。

可能的解决方法:

  1. 停止使用服务。 Windows Task sheduler可以完成同样的工作,同时为您提供完整的交互式会话。甚至MS本身也开始将服务从服务中移出,尽可能地进入Sheduler
  2. 将DLL访问移动到Helper进程。那个可以在交互式会话中运行。使用任何进程间通信方式在帮助程序和主服务之间进行通信。此模式主要用于处理来自x64程序的x32仅dll,但它也应该在这里工作。清单和Process.Start()都可以通过服务以交互方式启动程序。
  3. 根据其中一条评论显示您选择选项2,但改为使用Web服务。 遗憾的是,Webserices / Web应用程序通常作为Windows服务运行。这是在您考虑它们运行在一些最严格的权利之前(因为它们可以通过Web访问)。 所以它只会让你回到方形1或甚至另一步倒退到方形0。

答案 2 :(得分:0)

如果必须从服务中调用本机dll,请在启动之前尝试按以下方式更改当前目录:

static void Main()
{
    System.Environment.CurrentDirectory = System.AppDomain.CurrentDomain.BaseDirectory;
    System.IO.Directory.SetCurrentDirectory(System.AppDomain.CurrentDomain.BaseDirectory);

    ServiceBase[] ServicesToRun;
    ServicesToRun = new ServiceBase[]
    {
        new XYZService()
    };
    ServiceBase.Run(ServicesToRun);
}

此后,该服务无需更改环境变量或将本机DLL移入系统文件夹即可轻松找到本机DLL。