Link to home
Start Free TrialLog in
Avatar of xenia27
xenia27Flag for Taiwan, Province of China

asked on

about Windows Service

Hi,

I got this problem...>"<...help~~~

I am trying to create a windows service...so I separate one program into two programs...one is UI part and the other one is for background part...Just keep running and getting data...

Now I know in the service list of System Management Tools, I can see the background program is added into the list...but when I reboot the computer, the program was not running at all...so I tried to start it manually but it gave me some message...like error code 1054...and the Event log said "service does not response in a proper way..." or something like it (Sorry, I'm not using English version...not sure what's wrong...>"<)

So what's wrong with my program?  What should I do with it???

Help please~~~~



Xenia
Avatar of D_M_D
D_M_D

Did you add it at startup?  The program wont run after rebooting if it's not in startup.

--------
D_M_D
A service is a slightly different creature from a regular EXE.

Does your service register itself with RegisterServiceCtrlHandler(), specifying a handler for service control messages such as

SERVICE_CONTROL_STOP
SERVICE_CONTROL_SHUTDOWN
SERVICE_CONTROL_PAUSE
SERVICE_CONTROL_CONTINUE
SERVICE_CONTROL_INTERROGATE

Also, be aware that the service becomes active before a user has logged in, so attempts to read the Registry other than classes and local machine won't work as expected, nor will fiddling with the desktop, task bar, or system tray.

Was the error, perhaps, a 1053? That's what you'd get if you don't handle service control messages.

A 1054 indicates a thread creattion failure.


The source code download here is a good example of a Windows service:
http://www.codeproject.com/system/xyntservice.asp?print=true
Avatar of xenia27

ASKER

Ok...I got a 1053...so what should I do?  I'm almost following the example...except I know which exe file I will add into windows service...and I don't have the program added into system tray, task bar, or the desktop...but I don't have an icon in the folder where UI program will call...shouldn't I have it??? mMmmm...how different between the regular exe file and windows service exe file???  Can it be console application or something else?  I'm using VC++ 6.0...Help please~~


Xenia
First, take a look at the downloadable code linked to at the top of the above link (you have to register, but it's free).

Structurally, a service is like an exe, but it does have to be able to accept control messages sent to it by the OS, and it has to be aware of the environment it's running in.  

Any of those SERVICE_CONTROL_* messages mentioned above can be sent to the service by the OS at any time and the service has to be able to handle them gracefully and punctually.  The OS passes those messages to the service by calling the routine specified in the call to RegisterServiceCtrlHandler() made by the service when it starts.  You got the 1053 because the OS didn't have a valid control message handler in your service to call.

Also, a service's operating environment is a bit different.  Services rarely create a window (although there is no explicit prohibition against doing so), so, as such, there is no message pump.  You can, however, monitor the Window's message queue with SetWindowsHookEx().  Similarly, there is no console window to do printfs into, so service output is generally text written to its own log file, entries made to the application's event log, or, rarely, message boxes.  Consider - when you're using your box, you see a desktop that is specific to you - a desktop that doesn't paint until you logon, and services start before any logon occurs, so there's no user desktop, no HKCU Registry hive, and no default user for remote connections.  If you want a service to interact with a user, you have to wait until logon processing is complete.

NB: The code sample linked to above has a few more features that many services don't have, so you'll have to ignore those to see the basics of a service.  Specifically, those extras are:
* Self install
* Self uninstall
* Starting other process specified in an ini file

Whether you create it as a console app or a win32 exe is up to you - either one can be used.
Avatar of xenia27

ASKER

Question,

If I try to add another console application into windows service...does it mean in the target application required some functions to take care control message handles???

Also, what kinda function I cannot call in the target application??  I mean like MessageBox and something else?  I'm quite confused on what kinda function call that I cannot call in a service...sorry~~

Also, I have a problem which is not about windows service...
I create a console application...and I have a thread to run my main function which consists of a while(1) loop so it can keep running...but the thread seems not created at all and the program stopped...any idea what's wrong with it??  Sorry about asking this kinda question.

I'm really apprecaite your helps...thanks!!!


Xenia
Avatar of xenia27

ASKER

Hihi,

Got another question...how can I not showing the console window??  Just acting like a exe file which is running in the background??  Everytime I execute the application and it pops up a MS-DOS-like window...how can I not show this window???

Thanks~~~


Xenia
Avatar of xenia27

ASKER

Another question...^^"

When the program run this line "StartService" and it's failed and the message code is 1053...What happened?


Avatar of xenia27

ASKER

Please tell me whether the code I'm using is right or not...

bool AddService()
{
      SERVICE_TABLE_ENTRY dispatchTable[] =
    {
        { SERVICE_SERVICENAME, (LPSERVICE_MAIN_FUNCTION)service_main },
        { NULL, NULL }
    };

    dispatchTable[0].lpServiceName = TEXT(SERVICE_SERVICENAME);
      CmdInstallService();

      if(!StartServiceCtrlDispatcher(dispatchTable))
      {
            long nError = GetLastError();
      }

      return 1;
}

void CmdInstallService()
{
   SC_HANDLE   schService;
   SC_HANDLE   schSCManager;

   TCHAR szPath[512];

   if ( GetModuleFileName( NULL, szPath, 512 ) == 0 )
   {
      _tprintf(TEXT("Unable to install %s - %s\n"), TEXT(SERVICE_SERVICEDISPLAYNAME), GetLastErrorText(szErr, 256));
      return;
   }


   schSCManager = OpenSCManager(
                               NULL,                   // machine (NULL == local)
                               NULL,                   // database (NULL == default)
                               SC_MANAGER_ALL_ACCESS   // access required
                               );
   if ( schSCManager )
   {
      schService = CreateService(
                                schSCManager,               // SCManager database
                                TEXT(SERVICE_SERVICENAME),        // name of service, TEXT(SERVICE_SERVICENAME)
                                TEXT(SERVICE_SERVICEDISPLAYNAME), // name to display
                                SERVICE_ALL_ACCESS,         // desired access
                                SERVICE_WIN32_OWN_PROCESS| SERVICE_INTERACTIVE_PROCESS,  // SERVICE_WIN32_OWN_PROCESS| SERVICE_INTERACTIVE_PROCESS, // service type
                                SERVICE_AUTO_START,                  // start type
                                SERVICE_ERROR_NORMAL,       // error control type
                                lpServicePath,                     // service's binary, szPath
                                NULL,                       // no load ordering group
                                NULL,                       // no tag identifier
                                TEXT(SERVICE_DEPENDENCIES),       // dependencies
                                NULL,                       // LocalSystem account
                                NULL);                      // no password

      if ( schService )
      {
         _tprintf(TEXT("%s installed.\n"), TEXT(SERVICE_SERVICEDISPLAYNAME) );
             if(!ServiceStart(SERVICE_SERVICENAME))
             {
                               GetLastError();
             }
         CloseServiceHandle(schService);
      }
      else
      {
         _tprintf(TEXT("CreateService failed -%d <%s>\n"), GetLastError(),GetLastErrorText(szErr, 256));
      }

      CloseServiceHandle(schSCManager);
   }
   else
   {
      _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText(szErr,256));
   }
}

bool ServiceStart (const char * szServiceName)
{
SC_HANDLE handle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  if (handle)
  {
      SC_HANDLE hService = OpenService(handle, szServiceName, SERVICE_ALL_ACCESS);
      if (hService)
      {
            if (StartService(hService, 0, NULL))
            {
                  CloseServiceHandle(hService);
                  CloseServiceHandle(handle);
                  return 1;
            }else
            {
                  ULONG      Err = GetLastError();
            }
      } else
      {
            ULONG      Err = GetLastError();
      }
      CloseServiceHandle(hService);
  }
  CloseServiceHandle(handle);
  return 0;
}

void WINAPI service_main(DWORD dwArgc, char** lpszArgv)
{

    // register our service control handler:
    //
    sshStatusHandle = RegisterServiceCtrlHandler( TEXT(szServiceName), service_ctrl);

    if (!sshStatusHandle)
        goto cleanup;

    // SERVICE_STATUS members that don't change in example
    //
    ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS;
    ssStatus.dwServiceSpecificExitCode = 0;


    // report the status to the service control manager.
    //
    if (!ReportStatusToSCMgr(
        SERVICE_START_PENDING, // service state
        NO_ERROR,              // exit code
        3000))                 // wait hint
        goto cleanup;


    ServiceStart( SERVICE_SERVICENAME );

cleanup:

    // try to report the stopped status to the service control manager.
    //
    if (sshStatusHandle)
        (void)ReportStatusToSCMgr(
                            SERVICE_STOPPED,
                            dwErr,
                            0);

    return;
}

void WINAPI service_ctrl(DWORD dwCtrlCode)
{
    // Handle the requested control code.
    //
    switch(dwCtrlCode)
    {
        // Stop the service.
        //
        // SERVICE_STOP_PENDING should be reported before
        // setting the Stop Event - hServerStopEvent - in
        // serviceStop().  This avoids a race condition
        // which may result in a 1053 - The Service did not respond...
        // error.
        case SERVICE_CONTROL_STOP:
            ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 0);
            ServiceStop();
            return;

        // Update the service status.
        //
        case SERVICE_CONTROL_INTERROGATE:
            break;

        // invalid control code
        //
        default:
            break;

    }

    ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);
}

BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
                         DWORD dwWin32ExitCode,
                         DWORD dwWaitHint)
{
    static DWORD dwCheckPoint = 1;
    BOOL fResult = TRUE;


    if ( (!bDebug) && (!bDetach) ) // when debugging we don't report to the SCM
    {
        if (dwCurrentState == SERVICE_START_PENDING)
            ssStatus.dwControlsAccepted = 0;
        else
            ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
                  // SERVICE_ACCEPT_STOP

        ssStatus.dwCurrentState     = dwCurrentState;
        ssStatus.dwWin32ExitCode    = dwWin32ExitCode;
        ssStatus.dwWaitHint         = dwWaitHint;

        if ( ( dwCurrentState == SERVICE_RUNNING ) ||
             ( dwCurrentState == SERVICE_STOPPED ) )
            ssStatus.dwCheckPoint = 0;
        else
            ssStatus.dwCheckPoint = dwCheckPoint++;


        // Report the status of the service to the service control manager.
        //
        if (!(fResult = SetServiceStatus( sshStatusHandle, &ssStatus))) {
            AddToMessageLog(TEXT("SetServiceStatus"));
        }
    }
    return fResult;
}

*******************************************************
I tried to add a console application into windows services...all these functions are in a UI application.
Is all that code in a single module?
-----
To start a hidden app, use CreateProcess() with STARTUPINFO .dwFlags set with STARTF_USESHOWWINDOW and .wShowWindow set with SW_HIDE
---
Yes, you can use MessageBox().  
I don't believe any calls are prohibited, they may just behave differently.  The best thing to do is to see what happens.
---
re: while(1) Do you not get a failed CreateThread()?  What doe GetLastError() report?
Avatar of xenia27

