![]() |
| | #1 |
| Banned Join Date: Feb 2003 Location: Australia
Posts: 986
| Telling other applications to stop This is a snapshot of the WinMain() of the application Code: int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprev, PSTR cmdline, int ishow)
{
//-----------------------------------------------------------------------------------------
// Step 1: Do stuff we must do as a windows application
//-----------------------------------------------------------------------------------------
WSADATA wsaData;
WSAStartup(MAKEWORD(1,1), &wsaData);
HWND Hwnd; // Handle for this window
MSG Message; // Current message
WNDCLASSEX WndClassEx = {0}; // Window Class
WndClassEx.cbSize = sizeof(WndClassEx); // Size of itself
WndClassEx.lpfnWndProc = WinProc; // Message Handler
WndClassEx.hInstance = hinstance; // Instance of this window class
WndClassEx.lpszClassName = "SWEBSWindowClass"; // Class Name
This is the WinProc function of the application: Code: LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
switch(message)
{
case WM_DESTROY:
case WM_CLOSE:
SERVER_STOP = true;
PostQuitMessage(0);
break;
default:
break;
}
// Report current status
return DefWindowProc(hwnd, message, wparam, lparam);
}
Code: case SERVICE_CONTROL_STOP:
SERVER_STOP = true;
SendMessage((HWND)pi.hProcess , WM_CLOSE, NULL, NULL);
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (hStatus, &ServiceStatus);
return;
case SERVICE_CONTROL_SHUTDOWN:
SERVER_STOP = true;
SendMessage((HWND)pi.hProcess, WM_CLOSE, NULL, NULL);
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (hStatus, &ServiceStatus);
return;
default:
break;
}
When the service is told to stop, it does, but the application doesn't. What should I do to make sure the application is shut down properly? This is the call to CreateProcess: Code: if( !CreateProcess( EnginePath.c_str(), // No module name (use command line).
NULL, // 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.
AppPath.c_str(), // Starting directory.
&si, // Pointer to STARTUPINFO structure.
&pi ) // Pointer to PROCESS_INFORMATION structure.
)
{
TestLog("Could not create process for SWEBSEngine.exe");
}
SERVER_STOP = false;
while (SERVER_STOP == false)
{
Sleep(3000);
}
GetExitCodeProcess(pi.hProcess, &ExitCode);
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
|
| nickname_changed is offline | |
| | #2 |
| Yes, my avatar is stolen Join Date: Dec 2002
Posts: 2,544
| Firstly, you can't post a message to the process handle but you can post a message to the thread id. PostThreadMessage(pi.dwThreadId, WM_CLOSE, 0,0); Also Try WM_QUIT if that doesn't work. There are some issues here if the service and the application do not share the same window station. Suggestion: Code: while (SERVER_STOP == false)
{
Sleep(3000);
}
Code: while (SERVER_STOP == false)
{
if (WaitForSingleObject(pi.hProcess, 1000) != WAIT_TIMEOUT) break;
}
Can I also suggest that your control handler looks like this and you put the other code below the loop: Code: case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_SHUTDOWN: SERVER_STOP = true; I just implemented a similar service that starts an application, so if you need more help/code please post back. P.S Using CreateProcess without both an application path and command line can lead to serious security holes. P.P.S Is the the open source web server you are working on? Looks intersting. |
| anonytmouse is offline | |
| | #3 |
| Banned Join Date: Feb 2003 Location: Australia
Posts: 986
| Thanks anontymouse, but it still doesn't seem to be working. I added a handle for the WM_QUIT message in the application, and I change the serviceControl function to look like this: Code:
//---------------------------------------------------------------------------------------------
// Control Handler
//---------------------------------------------------------------------------------------------
void ControlHandler(DWORD request)
{
switch(request)
{
case SERVICE_CONTROL_STOP:
SERVER_STOP = true;
PostThreadMessage(pi.dwThreadId, WM_QUIT, 0, 0);
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (hStatus, &ServiceStatus);
return;
case SERVICE_CONTROL_SHUTDOWN:
SERVER_STOP = true;
PostThreadMessage(pi.dwThreadId, WM_QUIT, 0, 0);
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (hStatus, &ServiceStatus);
return;
default:
break;
}
// Report current status
SetServiceStatus (hStatus, &ServiceStatus);
return;
}
Code: SERVER_STOP = false;
while (SERVER_STOP == false)
{
if (WaitForSingleObject(pi.hProcess, 1000))
break;
}
GetExitCodeProcess(pi.hProcess, &ExitCode);
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
Thanks for all your help so far anontymouse, its greatly appreciated! In regards to your first PS, I don't have them both NULL, the first is the application I wish to open. And for your second, yes this is the SWEBS Web Server. We are moving all the server code to an external application, so that it can use DLL's and Pipes easier (services have problems with pipes). |
| nickname_changed is offline | |
| | #4 |
| Yes, my avatar is stolen Join Date: Dec 2002
Posts: 2,544
| I could be barking up the wrong tree, but do you actually have a message loop in the launched application? Without a message loop your window procedure will never be called. If you don't need a window, get rid of it and the window procedure and use this: Code: MSG msg;
// This will create a message queue for the thread...
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
// Check for a WM_QUIT in the message queue...
while(!PeekMessage(&msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE)) {
// do server stuff
}
// cleanup code
An alternative approach would be to use named events. These can be waited on which may be an advantage depending on the program. In regards to CreateProcess, both arguments should be non-null. Simply use an empty string("") as lpCommandLine if the program takes no arguments. |
| anonytmouse is offline | |
| | #5 |
| Banned Join Date: Feb 2003 Location: Australia
Posts: 986
| Hehe, that could be my problem. I create a window class, and tell it what function to use as the message loop, but since I dont have an actual window maybe the messages never get sent to it? Heres the bottom of my WinMain(): Code: while (!SERVER_STOP)
{
// Get message(s) if there is one
if(PeekMessage(&Message,Hwnd,0,0,PM_REMOVE))
{
if(Message.message == WM_QUIT)
break;
TranslateMessage(&Message);
DispatchMessage(&Message);
}
else
{
// Handle some requests
SFD_New = accept(SFD_Listen, (struct sockaddr *) &ClientAddress, &Size);
DWORD dwThreadId; // Info for the thead
HANDLE hThread;
// Create a structure of type ARGUMENT to be passed to the new thread
ARGUMENT Argument;
Argument.CLA = ClientAddress;
Argument.SFD = SFD_New;
// CreateThread and process the request
hThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
ProcessRequest, // thread function
&Argument, // argument to thread function
0, // use default creation flags
&dwThreadId
); // returns the thread identifier
if (hThread != NULL) // If the thread was created, destroy it
{
CloseHandle( hThread );
}
}
}
|
| nickname_changed is offline | |
| | #6 |
| Yes, my avatar is stolen Join Date: Dec 2002
Posts: 2,544
| >If I move my WinProc functions into the PeekMessage part of that loop, should that work? Most likely. A thread message will not be dispatched to a window procedure anyway, even if that window happens to exist. :-) I assumed you were using a GetMessage loop which will 'automatically' exit(return 0) if the thread receives a WM_QUIT. EDIT: The second argument of PeekMessage must be null to retrieve thread messages, not a (non-existant) window handle. Last edited by anonytmouse; 09-24-2003 at 05:27 AM. |
| anonytmouse is offline | |
| | #7 |
| Banned Join Date: Feb 2003 Location: Australia
Posts: 986
| Well, heres my WinProc(): Code: LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
switch(message)
{
case WM_DESTROY:
case WM_QUIT:
case WM_CLOSE:
SERVER_STOP = true;
PostQuitMessage(0);
break;
default:
break;
}
// Report current status
return DefWindowProc(hwnd, message, wparam, lparam);
}
|
| nickname_changed is offline | |
| | #8 |
| Banned Join Date: Feb 2003 Location: Australia
Posts: 986
| Ok, thanks, heres what that loop looks like now: Code: while (!SERVER_STOP)
{
PeekMessage(&Message, NULL, WM_USER, WM_USER, PM_NOREMOVE);
// Get message(s) if there is one
if(PeekMessage(&Message, NULL, 0, 0, PM_REMOVE))
{
if(Message.message == WM_QUIT)
break;
TranslateMessage(&Message);
DispatchMessage(&Message);
}
else
{
// Handle some requests
SFD_New = accept(SFD_Listen, (struct sockaddr *) &ClientAddress, &Size);
DWORD dwThreadId; // Info for the thead
HANDLE hThread;
// Create a structure of type ARGUMENT to be passed to the new thread
ARGUMENT Argument;
Argument.CLA = ClientAddress;
Argument.SFD = SFD_New;
// CreateThread and process the request
hThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
ProcessRequest, // thread function
&Argument, // argument to thread function
0, // use default creation flags
&dwThreadId
); // returns the thread identifier
if (hThread != NULL) // If the thread was created, destroy it
{
CloseHandle( hThread );
}
}
}
|
| nickname_changed is offline | |
| | #9 |
| Yes, my avatar is stolen Join Date: Dec 2002
Posts: 2,544
| It looks like that is a blocking accept() call in the loop so the program will not get the WM_QUIT message and exit until the accept() function returns (which is probably never if no one is connecting to the web server when you are trying to shut it down). Comment out the accept and see if it works. The first PeekMessage call should not be in the loop. It should be at the start of the program to set up the message queue. There is no need for Translate and DispatchMessage. |
| anonytmouse is offline | |
| | #10 |
| Banned Join Date: Feb 2003 Location: Australia
Posts: 986
| Hehe, yep you were right, thats exactly what it was... looks like im going to have to look up some non-blocking sockets now If your interested heres the code so far:Code: // This will create a message queue for the thread...
PeekMessage(&Message, NULL, WM_USER, WM_USER, PM_NOREMOVE);
// Check for a WM_QUIT in the message queue...
while(!PeekMessage(&Message, NULL, WM_QUIT, WM_QUIT, PM_REMOVE))
{
// Handle some requests
//SFD_New = accept(SFD_Listen, (struct sockaddr *) &ClientAddress, &Size);
DWORD dwThreadId; // Info for the thead
HANDLE hThread;
// Create a structure of type ARGUMENT to be passed to the new thread
ARGUMENT Argument;
Argument.CLA = ClientAddress;
Argument.SFD = SFD_New;
// CreateThread and process the request
hThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
ProcessRequest, // thread function
&Argument, // argument to thread function
0, // use default creation flags
&dwThreadId
); // returns the thread identifier
if (hThread != NULL) // If the thread was created, destroy it
{
CloseHandle( hThread );
}
}
|
| nickname_changed is offline | |
| | #11 |
| Yes, my avatar is stolen Join Date: Dec 2002
Posts: 2,544
| >looks like im going to have to look up some non-blocking sockets now In the meantime, you could simple connect() to the web server after you have posted the WM_QUIT. This would release the accept() call. |
| anonytmouse is offline | |
| | #12 |
| Banned Join Date: Feb 2003 Location: Australia
Posts: 986
| Ok... I have another idea. Is it possible before going into the loop to tell all thread messages to go to the winproc? Or, to another thread running at the same time? That way I can catch the message and do ExitProcess or another function to close the program. Non-blocking sockets don't look to be what I want right now... I need to use another thread or something. |
| nickname_changed is offline | |
![]() |
| Thread Tools | |
| Display Modes | |
|
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Get Installed applications list and applications activity | arunarora | C++ Programming | 5 | 05-25-2009 09:41 AM |
| fscanf %s or %d integer input space char stop question... | transgalactic2 | C Programming | 5 | 04-14-2009 10:44 AM |
| Error stop Http Listener | George2 | C# Programming | 1 | 06-04-2008 02:14 AM |
| A question about windows programming | Hussain Hani | Windows Programming | 16 | 05-23-2007 07:38 AM |
| when a while loop will stop ? | blue_gene | C Programming | 13 | 04-20-2004 03:45 PM |