Link to home
Start Free TrialLog in
Avatar of thanesh
thanesh

asked on

CreateProcess and xcopy.exe

Hi Experts,

I am trying to copy some files using the following program.  I need to check whether the files are copied successfully. Therefore, I am doing the following way to get the output of the xcopy.exe in buf and then parse the string to check if there were any problems.  In the following sample, the files from C:\Temp aren't copied to G:

The CreateProcess seems to work, and I could not find why the files aren't copied.

#include <fstream.h>
#include <iostream.h>
#include <windows.h>
#include <stdio.h>

bool IsWinNT()
{
      OSVERSIONINFO osv;
      osv.dwOSVersionInfoSize = sizeof(osv);
      GetVersionEx(&osv);
      return (osv.dwPlatformId == VER_PLATFORM_WIN32_NT);
}

bool ExecParseCmd(char* buf, unsigned int bufsize, char* cmd)
{
      const char * fName = "ExecParseCmd";

      STARTUPINFO                  si;
      SECURITY_ATTRIBUTES      sa;
      SECURITY_DESCRIPTOR      sd;
      PROCESS_INFORMATION      pi;
      HANDLE              h_Fileout;
      unsigned long       bRead;   //bytes read
      char               *parseFile = "parse.txt";


      if (IsWinNT())
      {
            InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
            SetSecurityDescriptorDacl(&sd, true, NULL, false);
            sa.lpSecurityDescriptor = &sd;
      }
      else
      {
            sa.lpSecurityDescriptor = NULL;
      }

      sa.nLength = sizeof(SECURITY_ATTRIBUTES);
      sa.bInheritHandle = true;


      h_Fileout = CreateFile( parseFile,
            GENERIC_READ| GENERIC_WRITE,
            FILE_SHARE_READ | FILE_SHARE_WRITE,
            &sa,
            CREATE_ALWAYS,
            FILE_ATTRIBUTE_TEMPORARY,
            NULL
            );

      if( h_Fileout == INVALID_HANDLE_VALUE ) {
            int err = GetLastError();
            return FALSE;
      }

      GetStartupInfo(&si);
      si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
      si.wShowWindow = SW_HIDE;
      si.hStdOutput = h_Fileout;
      si.hStdError = h_Fileout;     //set the new handles for the child process
      si.hStdInput = INVALID_HANDLE_VALUE;
      ZeroMemory(&pi, sizeof(pi));
      
      //spawn the child process which writes to the parse.txt

      if (!CreateProcess(0, cmd, NULL, NULL, TRUE,0,
                         NULL, NULL, &si, &pi))
      {
            DWORD err = GetLastError();
            CloseHandle(h_Fileout);
            return FALSE;
      }

      //wait until child process exits
                WaitForSingleObject( pi.hProcess, INFINITE );
      CloseHandle(pi.hThread);
      CloseHandle(pi.hProcess);

      ZeroMemory(buf, bufsize);

      if(!ReadFile(h_Fileout, buf, (bufsize-1), &bRead, NULL )) {
            DWORD err = GetLastError();
            return FALSE;
      }

      CloseHandle(h_Fileout);
      if(!DeleteFile(parseFile)) {
            DWORD err = GetLastError();
      }

      return TRUE;
}

void main()
{

      char buf[1024];
      char cmd[256];

      SetCurrentDirectory("C:\\Temp");
      sprintf(cmd, "xcopy.exe * g:");
      if( ExecParseCmd(buf, 1024, cmd) == false ) {
            printf("Error\n");
      }
}
ASKER CERTIFIED SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of thanesh
thanesh

ASKER

Ok, thanks.  I had the above code implemented in my code for some other purpose.  So, I was trying to reuse that.
Anyway, the SHFileOperation approach is neet.  But, I still couldn't get it working using the new code shown below.  I am getting error 6( access denied). I was able to copy files using copy command from a dos prompt.  

bool CopyFiles(char *driveLetter)
{
      const char *fName = "CopyFiles";
      char from[256];
      char to[256];
      
      SHFILEOPSTRUCT  sfo;
                ZeroMemory  (   &sfo,   sizeof  (   SHFILEOPSTRUCT));
      
      sprintf(to, "%s:", driveLetter );
      sprintf(from, "%s\\*.*", "c:\\bin" );
                sfo.wFunc   =   FO_COPY;
                sfo.pFrom   =   from;
                sfo.pTo     =   to;
                sfo.fFlags  =   FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI;
      
               if(SHFileOperation (&sfo))
      {
         int err = GetLastError();
                   printf("error %d\n", err);
                   return FALSE;
      }
      
      return TRUE;
}

void main()
{

      CopyFiles("g");
}
Try

    sprintf(to, "%s:\\", driveLetter );