ASKER

First, No...there is more codes...
Basically this program will first detect what kinda device is attached...then, show up a dialog to indicate the information about the device attached...Then, it will CreateProcess to call another exe file..which is the target exe file I would like to add into windows service...Whenever the user feels right to add the target file into windows service, the user will click on an icon and set the choice...then this program will call another function "AddService" to do whatever it needs to do in order to adding target exe file.

Then, the whie(1) loop did well...nothing wrong over there....
I tried to adjust all these codes into simple program...doing nothing...no functions called..and using the sample you gave me...and tried to create a service...but I got the same error code (1053)... Here my target file will only do this loop
while(1)
{
  Sleep(1000);
}

By the way, my target exe file will keep sending message to the device so it will have latest data...the device will be something like COM Port or SCSI...

Thanks for your help~~ ^^

Xenia
Uh Oh, Sleep() is a baaad way to delay.  If the thread issuing the Sleep() created any windows, no messages will get through, since the entire thread shuts down.  Although it's a tad more involved, the best way would be to use a timer.

In general, if you're going to have user interaction, you're best served just running the program from the 'all users' startup folder or from HKLM/Software/Microsoft/Windows/CurrentVersion/Run.  That way you don't have to figure out when a user has logged in or out.
Avatar of xenia27

ASKER

mMmm...
but windows service is required...
What else I can do to figure out what's wrong with my program??  Any suggestion??  Can I have your email address??  Please??? ^^
Post the code for the service and we'll look at it.
Avatar of xenia27

ASKER

It's exactly like the sample codes...except I took off all file open and writing stuff

in Service.cpp
//////////////////////////////////////////////////////////////////////
// NT Service Stub Code (For XYROOT )
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <winbase.h>
#include <winsvc.h>
#include <process.h>


const int nBufferSize = 500;
char pServiceName[nBufferSize+1];
char pExeFile[nBufferSize+1];
char pInitFile[nBufferSize+1];
char pLogFile[nBufferSize+1];
int nProcCount = 0;
PROCESS_INFORMATION* pProcInfo = 0;

SERVICE_STATUS          serviceStatus;
SERVICE_STATUS_HANDLE   hServiceStatusHandle;

VOID WINAPI XYNTServiceMain( DWORD dwArgc, LPTSTR *lpszArgv );
VOID WINAPI XYNTServiceHandler( DWORD fdwControl );


//////////////////////////////////////////////////////////////////////
//
// Configuration Data and Tables
//

