从C#windows服务调用C++ DLL(非托管代码)(用托管代码编写)

vna*_*our 6 c c# windows dll service

我正在开发一个具有不同组件的C++项目.我们需要将应用程序作为Windows服务启动.该项目是非托管C++代码.我写了一个C#windows服务,还有一个C风格的dll,它有一个启动不同组件的功能,另一个用来阻止它们.该DLL有两个文件,一个头文件和一个.cpp文件:RTSS.h:

namespace PFDS
{
  extern "C" __declspec(dllexport) int runRTS(char*);
}
Run Code Online (Sandbox Code Playgroud)

RTSS.cpp:

using namespace PFDS;
/* ... includes and declarations */
extern "C" __declspec(dllexport) int runRTS(char* service_name)
{
   g_reserved_memory = (char*) malloc(sizeof(char) * RESERVED_MEMORY_SIZE);
   _set_new_handler(memory_depletion_handler);
   // this function is from a C++ .lib which is included in
   // the linker input for the RTSS dll project setting.
   // SetUnhandledExceptionHandler("RTS");       
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

在Windows服务的ServiceBase子类中,我有以下内容:

[DllImport("RTSSd.dll")]
public static extern int runRTS(string serviceName);

protected override void OnStart(string[] args)
{
  try
  {
    // the bin directory has all dependencies (dlls needed)
    Environment.CurrentDirectory = "D:/work/projects/bin";
    eventLog1.WriteEntry("RTSWinService: Starting " + this.ServiceName);
    int result = runRTS(this.ServiceName);
    eventLog1.WriteEntry("Result of invoking runRTS = " + result);
  }
  catch (Exception e)
  {
    eventLog1.WriteEntry("Exception caught: " + e.ToString());
  }
}
Run Code Online (Sandbox Code Playgroud)

此外,我有一个控制台测试应用程序,其内部代码类似于OnStart内部的代码.当注释SetUnhandledException函数时,应用程序和Windows服务都运行没有问题.但是当我取消注释该功能时,Windows控制台应用程序运行正常,但Windows服务输出以下异常:

System.DllNotFoundException:无法加载DLL"RTSSd.dll":找不到指定的模块.(来自HRESULT的异常:0x8007007E)RTSWS.RTSWinService.runRTS(String serviceName)位于D:\ work\project\...\RTSWinService.cs中的RTSWS.RTSWinService.OnStart(String [] args):第39行

我已经在不同论坛的一些线程中读到了Windows服务从C:\ WINDOWS\System32开始,并且它是正确的,因为初始化DirectoryInfo并打印其全名显示如此.我尝试使用Environment.CurrentDirectory ="Windows服务可执行文件和dll所在的目录"更改默认启动目录,但这不起作用.我也尝试更改Process目录,但也失败了.其他线程导致这个结论链接文本,但它真的是这样吗?这可能更简单吗?我应该注意,SetUnhandledException函数是用C++而不是C编写的,因此我需要调用许多其他函数.所有需要的dll都放在服务可执行文件旁边.非常感谢您的反馈.

谢谢.

Ton*_*Lee 2

当某些东西在控制台上运行但不能作为服务时,我会怀疑访问权限。确保运行服务的用户具有对 d:\work\projects\bin 的读取/执行访问权限。

另一个建议是调用 SetDllDirectory,这是比使用当前目录更直接的方式来说明 DLL 的位置。请参阅pinvoke dll 搜索路径上的此 SO 线程

您还可以使用SysInternal 的 ProcMon来观察系统尝试并定位您的 DLL。有时,不是 DLL 存在问题,而是 DLL 所依赖的 DLL 存在问题,而 ProcMon 可以很好地查找这些问题。