MattC
asked on
timed polling of a database in a W2K service
Using the ATL Wizard in VC++6 I've created a service. I'm guessing that my code has to go in the run() method.
My first question is:
If all I want my service to do is after a set time interval get some data from the database. How do I loop?
If I put a while loop in the run method then i will effectively lock the service from communicating with the SCM.
Any help or small examples would be great, I do have a book on it but as of yet I've not found anything regarding this, and I am pushed for time.
Second question:
Can ATL system services support MFC class usage?
My first question is:
If all I want my service to do is after a set time interval get some data from the database. How do I loop?
If I put a while loop in the run method then i will effectively lock the service from communicating with the SCM.
Any help or small examples would be great, I do have a book on it but as of yet I've not found anything regarding this, and I am pushed for time.
Second question:
Can ATL system services support MFC class usage?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
oops that should be:
while(_Module.m_status = SERVICE_RUNNING){
Sleep(300000);
//do code here
}
while(_Module.m_status = SERVICE_RUNNING){
Sleep(300000);
//do code here
}
Sounds reasonable, as long as you don't need to be doing anything else at the time (including message processing).
>>Can ATL system services support MFC class usage?
When you create the service, the AppWizard presents that as an option. There is a "Support MFC" checkbox.
-- Dan
When you create the service, the AppWizard presents that as an option. There is a "Support MFC" checkbox.
-- Dan
oops, I see that the Support MFC checkbox gets dimmed when you select the Service radio button. Looking at my code, for a service that uses MFC, I see that I needed to add some headers to StdAfx.h:
#include <afxwin.h> // MFC core and standard components
#include <afxext.h> // MFC extensions
I also see that for some reason I have this in the InitInstance:
afxContextIsDLL= FALSE;
Alas, I did not comment the reason for that code!
-- Dan
#include <afxwin.h> // MFC core and standard components
#include <afxext.h> // MFC extensions
I also see that for some reason I have this in the InitInstance:
afxContextIsDLL= FALSE;
Alas, I did not comment the reason for that code!
-- Dan
Why don't you just kick off a separate thread from the service in order to do the polling work - it could be as simple as
long WINAPI TimerThread ( LPVOID pv) {
DWORD dwWait = ( DWORD) pv,
for ( ;;) {
Sleep ( dwWait);
// do work here...
}
}
long WINAPI TimerThread ( LPVOID pv) {
DWORD dwWait = ( DWORD) pv,
for ( ;;) {
Sleep ( dwWait);
// do work here...
}
}
BTW, if you'd like something more sophisticated than the above, check out http://support.microsoft.com/support/kb/articles/q184/7/96.asp ("HOWTO: Use a Waitable Timer with an Asynchronous Procedure Call (Q184796)") and http://msdn.microsoft.com/library/en-us/dllproc/synchro_2bcj.asp ("Using Waitable Timer Objects")
ASKER
Ah, drat as usual, excellent answer....but from completely different people.
Thanks guys. Gimme a couple of days and I will dish out some points. :-)
MattC
Thanks guys. Gimme a couple of days and I will dish out some points. :-)
MattC
ASKER
one last thing :-)
below is the Run() method.
I have put '*****************' where i think my code should go, is this right???
void CServiceModule::Run()
{
_Module.dwThreadID = GetCurrentThreadId();
HRESULT hr = CoInitialize(NULL);
// If you are running on NT 4.0 or higher you can use the following call
// instead to make the EXE free threaded.
// This means that calls come in on a random RPC thread
// HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
_ASSERTE(SUCCEEDED(hr));
// This provides a NULL DACL which will allow access to everyone.
CSecurityDescriptor sd;
sd.InitializeFromThreadTok en();
hr = CoInitializeSecurity(sd, -1, NULL, NULL,
RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONAT E, NULL, EOAC_NONE, NULL);
_ASSERTE(SUCCEEDED(hr));
hr = _Module.RegisterClassObjec ts(CLSCTX_ LOCAL_SERV ER | CLSCTX_REMOTE_SERVER, REGCLS_MULTIPLEUSE);
_ASSERTE(SUCCEEDED(hr));
LogEvent(_T("Service started"));
if (m_bService)
SetServiceStatus(SERVICE_R UNNING);
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
DispatchMessage(&msg);
************************** ********** ** //<-- My Code here
_Module.RevokeClassObjects ();
CoUninitialize();
}
below is the Run() method.
I have put '*****************' where i think my code should go, is this right???
void CServiceModule::Run()
{
_Module.dwThreadID = GetCurrentThreadId();
HRESULT hr = CoInitialize(NULL);
// If you are running on NT 4.0 or higher you can use the following call
// instead to make the EXE free threaded.
// This means that calls come in on a random RPC thread
// HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
_ASSERTE(SUCCEEDED(hr));
// This provides a NULL DACL which will allow access to everyone.
CSecurityDescriptor sd;
sd.InitializeFromThreadTok
hr = CoInitializeSecurity(sd, -1, NULL, NULL,
RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONAT
_ASSERTE(SUCCEEDED(hr));
hr = _Module.RegisterClassObjec
_ASSERTE(SUCCEEDED(hr));
LogEvent(_T("Service started"));
if (m_bService)
SetServiceStatus(SERVICE_R
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
DispatchMessage(&msg);
**************************
_Module.RevokeClassObjects
CoUninitialize();
}
Well, that depends on what your code is like :o)
ASKER
:-)
see cookre's response at the top, I was gonna do something like that.
Matt
see cookre's response at the top, I was gonna do something like that.
Matt
>>I was gonna do something like that
Uh, so your service has a UI?
Uh, so your service has a UI?
ASKER
no, but the hWnd argument can be NULL.
Yes, but the docs to 'SetTimer()' state:
"Remarks
An application can process WM_TIMER messages by including a WM_TIMER case statement in the window procedure or by specifying a TimerProc callback function when creating the timer. When you specify a TimerProc callback function, the default window procedure calls the callback function when it processes WM_TIMER. Therefore, you need to dispatch messages in the calling thread, even when you use TimerProc instead of processing WM_TIMER."
If you don't have any UI, there will be no msg processing/dispatching...
"Remarks
An application can process WM_TIMER messages by including a WM_TIMER case statement in the window procedure or by specifying a TimerProc callback function when creating the timer. When you specify a TimerProc callback function, the default window procedure calls the callback function when it processes WM_TIMER. Therefore, you need to dispatch messages in the calling thread, even when you use TimerProc instead of processing WM_TIMER."
If you don't have any UI, there will be no msg processing/dispatching...
ASKER
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
DispatchMessage(&msg);
i thought that's what this section did?
while (GetMessage(&msg, 0, 0, 0))
DispatchMessage(&msg);
i thought that's what this section did?
Ooops :o)
ASKER
phew, i thought i was gonna have to rewrite a whole load of documentation there :0)
Documentation?
You mean there's more to this job than coding?
You mean there's more to this job than coding?
>>************************ ******* //<-- My Code here
I think you would want to start the timer above there, then handle it in the TimerProc, outside of the loop.
-- Dan
I think you would want to start the timer above there, then handle it in the TimerProc, outside of the loop.
-- Dan
Dear MattC
I think you forgot this question. I will ask Community Support to close it unless you finalize it within 7 days. You can always request to keep this question open. But remember, experts can only help you if you provide feedback to their questions.
Unless there is objection or further activity, I will suggest to split between
"jkr, DanRollins, cookre"
comment(s) as an answer.
If you think your question was not answered at all, you can post a request in Community support (please include this link) to refund your points. The link to the Community Support area is: https://www.experts-exchange.com/commspt/
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!
======
Werner
I think you forgot this question. I will ask Community Support to close it unless you finalize it within 7 days. You can always request to keep this question open. But remember, experts can only help you if you provide feedback to their questions.
Unless there is objection or further activity, I will suggest to split between
"jkr, DanRollins, cookre"
comment(s) as an answer.
If you think your question was not answered at all, you can post a request in Community support (please include this link) to refund your points. The link to the Community Support area is: https://www.experts-exchange.com/commspt/
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!
======
Werner
ASKER