SERVICE_TABLE_ENTRY   DispatchTable[] =
{
      {pServiceName, XYNTServiceMain},
      {NULL, NULL}
};


// helper functions

BOOL StartProcess(int nIndex)
{
      STARTUPINFO startUpInfo = { sizeof(STARTUPINFO),NULL,"",NULL,0,0,0,0,0,0,0,0,SW_HIDE,0,NULL,0,0,0};  
      
      char pItem[nBufferSize+1];
      sprintf(pItem,"Process%d\0",nIndex);
      char pCommandLine[nBufferSize+1];
      GetPrivateProfileString(pItem,"CommandLine","",pCommandLine,nBufferSize,pInitFile);
      char pUserInterface[nBufferSize+1];
      GetPrivateProfileString(pItem,"UserInterface","N",pUserInterface,nBufferSize,pInitFile);
      BOOL bUserInterface = (pUserInterface[0]=='y'||pUserInterface[0]=='Y'||pUserInterface[0]=='1')?TRUE:FALSE;
      if(bUserInterface)
      {
            startUpInfo.wShowWindow = SW_SHOW;
            startUpInfo.lpDesktop = NULL;
      }
      char pWorkingDir[nBufferSize+1];
      GetPrivateProfileString(pItem,"WorkingDir","",pWorkingDir,nBufferSize,pInitFile);
      if(CreateProcess(NULL,pCommandLine,NULL,NULL,TRUE,NORMAL_PRIORITY_CLASS,NULL,strlen(pWorkingDir)==0?NULL:pWorkingDir,&startUpInfo,&pProcInfo[nIndex]))
      {
            char pPause[nBufferSize+1];
            GetPrivateProfileString(pItem,"PauseStart","100",pPause,nBufferSize,pInitFile);
            Sleep(atoi(pPause));
            return TRUE;
      }
      else
      {
            long nError = GetLastError();

            return FALSE;
      }
}

void EndProcess(int nIndex)
{            
      char pItem[nBufferSize+1];
      sprintf(pItem,"Process%d\0",nIndex);
      char pPause[nBufferSize+1];
      GetPrivateProfileString(pItem,"PauseEnd","100",pPause,nBufferSize,pInitFile);
      int nPauseEnd = atoi(pPause);
      if(nIndex>=0&&nIndex<nProcCount)
      {
            if(pProcInfo[nIndex].hProcess)
            {
                  if(nPauseEnd>0)
                  {
                        PostThreadMessage(pProcInfo[nIndex].dwThreadId,WM_QUIT,0,0);
                        Sleep(nPauseEnd);
                  }
                  TerminateProcess(pProcInfo[nIndex].hProcess,0);
            }
      }
}

BOOL BounceProcess(char* pName, int nIndex)
{
      SC_HANDLE schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS);
      if (schSCManager==0)
      {
            long nError = GetLastError();

      }
      else
      {
            SC_HANDLE schService = OpenService( schSCManager, pName, SERVICE_ALL_ACCESS);
            if (schService==0)
            {
                  long nError = GetLastError();

            }
            else
            {
                  SERVICE_STATUS status;
                  if(nIndex>=0&&nIndex<128)
                  {
                        if(ControlService(schService,(nIndex|0x80),&status))
                        {
                              CloseServiceHandle(schService);
                              CloseServiceHandle(schSCManager);
                              return TRUE;
                        }
                        long nError = GetLastError();

                  }
                  else
                  {

                  }
                  CloseServiceHandle(schService);
            }
            CloseServiceHandle(schSCManager);
      }
      return FALSE;
}

BOOL KillService(char* pName)
{
      SC_HANDLE schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS);
      if (schSCManager==0)
      {
            long nError = GetLastError();
      }
      else
      {
            SC_HANDLE schService = OpenService( schSCManager, pName, SERVICE_ALL_ACCESS);
            if (schService==0)
            {
                  long nError = GetLastError();
            }
            else
            {
                  SERVICE_STATUS status;
                  if(ControlService(schService,SERVICE_CONTROL_STOP,&status))
                  {
                        CloseServiceHandle(schService);
                        CloseServiceHandle(schSCManager);
                        return TRUE;
                  }
                  else
                  {
                        long nError = GetLastError();
                  }
                  CloseServiceHandle(schService);
            }
            CloseServiceHandle(schSCManager);
      }
      return FALSE;
}

