Ich hab mit dem Beispiel vom letzten Link von bobobo etwas rumgespielt - scheint mir durchaus zu funktionieren...
Frag mich jetzt nur nicht, wie man
korrekt den eigenen Code integriert! Ich würde es so machen, dass ich meinen Code in ServiceProcedure() einfügen und entsprechend auf den Status reagieren würde.
Ausserdem sollte man daran denken, keine GUI-Ausgaben zu machen, d.h. keine MessageRequester etc. - Dienste machen das nicht, besonders nicht unter Windows Vista/7 - so wie ich das mitbekommen hab... ^^
In ServiceFramework.pbi müsste man evtl. in ServiceMain() den Sleep_(100) entfernen, je nach dem was man genau machen will (allerdings nicht für ExampleService.pb!). Fragt sich noch, ob man ServiceInit() verändern dürfte, denn diese Prozedur wird offenbar auch beim Stoppen des Dienstes ausgeführt. Dort würde zum Beispiel dein CloseNetworkServer(0) hin gehören... imho...
Achja - die Deklarationen der Konstanten sind evtl. überflüssig - hab mich aber nicht getraut, die zu entfernen. Die einzige die PB moniert hat, habe ich auskommentiert...
Hier noch die unter PB 4.40 lauffähigen Codes (WinXP 32):
ServiceFramework.pbi
Code: Alles auswählen
;Originalcode from akee
;http://www.purebasic.fr/english/viewtopic.php?p=84001#p84001
;Converted for PureBasic 4.40
Global AppHome.s
Global AppExeName.s
Global AppExeFileName.s
Global AppIniFileName.s
AppIniFileName = ProgramFilename()
AppHome.s = GetPathPart(AppIniFileName)
AppExeFileName.s = GetFilePart(AppIniFileName)
AppExeName.s = Left(AppExeFileName, Len(AppExeFileName) - Len(GetExtensionPart(AppIniFileName)) - 1)
AppIniFileName.s = AppExeName + ".ini"
#READ_CONTROL = $20000
#STANDARD_RIGHTS_ALL = $1F0000
#STANDARD_RIGHTS_EXECUTE = (#READ_CONTROL)
#STANDARD_RIGHTS_READ = (#READ_CONTROL)
#STANDARD_RIGHTS_REQUIRED = $F0000
#STANDARD_RIGHTS_WRITE = (#READ_CONTROL)
#SERVICE_WIN32_OWN_PROCESS = $10
#SERVICE_WIN32_SHARE_PROCESS = $20
#SERVICE_WIN32 = #SERVICE_WIN32_OWN_PROCESS + #SERVICE_WIN32_SHARE_PROCESS
#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
#SC_MANAGER_ALL_ACCESS_2 = (#STANDARD_RIGHTS_REQUIRED | #SC_MANAGER_CONNECT | #SC_MANAGER_CREATE_SERVICE | #SC_MANAGER_ENUMERATE_SERVICE | #SC_MANAGER_LOCK | #SC_MANAGER_QUERY_LOCK_STATUS | #SC_MANAGER_MODIFY_BOOT_CONFIG)
#SERVICE_ACCEPT_STOP = $1
#SERVICE_ACCEPT_PAUSE_CONTINUE = $2
#SERVICE_ACCEPT_SHUTDOWN = $4
#SERVICE_ACTIVE = $1
#SERVICE_ALL_ACCESS_2 = (#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_CHANGE_CONFIG = $2
#SERVICE_CONTINUE_PENDING = $5
#SERVICE_CONTROL_CONTINUE = $3
#SERVICE_CONTROL_INTERROGATE = $4
#SERVICE_CONTROL_PAUSE = $2
#SERVICE_CONTROL_SHUTDOWN = $5
#SERVICE_CONTROL_STOP = $1
#SERVICE_DEMAND_START = $3
#SERVICE_ENUMERATE_DEPENDENTS = $8
#SERVICE_ERROR_NORMAL = $1
#SERVICE_INACTIVE = $2
#SERVICE_INTERROGATE = $80
;#SERVICE_NO_CHANGE = $FFFF
#SERVICE_PAUSE_CONTINUE = $40
#SERVICE_PAUSE_PENDING = $6
#SERVICE_PAUSED = $7
#SERVICE_QUERY_CONFIG = $1
#SERVICE_QUERY_STATUS = $4
#SERVICE_RUNNING = $4
#SERVICE_START = $10
#SERVICE_START_PENDING = $2
#SERVICE_STATE_ALL = (#SERVICE_ACTIVE | #SERVICE_INACTIVE)
#SERVICE_STOP = $20
#SERVICE_STOP_PENDING = $3
#SERVICE_STOPPED = $1
#SERVICE_USER_DEFINED_CONTROL = $100
#SERVICE_CONFIG_DESCRIPTION = $1
#SERVICE_CONFIG_FAILURE_ACTIONS = $2
Global X_SERVICE_STATUS.SERVICE_STATUS
Global X_SERVICE_STATUS_HANDLE.i
Global X_SERVICE_RUNNING.i
Declare ServiceProcedure(ServiceState.i)
;
;
;
Procedure _WriteLog(LogMessage.s)
T_LOGFILE.s = AppHome + AppExeName + ".log"
T_HANDLE.i
If FileSize(T_LOGFILE) = -1
T_HANDLE = CreateFile(#PB_Any, T_LOGFILE)
Else
T_HANDLE = OpenFile(#PB_Any, T_LOGFILE)
FileSeek(T_HANDLE,Lof(T_HANDLE))
EndIf
WriteStringN(T_HANDLE,FormatDate("%yyyy/%mm/%dd,%hh:%ii:%ss,", Date()) + LogMessage)
CloseFile(T_HANDLE)
EndProcedure
;
;
;
Procedure ServiceHandler(OperationCode.i)
Select OperationCode
Case #SERVICE_CONTROL_PAUSE
X_SERVICE_STATUS\dwCurrentState = #SERVICE_PAUSED
SetServiceStatus_(X_SERVICE_STATUS_HANDLE, X_SERVICE_STATUS)
Case #SERVICE_CONTROL_CONTINUE
X_SERVICE_STATUS\dwCurrentState = #SERVICE_RUNNING
SetServiceStatus_(X_SERVICE_STATUS_HANDLE, X_SERVICE_STATUS)
Case #SERVICE_CONTROL_STOP
X_SERVICE_STATUS\dwWin32ExitCode = 0
X_SERVICE_STATUS\dwCheckPoint = 0
X_SERVICE_STATUS\dwWaitHint = 0
X_SERVICE_STATUS\dwCurrentState = #SERVICE_STOPPED
SetServiceStatus_(X_SERVICE_STATUS_HANDLE, X_SERVICE_STATUS)
X_SERVICE_RUNNING = #False
Case #SERVICE_CONTROL_INTERROGATE
X_SERVICE_RUNNING = #False
EndSelect
EndProcedure
;
;
;
Procedure ServiceMain()
X_SERVICE_STATUS\dwServiceType = #SERVICE_WIN32
X_SERVICE_STATUS\dwCurrentState = #SERVICE_START_PENDING
X_SERVICE_STATUS\dwControlsAccepted = #SERVICE_ACCEPT_STOP | #SERVICE_ACCEPT_PAUSE_CONTINUE
X_SERVICE_STATUS\dwWin32ExitCode = 0
X_SERVICE_STATUS\dwServiceSpecificExitCode = 0
X_SERVICE_STATUS\dwCheckPoint = 0
X_SERVICE_STATUS\dwWaitHint = 0
X_SERVICE_STATUS_HANDLE = RegisterServiceCtrlHandler_(AppExeName, @ServiceHandler())
X_SERVICE_STATUS\dwCurrentState = #SERVICE_RUNNING
SetServiceStatus_(X_SERVICE_STATUS_HANDLE, X_SERVICE_STATUS)
X_SERVICE_RUNNING = #True
While X_SERVICE_RUNNING
Sleep_(100)
ServiceProcedure(X_SERVICE_STATUS\dwCurrentState)
Wend
EndProcedure
;
;
;
Procedure ServiceInit(ServiceName.s)
T_TABLE_ENTRY.SERVICE_TABLE_ENTRY
T_SCMANAGER.i
T_SERVICE.i = 0
T_RETURNS.i = 1
T_PARAMETER.s = Trim(LCase(ProgramParameter()))
X_SERVICE_RUNNING = #False
If T_PARAMETER = ""
T_TABLE_ENTRY\lpServiceName = @AppExeName
T_TABLE_ENTRY\lpServiceProc = @ServiceMain()
If StartServiceCtrlDispatcher_(@T_TABLE_ENTRY)
_WriteLog("Service " + AppExeName + " dispatched.")
T_RETURNS = 0
EndIf
Else
T_SCMANAGER = OpenSCManager_(0, 0, #SC_MANAGER_ALL_ACCESS_2)
If T_SCMANAGER
Select T_PARAMETER
Case "-i"
_WriteLog("Installing service " + AppExeName + ".")
ServiceName = Trim(ServiceName)
If ServiceName = ""
ServiceName = AppExeName
EndIf
T_SERVICE = CreateService_(T_SCMANAGER, AppExeName, ServiceName, #SERVICE_ALL_ACCESS, #SERVICE_WIN32_OWN_PROCESS, #SERVICE_DEMAND_START, #SERVICE_ERROR_NORMAL, AppHome + AppExeFileName, 0, 0, 0, 0, 0)
If T_SERVICE
_WriteLog("Service installed succesfully.")
T_RETURNS = 0
Else
_WriteLog("Error installing service.")
EndIf
CloseServiceHandle_(T_SERVICE)
Case "-u"
_WriteLog("Uninstalling service " + AppExeName + ".")
T_SERVICE = OpenService_(T_SCMANAGER, AppExeName, #SERVICE_ALL_ACCESS_2)
If T_SERVICE
DeleteService_(T_SERVICE)
_WriteLog("Service uninstalled succesfully.")
T_RETURNS = 0
Else
_WriteLog("Error uninstalling service.")
EndIf
CloseServiceHandle_(T_SERVICE)
Default
_WriteLog("Unknown parameter " + T_PARAMETER + ". Use -i to install or -u to uninstall service.")
EndSelect
Else
_WriteLog("Error opening service control manager.")
EndIf
CloseServiceHandle_(T_SCMANAGER)
EndIf
_WriteLog("Program returned " + Str(T_RETURNS) + ".")
End T_RETURNS
EndProcedure
ExampleService.pb
Code: Alles auswählen
XIncludeFile "ServiceFramework.pbi"
;
;
;
Procedure ServiceProcedure(State.i)
Select State
Case #SERVICE_RUNNING
_WriteLog("RUNNING:" + Str(State))
Case #SERVICE_PAUSED
_WriteLog("PAUSED:" + Str(State))
EndSelect
EndProcedure
ServiceInit("ExampleService")
Executable erstellen und mit dem Parameter "-i" starten, um es als Dienst zu installieren - mit "-u" um es zu deinstallieren. Nicht laufen lassen - sonst wird die Logdatei irgendwann die Festplatte füllen...

.