2011-01-21 339 views
6

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

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)D:\ work \ project \ ... \ RTSWinService.cs中的RTSWS.RTSWinService.OnStart(String [] args)上的RTSWS.RTSWinService.runRTS(String serviceName) 处的 :第39行

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

谢谢。

+0

完整性检查:打开依赖关系的步行者,看看你的DLL依赖于什么,然后确保你的DLL和DLL依赖于你的路径上的某个地方。 – Shog9 2011-01-21 23:56:43

+0

另外,您可以运行SysInternal的filemon来监视您的服务尝试加载的DLL。请记住,Windows服务运行在不同的用户会话(和桌面)中,因此它有自己的环境。并确保你的'd:'(或者你安装到的任何地方)实际上是一个真正的本地路径,而不是网络,也不是SUBST'ed(那里做过;-) – 2011-01-22 00:02:12

回答

2

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

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

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

1

只是想更新这个线程。原来,这个问题是我的机器专用的。相同的代码集在不同的机器上工作就像一个魅力,相同的Windows版本(Windows XP 32位,SP2)。在两台机器上,都使用Visual Studio 2008来构建服务。 非常感谢所有的评论和答案。我很感激。