Page 1 of 1

Creating a Service ?

Posted: Tue Dec 16, 2003 9:23 pm
by dontmailme
Can you create a Windows Service with PB ?

You can probably tell, I've absolutely no idea about coding Services :oops:

Posted: Tue Dec 16, 2003 9:31 pm
by Num3
Well this works ok under W2K and XP...

Code: Select all

; Apr. 12, 2003
; Converted to PB by Richard Eikeland
; This code is posted as is with out any waranties.
; 
#SERVICE_WIN32_OWN_PROCESS = $10
#SERVICE_WIN32_SHARE_PROCESS = $20
#SERVICE_WIN32 = #SERVICE_WIN32_OWN_PROCESS + #SERVICE_WIN32_SHARE_PROCESS
#SERVICE_ACCEPT_STOP = $1
#SERVICE_ACCEPT_PAUSE_CONTINUE = $2
#SERVICE_ACCEPT_SHUTDOWN = $4
#SC_MANAGER_CONNECT = $1
#SC_MANAGER_CREATE_SERVICE = $2
#SC_MANAGER_ENUMERATE_SERVICE = $4
#SC_MANAGER_LOCK = $8
#SC_MANAGER_QUERY_LOCK_STATUS = $10
#SC_MANAGER_MODIFY_BOOT_CONFIG = $20

#STANDARD_RIGHTS_REQUIRED = $F0000
#SERVICE_QUERY_CONFIG = $1
#SERVICE_CHANGE_CONFIG = $2
#SERVICE_QUERY_STATUS = $4
#SERVICE_ENUMERATE_DEPENDENTS = $8
#SERVICE_START = $10
#SERVICE_STOP = $20
#SERVICE_PAUSE_CONTINUE = $40
#SERVICE_INTERROGATE = $80
#SERVICE_USER_DEFINED_CONTROL = $100
#SERVICE_ALL_ACCESS = #STANDARD_RIGHTS_REQUIRED | #SERVICE_QUERY_CONFIG | #SERVICE_CHANGE_CONFIG | #SERVICE_QUERY_STATUS | #SERVICE_ENUMERATE_DEPENDENTS | #SERVICE_START | #SERVICE_STOP | #SERVICE_PAUSE_CONTINUE | #SERVICE_INTERROGATE |#SERVICE_USER_DEFINED_CONTROL

#SERVICE_DEMAND_START = $3
#SERVICE_ERROR_NORMAL = $1

;- SERVICE_CONTROL
#SERVICE_CONTROL_STOP = $1
#SERVICE_CONTROL_PAUSE = $2
#SERVICE_CONTROL_CONTINUE = $3
#SERVICE_CONTROL_INTERROGATE = $4
#SERVICE_CONTROL_SHUTDOWN = $5


;-SERVICE_STATE
#SERVICE_STOPPED = $1
#SERVICE_START_PENDING = $2
#SERVICE_STOP_PENDING = $3
#SERVICE_RUNNING = $4
#SERVICE_CONTINUE_PENDING = $5
#SERVICE_PAUSE_PENDING = $6
#SERVICE_PAUSED = $7



Global ServiceStatus.SERVICE_STATUS, hServiceStatus.l, SERVICE_NAME.s, Finish.l
Declare Handler(fdwControl.l)
Declare ServiceMain(dwArgc.l, lpszArgv.l)
Declare WriteLog(Value.s)

