Hi guys,
I have a problem with the nt service issue. If I run as a console
application, everything seem to work probably, but when I convert the code
to run as a service, I got the Call cmd :C:\WINDOWS\system32\cmd.exe
Call opts :/C set
CreateChildProcess
child read pipe
ReadFromPipe
Read data from child
ReadFile Failed:109
child Done
// CallCmd.cpp: implementation of the CCallCmd class.
//
//////////////////////////////////////////////////////////////////////
#include “CallCmd.h”
#include <stdio.h>
#include <windows.h>
#include <winerror.h>
#define BUFSIZE 256
#include “…/service/PipeClient.h”
#ifdef debug
extern CPipeClient m_clientPipe;
#endif
HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup,
hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup,
hInputFile, hSaveStdin, hSaveStdout;
BOOL CreateChildProcess(char *cmdline, char *options);
long WriteToPipe(VOID);
long ReadFromPipe(VOID);
VOID ErrorExit(LPTSTR);
VOID ErrMsg(LPTSTR, BOOL);
//#define pInputFile “parentInput”
#define pInputFile NULL
long CallCmd(char *cmdLine, char *options)
{
SECURITY_ATTRIBUTES saAttr;
BOOL fSuccess;
DEBUG_OUT1(“Call cmd :%s”, cmdLine);
DEBUG_OUT1(“Call opts :%s”, options);
// Set the bInheritHandle flag so pipe handles are inherited.
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
// The steps for redirecting child process’s STDOUT:
// 1. Save current STDOUT, to be restored later.
// 2. Create anonymous pipe to be STDOUT for child process.
// 3. Set STDOUT of the parent process to be write handle to
// the pipe, so it is inherited by the child process.
// 4. Create a noninheritable duplicate of the read handle and
// close the inheritable read handle.
// Save the handle to the current STDOUT.
hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
// Create a pipe for the child process’s STDOUT.
if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
{
ErrorExit(“Stdout pipe creation failed\n”);
return 1;
}
// Set a write handle to the pipe to be STDOUT.
if (! SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr))
ErrorExit(“Redirecting STDOUT failed”);
// Create noninheritable read handle and close the inheritable read
// handle.
fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
GetCurrentProcess(), &hChildStdoutRdDup , 0,
FALSE,
DUPLICATE_SAME_ACCESS);
if( !fSuccess )
{
ErrorExit(“DuplicateHandle failed”);
return 1;
}
CloseHandle(hChildStdoutRd);
// The steps for redirecting child process’s STDIN:
// 1. Save current STDIN, to be restored later.
// 2. Create anonymous pipe to be STDIN for child process.
// 3. Set STDIN of the parent to be the read handle to the
// pipe, so it is inherited by the child process.
// 4. Create a noninheritable duplicate of the write handle,
// and close the inheritable write handle.
// Save the handle to the current STDIN.
hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);
// Create a pipe for the child process’s STDIN.
if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
{
ErrorExit(“Stdin pipe creation failed\n”);
return 1;
}
// Set a read handle to the pipe to be STDIN.
if (! SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd))
{
ErrorExit(“Redirecting Stdin failed”);
return 1;
}
// Duplicate the write handle to the pipe so it is not inherited.
fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
GetCurrentProcess(), &hChildStdinWrDup, 0,
FALSE, // not inherited
DUPLICATE_SAME_ACCESS);
if (! fSuccess)
{
ErrorExit(“DuplicateHandle failed”);
return 1;
}
CloseHandle(hChildStdinWr);
// Now create the child process.
if (! CreateChildProcess(cmdLine, options))
{
ErrorExit(“Create process failed”);
return 1;
}
// After process creation, restore the saved STDIN and STDOUT.
if (! SetStdHandle(STD_INPUT_HANDLE, hSaveStdin))
{
ErrorExit(“Re-redirecting Stdin failed\n”);
return 1;
}
if (! SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout))
{
ErrorExit(“Re-redirecting Stdout failed\n”);
return 1;
}
// Get a handle to the parent’s input file.
if (pInputFile)
hInputFile = CreateFile(pInputFile, GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
else
hInputFile = hSaveStdin;
if (hInputFile == INVALID_HANDLE_VALUE)
{
ErrorExit(“no input file\n”);
return 1;
}
// Write to pipe that is the standard input for a child process.
// WriteToPipe();
// Read from pipe that is the standard output for child process.
DEBUG_OUT(“child read pipe”);
ReadFromPipe();
DEBUG_OUT(“child Done”);
return 0;
}
BOOL CreateChildProcess(char *cmdline, char *options)
{
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
int status = 1;
DEBUG_OUT(“CreateChildProcess”);
// Set up members of the PROCESS_INFORMATION structure.
ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
// Set up members of the STARTUPINFO structure.
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);
// Create the child process.
if (!(status = CreateProcess(
cmdline, // program
options, // command line options
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
CREATE_NEW_CONSOLE, // creation flags
NULL, // use parent’s environment
NULL, // use parent’s current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo))) // receives PROCESS_INFORMATION
{
DEBUG_OUT1(“CreateProcess failed. Error:%d\n”, GetLastError());
}
return status;
}
long WriteToPipe(VOID)
{
DWORD dwRead, dwWritten;
CHAR chBuf[BUFSIZE];
// Read from a file and write its contents to a pipe.
for (;![]()
{
if (! ReadFile(hInputFile, chBuf, BUFSIZE, &dwRead, NULL) ||
dwRead == 0) break;
if (! WriteFile(hChildStdinWrDup, chBuf, dwRead,
&dwWritten, NULL)) break;
}
// Close the pipe handle so the child process stops reading.
if (! CloseHandle(hChildStdinWrDup))
{
ErrorExit(“Close pipe failed\n”);
return 1;
}
return 0;
}
long ReadFromPipe(VOID)
{
DWORD dwRead;
CHAR chBuf[BUFSIZE];
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
// Close the write end of the pipe before reading from the
// read end of the pipe.
DEBUG_OUT(“ReadFromPipe”);
if (!CloseHandle(hChildStdoutWr))
{
ErrorExit(“Closing handle failed”);
return 1;
}
// Read output from the child process, and write to parent’s STDOUT.
Sleep(500);
for (;![]()
{
DEBUG_OUT(“Read data from child”);
if( !ReadFile( hChildStdoutRdDup, chBuf, BUFSIZE, &dwRead, NULL) ||
dwRead == 0)
{
DEBUG_OUT1(“ReadFile Failed:%d”, GetLastError());
break;
}
DEBUG_OUT(“Got data from child”);
chBuf[dwRead] = 0;
DEBUG_OUT1(“child out: %s\n”, chBuf);
}
return 0;
}
VOID ErrorExit (LPTSTR lpszMessage)
{
DEBUG_OUT1(“child Error: %s”, lpszMessage);
}</winerror.h></windows.h></stdio.h>