dmetzler
asked on
NT service
I have created an NT service/app hybrid. When starting up the service, I get a timeout error (running in Win2000 Pro):
Microsoft Management Console gives an error of:
Error 1053: The service did not respond to the start or control request in a timely fashion.
What does this mean, specifically, and where do I look in my code to correct it?
I also get a system log error: Timeout (30000 milliseconds) waiting for service to connect. (Before the above error). However, it is not 30 seconds but close to 5 seconds.
Thanks,
Don
Microsoft Management Console gives an error of:
Error 1053: The service did not respond to the start or control request in a timely fashion.
What does this mean, specifically, and where do I look in my code to correct it?
I also get a system log error: Timeout (30000 milliseconds) waiting for service to connect. (Before the above error). However, it is not 30 seconds but close to 5 seconds.
Thanks,
Don
ASKER
No - the service does not get to run - it stops with an error. It looks like the SERVICE_ALL_ACCESS changes this so it will run, but then it exits almost immediately.
How do I keep my service running until it gets a stop request?
Thanks!
Don
How do I keep my service running until it gets a stop request?
Thanks!
Don
What code are you using in your 'ServiceMain()' function? Are you reporting 'SERVICE_RUNNING' to the SCM correctly?
ASKER
>>
What code are you using in your 'ServiceMain()' function? Are you reporting 'SERVICE_RUNNING' to the SCM correctly?
>>
I think so, but I will check.
Also - does the ServiceMain() function run in a new thread? If so, how can I call methods in the main CWinApp derived application?
Thanks!
Son
ASKER
>>
What code are you using in your 'ServiceMain()' function? Are you reporting 'SERVICE_RUNNING' to the SCM correctly?
>>
Yes - this is being done. Then I sit in a loop until a flag is set to let me know to exit the service/application. It seems I will need to handle the main app msg queue checking here - yes?
Thanks,
Don (not Son)
Hmm - could you post the code?
ASKER
Essentially, it looks like this (some things are missing, but I have included the ServiceMain routine from the CASService class):
void CMyApp::InitInstance()
{
if (bService)
{
StartNTService();
}
}
void CMyApp::StartNTService()
{
CASService service;
}
void CASService::ServiceMain()
{
RegisterCtrlHandler();
m_bStopped = FALSE;
ReportStatusToSCM(SERVICE_
Sleep(500);
ReportStatusToSCM(SERVICE_
// sit in a tight-loop until we're ready to exit
while (!m_bStopped)
{
theApp.CheckStatus();
}
}
Could you post the code for 'CheckStatus()' also?
ASKER
It's pretty simple - it current checks memory and disk drive space - nothing complicated.
Don
Don
Have you considered something like this (a loop seems to be a bit inappropriate to me):
void SocketServerStartup ()
{
HANDLE hEvent;
hEvent = CreateEvent ( NULL, FALSE, FALSE, TEXT ( OBJECT_NAME));
if ( ERROR_ALREADY_EXISTS == GetLastError ()
|| ERROR_SUCCESS == GetLastError ()
)
{
HANDLE hThread;
DWORD dwTID;
hThread = CreateThread ( NULL,
0,
CommThread,
NULL,
0,
&dwTID
);
DBGTRACE ( L"SocketServerStartup():\t waiting for stop event...\n");
ReportStatusToSCMgr ( SERVICE_RUNNING,
g_dwErr,
0
);
WaitForSingleObject ( hEvent, INFINITE);
DBGTRACE ( L"SocketServerStartup():\t received stop event...\n");
return;
}
}
void ServiceStop ( void)
{
HANDLE hEvent;
ReportStatusToSCMgr ( SERVICE_STOP_PENDING,
NO_ERROR,
1000
);
hEvent = CreateEvent ( NULL, FALSE, FALSE, TEXT ( OBJECT_NAME));
if ( ERROR_ALREADY_EXISTS == GetLastError ())
{
DBGTRACE ( L"HPSUDServiceStop():\tset ting event...\n");
SetEvent ( hEvent);
}
Sleep ( 500);
ReportStatusToSCMgr ( SERVICE_STOPPED,
NO_ERROR,
0
);
}
VOID WINAPI ServiceCtrl ( DWORD dwCtrlCode)
{
// Handle the requested control code.
switch ( dwCtrlCode)
{
// stop service.
case SERVICE_CONTROL_STOP:
ServiceStop ();
return;
// update the service status.
case SERVICE_CONTROL_INTERROGAT E:
break;
// invalid control code
default:
break;
}
ReportStatusToSCMgr ( g_ssStatus.dwCurrentState, NO_ERROR, 0);
}
void SocketServerStartup ()
{
HANDLE hEvent;
hEvent = CreateEvent ( NULL, FALSE, FALSE, TEXT ( OBJECT_NAME));
if ( ERROR_ALREADY_EXISTS == GetLastError ()
|| ERROR_SUCCESS == GetLastError ()
)
{
HANDLE hThread;
DWORD dwTID;
hThread = CreateThread ( NULL,
0,
CommThread,
NULL,
0,
&dwTID
);
DBGTRACE ( L"SocketServerStartup():\t
ReportStatusToSCMgr ( SERVICE_RUNNING,
g_dwErr,
0
);
WaitForSingleObject ( hEvent, INFINITE);
DBGTRACE ( L"SocketServerStartup():\t
return;
}
}
void ServiceStop ( void)
{
HANDLE hEvent;
ReportStatusToSCMgr ( SERVICE_STOP_PENDING,
NO_ERROR,
1000
);
hEvent = CreateEvent ( NULL, FALSE, FALSE, TEXT ( OBJECT_NAME));
if ( ERROR_ALREADY_EXISTS == GetLastError ())
{
DBGTRACE ( L"HPSUDServiceStop():\tset
SetEvent ( hEvent);
}
Sleep ( 500);
ReportStatusToSCMgr ( SERVICE_STOPPED,
NO_ERROR,
0
);
}
VOID WINAPI ServiceCtrl ( DWORD dwCtrlCode)
{
// Handle the requested control code.
switch ( dwCtrlCode)
{
// stop service.
case SERVICE_CONTROL_STOP:
ServiceStop ();
return;
// update the service status.
case SERVICE_CONTROL_INTERROGAT
break;
// invalid control code
default:
break;
}
ReportStatusToSCMgr ( g_ssStatus.dwCurrentState,
}
ASKER
Using an event seems to be a better way. I will implement this.
However, my real concern is the call to theApp.CheckStatus(). Is this reference still valid now that my service is running in a new thread? What happens to the original thread for the CWinApp derived class?
I understand about 90% of what is happening, but need to get over the last 10%.
Thanks!
Don
However, my real concern is the call to theApp.CheckStatus(). Is this reference still valid now that my service is running in a new thread? What happens to the original thread for the CWinApp derived class?
I understand about 90% of what is happening, but need to get over the last 10%.
Thanks!
Don
>>Is this reference still valid now that my service is running
>>in a new thread?
It is (assuming that it is global), but if you're about to use several threads, you'll have to protect the access to it ...
>>in a new thread?
It is (assuming that it is global), but if you're about to use several threads, you'll have to protect the access to it ...
ASKER
>>
It is (assuming that it is global), but if you're about to use several threads, you'll have to protect the access to it ...
>>
Like with a CSingleLock?
Yes - I am doing that.
The odd thing is that after the CWinApp starts and calls the thread functions, the tray icon installed by the CWinApp disappears, as if the main app thread has exited.
Don
>>The odd thing is that after the CWinApp starts and calls
>>the thread functions, the tray icon installed by the
>>CWinApp disappears
That's not odd at all - you'll have to use a message pump to process the callback messages from the system tray icon, otherwise it'll lead the system to remove the icon...
>>the thread functions, the tray icon installed by the
>>CWinApp disappears
That's not odd at all - you'll have to use a message pump to process the callback messages from the system tray icon, otherwise it'll lead the system to remove the icon...
ASKER
>>
That's not odd at all - you'll have to use a message pump to process the callback messages from the system tray icon, otherwise it'll lead the system to remove the icon...
>>
I did not know that, but that you.
One other thing - my service name is the same as the display name. Would this be a problem?
That's not odd at all - you'll have to use a message pump to process the callback messages from the system tray icon, otherwise it'll lead the system to remove the icon...
>>
I did not know that, but that you.
One other thing - my service name is the same as the display name. Would this be a problem?
No, this usually isn't a problem (though that maybe your service name is is a bit less 'illustrating' than the display name ;-)
ASKER
Okay - I have my service functions communicating with the SCM successfully. However, now I need to get the main CWinApp thread to complete and process. It seems when the service code starts, the main app thread is suspended. When the service stops, then the main app continues.
Is there a good way to handle this, perhaps by having my service code start at the end of the CWinApp::InitInstance() or perhaps via callback message?
Is there anyway to have both processes/threads running concurrently, but started from the same entry point?
Thanks,
Don
Is there a good way to handle this, perhaps by having my service code start at the end of the CWinApp::InitInstance() or perhaps via callback message?
Is there anyway to have both processes/threads running concurrently, but started from the same entry point?
Thanks,
Don
Hmm, this is getting weird ;-)
So, you're mixing an MFC app with an NT service?
This IS possible, but I wouldn't recomment it (MFC performance resons...) - it'd be a good idea to separate maintaining the shell tray icon from the actual service code, e.g. by starting an application using the 'Run' registry entry (HKEY_LOCAL_MACHINE\SOFTWA RE\Microso ft\Windows \CurrentVe rsion\Run) and have it communicate with the service ( BTW, that's the way the McAfee Scanner communicates with it's SysTray Icon). The main reson for this concept is that a service does not necessarily have access rights to the currently logged-on user's window station ('LocalSystem' _usually_ has, but not necessarily).
(Err, I wrote a service that _can_ do this, but the code isn't available even for 50k points - but I know at least 10 MS URLs where they state that this is not possible... just showing off, sorry ;-)
It'll be difficult to start both a CWinApp and a service from the same entry point, as the assumptions/expections that both SCM and MFC make/have are a bit opposite - I've never tried it...
So, you're mixing an MFC app with an NT service?
This IS possible, but I wouldn't recomment it (MFC performance resons...) - it'd be a good idea to separate maintaining the shell tray icon from the actual service code, e.g. by starting an application using the 'Run' registry entry (HKEY_LOCAL_MACHINE\SOFTWA
(Err, I wrote a service that _can_ do this, but the code isn't available even for 50k points - but I know at least 10 MS URLs where they state that this is not possible... just showing off, sorry ;-)
It'll be difficult to start both a CWinApp and a service from the same entry point, as the assumptions/expections that both SCM and MFC make/have are a bit opposite - I've never tried it...
ASKER
>>
Hmm, this is getting weird ;-)
>>
I like the more obscure programming challenges. ;-)
>>
So, you're mixing an MFC app with an NT service?
>>
Yes. What if I ignore the tray icon for the service and then start a separate thread for the service, thus allowing the main app to run appropriately?
>>
...e.g. by starting an application using the 'Run' registry entry (HKEY_LOCAL_MACHINE\SOFTWA RE\Microso ft\Windows \CurrentVe rsion\Run) and have it communicate with the service ( BTW, that's the way the McAfee Scanner communicates with it's SysTray Icon). The main reson for this concept is that a service does not necessarily have access rights to the currently logged-on user's window station ('LocalSystem' _usually_ has, but not necessarily).
>>
Is this valid for NT too?
>>
(Err, I wrote a service that _can_ do this, but the code isn't available even for 50k points - but I know at least 10 MS URLs where they state that this is not possible... just showing off, sorry ;-)
>>
So how did you do it - can you share the basic idea?
>>
It'll be difficult to start both a CWinApp and a service from the same entry point, as the assumptions/expections that both SCM and MFC make/have are a bit opposite - I've never tried it...
>>
I am close - I start the CWinApp, which kicks off another thread to start the service (which starts another thread to handle the SCM). Sloppy perhaps, but I think I can do it.
Thanks for ALL your help.
Don
Hmm, this is getting weird ;-)
>>
I like the more obscure programming challenges. ;-)
>>
So, you're mixing an MFC app with an NT service?
>>
Yes. What if I ignore the tray icon for the service and then start a separate thread for the service, thus allowing the main app to run appropriately?
>>
...e.g. by starting an application using the 'Run' registry entry (HKEY_LOCAL_MACHINE\SOFTWA
>>
Is this valid for NT too?
>>
(Err, I wrote a service that _can_ do this, but the code isn't available even for 50k points - but I know at least 10 MS URLs where they state that this is not possible... just showing off, sorry ;-)
>>
So how did you do it - can you share the basic idea?
>>
It'll be difficult to start both a CWinApp and a service from the same entry point, as the assumptions/expections that both SCM and MFC make/have are a bit opposite - I've never tried it...
>>
I am close - I start the CWinApp, which kicks off another thread to start the service (which starts another thread to handle the SCM). Sloppy perhaps, but I think I can do it.
Thanks for ALL your help.
Don
>>Yes. What if I ignore the tray icon for the service and
>>then start a separate thread for the service, thus
>>allowing the main app to run appropriately?
Hmm, could work - i.e. one thread using a CWinApp, the other one calling 'StartServiceCtrlDispatche r()'
>>Is this valid for NT too?
Yes, definitely - I'm mainly using NT.
>>So how did you do it - can you share the basic idea?
The basic idea is to manipulate the access control lists for both the window station and the desktop ;-)
>>then start a separate thread for the service, thus
>>allowing the main app to run appropriately?
Hmm, could work - i.e. one thread using a CWinApp, the other one calling 'StartServiceCtrlDispatche
>>Is this valid for NT too?
Yes, definitely - I'm mainly using NT.
>>So how did you do it - can you share the basic idea?
The basic idea is to manipulate the access control lists for both the window station and the desktop ;-)
ASKER
Thanks for all of your help!
Don
Don
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks for all of your help!
Thanx a lot!!!
Regarding to tha fact that you raised the points, it seems that I indeed could help you, and that's a really good feedback ;-)
BTW: I'm glad that this Q moved to the PAQ section as I didn't take enough care when posting the code - there's still a reference to the customer (oops ;-) ...
Regarding to tha fact that you raised the points, it seems that I indeed could help you, and that's a really good feedback ;-)
BTW: I'm glad that this Q moved to the PAQ section as I didn't take enough care when posting the code - there's still a reference to the customer (oops ;-) ...
ASKER
Thanks for the help!
Don
Don
i had a service which did a lot of initializing, so the service control manager states a timeout error. but when i checked the running services "net start" th e service was runnig ok.
after i moved the init code the service starts ok.
maybe u got the same problem.
your app ids starting ok?