如何在CString路径中使用SHFileOperation()

时间:2018-09-21 09:48:06

标签: c++ string winapi mfc null-terminated

我正在尝试将CString转换为LPCWSTR,并且效果很好。但是在处理代码时出了点问题。

我想将目录复制到另一个路径,所以我正在使用SHFILEOPSTRUCT

HWND console = GetConsoleWindow();
SHFILEOPSTRUCT s = { 0 };
s.hwnd = console;
s.wFunc = FO_COPY;
s.fFlags = FOF_SILENT;

CString _folderName("a6_töüst-Oa5Z.OZS-CI5O5235"),
        firstPath("C:\\ORTIM-Daten\\a5Pc 2.0.3\\Temp\\"),
        lastPart("\\Documents\\*\0"),
        firstPathDest("C:\\ORTIM-Daten\\a5Pc 2.0.3\\"),
        lastPartDest("Documents\\"),
        _folderNameDest("a6_töüst-Oa5Z.OZS-CI5O5235\0");

CString cstrTemp = firstPath + _folderName + lastPart,
    cstrTempDest = firstPathDest + lastPartDest + _folderNameDest;

s.pTo   = cstrTempDest /*_TEXT("C:\\ORTIM-Daten\\a5Pc 2.0.3\\Documents\\a6_töüst-Oa5Z.OZS-CI5O5235\0")*/;
s.pFrom = cstrTemp     /*_TEXT("C:\\ORTIM-Daten\\a5Pc 2.0.3\\Temp\\a6_töüst-Oa5Z.OZS-CI5O5235\\Documents\\*\0")*/;

SHFileOperation(&s);

当我直接使用CString时,复制操作不起作用,但是当我使用_TEXT()宏(如注释中)在{结构一切正常。

编辑1

在源路径和目标路径的两种变体中,代码均会编译。

在此变体中,代码编译并执行复制操作:

LPCWSTR

在我实际需要的另一个变体中,代码也可以编译,但是复制操作不会发生:

s.pTo   = _TEXT("C:\\ORTIM-Daten\\a5Pc 2.0.3\\Documents\\a6_töüst-Oa5Z.OZS-CI5O5235\0");
s.pFrom = _TEXT("C:\\ORTIM-Daten\\a5Pc 2.0.3\\Temp\\a6_töüst-Oa5Z.OZS-CI5O5235\\Documents\\*\0");

3 个答案:

答案 0 :(得分:4)

SHFILEOPSTRUCT期望以两个个NUL字符结尾的字符串,但是根据定义,以NUL终止的字符串以一个结尾,并且{{1 }}不需要显式长度参数的方法。

您可以通过手动添加一个来强制双倍NUL:

CString

替代解决方案可以使用带有显式长度参数的方法:

CString cstrTempDest = firstPathDest + lastPartDest + _folderNameDest;

// *** Add NUL manually ***
cstrTempDest.AppendChar( 0 );
s.pTo = cstrTempDest;

// For debuging - verify resulting string with example.
TCHAR* test = _TEXT("C:\\ORTIM-Daten\\a5Pc 2.0.3\\Documents\\a6_töüst-Oa5Z.OZS-CI5O5235\0");
// +2 because we want to check two NULs at end.
ASSERT( memcmp( s.pTo, test, (_tcslen(test)+2)*sizeof(TCHAR) ) == 0 );


如果您的项目配置为使用Unicode字符集,请使用宽字符串调用CString cstrTempDest = firstPathDest + lastPartDest + CString(_folderNameDest, _tcslen(_folderNameDest)+1); 构造函数:

CString
Unicode模式下的

CString _folderName(_T("a6_töüst-Oa5Z.OZS-CI5O5235")), firstPath(_T("C:\\ORTIM-Daten\\a5Pc 2.0.3\\Temp\\")) ... 自动将窄字符串转换为宽字符串,但是当运行时代码页与开发代码页之间的差异严重时,它可能会失败。如果您打算使用Unicode而从不回头,则丢弃CString_TEXTTEXT宏,然后使用宽文字:

_T


您还应该检查CString _folderName( L"a6_töüst-Oa5Z.OZS-CI5O5235" ), firstPath( L"C:\\ORTIM-Daten\\a5Pc 2.0.3\\Temp\\" ) ... 的返回值。

答案 1 :(得分:1)

msp0815用户在creating double null ended CString上的回答解决了您的问题。

// strings must be double-null terminated

CString from(cstrTemp + (TCHAR)'\0');
PCZZTSTR szzFrom= from;
s.pFrom= szzFrom;

CString dest(cstrTempDest + (TCHAR)'\0');
PCZZTSTR szzDest= dest;
s.pTo= szzDest;

答案 2 :(得分:-3)

我通常不使用LPCWSTR,但这是我的主意:

CString TestCSTR = "Hello world";
LPCWSTR TestLPC;

TestLPC = (LPCWSTR)_TEXT(TestCSTR.GetString());

实际上它可以按预期运行,变量TestLPC拥有“ Hello world”,或者更确切地说是指向它的长指针。应该可以删除_TEXT而不会产生任何后果,但我不确定结果是否相同。