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())
{
InitializeSecurityDescript or(&sd, SECURITY_DESCRIPTOR_REVISI ON);
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:\\T emp");
sprintf(cmd, "xcopy.exe * g:");
if( ExecParseCmd(buf, 1024, cmd) == false ) {
printf("Error\n");
}
}
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())
{
InitializeSecurityDescript
SetSecurityDescriptorDacl(
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:\\T
sprintf(cmd, "xcopy.exe * g:");
if( ExecParseCmd(buf, 1024, cmd) == false ) {
printf("Error\n");
}
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Try
sprintf(to, "%s:\\", driveLetter );
instead.
sprintf(to, "%s:\\", driveLetter );
instead.
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:\\";
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;
sfo.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_FILESONLY;
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 ). :-(((((
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?
#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?
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.
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?
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");
}
#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...
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 );
But, I don't know why.
ZeroMemory( from, 256 );
Strange - does
sprintf(from, "c:\\bin\\test.txt\0");
work also?
sprintf(from, "c:\\bin\\test.txt\0");
work also?
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.
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\pro cess.exe.L ocal NOT FOUND Options: Open Access: All
2:45:39 PM process.exe:3024 OPEN C:\My_test\Process\process \Debug\AMI NIT.DLL NOT FOUND Options: Open Access: All
2:45:39 PM process.exe:3024 OPEN C:\WINDOWS\system32\SHELL3 2.dll.124. Manifest NOT FOUND Options: Open Access: All
2:45:39 PM process.exe:3024 OPEN C:\WINDOWS\system32\SHELL3 2.dll.124. Config NOT FOUND Options: Open Access: All
2:45:39 PM process.exe:3024 OPEN C:\WINDOWS\WindowsShell.Co nfig NOT FOUND Options: Open Access: All
2:45:39 PM process.exe:3024 OPEN C:\My_test\Process\process
2:45:39 PM process.exe:3024 OPEN C:\My_test\Process\process
2:45:39 PM process.exe:3024 OPEN C:\WINDOWS\system32\SHELL3
2:45:39 PM process.exe:3024 OPEN C:\WINDOWS\system32\SHELL3
2:45:39 PM process.exe:3024 OPEN C:\WINDOWS\WindowsShell.Co
Hm, that's not really what I was hoping for. Is that what is happening during the 'SHFileOperation()' call also included in the above?
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 FileBothDirectoryInformati on: *
shfcpy.exe:1688 DIRECTORY C:\bin\ SUCCESS FileBothDirectoryInformati on
shfcpy.exe:1688 DIRECTORY C:\bin\ NO MORE FILES FileBothDirectoryInformati on
shfcpy.exe:1688 CLOSE C:\bin\ SUCCESS
shfcpy.exe:1688 OPEN D:\ SUCCESS Options: Open Directory Access: All
shfcpy.exe:1688 DIRECTORY D:\ SUCCESS FileBothDirectoryInformati on: *
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 FileBothDirectoryInformati on: 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
shfcpy.exe:1688 OPEN C:\bin\ SUCCESS Options: Open Directory Access: All
shfcpy.exe:1688 DIRECTORY C:\bin\ SUCCESS FileBothDirectoryInformati
shfcpy.exe:1688 DIRECTORY C:\bin\ SUCCESS FileBothDirectoryInformati
shfcpy.exe:1688 DIRECTORY C:\bin\ NO MORE FILES FileBothDirectoryInformati
shfcpy.exe:1688 CLOSE C:\bin\ SUCCESS
shfcpy.exe:1688 OPEN D:\ SUCCESS Options: Open Directory Access: All
shfcpy.exe:1688 DIRECTORY D:\ SUCCESS FileBothDirectoryInformati
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 FileBothDirectoryInformati
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
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.
know why it behaves this way, I am going to award the points to you.
ASKER
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");
}