Kill a process after creating not working - visual-c++

I've somehow written a program to spawn a process but unable to kill it after 2 seconds automatically( It actually does not kill):
void createproc() {
//WaitForSingleObject(&processInfo.hProcess, INFINITE)
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
wchar_t commandline_args[] = L"\"C:\\ddnvnc\\WebServer.exe\" ";
if (!CreateProcess(NULL, // No module name (use command line)
commandline_args, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
printf("CreateProcess failed (%d).\n", GetLastError());
MessageBox(NULL,
_T("Failed"),
_T("Windows Desktop Guided Tour"),
NULL);
}
Sleep(2000);
CloseHandle(&pi.hThread);
TerminateProcess(&pi.hProcess,0);
MessageBox(NULL,
_T("KIlled"),
_T("Windows Desktop Guided Tour"),
NULL);
}
What I want is to spawn and kill the process after 2 seconds, this will be in an infinite loop.

CloseHandle(&pi.hThread);
TerminateProcess(&pi.hProcess,0);
Use pi.hThread instead of &pi.hThread. Note that the order should be reversed.
You can use WaitForSingleObject instead of Sleep, and terminate the process only if it's not terminated already (for example by the user)
//Sleep(2000);
//TerminateProcess(pi.hProcess, 0);
if(WaitForSingleObject(pi.hProcess, 1000) == WAIT_TIMEOUT)
TerminateProcess(pi.hProcess, 0);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);

Related

Linux/OSX/Windows - Waiting end of process

Under OSX, there is "open -W" which allows to wait the end of an executable.
What is the equivalent instruction for windows ?
Linux does have this non-blocking behaviour with programs like sublime-text (subl). How does it do that (execv ?)
Basically, I'm trying ,within a C program, to launch an executable and wait until it ends up.
With the edit, under linux, you're looking at:
childpid = fork();
if (childpid) {
execve("program", argvp, envp);
} else {
int status;
pid_t pid = wait(&status);
}
under windows, you need to use CreateProcess to create the process, and then use WaitForSingleObject to wait for the process to terminate; e.g.
PROCESS_INFORMATION processInformation = {0};
STARTUPINFO startupInfo = {0};
startupInfo.cb = sizeof(startupInfo);
bool status = CreateProcess(L"Program", L"args", 0, 0, 0,
NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW,
0, 0, &startupInfo, &processInformation);
if (status) {
WaitForSingleObject(processInformation.hProcess, INFINITE);
}
Under Linux, a parent process can wait for a child process to terminate by using the wait or waitpid system call. For more finer process synchronization, use semaphores.

Terminating a Worker thread from a Parent thread - MFC