Procedure Main()
  
  hSCManager.l
  hService.l
  ServiceTableEntry.SERVICE_TABLE_ENTRY
  b.l
  cmd.s
  ;Change SERVICE_NAME and app name as needed
  AppPath.s = "MyService.exe"
  SERVICE_NAME = "MyService"
  
  cmd = Trim(LCase(ProgramParameter()))
  Select cmd
    Case "install" ;Install service on machine
      hSCManager = OpenSCManager_(0, 0, #SC_MANAGER_CREATE_SERVICE)
      hService = CreateService_(hSCManager, SERVICE_NAME, SERVICE_NAME, #SERVICE_ALL_ACCESS, #SERVICE_WIN32_OWN_PROCESS, #SERVICE_DEMAND_START, #SERVICE_ERROR_NORMAL, AppPath, 0, 0, 0, 0, 0)
      CloseServiceHandle_(hService)
      CloseServiceHandle_(hSCManager)
      Finish = 1
    Case "uninstall" ;Remove service from machine
      hSCManager = OpenSCManager_(0, 0, #SC_MANAGER_CREATE_SERVICE)
      hService = OpenService_(hSCManager, SERVICE_NAME, #SERVICE_ALL_ACCESS)
      DeleteService_(hService)
      CloseServiceHandle_(hService)
      CloseServiceHandle_(hSCManager)
      Finish = 1
    Default
      *sname.s = SERVICE_NAME 
      ;Start the service
      ServiceTableEntry\lpServiceName = @SERVICE_NAME
      ServiceTableEntry\lpServiceProc = @ServiceMain()
      b = StartServiceCtrlDispatcher_(@ServiceTableEntry)
      WriteLog("Starting Service bResult=" + Str(b))
      If b = 0 
        Finish = 1
      EndIf
  EndSelect
  
  Repeat
    
  Until Finish =1
  
  End
  
EndProcedure

Procedure Handler(fdwControl.l)
  b.l
  
  Select fdwControl
    Case #SERVICE_CONTROL_PAUSE
      ;** Do whatever it takes To pause here.
      ServiceStatus\dwCurrentState = #SERVICE_PAUSED
    Case #SERVICE_CONTROL_CONTINUE
      ;** Do whatever it takes To continue here.
      ServiceStatus\dwCurrentState = #SERVICE_RUNNING
    Case #SERVICE_CONTROL_STOP
      ServiceStatus\dwWin32ExitCode = 0
      ServiceStatus\dwCurrentState = #SERVICE_STOP_PENDING
      ServiceStatus\dwCheckPoint = 0
      ServiceStatus\dwWaitHint = 0 ;Might want a time estimate
      b = SetServiceStatus_(hServiceStatus, ServiceStatus)
      ;** Do whatever it takes to stop here.
      Finish = 1
      ServiceStatus\dwCurrentState = #SERVICE_STOPPED
    Case #SERVICE_CONTROL_INTERROGATE
      ;Fall through To send current status.
      Finish = 1
      ;Else
  EndSelect
  ;Send current status.
  b = SetServiceStatus_(hServiceStatus, ServiceStatus)
EndProcedure

Procedure ServiceMain(dwArgc.l, lpszArgv.l)
  b.l
  WriteLog("ServiceMain")
  ;Set initial state
  ServiceStatus\dwServiceType = #SERVICE_WIN32_OWN_PROCESS
  ServiceStatus\dwCurrentState = #SERVICE_START_PENDING
  ServiceStatus\dwControlsAccepted = #SERVICE_ACCEPT_STOP | #SERVICE_ACCEPT_PAUSE_CONTINUE | #SERVICE_ACCEPT_SHUTDOWN
  ServiceStatus\dwWin32ExitCode = 0
  ServiceStatus\dwServiceSpecificExitCode = 0
  ServiceStatus\dwCheckPoint = 0
  ServiceStatus\dwWaitHint = 0
  
  hServiceStatus = RegisterServiceCtrlHandler_(SERVICE_NAME, @Handler())
  ServiceStatus\dwCurrentState = #SERVICE_START_PENDING
  b = SetServiceStatus_(hServiceStatus, ServiceStatus)
  
  ;** Do Initialization Here
  
  ServiceStatus\dwCurrentState = #SERVICE_RUNNING
  b = SetServiceStatus_(hServiceStatus, ServiceStatus)
  
  ;** Perform tasks -- If none exit
  
  ;** If an error occurs the following should be used for shutting
  ;** down:
  ; SetServerStatus SERVICE_STOP_PENDING
  ; Clean up
  ; SetServerStatus SERVICE_STOPPED
EndProcedure

Procedure WriteLog(Value.s)
  sfile.s = "MyServiceLog.txt"
  If OpenFile(0, sfile)
    WriteStringN(Value)
    CloseFile(0) 
  Else
    If CreateFile(0,sfile)
      
      WriteStringN(Value)
      CloseFile(0)
    EndIf 
  EndIf
  
EndProcedure

Main()

Posted: Sun Jan 04, 2004 5:46 pm
by aaa_2500
When I compile, I keep getting this popup error:

Line 28: Constant already declared with a different value: #SERVICE_ALL_ACCESS

What am I doing wrong?

Andy

Posted: Mon Jan 05, 2004 9:58 pm
by johnfermor
Yeah, great code by Richard Eikeland but I too can't get it to work as I get a "Line 28: Constant Already Declared with a different value: #SERVICE_ALL_ACCESS".


Have I missed something here? I can't see any earlier declarations. Has the routine been broken by a PB update maybe? Is there a workaround?

Thanks everyone....

Oh and aplogies for submitting this to the Off-Topic post!

Posted: Mon Jan 05, 2004 10:11 pm
by Proteus
Workaround? Use the find/replace function to give #SERVICE_ALL_ACCESS a new name.

Posted: Mon Jan 05, 2004 10:41 pm
by aaa_2500
>Workaround? Use the find/replace function to give
>#SERVICE_ALL_ACCESS a new name.

I would assume that it has that name for a reason?!

It must have worked for somebody as it has been reposted in this forum several times... Is it broken because of an update to PB?

I am using PB3.30 updated to PB3.81.

Andy

Doh!

Posted: Mon Jan 05, 2004 10:43 pm
by johnfermor
Yeah thanks ... Just thought of that ..

Although I don't get the error any more and the service installs correctly, how can I start and stop the service? I can do it manually by starting and stopping it but is there a way it can be started automatically as part of the install flag?

Sorry.. I'm a bit new to this service malarky... 8O


John

Posted: Wed Feb 11, 2004 11:00 am
by jvalks
Can somebody post a simple example of a running service (created in PB) which does write to a logfile every 1 minute?

The code above does work, but I'm a bit confused where to put the actual program...

Thanks!

Posted: Wed Feb 11, 2004 1:38 pm
by PB
> Constant Already Declared with a different value

Means the constant is already in use and can't be redefined. Just use another
constant name instead, to avoid the clash.

> I can't see any earlier declarations

Then PureBasic already has that constant declared (internally) which means
you should just be able to delete the declaration and compile the app with no
problem. Try it and let me know. :)