Click here to Skip to main content
15,879,095 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
XML
Edited:
1) There are n number of process i.e. disk cleanup, disk fragmentation etc in my project.
2) User have check box facility to check which process he wants to execute and click on start button.
3) <b>Using WinExec i execute the first process with argument. but how to achieve that when this process complete than can i get the message or handle so that i run the other process</b>
4) If possible than can i get the time of process to complete the task.(It is second priority task for me)
<Edited>



If I launch some tool or process, can it be possible that I get the time when the process completes its task?
Or, that when the process is complete, that can I get the handle.

What I want in my project is this; Suppose my application has n number of processes and whatever process user checks, executes one by one.

When one process is complete then the next should start or if possible I will show the remaining time when process completed.

Example :To Analyze Disk,application launches “chkdsk” utility to fix any disk errors.
When it completes than other process is executed.




Thanks in advance..
Posted
Updated 24-Jan-11 23:12pm
v5
Comments
Indivara 25-Jan-11 2:05am    
Do you mean remaining time, or time the process terminated?
ShilpiP 25-Jan-11 2:09am    
Remaining time when process complete it task. Main thing is that how do i know that the process doing its task is completed so that i execute another process.
Indivara 25-Jan-11 2:25am    
OK, I misunderstood, since you said you want to know when the process completed (I assumed you meant terminated)

Is it only chkdsk? Can't you make it terminate once its task is done? (to my knowledge, the command line version of chkdsk terminates after checking the disk)

Can't think of a simple way of getting the progress, maybe you can parse its output and locate the percentage?
ShilpiP 25-Jan-11 2:37am    
No the scenario is like that: In a dialog based application some task is given with check boxes, user select the check boxes which task he want to perform and click ok now application starts with first task and when that task is completed than run for another task. For example disk cleanup, disk fragmentation etc.
It is quite tricky :) but i have to do it and if possible i have to find the time when that task is completed that is shown in dialog box.
Indivara 25-Jan-11 2:43am    
So can't you call the command line versions of the tools executed? It doesn't matter that your application has a GUI.
I don't see how to get the time of completion unless the tool actually terminates. I suppose you want all of this automated (run everything without user intervention?)

Call this when the process starts and when it ends
http://www.cplusplus.com/reference/clibrary/ctime/time/[^]
(there are several to choose from in in the list on the left of the page)

(see my comment above as well)
 
Share this answer
 
Comments
ShilpiP 25-Jan-11 2:16am    
You didn't get my point. Process is not ending but when the task that is given to the process is completed. For example when i execute the disk clean up and when clean up is completed than it shows the message that the task is completed. Process of disk cleanup is still in taskmgr but the task of process is completed. How do i know that it is completed.
You cannot (because it is physically impossible) know the time spent by a process before the process itself complete.
It's like asking Mr. Bolt how long will he take to run 100mt. We can estimate based on previous runs, but how long a specific run will be, we know only when the run will be over.

Programs that gives the "time to wait" are providing an estimation on a complessive duration of a loop based on the duration of that loop's previous iteration.

Unfortunately, scandisk, defrag etc. don't have just a linear loop, but may have more inner loops not necessarily of the same length (so an estimation will never be precise ...)
If you want to know how long a scan will take, you only have to estimate with the time taken by a previous run on that system (will be very inaccurate), or run it and see what estimation it can give you.

Other thing are ... parapsychology, not programming.
 
Share this answer
 
Comments
ShilpiP 25-Jan-11 3:29am    
Ok i understand your point now can it be possible that if some process start with some task than when its task completed than i get the message or handle so that i launch another application.
Emilio Garavaglia 25-Jan-11 8:01am    
When you lanch a process from within your process you have its handle.
And you can check through it if the process is running or not, as you can wait for it to terminate.

