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