instead.
Avatar of thanesh

ASKER

I get the same error.   When I use the commented out part below it works.  But, not when I use the sprintf to get the path.

sprintf(to, "%s:\\", driveLetter );
sprintf(from, "%s\\*.*", "c:\\bin" );
    sfo.wFunc   =   FO_COPY;
    sfo.pFrom   =   from;
    sfo.pTo     =   to;
   // sfo.pFrom   =   "c:\\bin\\*.*";
    //sfo.pTo     =   "g:\\";
That's odd, it works here - are there any other files in use under 'c:\bin'? That function copies the whole tree. If you don't want that, add 'FOF_FILESONLY' to the flags, i.e.

                sfo.fFlags  =   FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_FILESONLY;
Avatar of thanesh

ASKER

I want the whole tree to be copied. No none of the files are in use.
The problem is in the pFrom( The pTo seems to be ok ). :-(((((
Odd... that's exactly what I used:

#include <windows.h>
#include <stdio.h>

#pragma comment(lib,"shell32.lib")

bool CopyFiles(char *driveLetter)
{
     const char *fName = "CopyFiles";
     char from[256];
     char to[256];
     
     SHFILEOPSTRUCT  sfo;
                ZeroMemory  (   &sfo,   sizeof  (   SHFILEOPSTRUCT));
     
     sprintf(to, "%s:\\shftest", driveLetter );
     sprintf(from, "%s\\*.*", "c:\\tmp\\install" );

     printf("%s -> %s", from, to);



                sfo.wFunc   =   FO_COPY;
                sfo.pFrom   =   from;
                sfo.pTo     =   to;
                sfo.fFlags  =   FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI;
     
               if(SHFileOperation (&sfo))
     {
        int err = GetLastError();
                   printf("error %d\n", err);
                   return FALSE;
     }
     
     return TRUE;
}

void main()
{

     CopyFiles("d");
}

and it worked without any problem... Can you try an empty subdirecotry as the target, just for testing purposes?
Avatar of thanesh

ASKER

I did.  I even tried copying a single file without *.* and again same problem.  It is really odd.
sprintf(from, "c:\\bin\\test.txt");
 //  sfo.pFrom   =   "c:\\bin\\test.txt";
    sfo.pFrom   =   from;
In the above code, the commented out portion works.
Hm, just to be sure, could you post your exact code plus the compiler version?
Avatar of thanesh

ASKER

Here it is.  I am using Microsoft Visual C++ 6.0
#include <windows.h>
#include <stdio.h>


bool CopyFiles(char *driveLetter)
{
      const char *fName = "CopyFiles";
      char from[256];
      char to[256];
      
      SHFILEOPSTRUCT  sfo;
    ZeroMemory  (   &sfo,   sizeof  (   SHFILEOPSTRUCT));
      sprintf(to, "%s:\\", driveLetter );
      sprintf(from, "c:\\bin\\test.txt");

      printf("%s\n", from);
      printf("%s\n", to);

    sfo.wFunc   =   FO_COPY;
   // sfo.pFrom   =   "c:\\bin\\test.txt";
    sfo.pFrom   =   from;
    sfo.pTo     =   to;

    sfo.fFlags  =   FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI;
    if(SHFileOperation (&sfo))
      {
            int err = GetLastError();

            printf("error %d\n", err);
      }
      
      return TRUE;
}

void main()
{

      CopyFiles("g");
}

OK, tried the same - with the only exception that my destination drive is 'g' and I used 'c:\bin\*.*'. Works fine...
Avatar of thanesh

ASKER

Hmmm.   I am not sure why, but when I try memset the from array to zero it works.
But, I don't know why.

ZeroMemory( from, 256 );

Strange - does

    sprintf(from, "c:\\bin\\test.txt\0");

work also?
Avatar of thanesh

ASKER

Nope.  I tried that.
OK, time for the heavy machinery - try http://www.sysinternals.com/Utilities/Filemon.html and filter for your app's name to see what exactly is accessed and what errors are shown.
Avatar of thanesh

ASKER

JKR.  I tried it.  There were couple of Not Found errors. I have copied them below. Thanks.

2:45:39 PM      process.exe:3024      OPEN      C:\My_test\Process\process\Debug\process.exe.Local      NOT FOUND      Options: Open  Access: All      
2:45:39 PM      process.exe:3024      OPEN      C:\My_test\Process\process\Debug\AMINIT.DLL      NOT FOUND      Options: Open  Access: All      
2:45:39 PM      process.exe:3024      OPEN      C:\WINDOWS\system32\SHELL32.dll.124.Manifest      NOT FOUND      Options: Open  Access: All      
2:45:39 PM      process.exe:3024      OPEN      C:\WINDOWS\system32\SHELL32.dll.124.Config      NOT FOUND      Options: Open  Access: All      
2:45:39 PM      process.exe:3024      OPEN      C:\WINDOWS\WindowsShell.Config      NOT FOUND      Options: Open  Access: All      
Hm, that's not really what I was hoping for. Is that what is happening during the 'SHFileOperation()' call also included in the above?
Avatar of thanesh

ASKER

Yes, there were lot of other logs.  but, they all say SUCCESS. So, I did not post them.
Hm, the part of interest is where the files are copied, i.e.

      shfcpy.exe:1688      OPEN      C:\bin\      SUCCESS      Options: Open Directory  Access: All      
      shfcpy.exe:1688      DIRECTORY      C:\bin\      SUCCESS      FileBothDirectoryInformation: *      
      shfcpy.exe:1688      DIRECTORY      C:\bin\      SUCCESS      FileBothDirectoryInformation      
      shfcpy.exe:1688      DIRECTORY      C:\bin\      NO MORE FILES      FileBothDirectoryInformation      
      shfcpy.exe:1688      CLOSE      C:\bin\      SUCCESS            
      shfcpy.exe:1688      OPEN      D:\      SUCCESS      Options: Open Directory  Access: All      
      shfcpy.exe:1688      DIRECTORY      D:\      SUCCESS      FileBothDirectoryInformation: *      
      shfcpy.exe:1688      CLOSE      D:\      SUCCESS            
      shfcpy.exe:1688      OPEN      D:\      SUCCESS      Options: Open Directory  Access: All      
      shfcpy.exe:1688      CLOSE      D:\      SUCCESS            
      shfcpy.exe:1688      OPEN      C:\bin\testfile.txt      SUCCESS      Options: Open  Access: All      
      shfcpy.exe:1688      OPEN      D:\      SUCCESS      Options: Open Directory  Access: All      
      shfcpy.exe:1688      CLOSE      C:\bin\testfile.txt      SUCCESS            
      shfcpy.exe:1688      CLOSE      D:\      SUCCESS            
      shfcpy.exe:1688      OPEN      C:\bin\testfile.txt      SUCCESS      Options: Open Sequential  Access: All      
      shfcpy.exe:1688      QUERY INFORMATION      C:\bin\testfile.txt      SUCCESS      Length: 52      
      shfcpy.exe:1688      QUERY INFORMATION      C:\bin\testfile.txt      SUCCESS      Attributes: A      
      shfcpy.exe:1688      QUERY INFORMATION      C:\bin\testfile.txt      SUCCESS      Attributes: A      
      shfcpy.exe:1688      CREATE      D:\testfile.txt      NAME COLLISION      Options: Create Sequential  Access: All      
      shfcpy.exe:1688      CLOSE      C:\bin\testfile.txt      SUCCESS            
      shfcpy.exe:1688      OPEN      D:\      SUCCESS      Options: Open Directory  Access: All      
      shfcpy.exe:1688      DIRECTORY      D:\      SUCCESS      FileBothDirectoryInformation: testfile.txt      
      shfcpy.exe:1688      CLOSE      D:\      SUCCESS            
      shfcpy.exe:1688      OPEN      C:\bin\testfile.txt      SUCCESS      Options: Open Sequential  Access: All      
      shfcpy.exe:1688      QUERY INFORMATION      C:\bin\testfile.txt      SUCCESS      Length: 52      
      shfcpy.exe:1688      QUERY INFORMATION      C:\bin\testfile.txt      SUCCESS      Attributes: A      
      shfcpy.exe:1688      QUERY INFORMATION      C:\bin\testfile.txt      SUCCESS      Attributes: A      
      shfcpy.exe:1688      CREATE      D:\testfile.txt      SUCCESS      Options: OverwriteIf Sequential  Access: All      
      shfcpy.exe:1688      SET INFORMATION       D:\testfile.txt      SUCCESS      Length: 52      
      shfcpy.exe:1688      SET INFORMATION       D:\testfile.txt      SUCCESS      FileBasicInformation      
      shfcpy.exe:1688      QUERY INFORMATION      C:\bin\testfile.txt      SUCCESS      Length: 52      
      shfcpy.exe:1688      WRITE       D:\testfile.txt      SUCCESS      Offset: 0 Length: 52      
      shfcpy.exe:1688      SET INFORMATION       D:\testfile.txt      SUCCESS      FileBasicInformation      
      shfcpy.exe:1688      CLOSE      C:\bin\testfile.txt      SUCCESS            
      shfcpy.exe:1688      CLOSE      D:\testfile.txt      SUCCESS            
Avatar of thanesh

ASKER

Thanks for the help JKR.  I really appriciate your help.  Although I still wanting to
know why it behaves this way, I am going to award the points to you.