CPP Windows字符串转换混淆CStringA和LPCWSTR

时间:2019-07-09 19:32:36

标签: c++ string windows

我需要使用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

我尝试遵循:

  1. CA2W(serviceName, CP_UTF8);
  2. CString str("MyServiceName"); CStringW strw(str); LPCWSTR ptr = strw;

它们都无法正常工作,它们进行了编译,但是当我尝试执行代码时。
未能OpenService()
有效的方法:

  1. LPCWSTR newString = serviceName.AllocSysString();

我在这里想念什么?为什么1和2不起作用?为什么3个有效?

如何正确地释放newString?

2 个答案:

答案 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)

CStringACStringW的构造函数同时使用const char*const wchar_t* C字符串。

写以下内容:

CStringW serviceNameW( serviceName );

关于AllocSysString,它会在BSTR中创建一个副本,它们比C字符串复杂,它们也以零结尾,但它们的长度也为负偏移量。如果要执行手动内存管理,请在指针上调用SysFreeString。或者,如果您想要BSTR但不希望手动进行内存管理,请使用CComBSTR类。