调用C++;来自C#windows服务(以托管代码编写)的dll(非托管代码) 我正在研究一个C++项目,它有不同的组件。我们需要将应用程序作为windows服务启动。该项目是非托管C++代码。我编写了一个C#windows服务和一个C风格的dll,该dll将有一个启动不同组件的函数,还有一个停止它们的函数。dll有两个文件,一个头文件和一个.cpp文件: RTSS.h:

调用C++;来自C#windows服务(以托管代码编写)的dll(非托管代码) 我正在研究一个C++项目,它有不同的组件。我们需要将应用程序作为windows服务启动。该项目是非托管C++代码。我编写了一个C#windows服务和一个C风格的dll,该dll将有一个启动不同组件的函数,还有一个停止它们的函数。dll有两个文件,一个头文件和一个.cpp文件: RTSS.h:,c#,c,windows,dll,service,C#,C,Windows,Dll,Service,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_han

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;
}
在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());
  }
}
此外,我还有一个控制台测试应用程序,main中的代码类似于OnStart中的代码。当对SetUnhandledException函数进行注释时,应用程序和windows服务都可以正常运行。但当我取消注释该函数时,windows控制台应用程序运行正常,但windows服务输出以下异常:

System.DllNotFoundException:无法加载DLL“RTSSd.DLL”:找不到指定的模块。(来自HRESULT的异常:0x8007007E) 在RTSWS.RTSWinService.runRTS(字符串serviceName) 在D:\work\project\…\RTSWinService.cs中的RTSWS.RTSWinService.OnStart(字符串[]args)处:第39行

我在不同论坛的一些帖子中读到,windows服务在C:\windows\System32中启动,这是真的,因为初始化DirectoryInfo并打印其全名显示了这一点。我试图用Environment.CurrentDirectory=“windows服务可执行文件和DLL所在的目录”更改默认的开始目录,但没有成功。我还试图更改进程目录,但也失败了。其他线索导致了这个结论,但真的是这样吗?能简单点吗? 我应该注意到,StunHANDLIENDEXCEPROTION函数是用C++编写的,而不是C语言,所以我需要调用的许多其他函数也是如此。所有需要的DLL都放在服务可执行文件旁边。非常感谢您的反馈


谢谢。

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

另一个建议是调用SetDllDirectory,这是一种比使用当前目录更直接的方式来说明DLL在哪里。请参见pinvoke dll搜索路径上的


您还可以使用监视系统并尝试定位DLL。有时不是DLL,而是DLL所依赖的DLL有问题,ProcMon有助于发现这些问题。

只是想更新此线程。 原来这个问题是我的机器独有的。同一个代码集在不同的机器、相同的windows版本(windows XP 32位,SP2)上工作得非常好。在这两台机器上,使用VisualStudio2008构建服务。
非常感谢所有的评论和答案。我很感激。

健全性检查:打开依赖项walker,查看您的DLL依赖于什么,然后确保您的DLL及其依赖的DLL都位于您的路径上。此外,您还可以运行SysInternal的filemon来查看您的服务尝试加载的DLL。请记住,windows服务在不同的用户会话(和桌面)中运行,因此有自己的环境。并确保您的“d:”(或您安装到的任何位置)实际上是一个真正的本地路径,而不是网络或子路径(已在那里完成;-)进行了依赖项检查,但由于控制台应用程序运行时没有问题,我假设没有缺少依赖项。顺便说一句,我确实遇到了在替代驱动器上安装服务的问题,删除它是一件痛苦的事情:)如果有人有类似的问题,当我更改
环境时。CurrentDirectory
到我的DLL所在的目录,它在那里工作。非常感谢您的回答和评论。我很高兴它很快:)我正在以本地服务的形式运行该服务。我也尝试过它作为用户(我的帐户是这台机器上的管理员)和本地系统,但没有什么不同。我还从OnStart方法中调用了SetDllDirectory(“D:\work\projects\bin”),结果返回true,但没有解决问题。当我打开依赖项工具(dependence.exe)并检查RTSSd.dll时,它给出了一个关于找不到IESHIMS.dll和WER.dll(可能是系统dll)的错误。但我认为,如果缺少依赖项,控制台应用程序可能会失败。学习如何使用procmon是值得的,因此,考虑到显而易见的东西并不能解决您的问题,您可能试图解决错误的问题。Procmon经常帮助您了解它是什么。+1用于推荐Procmon。以下是更新的下载链接:
[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());
  }
}