Как использовать SHFileOperation () с путями CString - PullRequest
0 голосов
/ 21 сентября 2018

Я пытаюсь преобразовать 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() (как в комментариях) для назначения LPCWSTR членов в структуре, все работает.

EDIT 1

В обоих вариантах исходного и целевого путей код компилируется.

В этом варианте код компилируется и выполняет операцию копирования:

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");

В другом варианте, который мне действительно нужен, код также компилируется, но операция копирования не выполняется.состоится:

 s.pTo   = cstrTempDest;
 s.pFrom = cstrTemp;

Ответы [ 3 ]

0 голосов
/ 21 сентября 2018

SHFILEOPSTRUCT ожидает строки, заканчивающиеся двумя символами NUL, но строки, заканчивающиеся NUL, по определению заканчиваются одним , а любые дополнительные символы NUL игнорируются CString методами, которые неt принимать аргумент явной длины.

Вы можете принудительно задать двойной NUL, добавив один вручную:

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 );

Альтернативное решение может использовать методы с аргументом явной длины:

CString cstrTempDest = firstPathDest + lastPartDest
                           + CString(_folderNameDest, _tcslen(_folderNameDest)+1);


Если ваш проект настроен на использование набора символов Unicode, вызовите конструкторы CString с широкими строками:

CString _folderName(_T("a6_töüst-Oa5Z.OZS-CI5O5235")),
        firstPath(_T("C:\\ORTIM-Daten\\a5Pc 2.0.3\\Temp\\"))
        ...

CString в режиме Unicode автоматически преобразует узкие строки в широкие, но может потерпеть неудачукогда есть несоответствие между кодовыми страницами времени выполнения и разработки.Если вы планируете использовать Unicode и никогда не оглядываться назад, отбросьте макросы _TEXT, TEXT и _T и просто используйте широкие литералы:

CString _folderName( L"a6_töüst-Oa5Z.OZS-CI5O5235" ),
        firstPath( L"C:\\ORTIM-Daten\\a5Pc 2.0.3\\Temp\\" )
        ...


Вам также следует проверить SHFileOperationвозвращаемое значение.

0 голосов
/ 21 сентября 2018

Ответ пользователя msp0815 на создание двойного нулевого конца 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;
0 голосов
/ 21 сентября 2018

Я обычно не так часто использую LPCWSTR, но вот моя идея:

CString TestCSTR = "Hello world";
LPCWSTR TestLPC;

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

Она работает, как и ожидалось, на самом деле переменная TestLPC содержит "Hello world" или, точнее, длинный указатель наЭто.Должна быть возможность удалить _TEXT без последствий, но я не уверен, результат тот же, кстати.

...