Typically, you call WaitForSingleObject on the process handle.
Dalek Dave 25-Jan-11 3:45am    
True, impossible to assess the completion time of a process.
ShilpiP 25-Jan-11 5:13am    
Sorry i didn't check that the tag of my question is edited and it change the sense. Please check the question again. Thanks :)
Firstly, Create the process using CreateProcess[^].
The last parameter of this function outputs a PROCESS_INFORMATION struct, which has a hProcess member.
Then use WaitForSingleObject[^] to wait for the PROCESS_INFORMATION.hProcess with a timeout of INFINITE (because defrag often takes ages).
Once completed, you can use GetExitCodeProcess[^] with the PROCESS_INFORMATION.hProcess if you care about the exit code (general convention is error will return a number with the highest bit set (i.e if (nRetCode & 0x80000000) { /*error*/ })

There are 2 ways of getting the execution time (after WaitForSingleObject[^] returned successfully. You can start a timer and stop it when the task completes (timeGetTime[^] would be pretty good for this), otherwise you can use the function GetProcessTimes[^] The 2nd parameter to this returns the time that the process was created, accurate to about 1ms, just get the current system time with GetSystemTimeAsFileTime[^] to get the difference in times (you may need to do this by converting them to an unsigned long long since they are a struct of 2 DWORDs)
 
Share this answer
 
Comments
ShilpiP 1-Feb-11 4:51am    
Hi Andrew, Sorry for late reply. Actually i was working for some other project and not able to implement it. So today i do this but when i execute it that my application hangs and when i checked it on task mgr than its status is not responding. I am sending you the source code

LPCWSTR lpApplicationName = L"D:\\WINDOWS\\system32\\cleanmgr.exe";
LPWSTR lpCommandLine = L" /d C:";
DWORD dwCode = 0;

LPSECURITY_ATTRIBUTES lpProcessAttributes = NULL;
LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL;
BOOL bInheritHandles = FALSE;
DWORD dwCreationFlags = CREATE_NEW_CONSOLE;
LPVOID lpEnvironment = NULL;
LPCWSTR lpCurrentDirectory = NULL;

STARTUPINFO StartupInfo = { 0 };
PROCESS_INFORMATION ProcessInfo = { 0 };
ZeroMemory( &StartupInfo, sizeof(StartupInfo) );
StartupInfo.cb = sizeof(StartupInfo);
ZeroMemory( &ProcessInfo, sizeof(ProcessInfo) );


StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow = SW_HIDE;

if (::CreateProcess(lpApplicationName,
lpCommandLine,
lpProcessAttributes,
lpThreadAttributes,
bInheritHandles,
dwCreationFlags,
lpEnvironment,
lpCurrentDirectory,
&StartupInfo,
&ProcessInfo))
{
while(WAIT_OBJECT_0 !=WaitForSingleObject(ProcessInfo.hProcess,INFINITE))
{
MSG msg;
while (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
DispatchMessage(&msg);
}
}
GetExitCodeProcess ( ProcessInfo.hProcess, &dwCode);
::CloseHandle(ProcessInfo.hProcess);
::CloseHandle(ProcessInfo.hThread);

}
Shilpi Boosar Says:
So today i do this but when i execute it that my application hangs and when i checked it on task mgr than its status is not responding.

The reason it hangs is because you are making the main thread wait for the other process to finish. The main thread is responsible for processing messages sent from windows, hence the messages are not reaching your application (worse, you are deleting them).

What you need to do is create a second thread which will do all the executing and waiting, while the main thread continues to handle the message pump. You can then use something like an event[^] or a PostMessage to notify the main thread that something has happened.

If you are using a GUI program, which it seems you are, then I would reccomend using PostMessage.

It is unclear weather you are using MFC, Win32 API or some other GUI library, so I will post the code for a console program
#include <StdIO.h>
#include <tchar.h>
#include <Windows.h>

#define CM_WAITED WM_APP //This is if you use SendMessage/PostMessage. Add this to your message handler.

DWORD g_nRetVal = 0;
DWORD g_nWaitCode = 0;
HANDLE g_hWaited = NULL;

DWORD WINAPI RunUtils(void *pParam) { //Note: pParam is unused in this example, but you may choose to pass something in
	LPCTSTR szExe = TEXT("C:\\WINDOWS\\system32\\cleanmgr.exe");
	LPTSTR szParams = TEXT(" /d C:");
	PROCESS_INFORMATION ProcessInfo;
	ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
	STARTUPINFO StartupInfo;
	ZeroMemory(&StartupInfo, sizeof(StartupInfo));
	StartupInfo.cb = sizeof(StartupInfo);
	StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
	StartupInfo.wShowWindow = SW_HIDE;
	if (CreateProcess(szExe, szParams, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &StartupInfo, &ProcessInfo)) {
		g_nWaitCode = WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
		switch (g_nWaitCode) {
			case WAIT_OBJECT_0:
				GetExitCodeProcess(ProcessInfo.hProcess, &g_nRetVal);
				break;

			case WAIT_FAILED:
				g_nWaitCode = GetLastError();
				break;
		}
		::CloseHandle(ProcessInfo.hProcess);
		::CloseHandle(ProcessInfo.hThread);
		//You may choose to use PostMessage instead here.
		//This will allow you to pass back some information without the need for global variables.
		//It will also mean that you don't need to periodically check if the event is set as it will work its way through the message pump
		SetEvent(g_hWaited);
	}
	return 0;
}

int main() {
	g_hWaited = CreateEvent(NULL, FALSE, FALSE, TEXT("Local\\WaitedEvent"));
	HANDLE hExecThread = CreateThread(NULL, 0, &RunUtils, NULL, 0, NULL);
	//This is some random wait loop, you will probably not need this as you should be using PostMessage (hence this is like your message pump)
	DWORD nLoops = 0;
	for (;;) {
		if (WaitForSingleObject(g_hWaited, 0) == WAIT_OBJECT_0) {
			if (g_nWaitCode == WAIT_OBJECT_0) {
				_tprintf(TEXT("Process completed successfully and returned %u\n"), g_nRetVal);
			} else {
				_tprintf(TEXT("Wait failed with error code %u\n"), g_nWaitCode);
			}
			break;
		}
		_tprintf("%u\n", ++nLoops);
		Sleep(1000);
	}
	return 0;
}
 
Share this answer
 
Comments
ShilpiP 1-Feb-11 6:13am    
Hi Andrew Thanks for your reply. Got your point now.
BTW I am using MFC based application and I have to execute all process without showing their UI.
Andrew Brock 1-Feb-11 6:28am    
In the case of MFC you will need to put a ON_MESSAGE(CM_WAITED, &OnWaited) into 1 of the message maps, which you can then post the message CM_WAITED to that window.
As for hiding the window, that may be a bit tricky, passing in a parameter of SW_HIDE will only work if the program uses the value of nCmdShow when showing all of the windows rather than SW_SHOW which is rather common. In the case of cleanmgr.exe, only the initial window, searching for data to clean, uses the value of nCmdShow, hence only that window is hidden while the main application window uses the SW_SHOW.
If there is no command line options to run in a scripted mode without showing an interface then you might try using something like hooks, otherwise I would suggest creating a new question asking how to hide the windows.
ShilpiP 4-Feb-11 1:41am    
Thanks Andrew, I have done it on MFC :) Thanks for your kind support. I dont have one more 5 for you as I voted you 5 already:(

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900