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");
      }
}
LVL 1
thaneshAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jkrCommented:
That seems to be way too complicated. Why don't you just  use 'SHFileOperation()', it is designed for that purpose:

    SHFILEOPSTRUCT  sfo;
    ZeroMemory  (   &sfo,   sizeof  (   SHFILEOPSTRUCT));

    sfo.wFunc   =   FO_COPY;
    sfo.pFrom   =   "c:\\path\\*.*";
    sfo.pTo     =   "c:\\anotherpath";
    sfo.fFlags  =   FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI;

    if  (   SHFileOperation (   &sfo))
        {
            // error
        }
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
thaneshAuthor Commented:
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");
}
0
jkrCommented:
Try

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

instead.
0
Cloud Class® Course: Microsoft Exchange Server

The MCTS: Microsoft Exchange Server 2010 certification validates your skills in supporting the maintenance and administration of the Exchange servers in an enterprise environment. Learn everything you need to know with this course.

thaneshAuthor Commented:
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:\\";
0
jkrCommented:
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;
0
thaneshAuthor Commented:
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 ). :-(((((
0
jkrCommented:
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?
0
thaneshAuthor Commented:
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.
0
jkrCommented:
Hm, just to be sure, could you post your exact code plus the compiler version?
0
thaneshAuthor Commented:
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");
}

0
jkrCommented:
OK, tried the same - with the only exception that my destination drive is 'g' and I used 'c:\bin\*.*'. Works fine...
0
thaneshAuthor Commented:
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 );

0
jkrCommented:
Strange - does

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

work also?
0
thaneshAuthor Commented:
Nope.  I tried that.
0
jkrCommented:
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.
0
thaneshAuthor Commented:
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      
0
jkrCommented:
Hm, that's not really what I was hoping for. Is that what is happening during the 'SHFileOperation()' call also included in the above?
0
thaneshAuthor Commented:
Yes, there were lot of other logs.  but, they all say SUCCESS. So, I did not post them.
0
jkrCommented:
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            
0
thaneshAuthor Commented:
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.  
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.