[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1452
  • Last Modified:

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");
      }
}
0
thanesh
Asked:
thanesh
  • 10
  • 10
1 Solution
 
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
 
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 10
  • 10
Tackle projects and never again get stuck behind a technical roadblock.
Join Now