0

I have batch script, to create backup of some 30 locations on work network, and it works. Now I am programming the same app, but in MFC VC++, so im using little trick to set parameters for xcopy in string, then execute it with ShellExecute.

m_destination is variable from editbox, as destination input, where files are going.

Code is:

if (m_line1.GetCheck() == BST_CHECKED)
{
    temp_dest = _T("/min /c xcopy \"\\\\pc_name.sub_domain.domain.local\\c$\\Users\\Test\\Desktop\\Test\\*.*\" \"") + m_destination + _T("\" /Y /E /Q");
    ShellExecute(
        GetSafeHwnd(),
        L"open",            // open edit print
        L"C:\\Windows\\System32\\cmd.exe", // FILE PATH,  
        temp_dest,          // PARAMETERS
        NULL,               // WORKING DIR
        SW_HIDE);           // WINDOW SHOW HIDE
    m_status = "Line 1 - OK\r\n";
}

This code above works, but there are some cases, when target PC is shutdown, and in cmd window, it says "path has changed or destination unreachable" (something like that). In that case, %errorlevel% has some value, and some other if copying successfully done. Then u have condition to trigger different warnings to user. The thing is, I dont have clue how to catch it to indicate unsuccessful copying.

I need some kind of warning that copying from that PC is not done. How can I retrieve error code after copying in this way?

Or if there is simple function to replace copyx with (*.*) (all contents) copying, with ability to be directed to specific directory, I would like to hear about it.

Thanks in advance.

Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77
  • 2
    Try `SHFileOperation` – Barmak Shemirani Jun 05 '18 at 16:17
  • 2
    Google "createprocess waitforsingleobject getexitcodeprocess". – zett42 Jun 05 '18 at 16:38
  • Using a batch for this seems kinda flaky, since you are programming, do the copy from your program. – David Heffernan Jun 06 '18 at 04:52
  • Just in case someone is reading, I have managed to solve it... to detect if it copied all, or not... `LPTSTR temp_dest2 = (LPTSTR)(LPCTSTR)temp_dest;BOOL bSucess = CreateProcess(L"C:\\Windows\\System32\\cmd.exe", temp_dest2, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &sinfo, &pinfo); TerminateProcess(pinfo.hProcess, 2); GetExitCodeProcess(pinfo.hProcess, &dwCode); TCHAR msg2[100]; StringCbPrintf(msg2, 100, TEXT("%X"), dwCode); MessageBox(msg2, (LPCWSTR)L"DWCode 2", MB_OK | MB_ICONERROR);` @zett42 thank you – Orion310591 Jun 06 '18 at 19:58
  • ERRORLEVEL and process exit code are two different things. – Anders Jun 06 '18 at 22:00
  • @Anders [It depends](https://blogs.msdn.microsoft.com/oldnewthing/20080926-00/?p=20743/). If you mean the %ERRORLEVEL% *environment variable*, then yes they are different things, but the ERRORLEVEL *state* of the command processor contains the last process exit code. – zett42 Jun 07 '18 at 09:45
  • @zett42 some commands are internal in cmd.exe and there are instances where things don't match correctly. https://stackoverflow.com/questions/4632891/exiting-batch-with-exit-b-x-where-x-1-acts-as-if-command-completed-successfu and broken `RD` & redirection: https://stackoverflow.com/a/6817833/3501 – Anders Jun 07 '18 at 11:33

1 Answers1

0

I don't think there's a straightforward way to do this with ShellExecute because it doesn't give you a process handle. However, ShellExecuteEx does, via the hProcess field of the SHELLEXECUTEINFO struct you pass in. With that handle, you can wait (WaitForSingleObject) and then get the exit code (GetExitCodeProcess). However, you can also do this with a simple CreateProcess. Also SHFileOperation supports some xcopy-like operations and gives you additional programmatic control.

Michael Gunter
  • 12,528
  • 1
  • 24
  • 58
  • I don't think that the exit code of the command interpreter is set to the `ERRORLEVEL`, so using `ShellExecuteEx` in place of `ShellExecute` doesn't buy you anything. – IInspectable Jun 06 '18 at 10:51
  • @IInspectable True. OP doesn't actually need to use cmd.exe, though, if the post completely shows what they're trying to do. They can just `CreateProcess` on `xcopy.exe` directly with the `CREATE_NO_WINDOW` flag. – Michael Gunter Jun 06 '18 at 20:10
  • Yes, of course, and yet this answer implies that exchanging `ShellExecute` for `ShellExecuteEx` were sufficient. That needs clarification. It's also very unusual to use `ShellExecuteEx` to launch a process. It requires environment setup to function properly. `CreateProcess` does not, and imposes no restrictions on the thread it can be called from. – IInspectable Jun 06 '18 at 22:59