I've just started with learning MFC and I'm writing one dialog based application for better understanding of Multi-Threading.
The main dialog has a progress bar, a Start button and a Cancel button.
On click of the start button, i'm creating a worker thread to do some processing(through API call) and the main thread takes care of Progress bar.
I've defined a couple of Windows Messages to update and stop Progress bar status
WM_UPDATE_CONTROL
WM_STOP_CONTROL
Below is the code that i've created so far
HWND* phObjectHandle;
CWinThread* thread;
void CprogCtrlDlg::OnBnClickedStart() {
phObjectHandle = new HWND; // Set object handle for Worker thread
*phObjectHandle = GetSafeHwnd();
// create worker thread
if(NULL == (thread = AfxBeginThread(ThreadFunc, phObjectHandle))) {
EndDialog(IDCANCEL);
}
AfxMessageBox(L"Thread started");
// Set Progress bar to marquee
}
void CprogCtrlDlg::OnBnClickedCancel() {
// kill the Worker thread
}
UINT CprogCtrlDlg::ThreadFunc(LPVOID pParam) {
HWND *pObjectHandle = static_cast<HWND *>(pParam);
CprogCtrlImpDlg* threadDlg = (CprogCtrlImpDlg*) pParam;
return threadDlg->ThreadFuncRun(pObjectHandle);
}
UINT CprogCtrlDlg::ThreadFuncRun(HWND* pObjectHandle) {
::PostMessage(*pObjectHandle, WM_UPDATE_CONTROL, 0, 0);
// repetitive API CALL in a loop
::PostMessage(*pObjectHandle, WM_STOP_CONTROL, 0, 0);
AfxMessageBox(L"Thread completed");
return 0;
}
I want to terminate the Worker thread from a Parent thread, if a Cancel button is clicked.
I tried using TerminateThread()(though it wasn't a suggested one) but I couldn't kill the thread.
Please comment and share your thoughts on terminating a worker thread from a parent thread.
I'm using visual studio 2010 on Windows 7
TIA
I would amend your code something like this.
Have some member variables in your dialog class to hold the thread handle and an event handle (initialise to NULL in the constructor):
CWinThread* m_hThread;
HANDLE m_hKillEvent;
Use a static function as your thread entry point, pass the dialog this as the parameter, then delegate the call back to the class instance so you have access to all of the dialog's variables:
UINT ThreadFunc(LPVOID pParam)
{
// static thread func - delegate to instance
CprogCtrlDlg* pDlg = static_cast<CprogCtrlDlg*>(pParam);
return pDlg->ThreadFuncRun();
}
When you start the thread, create an event too:
void CprogCtrlDlg::OnBnClickedStart()
{
// create worker thread
m_hKillEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
m_hThread = AfxBeginThread(ThreadFunc, this);
AfxMessageBox(L"Thread started");
}
To kill the thread, just set the event and wait on the thread handle, which will get signaled on death:
void CprogCtrlDlg::OnBnClickedCancel()
{
// kill the Worker thread
SetEvent(m_hKillEvent);
// wait for it to die
DWORD dwRet = WaitForSingleObject(m_hThread->m_hThread, 5000);
if (dwRet == WAIT_TIMEOUT)
{
// thread failed to die after 5 seconds
// error handling (maybe TerminateThread here)
}
}
In the thread function (now in the dialog class) you can post messages to yourself to indicate progress and use a wait on the event to catch a kill request:
UINT CprogCtrlDlg::ThreadFuncRun()
{
// instance thread func
PostMessage(WM_UPDATE_CONTROL, 0, 0);
// main loop
while (true)
{
// check kill
DWORD dwRet = WaitForSingleObject(m_hKillEvent, 0);
if (dwRet == WAIT_OBJECT_0) break;
// do a little work here and update progress
// ... so this is part of your working loop ...
PostMessage(WM_UPDATE_CONTROL, 0, 1 /*2,3,4,...*/);
}
// normal thread exit
PostMessage(WM_STOP_CONTROL, 0, 0);
return 0;
}
I've left out initialisation, cleanup of pointers, handles etc. but you get the general idea I hope.
There are several ways you can code the thread loop, you can do it like above where you periodically check to see if the event is signaled, or you can wait on the event to get signaled to do the work. Both are common patterns and often used together with two events - one for triggering work and the other for killing. See this answer for some important points to note if waiting on multiple events.
For a simple progress bar update, you can put the event check inside the work loop, something like this:
UINT CprogCtrlDlg::ThreadFuncRun()
{
// instance thread func
PostMessage(WM_UPDATE_CONTROL, 0, 0);
// main loop
for (int i = 0; i < 100; ++i)
{
// check kill
DWORD dwRet = WaitForSingleObject(m_hKillEvent, 0);
if (dwRet == WAIT_OBJECT_0) break;
// do a little work here and update progress
PostMessage(WM_UPDATE_CONTROL, 0, (LPARAM)i);
}
// normal thread exit
PostMessage(WM_STOP_CONTROL, 0, 0);
return 0;
}

How to wait for ShellExecute to run?

I have manages to use ShellExecute in VC++ in order to launch a document.
Now I wish to run a command-line tool that receives some arguments, and to run in the background (as hidden, not minimized) and let it block my program flow, so that i'll be able to wait for it to finish.
How to i alter the command-line of:
ShellExecute(NULL,"open",FULL_PATH_TO_CMD_LINE_TOOL,ARGUMENTS,NULL,SW_HIDE);
The problem is, I have tool that converts html to pdf, and I wish that once the tool finished, aka pdf is ready, to have another ShellExecute to view it.
There is a CodeProject article that shows how, by using ShellExecuteEx instead of ShellExecute:
SHELLEXECUTEINFO ShExecInfo = {0};
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpFile = "c:\\MyProgram.exe";
ShExecInfo.lpParameters = "";
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_SHOW;
ShExecInfo.hInstApp = NULL;
ShellExecuteEx(&ShExecInfo);
WaitForSingleObject(ShExecInfo.hProcess, INFINITE);
CloseHandle(ShExecInfo.hProcess);
The crucial point is the flag SEE_MASK_NOCLOSEPROCESS, which, as MSDN says
Use to indicate that the hProcess member receives the process handle. This handle is typically used to allow an application to find out when a process created with ShellExecuteEx terminates
Also, note that:
The calling application is responsible for closing the handle when it is no longer needed.
You can also use CreateProcess instead of ShellExecute/ShellExecuteEx. This function includes a cmd.exe wrapper option, returning the exit code, and returning stdout. (The includes may not be perfect).
Notes: In my use, I knew that there had to be stdout results, but the PeekedNamePipe function wouldn't always return the bytes count on the first try, hence the loop there. Perhaps, someone can figure this out and post a revision? Also, maybe an alternate version should be produced which returns stderr separately?
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <Shellapi.h>
/*
Note:
The exitCode for a "Cmd Process" is not the exitCode
for a sub process launched from it! That can be retrieved
via the errorlevel variable in the command line like so:
set errorlevel=&[launch command]&echo.&echo exitCode=%errorlevel%&echo.
The stdOut vector will then contain the exitCode on a seperate line
*/
BOOL executeCommandLine( const CStringW &command,
DWORD &exitCode,
const BOOL asCmdProcess=FALSE,
std::vector<CStringW> *stdOutLines=NULL )
{
// Init return values
BOOL bSuccess = FALSE;
exitCode = 0;
if( stdOutLines ) stdOutLines->clear();
// Optionally prepend cmd.exe to command line to execute
CStringW cmdLine( (asCmdProcess ? L"cmd.exe /C " : L"" ) +
command );
// Create a pipe for the redirection of the STDOUT
// of a child process.
HANDLE g_hChildStd_OUT_Rd = NULL;
HANDLE g_hChildStd_OUT_Wr = NULL;
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
bSuccess = CreatePipe( &g_hChildStd_OUT_Rd,
&g_hChildStd_OUT_Wr, &saAttr, 0);
if( !bSuccess ) return bSuccess;
bSuccess = SetHandleInformation( g_hChildStd_OUT_Rd,
HANDLE_FLAG_INHERIT, 0 );
if( !bSuccess ) return bSuccess;
// Setup the child process to use the STDOUT redirection
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = g_hChildStd_OUT_Wr;
siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
// Execute a synchronous child process & get exit code
bSuccess = CreateProcess( NULL,
cmdLine.GetBuffer(), // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo ); // receives PROCESS_INFORMATION
if( !bSuccess ) return bSuccess;
WaitForSingleObject( piProcInfo.hProcess, (DWORD)(-1L) );
GetExitCodeProcess( piProcInfo.hProcess, &exitCode );
CloseHandle( piProcInfo.hProcess );
CloseHandle( piProcInfo.hThread );
// Return if the caller is not requesting the stdout results
if( !stdOutLines ) return TRUE;
// Read the data written to the pipe
DWORD bytesInPipe = 0;
while( bytesInPipe==0 ){
bSuccess = PeekNamedPipe( g_hChildStd_OUT_Rd, NULL, 0, NULL,
&bytesInPipe, NULL );
if( !bSuccess ) return bSuccess;
}
if( bytesInPipe == 0 ) return TRUE;
DWORD dwRead;
CHAR *pipeContents = new CHAR[ bytesInPipe ];
bSuccess = ReadFile( g_hChildStd_OUT_Rd, pipeContents,
bytesInPipe, &dwRead, NULL);
if( !bSuccess || dwRead == 0 ) return FALSE;
// Split the data into lines and add them to the return vector
std::stringstream stream( pipeContents );
std::string str;
while( getline( stream, str ) )
stdOutLines->push_back( CStringW( str.c_str() ) );
return TRUE;
}
Using ShellExecuteEx sometimes doesn't work if COM is used, so the following remarks must be considered.
Because ShellExecuteEx can delegate execution to Shell extensions
(data sources, context menu handlers, verb implementations) that are
activated using Component Object Model (COM), COM should be
initialized before ShellExecuteEx is called. Some Shell extensions
require the COM single-threaded apartment (STA) type. In that case,
COM should be initialized as shown here:
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)
There are instances where ShellExecuteEx does not use one of these
types of Shell extension and those instances would not require COM to
be initialized at all. Nonetheless, it is good practice to always
initalize COM before using this function.
More from MSDN here
https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecuteexa

Synchronising threads using Events in windows

I need to synchronize threads using events. First I am not getting concept of Events in windows. I will take an example, I have main thread and secondary thread. I created a two events called "write" and "test". In main thread I signaled for 'write" event and waited on the "test" event. Both the events are getting signaled.
Basically I am porting an appli from linux to windows. The linux program uses condition variable to signaling the thread. Condition variable is not available in window XP.
Ex:
#include <windows.h>
#include <stdio.h>
#define THREADCOUNT 1
HANDLE ghWriteEvent;
HANDLE ghtestEvent;
HANDLE ghThreads[THREADCOUNT];
DWORD WINAPI ThreadProc(LPVOID);
void CreateEventsAndThreads(void)
{
int i;
DWORD dwThreadID;
ghWriteEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // initial state is nonsignaled
TEXT("WriteEvent") // object name
);
if (ghWriteEvent == NULL)
{
printf("CreateEvent failed (%d)\n", GetLastError());
return;
}
ghtestEvent = CreateEvent(
NULL, // default security attributes
FALSE, // manual-reset event
FALSE, // initial state is nonsignaled
TEXT("WriteEvent") // object name
);
if (ghtestEvent == NULL)
{
printf("CreateEvent failed (%d)\n", GetLastError());
return;
}
// Create multiple threads to read from the buffer.
for(i = 0; i < THREADCOUNT; i++)
{
// TODO: More complex scenarios may require use of a parameter
// to the thread procedure, such as an event per thread to
// be used for synchronization.
ghThreads[i] = CreateThread(
NULL, // default security
0, // default stack size
ThreadProc, // name of the thread function
NULL, // no thread parameters
0, // default startup flags
&dwThreadID);
if (ghThreads[i] == NULL)
{
printf("CreateThread failed (%d)\n", GetLastError());
return;
}
}
}
void WriteToBuffer(VOID)
{
DWORD dwWaitResult;
printf("Main thread writing to the shared buffer...\n");
printf("Posting Events for %d\n",ghWriteEvent );
// Set ghWriteEvent to signaled
if (! SetEvent(ghWriteEvent) )
{
printf("SetEvent failed (%d)\n", GetLastError());
return;
}
dwWaitResult= WaitForSingleObject(
ghtestEvent, // event handle
INFINITE); // indefinite wait
printf("WaitForSingleObject signelled (%d)\n", GetLastError());
if ( dwWaitResult == WAIT_OBJECT_0)
printf("Signlled State for %d with ret val : %d\n",ghtestEvent,dwWaitResult );
}
void CloseEvents()
{
// Close all event handles (currently, only one global handle).
CloseHandle(ghWriteEvent);
}
int main( void )
{
DWORD dwWaitResult;
CreateEventsAndThreads();
WriteToBuffer();
printf("Main thread waiting for threads to exit...\n");
// The handle for each thread is signaled when the thread is
// terminated.
dwWaitResult = WaitForMultipleObjects(
THREADCOUNT, // number of handles in array
ghThreads, // array of thread handles
TRUE, // wait until all are signaled
INFINITE);
switch (dwWaitResult)
{
// All thread objects were signaled
case WAIT_OBJECT_0:
printf("All threads ended, cleaning up for application exit...\n");
break;
// An error occurred
default:
printf("WaitForMultipleObjects failed (%d)\n", GetLastError());
return 1;
}
// Close the events to clean up
CloseEvents();
return 0;
}
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
// lpParam not used in this example.
UNREFERENCED_PARAMETER(lpParam);
DWORD dwWaitResult;
printf("Thread %d waiting for write event...\n", GetCurrentThreadId());
dwWaitResult = WaitForSingleObject(
ghWriteEvent, // event handle
INFINITE); // indefinite wait
printf("rcvd event for Write is %d \n", ghWriteEvent);
switch (dwWaitResult)
{
// Event object was signaled
case WAIT_OBJECT_0:
WaitForSingleObject(
ghtestEvent, // event handle
INFINITE); // indefinite wait
printf("rcvd event for %d with Error %d\n", ghtestEvent,GetLastError());
if ( dwWaitResult == WAIT_OBJECT_0)
{
printf("Test event signaled for second thread \n");
}
break;
// An error occurred
default:
printf("Wait error (%d)\n", GetLastError());
printf("Wait error (%d)\n", GetLastError());
return 0;
}
printf("Thread %d exiting\n", GetCurrentThreadId());
return 1;
}
Output of the program is:
Main thread writing to the shared buffer...
Posting Events for 2012
WaitForSingleObject signelled (183)
Signlled State for 2008 with ret val : 0
Main thread waiting for threads to exit...
Thread 2016 waiting for write event...
rcvd event for Write is 2012
rcvd event for 2008 with Error 0
Test event signaled for second thread
Thread 2016 exiting
All threads ended, cleaning up for application exit...
After a long struggle I found out the reason. If Two events are created with same Name, the second event while creating will throw an Error "ERROR_ALREADY_EXISTS (183).
If event are created with different name, it works without any issue. It is good programming to check the error and proceed accordingly.
ghtestEvent = CreateEvent(
NULL, // default security attributes
FALSE, // manual-reset event
FALSE, // initial state is nonsignaled
TEXT("WriteEvent") // object name
);
if ( ERROR_ALREADY_EXISTS == GetLastError() )
{
printf("unable to create event (%d)\n".GetLastError());
exit(0);
}
Regards
JOhnnie
You only need to name events if you're going to use them to communicate between processes. You can pass NULL as the name if you're only synchronization threads within a single process.
When I'm creating named synchronization objects for inter-process communication, I generally give them a descriptive name (like "MyCompany - MyApp - WriteEvent") and tack on a GUID for good measure. You don't want to have a name conflict with some other developer who named his event "WriteEvent". The name can be up to MAX_PATH characters long and there is no performance penalty.

