![]() |
Delphi und Serviceanwendungen, demo?
Hallo Zusammen...
Hat jemand ein working demo um einen Service-Anwendung zu starten, stoppen und zu beenden. Nicht mit NET START... Sondern per Token die Adminrechte holen und dann WinSVC? Ich habe vor Jahren - da gab es noch keinen TeamViewer - "so etwas" als Service programmiert. Das hat jedoch alles auf JEDI-Zeugs aufgebaut, was ich in der neuen Anwendungen nicht verwenden möchte... Vielleicht hat ja jemand so ein codeschnipsel... Vorab Danke Mavarik :coder: |
AW: Delphi und Serviceanwendungen, demo?
Von Luckie und CalganX stammt da ein Post mit
![]() |
AW: Delphi und Serviceanwendungen, demo?
Zitat:
Und dann könntest du einfach ganz normal Quelltext wie diesen nutzen, um den Dienst zu starten oder zu stoppen: ![]() Auch wenn es deiner Anforderung nicht entspricht (benutzt net start, weil wie erwähnt die OOP-COM-Variante wieder ausgebaut ist) verlinke ich trotzdem mal ein Beispiel wie wir bei uns Dienste gestalten: ![]() Diese kann man normal als Anwendung starten und bekommt dann eine GUI zum Installieren, Starten usw., natürlich mit Statusprüfung über die API. An den Stellen, wo wir extern net.exe benutzen kann natürlich auch einfach der verlinkte Quelltext eingesetzt werden. |
AW: Delphi und Serviceanwendungen, demo?
Hmm..
hab hier ne Unit (weiß nicht mehr woher), jedoch ist die mit Delphi6 erstellt und würde wohl Überarbeitungen im Bezug auf PChar benötigen ;) Für die benötigten Admin-Rechte musst Du jedoch selber schauen ;) Ich verwende Sie zum Auflisten/Starten/Stoppen von Diensten...
Delphi-Quellcode:
unit UStartStopService;
interface uses Windows, Classes, SysUtils; function ServiceGetStatus(sMachine, sService : string ) : DWord; function ServiceStart(sMachine, sService : string ) : boolean; function ServiceStop(sMachine, sService : string ) : boolean; function ServiceRunning(sMachine, sService : string ) : boolean; { // "alerter" service on \ComputerName was started take appropriate action here if( ServiceStart('\ComputerName','alerter' ) )then begin end; // stop "alerter" service running on the local computer if( ServiceStop('','alerter' ) )then begin end; } function ServiceGetList(sMachine : string; dwServiceType, dwServiceState : DWord; slServicesList : TStrings ): boolean; { To get a list of all Windows services into a listbox named ListBox1: ServiceGetList( '', SERVICE_WIN32, SERVICE_STATE_ALL, ListBox1.Items ); } const // Service Types SERVICE_KERNEL_DRIVER = $00000001; SERVICE_FILE_SYSTEM_DRIVER = $00000002; SERVICE_ADAPTER = $00000004; SERVICE_RECOGNIZER_DRIVER = $00000008; SERVICE_DRIVER = (SERVICE_KERNEL_DRIVER or SERVICE_FILE_SYSTEM_DRIVER or SERVICE_RECOGNIZER_DRIVER); SERVICE_WIN32_OWN_PROCESS = $00000010; SERVICE_WIN32_SHARE_PROCESS = $00000020; SERVICE_WIN32 = (SERVICE_WIN32_OWN_PROCESS or SERVICE_WIN32_SHARE_PROCESS); SERVICE_INTERACTIVE_PROCESS = $00000100; SERVICE_TYPE_ALL = (SERVICE_WIN32 or SERVICE_ADAPTER or SERVICE_DRIVER or SERVICE_INTERACTIVE_PROCESS); implementation uses WinSvc; //------------------------------------- // get service status // return status code if successful // 0 if not // // return codes: // SERVICE_STOPPED // SERVICE_RUNNING // SERVICE_PAUSED // // following return codes // are used to indicate that // the service is in the // middle of getting to one // of the above states: // SERVICE_START_PENDING // SERVICE_STOP_PENDING // SERVICE_CONTINUE_PENDING // SERVICE_PAUSE_PENDING // // sMachine: // machine name, ie: \SERVER // empty = local machine // // sService // service name, ie: Alerter function ServiceGetStatus(sMachine, sService : string ) : DWord; var schm, // service control manager handle schs : SC_Handle; // service handle ss : TServiceStatus; // service status dwStat : DWord; // current service status begin dwStat := 0; // connect to the service control manager schm := OpenSCManager( PChar(sMachine), Nil, SC_MANAGER_CONNECT); // if successful... if(schm > 0)then begin // open a handle to the specified service schs := OpenService( schm, PChar(sService), SERVICE_QUERY_STATUS); // we want to query service status // if successful... if(schs > 0)then begin // retrieve the current status of the specified service if(QueryServiceStatus( schs, ss))then begin dwStat := ss.dwCurrentState; end; CloseServiceHandle(schs); // close service handle end; CloseServiceHandle(schm); // close service control manager handle end; Result := dwStat; end; // start service // return TRUE if successful // sMachine: // machine name, ie: \SERVER // empty = local machine // sService // service name, ie: Alerter function ServiceStart(sMachine, sService : string ) : boolean; var schm, // service control manager handle schs : SC_Handle; // service handle ss : TServiceStatus; // service status psTemp : PChar; // temp char pointer dwChkP : DWord; // check point begin ss.dwCurrentState := 0; // connect to the service control manager schm := OpenSCManager( PChar(sMachine), Nil, SC_MANAGER_CONNECT); // if successful... if(schm > 0)then begin // open a handle to the specified service schs := OpenService( schm, PChar(sService), SERVICE_START or // we want to start the service and SERVICE_QUERY_STATUS); // query service status // if successful... if(schs > 0)then begin psTemp := Nil; if(StartService( schs, 0, psTemp))then begin // check status if(QueryServiceStatus( schs, ss))then begin while(SERVICE_RUNNING <> ss.dwCurrentState)do begin // dwCheckPoint contains a value that the service // increments periodically to report its progress // during a lengthy operation. dwChkP := ss.dwCheckPoint; // save current value // wait a bit before checking status again // dwWaitHint is the estimated amount of time // the calling program should wait before calling // QueryServiceStatus() again // idle events should be handled here... Sleep(ss.dwWaitHint); if(not QueryServiceStatus( schs, ss))then begin break; // couldn't check status break from the loop end; if(ss.dwCheckPoint < dwChkP)then begin // QueryServiceStatus didn't increment // dwCheckPoint as it should have. // avoid an infinite loop by breaking break; end; end; end; end; CloseServiceHandle(schs); // close service handle end; // close service control manager handle CloseServiceHandle(schm); end; // return TRUE if the service status is running Result := SERVICE_RUNNING = ss.dwCurrentState; end; // stop service // // return TRUE if successful // // sMachine: // machine name, ie: \SERVER // empty = local machine // // sService // service name, ie: Alerter // function ServiceStop(sMachine, sService : string ) : boolean; var schm, // service control manager handle schs : SC_Handle; // service handle ss : TServiceStatus; // service status dwChkP : DWord; // check point begin // connect to the service control manager schm := OpenSCManager(PChar(sMachine), Nil, SC_MANAGER_CONNECT); // if successful... if(schm > 0)then begin // open a handle to the specified service schs := OpenService( schm, PChar(sService), SERVICE_STOP or // we want to stop the service and SERVICE_QUERY_STATUS);// query service status // if successful... if(schs > 0)then begin if(ControlService( schs, SERVICE_CONTROL_STOP, ss))then begin // check status if(QueryServiceStatus( schs, ss))then begin while(SERVICE_STOPPED <> ss.dwCurrentState)do begin // dwCheckPoint contains a value that the service // increments periodically to report its progress // during a lengthy operation. // save current value dwChkP := ss.dwCheckPoint; // wait a bit before checking status again // dwWaitHint is the estimated amount of time // the calling program should wait before calling // QueryServiceStatus() again // idle events should be handled here... Sleep(ss.dwWaitHint); if(not QueryServiceStatus( schs, ss))then begin break; // couldn't check status break from the loop end; if(ss.dwCheckPoint < dwChkP)then begin // QueryServiceStatus didn't increment // dwCheckPoint as it should have. // avoid an infinite loop by breaking break; end; end; end; end; CloseServiceHandle(schs); // close service handle end; CloseServiceHandle(schm); // close service control manager handle end; // return TRUE if the service status is stopped Result := SERVICE_STOPPED = ss.dwCurrentState; end; function ServiceRunning(sMachine, sService : string ) : boolean; begin result := ServiceGetStatus(sMachine, sService) = SERVICE_RUNNING; end; // Get a list of services // return TRUE if successful // sMachine: // machine name, ie: \SERVER // empty = local machine // dwServiceType // SERVICE_WIN32, // SERVICE_DRIVER or // SERVICE_TYPE_ALL // dwServiceState // SERVICE_ACTIVE, // SERVICE_INACTIVE or // SERVICE_STATE_ALL // slServicesList // TStrings variable to storage function ServiceGetList(sMachine : string; dwServiceType, dwServiceState : DWord; slServicesList : TStrings ): boolean; const // assume that the total number of services is less than 4096. // increase if necessary cnMaxServices = 4096; type TSvcA = array[0..cnMaxServices] of TEnumServiceStatus; PSvcA = ^TSvcA; var j : integer; schm : SC_Handle; // service control manager handle nBytesNeeded, // bytes needed for the next buffer, if any nServices, // number of services nResumeHandle : DWord; // pointer to the next unread service entry ssa : PSvcA; // service status array begin Result := false; slServicesList.Clear; // connect to the service control manager schm := OpenSCManager(PChar(sMachine), Nil, SC_MANAGER_ALL_ACCESS); // if successful... if(schm > 0)then begin nResumeHandle := 0; New(ssa); EnumServicesStatus( schm, dwServiceType, dwServiceState, ssa^[0], SizeOf(ssa^), nBytesNeeded, nServices, nResumeHandle ); // assume that our initial array was large enough to hold all // entries. add code to enumerate if necessary. for j := 0 to nServices-1 do begin slServicesList.Add( StrPas(ssa^[j].lpServiceName ) + '=' + StrPas(ssa^[j].lpDisplayName ) ); end; Result := true; Dispose(ssa); CloseServiceHandle(schm); // close service control manager handle end; end; end. |
AW: Delphi und Serviceanwendungen, demo?
Liste der Anhänge anzeigen (Anzahl: 1)
Der Code über mir sieht auf den ersten Blick bezüglich Unicode nicht schlecht aus.
Gut, die Fehlerbehandlung lässt manchmal etwas zu Wünschen über, falls es einen nicht nur interessiert ob etwas nicht ging, sondern auch warum es nicht ging. ---- Nja, der Code selbst läuft mit Unicode und könnte sich wohl auch im ANSI heimisch fühlen, aber da einige Typen generisch deklariert sind, ist es erstmal etwas egal. (TArray<> und Co. könnte man aber notfalls rauswerfen). Für Start/Stop muß der Entwickler selber für die nötigen Rechte sorgen. (noch) Das Ganze ist eine Pascal-OOP-Kapselung, also also in einer Klasse verpackt, zuzüglich globale Klasse mit Grundfunktionen, alles mit String statt PChar, ENUMs statt Konstanten und Eyceptions statt Errorcodes. Und ich hatte da ein bissl mit DocInsight/HelpInsight und Attributen für die Dokumentation rumgespielt. [edit]nee, fehlte noch, aber es sollte selbsterklärend sein und alle Konstanten wurden noch nicht übersetzt[/edit] > siehe h5u.WinAPI.pas Und in die Basis-Units besser nicht so genau reingucken. Musste mal schnell bissl was rauswerfen, damit es kompiliert. |
AW: Delphi und Serviceanwendungen, demo?
![]() Hatte auf der Basis mal was gemacht, wenn es das ist was du suchst. |
AW: Delphi und Serviceanwendungen, demo?
Zitat:
Der Trick mit dem sich doppelt selbst startenden Programmen um Admin-Rechte zu bekommen, funktioniert leider in diesem Fall nicht, trotzdem Danke! Mavarik |
AW: Delphi und Serviceanwendungen, demo?
Out-Of-Process ... neuer Prozess mit höheren Rechten ... komplett abgetrennt.
In-Process, da stellt man die Rechte für einen Thread um (genauso kann man auch den "Desktop" für einen Thread ändern, um z.B. auf die UAC-Fenster zugreifen zu können), aber da haben dann die anderen Threads Zugriff auf den gemeinsamen Speicher/Programmcode. Auch Threads von Fremd-Code aus DLLs, die dir jemand wie Maustreiber, TeamViewer oder weniger Böswillige in deinen Process gehookt haben. Wenn dein Programm aber nicht das Recht zum Ändern der Rechte besitzt, dann funktioniert das nicht. (vor allem in Firmenumgebungen ist da oftmls sehr viel eingeschränkt) |
AW: Delphi und Serviceanwendungen, demo?
Zitat:
Vielleicht finde ich in den Tiefen meiner Delphi-Sourcen noch die richtige procedure... |
AW: Delphi und Serviceanwendungen, demo?
Du kannst auch dein Programm nochmals mit Adminrechten starten und via Parameter nur die gewünschte Aktion ausführen.
Der Witz: EXE und DLL sind praktisch das Gleiche (abgesehn von der Startprozedur). Ich hatte auch mal ein Programm, das sich selber oder von Fremden als DLL geladen werden konnte. > Ein Programm kann nicht nur Einwas machen. Windows kann sogar in einer EXE mehrere Services laufen lassen. Nur die TService-Implementierung von Delphi kann das nicht. Man kann nativ nichtmal die selbe EXE/Service mehrmals in einem System starten (Startparameter/Registrierung überschreiben und beim Start manuell drauf reagieren) - eine EXE mehrmals mit unterschiedlichem Namen starten - oder mehrere Services aus einer EXE in unterschiedlichen Prozessen starten - oder mehrere Services innerhalb eines Prozesses starten |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:31 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz