start a process and obtain its pid - delphi

using delphi XE I am trying to execute an exe file multiple times with different parameters
but i will need to close/restart each one separately for various reasons.
so i thought if i start that example.exe and get its pid
i will be able to kill it later using that unique pid value.
see if i simply execute the example.exe THEN try to get the PID of that process using process name or the process file path it will end up giving me wrong result because there are like 4 processes with that name.
any suggestions or ideas ?
my question might seem similar to some others but i need to return the pid value so keep that in mind

Use the Win32 API CreateProcess() function. It outputs a PROCESS_INFORMATION struct that contains the IDs and handles of the launched process and its main thread. You can use the process handle to wait for the process to exit.
To terminate the process, you can pass the process handle to TerminateProcess().
Or, you can be more civil and:
enumerate the process's UI windows using EnumWindows() or EnumThreadWindows(), posting a WM_CLOSE message to each one.
And/Or:
post a WM_QUIT message to the main thread.
If that does not work, then use TerminateProcess() as a last resort.

Look into using CreateProcess. There are multiple examples on StackOverflow including: Hide process window with 'CreateProcess'
If the call is successful, you will have the handle of the Process in the TProcessInformation parameter which you pass into CreateProcess.

Related

Why does OpenProcess() return a non 0 value when the process ID is no longer running

I'm starting a new instance of another application using CreateProcess from Example and I end up saving the PID so that I can later check if that process is still running.
I'm using to following method to check if it's running or not:
procedure TfrmRSM.Button1Click(Sender: TObject);
begin
var
ahandle := OpenProcess(PROCESS_ALL_ACCESS, true, aPID);
if ahandle = 0 then
ShowMessage('is not running')
else
ShowMessage('is running');
CloseHandle(ahandle);
end;
The code above should return 0 when the process is no longer running but it still returns a number greater than 0
I am closing the handle after using CreateProcess
Whats to propper way to check if a PID is running if the method I'm using is incorrect? I'm only able to find methods that use the application name.
I'm starting a new instance of another application using CreateProcess from Example and I end up saving the PID so that I can later check if that process is still running.
The correct way to handle this is to keep open the HANDLE that CreateProcess() gives you, and then you can query it via WaitForSingleObject() or GetExitCodeProcess() to see if the process has terminated or not, and then close the HANDLE when you no longer need it.
In comments, you mention that your launching app may terminate and be restarted separate from the target process. In that case, you could close the HANDLE if you still have it open, saving its PID and creation date/time somewhere you can get it back from, and then when your app restarts it can enumerate running processes (alternatively) to see if the target EXE is still running and has a matching PID and date/time, and if so then open a new HANDLE to that PID. Just be careful, because this does introduce a small race condition where the target process might terminate after you detect its presence and its PID could get recycled before you have a chance to open it. So you might need to re-validate the HANDLE's info again after opening it.
Otherwise, during your app's shutdown (or even before), you can off-load the open HANDLE from CreateProcess() to a separate helper process that stays running in the background monitoring the HANDLE, and then your main app can get the HANDLE back from that helper after restarting. Or, perform the actual CreateProcess() call in the helper to begin with, so the HANDLE monitoring stays within a single process at all times, and let your main app query the helper for status when needed.
I'm using to following method to check if it's running or not:
That will not work, as you don't know whether the PID is still valid, or even still refers to the same process you are interested in. Once that process has terminated, its PID can be recycled at any time for use with a new process.
The code above should return 0 when the process is no longer running but it still returns a number greater than 0
The only way OpenProcess() can return non-zero is if the specified PID is actually running. But that does not guarantee it is the same process you are interested in. At the very least, after OpenProcess() returns a non-zero HANDLE, you can query that HANDLE for its info (EXE file path, creation date/time, etc) to see if it is the same process you are expecting. If the info does not match, the PID was recycled.
Why does OpenProcess() return a non 0 value when the process ID is no
longer running?
This is probably an undefined behavior or the PID has been recycled by Windows.
I want to check if a process I created is still running later even
after I quit my application and opened it again.
You said you cannot change the process. One work around is to use an intermediate and very simple process to launch the target process. The intermediate process can use any IPC (for example shared memory of shared file) to talk to the main process to inform it about running target process. This intermediate process will run the target process and update a flag that the main process can query (In my example in shared memory).
The intermediate process can also simply keep a file open for exclusive access while the target process is running. The main process can try to open the file and if it succeed, then the target process is done (Intermediate process use WaitForSingleObjector WaitForMultipleObject to wait for target process termination).
To wait for a process to end, simply use WaitForSingleObject() on the process handle: when the process ends, the handle is signaled and the function returns WAIT_OBJECT_0. This ensures that you "look" at the handle the whole time it lives, instead of only inspecting it from time to time and otherwise leave it unattended.
Most likely you put this into a separate thread, and upon its ending you have your event to react to when the watched process ended. If you have multiple handles to look for, use WaitForMultipleObjects() - be aware that it can't handle more than 64 (MAXIMUM_WAIT_OBJECTS) handles at once.
Edit: when not being able to track a process handle entirely you can at least use GetProcessTimes() to check if the process you're looking at still started at the same time you looked at it last time - that should make it pretty distinctive: when the process handle is recycled by a new process then at least its starting time should differ.

Waiting for applications to finish loading [duplicate]

I have an application which needs to run several other applications in chain. I am running them via ShellExecuteEx. The order of running each of the apps is very important cause they are dependant on each other. For example:
Start(App1);
If App1.IsRunning then
Start(App2);
If App2.IsRunning then
Start(App3);
.........................
If App(N-1).IsRunning then
Start(App(N));
Everything works fine but there is a one possible problem:
ShellExecuteEx starts the application, and return almost immediately. The problem might arise when for example App1 has started properly but has not finished some internal tasks, it is not yet ready to use. But ShellExecuteEx is already starting App2 which depends on the App1, and App2 won't start properly because it needs fully initialized App1.
Please note, that I don't want to wait for App(N-1) to finish and then start AppN.
I don't know if this is possible to solve with ShellExecuteEx, I've tried to use
SEInfo.fMask := SEE_MASK_NOCLOSEPROCESS or SEE_MASK_NOASYNC;
but without any effect.
After starting the AppN application I have a handle to the process. If I assume that the application is initialized after its main window is created (all of Apps have a window), can I somehow put a hook on its message queue and wait until WM_CREATE appears or maybe WM_ACTIVATE? In pressence of such message my Application would know that it can move on.
It's just an idea. However, I don't know how to put such hook. So if you could help me in this or you have a better idea that would be great:)
Also, the solution must work on Windows XP and above.
Thanks for your time.
Edited
#Cosmic Prund: I don't understand why did you delete your answer? I might try your idea...
You can probably achieve what you need by calling WaitForInputIdle() on each process handle returned by ShellExecute().
Waits until the specified process has finished processing its initial input and is waiting for user input with no input pending, or until the time-out interval has elapsed.
If your application has some custom initialization logic that doesn't run in UI thread then WaitForInputIdle might not help. In that case you need a mechanism to signal the previous app that you're done initializing.
For signaling you can use named pipes, sockets, some RPC mechanism or a simple file based lock.
You can always use IPC and Interpocess Synchronization to make your application communicate with (and wait for, if needed) each other, as long as you code both applications.

%exec, system, IO.popopen .. which coomand to use in Ruby?

I am trying to understand which of the %exec, system, IO.popopen commands I can use in Ruby for what circumstances.
These pages explains it but I dont think so I quite understand what does starting a new application etc mean.
http://humblelittlerubybook.com/book/html/chapter4.html
From my understanding :
%exec: takes over your application process and runs the new command. So does that mean that once the system command is finished, it just exits OR does it resumes the parent application process ?
io.popopen: spawns a new thread and returns output and errs back to parent application ?. Is this safe command to use when you want to spawn a thread and do something in parallel ?
system: spawns a sub-process. This probably means that the control returns back to parent once the spawned process is done ? Does the parent process halts until the child completes execution ? [that sounds dangerous]
Can someone explain to me in English, in what circumstances do we use these commands?
Thanks
exec() is used to replace the currently executing program with the program specified as a parameter to exec(). The program you specify as a parameter to exec() becomes the currently executing program. If you're using RoR, you probably do not want to do this. If you're using plain old Ruby for a program, you might want to do this under certain circumstances.
system() is used to invoke a new program in a subshell. The currently executing program will block, or wait, until the program you invoked has finished running. You are right - this can be dangerous if you have a long-running program. If you have a program which can run-away but you want to use system, you can wrap the system call in the child part of a fork() call and have the parent kill the child process if it runs for too long. More on fork(): http://en.wikipedia.org/wiki/Fork_%28operating_system%29
system() will not give you the STDOUT or STDERR of the application in its return value. Instead, you'll get the exit status code. It's a general practice that programs will exit with a status code of 0 if they are successful, and anything else if they fail.
The backticks are an alternative to system() which return not the exit status code but the actual STDOUT of the program which was executed. You can obtain the exit status code of the program through the "$?" variable.
IO.popopen() (and Open3 and Open4) allows you to work with the STDIN and the STDOUT of a subprocess.
This seems to be a good place to get a little more familiar with some of these concepts as they are implemented in Ruby: http://tech.natemurray.com/2007/03/ruby-shell-commands.html
exec is something that most people don't need to use. The executed program becomes the active program, your original program looses execution, file handles etc.
popen is about standard input and output, meaning it's good to be used with filters, i.e. programs that write or read from standard input/output.
system is better used to execute a program, your original program keeps executing but waits till that program invoked by system finishes.

How to peek at STDIN with Delphi 7?

In a Delphi 7 console application, how can I check whether stdin holds a character, without blocking until one is entered?
My plan is that this console program will be executed by a GUI program, and its stdin will be written to by the GUI program.
So I want my console app to periodically check stdin, but I can't find a way of doing this without blocking.
I have looked at this answer, which gets me a stream pointing to stdin, but there's still no way to "peek" as far as I can see.
I think you have already found the right way to read stdin. It is meant to block when there's nothing more to be read.
The standard way to handle this is to use a separate thread to handle the pipe. When it receives new data from stdin it signals this to the processing thread, for example with a message passing mechanism.
Having said all that, if you really want to poll you can call PeekNamedPipe to check if there is data in the pipe.
You could as the other answer says use threads, but even then you might have problems (using the threading method) unless you also investigate overlapped IO.
I normally use overlapped IO with serial ports rather than stdin, where "read a character if one is ready" is commonly needed, and where non-blocking IO is a usual way of working. You should be able to adapt the technique shown here. However, if I was writing an application that was keyboard driven (instead of purely driven by say, a file redirected to standard input) I would let go of StdIN, and use a CRT type unit. So, if you don't mind letting go of StdIn, and simply want to have a keyboard-driven input model, you could look at console based APIs and abandon the very limiting StdIn capabilities. For an example of a "kbhit" function that uses the Win32 Console APIs see here.
There is no other way (as far as i know), as reading from a pipe inside a separate thread. Otherwise as you already have seen, the readfile operation will block. I wrote an example how to do this, an example project is also available: redirect stdoutput
Edit: Well, reading your question another time, i understand that your problem lies within the console program, not the calling application. I wonder what your console application expects, normally a console application knows when it needs input and cannot proceede until the user enters this information. Do you need to check for an exit?
For a Stream if you .Read() the function result is the number of bytes read which will be zero if there was nothing there even if you asked for more. From the Delphi help for Classes.TStream.Read:
Read is used in cases where the number of bytes to read from the stream is not necessarily fixed. It attempts to read up to Count bytes into buffer and returns the number of bytes actually read.

Multithreaded (TThread) Delphi application will not terminate

I have written an application (using Delphi 2009) that allows a user to select a series of queries which can be run across a number of different systems. In order to allow queries to be run concurrently, each query is run in its own thread, using a TADOQuery object. This all works fine.
The problem that I have is when I try to close the application when a query is still running (and therefore a separate thread is active). When I create each thread, I record the thread's THandle in an array. When I try to close the application, if any threads are still running, I retrieve the thread's handle and pass it to TerminateThread, which should theoretically terminate the thread and allow the application to close. However, this doesn't happen. The main form's onClose event is triggered and it looks like the application is closing, but the process remains active and my Delphi interface appears as though the application is still running (i.e. "Run" button greyed out, debug view active etc.). I don't get control back to Delphi until I manually end the process (either Ctrl-F2 in Delphi or via Task Manager).
I am using TerminateThread because the query can take a long time to run (a few minutes in cases where we're dealing with a million or so records, which in the end user environment is perfectly possible) and while it is running, unless I'm mistaken, the thread won't be able to check the Terminated property and therefore won't be able to end itself if this were set to True until the query had returned, so I can't terminate the thread in the usual way (i.e. by checking the Terminated property). It may be the case that the user wants to exit the application while a large query is running, and in that case, I need the application to immediately end (i.e. all running threads immediately terminate) rather than forcing them to wait until all queries have finished running, so TerminateThread would be ideal but it isn't actually terminating the thread!
Can anyone help out here? Does anyone know why TerminateThread doesn't work properly? Can anyone suggest anything to get the threads running large ADO queries to immediately terminate?
You should be able to cancel an ADO Query by hooking the OnFetchProgress event, and setting the Eventstatus variable to esCancel. This should cause your query to terminate and allow the thread to close gracefully without having to resort to using TerminateThread.
Instead of using threads with TADOQuery, maybe you should consider using the async options of ADO.
ADOQuery1.ExecuteOptions := [eoAsyncExecute, eoAsyncFetch, eoAsyncFetch];
Then when your application close, you can call :
ADOQuery1.cancel;
As you can read in the msdn using TerminateThread is dangerous.
TerminateThread is a dangerous
function that should only be used in
the most extreme cases. You should
call TerminateThread only if you know
exactly what the target thread is
doing, and you control all of the code
that the target thread could possibly
be running at the time of the
termination.
But it also is very effective in killing threads. Are you sure you are right in your conclusions? Maybe the thread is killed, but another thread is still running? Maybe your handles are not thread handles? Could you show us some code? Or even better: A small working example we could try for ourselves?

Resources