我需要使用 WinAPI 函数重新启动 Windows 服务,我不熟悉C++中的字符串。
我的函数接收为参数:const CStringA& serviceName
:
bool MyClassName::RestartServer(const CStringA& serviceName)
当我通过OpenService(..)
获取SC句柄时,我需要提供类型LPCWSTR
:
SC_HANDLE SHandle = OpenService(hSCManager, LPCWSTR serviceNameAsWideString, SC_MANAGER_ALL_ACCESS);
如何将CStringA
转换为LPCWSTR
?
我试图遵循:
CA2W(serviceName, CP_UTF8);
CString str("MyServiceName"); CStringW strw(str); LPCWSTR ptr = strw;
两者都无法正常工作,它们进行了编译,但是当我尝试执行代码时。
它未能OpenService()
.
什么有效:
LPCWSTR newString = serviceName.AllocSysString();
我在这里错过了什么?为什么 1 和 2 不起作用?为什么 3 有效?
如何正确释放新字符串?
您的代码需要转换,因为您正在调用基于TCHAR
的OpenService()
宏,该宏映射到OpenServiceW()
或OpenServiceA()
,具体取决于是否定义了UNICODE
:
__checkReturn
WINADVAPI
SC_HANDLE
WINAPI
OpenServiceA(
__in SC_HANDLE hSCManager,
__in LPCSTR lpServiceName,
__in DWORD dwDesiredAccess
);
__checkReturn
WINADVAPI
SC_HANDLE
WINAPI
OpenServiceW(
__in SC_HANDLE hSCManager,
__in LPCWSTR lpServiceName,
__in DWORD dwDesiredAccess
);
#ifdef UNICODE
#define OpenService OpenServiceW
#else
#define OpenService OpenServiceA
#endif // !UNICODE
在您的情况下,UNICODE
在您的项目中明确定义,因此您的代码实际上是在调用OpenServiceW()
,这就是为什么它需要LPCWSTR
作为输入。
您的RestartServer()
方法将CStringA
(基于char
的 ANSI)字符串作为输入,因此您应该显式使用OpenServiceA()
来匹配相同的字符类型,无需转换:
bool MyClassName::RestartServer(const CStringA& serviceName)
{
...
SC_HANDLE SHandle = OpenServiceA(hSCManager, serviceName, SC_MANAGER_ALL_ACCESS);
...
}
否则,如果要继续在代码1中使用基于TCHAR
的功能,则应将RestartServer()
方法更改为采用CString
而不是CStringA
,以便它采用与OpenService()
相同的 ANSI/Unicode 映射(以及其他基于TCHAR
的函数),再次避免转换:
1:你不应该这样做,因为现在很少需要为Win9x/ME编写代码。自NT4以来,Windows一直是基于Unicode的操作系统。
bool MyClassName::RestartServer(const CString& serviceName)
如果这不是您的选择,那么CA2W()
就可以正常工作:
bool MyClassName::RestartServer(const CStringA& serviceName)
{
USES_CONVERSION;
...
SC_HANDLE SHandle = OpenService(hSCManager, ATL::CA2W(serviceName), SC_MANAGER_ALL_ACCESS);
...
}
不过,您可以考虑在内部仅使用CString
,并在需要时让它处理转换:
bool MyClassName::RestartServer(const CStringA& serviceName)
{
...
SC_HANDLE SHandle = OpenService(hSCManager, CString(serviceName), SC_MANAGER_ALL_ACCESS);
...
}
或者,使代码具有条件:
bool MyClassName::RestartServer(const CStringA& serviceName)
{
...
SC_HANDLE SHandle = OpenService(hSCManager,
#ifdef UNICODE
CStringW(serviceName)
#else
serviceName
#endif
, SC_MANAGER_ALL_ACCESS);
...
}
CStringA
和CStringW
都有构造函数同时接受const char*
和const wchar_t*
C字符串。
写下以下内容:
CStringW serviceNameW( serviceName );
大约AllocSysString
,它在 BSTR 中创建一个副本,它们比 C 字符串更复杂,它们也是以 null 结尾的,但它们的长度也为负偏移量。如果要执行手动内存管理,请在指针上调用SysFreeString
。或者,如果需要 BSTR 但不需要手动内存管理,请使用CComBSTR
类。