how to create and update window in child thread using vc++

I just coded a child thread to create and update window but I am facing some problem. My window closes automatically after that thread execution is completed (naturally). But I don't want to close it so I tried putting a while loop in thread and in that loop I am calling InvalidateRect() function so that it can update window. Now window is not closing automatically but i can't move it or interact with it and cursor also showing some busy icon(means completely not responding). How I can solve that problem. below is code:
calling this from main()
bool CameraApp::OnInit()
{
hThread = (HANDLE)_beginthreadex( NULL, 0, &CameraFrame::StartCameraPreview,
NULL, 0, &threadID );
WaitForSingleObject( hThread, INFINITE );
CloseHandle( hThread );
return TRUE;
}
Thread function block
unsigned __stdcall CameraFrame::StartCameraPreview( void* pArgs )
{
cFrame.ShowCameraWindow();
while(1)
{
cFrame.StartCapture();
InvalidateRect(hwnd, NULL, false);
Sleep(5000);
}
_endthreadex( 0 );
return 0;
}
i can't use main() function to create window. So, i have to use thread and update that window with periodic image taken from web-camera.
Instead of your infinite loop you need to create message pump in secondary thread that processes windows messages.
unsigned __stdcall CameraFrame::StartCameraPreview( void* pArgs )
{
cFrame.ShowCameraWindow();
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
_endthreadex( 0 );
return 0;
}

Resources