我需要使用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个有效?
如何正确地释放newString?
答案 0 :(得分:3)
您的代码需要进行转换,因为您正在调用基于TCHAR
的{{1}}宏,该宏根据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
的ANSI)字符串作为输入,因此您应显式使用char
来匹配相同的字符类型,而不进行转换需要:
OpenServiceA()
否则,如果您要继续在代码 1 中使用基于bool MyClassName::RestartServer(const CStringA& serviceName)
{
...
SC_HANDLE SHandle = OpenServiceA(hSCManager, serviceName, SC_MANAGER_ALL_ACCESS);
...
}
的功能,则应更改TCHAR
方法以采用{{1} }而不是RestartServer()
,因此它采用与CString
相同的ANSI / Unicode映射(以及其他基于CStringA
的功能),再次避免了转换:
1:您不应该这样做,因为如今几乎不需要为Win9x / ME编写代码。自NT4以来,Windows一直是基于Unicode的操作系统。
OpenService()
如果这不是您的选择,那么TCHAR
可以正常工作:
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
答案 1 :(得分:2)
CStringA
和CStringW
的构造函数同时使用const char*
和const wchar_t*
C字符串。
写以下内容:
CStringW serviceNameW( serviceName );
关于AllocSysString
,它会在BSTR中创建一个副本,它们比C字符串复杂,它们也以零结尾,但它们的长度也为负偏移量。如果要执行手动内存管理,请在指针上调用SysFreeString
。或者,如果您想要BSTR但不希望手动进行内存管理,请使用CComBSTR
类。