Creating a Service ?

Just starting out? Need help? Post your questions and find answers here.
dontmailme
Enthusiast
Enthusiast
Posts: 537
Joined: Wed Oct 29, 2003 10:35 am

Creating a Service ?

Post by dontmailme »

Can you create a Windows Service with PB ?

You can probably tell, I've absolutely no idea about coding Services :oops:
Paid up PB User !
Num3
PureBasic Expert
PureBasic Expert
Posts: 2812
Joined: Fri Apr 25, 2003 4:51 pm
Location: Portugal, Lisbon
Contact:

Post 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()
aaa_2500
New User
New User
Posts: 3
Joined: Sun Jan 04, 2004 5:42 pm

Post 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
johnfermor
User
User
Posts: 29
Joined: Wed Dec 31, 2003 3:17 pm

Post 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!
Proteus
Enthusiast
Enthusiast
Posts: 113
Joined: Wed Sep 17, 2003 8:04 pm
Location: The Netherlands

Post by Proteus »

Workaround? Use the find/replace function to give #SERVICE_ALL_ACCESS a new name.
P4 2.4GHz, 256 MB, WinXP Pro, onboard video&audio.
The Programmer's Drinking Song:
"99 little bugs in the code,
99 little bugs.
Fix one bug, recompile
100 little bugs in the code."
aaa_2500
New User
New User
Posts: 3
Joined: Sun Jan 04, 2004 5:42 pm

Post 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
johnfermor
User
User
Posts: 29
Joined: Wed Dec 31, 2003 3:17 pm

Doh!

Post 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
jvalks
User
User
Posts: 17
Joined: Thu Jun 05, 2003 12:47 pm

Post 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!
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post 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. :)
Post Reply