BOOL RunService(char* pName, int nArg, char** pArg)
{
      SC_HANDLE schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS);
      if (schSCManager==0)
      {
            long nError = GetLastError();

      }
      else
      {
            SC_HANDLE schService = OpenService( schSCManager, pName, SERVICE_ALL_ACCESS);
            if (schService==0)
            {
                  long nError = GetLastError();

            }
            else
            {
                  if(StartService(schService,nArg,(const char**)pArg))
                  {
                        CloseServiceHandle(schService);
                        CloseServiceHandle(schSCManager);
                        return TRUE;
                  }
                  else
                  {
                        long nError = GetLastError();

                  }
                  CloseServiceHandle(schService);
            }
            CloseServiceHandle(schSCManager);
      }
      return FALSE;
}

//////////////////////////////////////////////////////////////////////
//
// This routine gets used to start your service
//
VOID WINAPI XYNTServiceMain( DWORD dwArgc, LPTSTR *lpszArgv )
{
      DWORD   status = 0;
    DWORD   specificError = 0xfffffff;
 
    serviceStatus.dwServiceType        = SERVICE_WIN32;
    serviceStatus.dwCurrentState       = SERVICE_START_PENDING;
    serviceStatus.dwControlsAccepted   = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
    serviceStatus.dwWin32ExitCode      = 0;
    serviceStatus.dwServiceSpecificExitCode = 0;
    serviceStatus.dwCheckPoint         = 0;
    serviceStatus.dwWaitHint           = 0;
 
    hServiceStatusHandle = RegisterServiceCtrlHandler(pServiceName, XYNTServiceHandler);
    if (hServiceStatusHandle==0)
    {
            long nError = GetLastError();
        return;
    }
 
    // Handle error condition
      status = GetLastError();
    if (status!=NO_ERROR)
      {
        serviceStatus.dwCurrentState       = SERVICE_STOPPED;
        serviceStatus.dwCheckPoint         = 0;
        serviceStatus.dwWaitHint           = 0;
        serviceStatus.dwWin32ExitCode      = status;
        serviceStatus.dwServiceSpecificExitCode = specificError;
        SetServiceStatus(hServiceStatusHandle, &serviceStatus);
        return;
    }
 
    // Initialization complete - report running status
    serviceStatus.dwCurrentState       = SERVICE_RUNNING;
    serviceStatus.dwCheckPoint         = 0;
    serviceStatus.dwWaitHint           = 0;  
    if(!SetServiceStatus(hServiceStatusHandle, &serviceStatus))
    {
            long nError = GetLastError();
    }

      for(int i=0;i<nProcCount;i++)
      {
            pProcInfo[i].hProcess = 0;
            StartProcess(i);
      }
}

//////////////////////////////////////////////////////////////////////
//
// This routine responds to events concerning your service, like start/stop
//
VOID WINAPI XYNTServiceHandler(DWORD fdwControl)
{
      switch(fdwControl)
      {
            case SERVICE_CONTROL_STOP:
            case SERVICE_CONTROL_SHUTDOWN:
                  serviceStatus.dwWin32ExitCode = 0;
                  serviceStatus.dwCurrentState  = SERVICE_STOPPED;
                  serviceStatus.dwCheckPoint    = 0;
                  serviceStatus.dwWaitHint      = 0;
                  {
                        for(int i=nProcCount-1;i>=0;i--)
                        {
                              EndProcess(i);
                        }                  
                        if (!SetServiceStatus(hServiceStatusHandle, &serviceStatus))
                        {
                              long nError = GetLastError();
                        }
                  }
                  return;
            case SERVICE_CONTROL_PAUSE:
                  serviceStatus.dwCurrentState = SERVICE_PAUSED;
                  break;
            case SERVICE_CONTROL_CONTINUE:
                  serviceStatus.dwCurrentState = SERVICE_RUNNING;
                  break;
            case SERVICE_CONTROL_INTERROGATE:
                  break;
            default:
                  if(fdwControl>=128&&fdwControl<256)
                  {
                        int nIndex = fdwControl&0x7F;
                        if(nIndex>=0&&nIndex<nProcCount)
                        {
                              EndProcess(nIndex);
                              StartProcess(nIndex);
                        }
                        else if(nIndex==127)
                        {
                              for(int i=nProcCount-1;i>=0;i--)
                              {
                                    EndProcess(i);
                              }
                              for(i=0;i<nProcCount;i++)
                              {
                                    StartProcess(i);
                              }
                        }
                  }
                  else
                  {

                  }
      };
    if (!SetServiceStatus(hServiceStatusHandle,  &serviceStatus))
      {
            long nError = GetLastError();

    }
}


