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

时间:2011-01-21 23:50:17

标签: 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*);
}

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());
  }
}

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

  

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

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

感谢。

2 个答案:

答案 0 :(得分:2)

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

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

您还可以使用SysInternal's ProcMon观看系统尝试并找到您的DLL。有时它不是DLL,而是你的DLL所依赖的DLL有问题,而ProcMon很适合发现这些问题。

答案 1 :(得分:1)

只是想更新这个帖子。 事实证明,问题是我的机器独有的。相同的代码集在不同的机器上工作,就像一个相同的Windows版本(Windows XP 32位,SP2)。在这两台机器上,Visual Studio 2008用于构建服务。 非常感谢所有评论和答案。我很感激。