I apreciate very much all of your comments. I came to the conclusion
that I have a lot to learn.
IDE wizard to buld this initial windows service skeleton. Parts I've
m_bService == FALSE...
Thanks very much and scuse me my poor English.
On 16 maio, 13:17, Joseph M. Newcomer <newco...@flounder.com> wrote:
See below...
On Fri, 16 May 2008 06:21:49 -0700 (PDT), VC <vcinqu...@gmail.com> wrote:
Hi, i'm new on C++ and I'm trying to write a simple windows service
for learning purposes. I created it on MS VC 6 (i'm sorry, this is the
official version of the company I work for) using the wizard. I'm
pasting only the code I've changed indicating them with *****.
The question is: when I run the service from inside the VS IDE, the
file writes normally. But when I go to a DOS window, register the
service and start it (using NET START command or Control Panel
Services applet), the file is not created. I though it was a question
of credentials and I configured the service to start using the
administrator account. But I've got no success. Could someone help.
I'm pretty sure that I'm doing something stupid, but I can't see what.
(if some one give me some advice about thread calling, I'd appreciate
very much)
in StdAfx
static DWORD WINAPI MyThreadWrapper(void *classPtr); //**********
// data members
public:
int iCounter; //**********
ofstream myfile; //**********
DWORD WINAPI MyThread(); //*******
on srv1.cpp
inline void CServiceModule::Start()
{
SERVICE_TABLE_ENTRY st[] =
{
{ m_szServiceName, _ServiceMain },
{ NULL, NULL }
};
if (m_bService && !::StartServiceCtrlDispatcher(st))
{
m_bService = FALSE;
}
if (m_bService == FALSE)
***
Never, ever, under any circumstances imaginable, EVER, write an expression that includes
==FALSE or ==TRUE as part of the expression. This is a programming error. If you want to
test if it is a not-service, you would write
if(!m_bService)
It is a common failure mode among beginners to think that a boolean must be tested against
some other literal value, but you are ignoring the fact that AS A BOOLEAN it already HAS a
true or false value, and comparing this value to another boolean literal value is stupid.
And it fools you into thinking that ==FALSE is the same as !=TRUE, or that the complement
of ==FALSE is ==TRUE, and neither of these are valid assumptions.
****
{
this->iCounter = 0; // *********
this->myfile.open("c:\\temp\\example.txt", ios::out |
ios::ate); //
**********
****
I see no path that opens the file if you are running as a service! Putting this open here
is poor style; the Run() method should handle this, then it would be common code whether
you are a service or not.
****> Run();
}
}
inline void CServiceModule::Handler(DWORD dwOpcode)
{
switch (dwOpcode)
{
case SERVICE_CONTROL_STOP:
SetServiceStatus(SERVICE_STOP_PENDING);
PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
****
What possible value does this have, given your thread has no message pump?
****> this->myfile.close(); //*********
break;
case SERVICE_CONTROL_PAUSE:
break;
case SERVICE_CONTROL_CONTINUE:
break;
case SERVICE_CONTROL_INTERROGATE:
break;
case SERVICE_CONTROL_SHUTDOWN:
break;
default:
LogEvent(_T("Bad service request"));
}
***
You do not call any function here to notify the service control manager what your status
is. In particular, SERVICE_CONTROL_INTERROGATE should tell what state the service is in.
Call your SetServiceStatus() function. I note that your SetServiceStatus function does
not report errors, or provide for checkpoints. This is a serious defect.
****
}
void CServiceModule::Run()
{
// some code here
if (m_bService)
SetServiceStatus(SERVICE_RUNNING);
DWORD dwID; //********
HANDLE hThread; //**********
this->bEndThreads = false; //************
hThread = ::CreateThread(0, 0, MyThreadWrapper, (void*)this,
0,
&dwID); //**********
***
You should *not* use CreateThread here. You are using the C runtime (that's how << is
implemented) so you should use, at the very least, _beginthreadex. If you are using any
MFC, you will need to use AfxBeginThread.
joe
MSG msg;
// some other code here
****
Whatever it is doing, it is almost certainly wrong. You would not put a message pump
here; typically you woud do a WFSO on an Event object, and your shutdown would call
::SetEvent to set the event to signaled. A message pump makes no sense.
}
// these two functions are new
DWORD WINAPI CServiceModule::MyThread()
{
while(!this->bEndThreads)
{
this->iCounter++;
myfile << "Executing thread (";
myfile << this->iCounter;
myfile << " times)\n";
Sleep(1000);
}
return 0;
}
/////////////////////////////////////////////////////////////////////////////
DWORD WINAPI MyThreadWrapper(void *classPtr)
{
CServiceModule *CsrvMod = (CServiceModule *)classPtr;
return CsrvMod->MyThread();
}
Thanks in advance
Joseph M. Newcomer [MVP]
email: newco...@flounder.com
Web:http://www.flounder.com
MVP Tips:http://www.flounder.com/mvp_tips.htm