//////////////////////////////////////////////////////////////////////
//
// Uninstall
//
VOID UnInstall(char* pName)
{
      SC_HANDLE schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS);
      if (schSCManager==0)
      {
            long nError = GetLastError();

      }
      else
      {
            SC_HANDLE schService = OpenService( schSCManager, pName, SERVICE_ALL_ACCESS);
            if (schService==0)
            {
                  long nError = GetLastError();

            }
            else
            {

                  if(!DeleteService(schService))
                  {

                  }
                  else
                  {

                  CloseServiceHandle(schService);
            }
            CloseServiceHandle(schSCManager);      
      }
}

//////////////////////////////////////////////////////////////////////
//
// Install
//
VOID Install(char* pPath, char* pName)
{  
      SC_HANDLE schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CREATE_SERVICE);
      if (schSCManager==0)
      {
            long nError = GetLastError();

      }
      else
      {
            SC_HANDLE schService = CreateService
            (
                  schSCManager,      /* SCManager database      */
                  pName,                  /* name of service         */
                  pName,                  /* service name to display */
                  SERVICE_ALL_ACCESS,        /* desired access          */
                  SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS , /* service type            */
                  SERVICE_AUTO_START,      /* start type              */
                  SERVICE_ERROR_NORMAL,      /* error control type      */
                  pPath,                  /* service's binary        */
                  NULL,                      /* no load ordering group  */
                  NULL,                      /* no tag identifier       */
                  NULL,                      /* no dependencies         */
                  NULL,                      /* LocalSystem account     */
                  NULL
            );                     /* no password             */
            if (schService==0)
            {
                  long nError =  GetLastError();

            }
            else
            {

                  CloseServiceHandle(schService);
            }
            CloseServiceHandle(schSCManager);
      }      
}

void WorkerProc(void* pParam)
{
      char pCheckProcess[nBufferSize+1];
      GetPrivateProfileString("Settings","CheckProcess","60",pCheckProcess, nBufferSize,pInitFile);
      int nCheckProcess = atoi(pCheckProcess);
      while(nCheckProcess>0&&nProcCount>0)
      {
            ::Sleep(1000*60*nCheckProcess);
            for(int i=0;i<nProcCount;i++)
            {
                  char pItem[nBufferSize+1];
                  sprintf(pItem,"Process%d\0",i);
                  char pRestart[nBufferSize+1];
                  GetPrivateProfileString(pItem,"Restart","No",pRestart,nBufferSize,pInitFile);
                  if(pRestart[0]=='Y'||pRestart[0]=='y'||pRestart[0]=='1')
                  {
                        DWORD dwCode;
                        if(::GetExitCodeProcess(pProcInfo[i].hProcess, &dwCode))
                        {
                              if(dwCode!=STILL_ACTIVE)
                              {
                                    if(StartProcess(i))
                                    {

                                    }
                              }
                        }
                        else
                        {
                              long nError = GetLastError();

                        }
                  }
            }
      }
}

/////////////////////////////////////////////////////////////////////
Where I call "AddService" is in wndProc...so when I choose the option...it will call "AddService"
bool AddService(void)
{
      Install(lpServicePath, SERVICE_SERVICENAME);
      return 1;
}


///////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
      int                        wmId, wmEvent;
      PAINTSTRUCT            ps;
      HDC                        hdc;
   
      HMENU                  hMenu;            /* menu template         */
      static HANDLE      WBTMHandle = NULL;
      BOOL                  bRet;
      HWND                  MainWnd = NULL;
      POINT            pt;
      FILE            *inifile;
      DWORD            ret;

      gHwnd = hWnd;

      switch (message)
      {

            case WM_COMMAND:
                  
                  hMenu = GetMenu (hWnd);
                  wmId    = LOWORD(wParam);
                  wmEvent = HIWORD(wParam);
                  // Parse the menu selections:
                  switch (wmId)
                  {
                        case IDM_EXIT:
                              Shell_NotifyIcon(NIM_DELETE, &NID);
                              DestroyWindow(hWnd);
                           break;
                        case IDM_SERVICEMENU:
                              if (GotServiceFlag == FALSE)
                              {
                              AddService();
                              GotServiceFlag = TRUE;
                              memset(iniSection, 0, INILENGTH);
                              length = 0;
                              Set_INI_For_All(iniSection);
                              Set_INI_Misc(iniSection);
                              if (strle(iniSection) > 0)
                              {
                              inifile = fopen(lpCurrentINI, "wt");      
                              fwrite(iniSection, sizeof(char), INILENGTH, inifile);
                              fclose(inifile);
                              }
                              RunnService(SERVICE_SERVICENAME,0,NULL);
                              } else
                              {
                                                   RemoveService();
                              GotServiceFlag = FALSE;
                              memset(iniSection, 0, INILENGTH);
                              length = 0;
                              Set_INI_For_All(iniSection);
                              Set_INI_Misc(iniSection);
                              if (strle(iniSection) > 0)
                              {
                              inifile = fopen(lpCurrentINI, "wt");      
                              fwrite(iniSection, sizeof(char), INILENGTH, inifile);
                              fclose(inifile);
                              }
                        }
                        break;
                                             default:

                           return DefWindowProc(hWnd, message, wParam, lParam);
                  }
                  
                  break;

            case WM_PAINT:
                  hdc = BeginPaint(hWnd, &ps);
                  // TODO: Add any drawing code here...
                  RECT rt;
                  GetClientRect(hWnd, &rt);
                  //DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
                  EndPaint(hWnd, &ps);
                  break;

            case WM_DESTROY:

                  Shell_NotifyIcon(NIM_DELETE, &NID);
                  PostQuitMessage(0);
                  break;

            case WM_MYHOOK:

                  if ( lParam == WM_RBUTTONUP )
                  {
                        SetForegroundWindow (hWnd);

                        hMenu =CreatePopupMenu();
                        if (AppendMenu(hMenu, MF_ENABLED|MF_STRING, IDM_SERVICEMENU, lpServiceOptions) == FALSE)
                              return 0;
                        if (AppendMenu(hMenu, MF_ENABLED|MF_STRING, IDM_REDETECTOPTION, "ReDetect the Controller") == FALSE)
                              return 0;
>>>>>  Here I use AppendMenu to set up all the choice
                                           } >> end of MY_HOOK (I delete some codes here)
            case WM_SIZE:

                  switch (wParam)
                  {
                        case SIZE_MINIMIZED:
                              ShowWindow(hWnd, SW_HIDE);
                              break;
                        default:
                              break;
                  }
                  break;

            case WM_QUIT:
                  Shell_NotifyIcon(NIM_DELETE, &NID);
                  break;

            default:
                  return DefWindowProc(hWnd, message, wParam, lParam);
      }


      return 0;

}
Poo, too many errors without resource files et al.
Although it's generally frowned upon, if you like, zip up the whole project directory and send it to the addr in my profile.

That way I'll get your project specific settings, too.
Avatar of xenia27

ASKER

Ok...I'll try to zip these files and send it to you...thanks~~  ^^


Xenia
I see you don't create the service in the code.  From that I presume you use SC to create it, and I bet  you don't create it as SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS.

You can get past the 1053 failure to start if you create it by:

sc create acsserverui binpath= wherever type= own type= interact
Avatar of xenia27

ASKER

Could you please help me on changing the codes so my codes will work???  Actually I don't understand why I didn't create the service as SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS...

So what can I do with my codes now??  Help please~~~


Xenia
ASKER CERTIFIED SOLUTION
Avatar of cookre
cookre
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of xenia27

ASKER

mMmm...so if I ask whether the user would like to install this program as a windows service in the beginning of this program, will this work?  I mean in "WinMain"..

Or is there other way that a user can decide when they want to install this program as a service anytime and remove from the service list anytime?  Will this possible??

What I am trying to do is creating a UI program that a user can monitor a particular hardware.  And now they need to run this program as a windows service...mMmm..

Should I ask what is a good way to create a windows service through writing a program to do so?
Avatar of xenia27

ASKER

Can I pop up a dialog and ask a user whether they wants to run this program as a windows service in the beginning of this program and then keep running a background exe file which I would like to run as a windows service???
Can I pop up a dialog and ask a user whether they wants to run this program as a windows service in the beginning of this program and then keep running a background exe file which I would like to run as a windows service???

Yes, as long as the service doesn't use the windows message pump.  You will note that the sample code linked to doesn't do any direct user interaction in the service itself, rather it starts windows processes to do that.  As a matter of fact, I've never done any interaction in a service other than plopping things in the system tray (which is handled by the shell and bypasses any talking of the service to the desktop).

Avatar of xenia27

ASKER

Thanks for your tips...I'm going to try to pop up a dialog to run "AddService"...and probably using system tray for removing service...Hope this will work~~

By the way, Happy New Year~~~ ^^


Xenia
Avatar of xenia27

ASKER

Question~

about DialogBox...won't it use windows message pumps??  Is there any other way to pop up a dialog box for choosing yes or not??
The only reason I can think of why they're requiring a service is because of the dificulty Joe User would have in stopping a service (as compared to killing a process from the TaskList).  If that's the case, It is worth noting that regular windows process can be hidden so they don't show up in the task list, and if somebody can figure out how to unmask a hidden process and kill it, then they can do the same for a service.
Cross posting is fun....

>>>about DialogBox...won't it use windows message pumps??  Is there any other way to pop up a dialog box for choosing yes or not??

I said yes because I thought you would ask that question in a normal (i.e., non-service) program.

Avatar of xenia27

ASKER

Stupid me...I'm confused now...
the UI program which is non-sercie part will use wndProc in the original program...and this is the reason casuing 1053, right?  So if I use DialogBox which is also using windows message pumps, will it cause 1053, too??

Now I will use MessageBox which also has yes or no choices...^^  Hope this will work.


Xenia
Avatar of xenia27

ASKER

I'm still having 1053 error message...
Should I use CreateEvent and if a user required to run it as a windows service...SetEvent to signal the background program become a windows service?  Will this work???


Xenia
What is the service supposed to do?  I ask this because right now your service does nothing aside from catching control messages.

====

MessageBox() to a NULL hwnd with options like MB_YESNO does work because it has no owner window.

The problem with windows and services is that services don't run under the user desktop and windows messages don't cross between desktops.

Avatar of xenia27

ASKER

The service should be pulling data from a device...this device will be connected and interact with users through RS232, SCSI or Fiber...
So what I am trying to do is start UI program and UI program will CreateProcess to run Server Program....Then, depends on what users want, the Server Program can be added into windows service...
So what should I do change my codes in order to make this works?
The way I se it is:

Normal Windows Program (NWP) presents menus and options.
Also present on the box is another exe that is just the service (S) that doesn't do anything with windows.
If the user indicates the need for S, NWP creates it and starts it by shelling out to an SC or doing the API equivalent.
You know have NWP happily doing whatever it does and S sitting in the background doing it's thing.

If NWP needs to monitor what S is doing, it has several ways open to it:
* service status query messages
* event log
* simple files
Avatar of xenia27

ASKER

So S can keep pulling data from a device?
What's the command for service status query message??


I'm so sorry for being such a troublesome...still learning~  >"<
Avatar of xenia27

ASKER

Can I have an example code for background program?  Please~
Sequence to query service:
OpenSCManager() to get handle to service control manager
OpenService() to get handle to desired service
QueryServiceStatus() to get the most recently reported SERVICE_STATUS structure from service.

In the service:
The service regularly updates its SERVICE_STATUS struct and reports it with SetServiceStatus()

The SERVICE_CONTROL_INTERROGATE message may be received at any time by the routine specified in the original call to RegisterServiceCtrlHandler().

===

A background program is nothing special - it's just something you start by shelling out or with a CreateProcess().  How you talk to it is entirely up to you - the OS makes no distinctions between it and any other 'normal' program.  Since both are running under the same desktop (unlike a service) an easy way for the two to talk to each other is by way of custom messages passed through the windows message pump.
Avatar of xenia27

ASKER

sorry to ask this...but...how would you change the codes I sent to you in order to this codes work????

I'm getting confused and have no idea to start it now...>"<...help please~~
Avatar of xenia27

ASKER

I just don't understand why Service program will not work...I eliminate all windows message pump and no dialog in the program.  What else it will cause 1053 error message?

Which step is incorrect?  Here is what I did in my programs...
1. I start UI program...
2. Install the service...
3. RunService --> here is the error happened.. 1053 here..

SC_HANDLE schService = CreateService
(
  schSCManager,      /* SCManager database      */
  pName,                  /* name of service         */
  pName,                  /* service name to display */
  SERVICE_ALL_ACCESS,        /* desired access          */
 SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS , /* service type            */
  SERVICE_AUTO_START,      /* start type              */
  SERVICE_ERROR_NORMAL,      /* error control type      */
  pPath,                  /* service's binary        */
  NULL,                      /* no load ordering group  */
  NULL,                      /* no tag identifier       */
  NULL,                      /* no dependencies         */
  NULL,                      /* LocalSystem account     */
  NULL
);  

pPath is where the Service program located...I have question on this one...shoudl pPath be the path of HKEY\...\??  Or where the exe file currently locates??

Also, do I need Service.cpp in the Service program since I try to install a service with UI program?? (not in the Service program...)
Avatar of xenia27

ASKER

Ok...
I finally figure out what's wrong with my codes...It's working now!!!!!!!!  Cannot believe it is working now...Thanks for your helps~~~  ^^
Well done.