How to use SHFileOperation() with CString paths

shfileoperation delete folder
shfileoperation c#
shfileoperationw
shfileoperation delphi
ifileoperation example

I am trying to convert CString to LPCWSTR and it works well. But something went wrong in the processing of the code.

I want to copy a directory to another path so I am using 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);

When I am using CString directly, the copy operation doesn't work, but when I use the _TEXT() macro (as in the comments) to assign the LPCWSTR members in the struct everything works.

EDIT 1

In both variants of source and destination paths the code compiles.

In this variant, the code compiles and does the copy operation:

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

In the other variant, which I actually need, the code compiles too, but the copy operation doesn't take place:

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

SHFILEOPSTRUCT expects strings ending with two NUL characters, but NUL terminated strings by definition end with one and any additional NUL characters are ignored by CString methods that don't take explicit length argument.

You can force double NUL by adding one manually:

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

Alternative solution can use methods with explicit length argument:

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

  If your project is configured to use unicode character set, call CString constructors with wide strings:

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

CString in unicode mode automatically converts narrow strings to wide ones, but it can fail when threre is discrepancy between runtime and development codepages. If you plan to go Unicode and never look back, throw away _TEXT, TEXT and _T macros and just use wide literals:

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

  You should also check SHFileOperation return value.

How to use SHFileOperation() with CString paths - c++ - android, OZS-CI5O5235\\Documents\\*\0")*/; SHFileOperation(&s); When I am using CString directly, the copy operation doesn't work, but when I use the _TEXT() macro  C++ (Cpp) SHFileOperation - 30 examples found. These are the top rated real world C++ (Cpp) examples of SHFileOperation extracted from open source projects. You can rate examples to help us improve the quality of examples.

The answer of user msp0815 on creating double null ended CString solves your issue.

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

SHFileOperationA function (shellapi.h), Using it with relative path names is not thread safe. With two exceptions, you cannot use SHFileOperation to move special folders from a local  You should use fully qualified path names with this function. Using it with relative path names is not thread safe. With two exceptions, you cannot use SHFileOperation to move special folders from a local drive to a remote computer by specifying a network path.

I generally don't use LPCWSTR that much but here is my idea:

CString TestCSTR = "Hello world";
LPCWSTR TestLPC;

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

It works as expected in fact the variable TestLPC holds "Hello world" or to be more precise a long pointer to it. It should be possible to remove _TEXT without consequences but I'm not sure, the result is the same btw.

Copy, Move and Delete files and directories without using , Class that allows file operations without using SHFileOperation. Path presentation: It is unimportant how you represent the path with '\' on end or without it. message (see functions, GetErrorCode() , GetErrorString() and ShowError() accordingly). bool Delete(CString sPathName); // delete file or folder  Introduction. The function SHFileOperation, enables you to copy, move or delete a file system object. As you can see, this function takes as its sole parameter a pointer to a SHFILEOPSTRUCT structure (also shown below).

File Deletion using SHFILEOPSTRUCT & SHFileOperation, I was trying to delete some specified files. and was able to delete the files using absolute path. But when i gave relative path, the thing is not working. Plz help. IFileOperation offers many advantages over the older SHFileOperation function. Use of IShellItem to identify items rather than string paths. SHFileOperation required path and destination strings to terminate in two null characters rather than the standard single null character, which itself was used to delimit multiple paths in the string.

Copy, Move and Delete files and rename directories , It's necessary to use SHFileOperation function from shell to do it. MFC was used for simplification of process (only CString and CFileFind classes Path presentation: It is unimportant how you represent the path with '\' on end or without it. (see functions, GetErrorCode() , GetErrorString() and ShowError() accordingly). The lack of a path before a file name does not indicate to SHFileOperation that this file resides in the root of the current directory. The PATH environment variable is not used by SHFileOperation to determine a valid path. SHFileOperation cannot be relied on to use the directory that is the current directory when it begins executing. The

Directory Copy: SHFileOperation() error, The code that I am using to do the copying is: SHFILEOPSTRUCT where pFrom and pTo will point to instead of using CString and using GetBuffer() I don't get this error even if I don't include the \0 at the end of the paths. C# (CSharp) SHFILEOPSTRUCT - 30 examples found. These are the top rated real world C# (CSharp) examples of SHFILEOPSTRUCT extracted from open source projects. You can rate examples to help us improve the quality of examples.

Comments
  • it works fine here, but you can try cstrTempDest.GetBuffer(0)
  • @ServeLaurijssen with your suggestion the copy operation don't work. Only the creation of the destination directory,-if it does not exist- works in this case. which means, that the struct can read the destination path "s.pTo" but cant do the copy operation for some reason!!
  • Is this project for UNICODE or ANSI? Is your CString the wchar_t variant? If you have a non-UNICODE project you need MultiByteToWideChar here.
  • @ServeLaurijssen GetBuffer(0) is the wrong approach because it doesn't garantuee that the string is zero-terminated. Use Data() instead.
  • Why are you using ANSI text in the first place? Start by fixing that.
  • thank you, that is the right solution and a constructive contribution
  • CString handles embedded nulls just fine, as your example shows. The real problem is when passing "a6_töüst-Oa5Z.OZS-CI5O5235\0" as-is to _folderNameDest, it is seen as a null-terminated string and ignores the terminator when initializing _folderNameDest. You can avoid by passing in a 2nd parameter for the string length to include the embedded terminator, eg: LPCTSTR szFolderNameDest = TEXT("a6_töüst-Oa5Z.OZS-CI5O5235\0"); ... , _folderNameDest(szFolderNameDest, _tcslen(szFolderNameDest)+1); Then you don't need to append the extra null terminator as a separate operation.
  • @RemyLebeau I have added your sugestion to answer.
  • This doesn't address the problems of using ANSI text
  • @DavidHeffernan Extended answer with the recommendation of consistent use of wide strings.
  • Wow, I just learned that there is a dedicated typedef for "double null-terminated" strings. For UNICODE it is declared as typedef __nullnullterminated CONST WCHAR *PCZZWSTR;. The __nullnullterminated is SAL annotation so the compiler can do some checking.
  • This will fail to compile, if _UNICODE is defined, an exhibit undefined behavior, if it isn't.
  • I'm curious, why it produces undefined behavior? Is it due to the fact that it cast into a pointer that may result in something not valid?
  • It's because you may be casting a char* to wchar_t*