繁体   English   中英

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

[英]CPP Windows string conversions confusion CStringA and LPCWSTR

我需要使用WinAPI函数来重新启动Windows服务,我对C ++中的字符串不熟悉。

我的函数接收作为参数: const CStringA& serviceName

bool MyClassName::RestartServer(const CStringA& serviceName)

当我通过OpenService(..)获得SC Handle时,我需要提供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?

您的代码需要进行转换,因为您正在调用基于TCHAROpenService()宏,该宏根据是否定义UNICODE映射到OpenServiceW()OpenServiceA()

__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);
    ...
}

CStringACStringW具有使用const char*const wchar_t* C字符串的构造const char*

写以下内容:

CStringW serviceNameW( serviceName );

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM