Ich habe Code, der sowohl in Diensten als auch in VCL-Formanwendungen (Win32-Anwendungen) verwendet wird. Wie kann ich feststellen, ob die zugrunde liegende Anwendung als NT-Dienst oder als Anwendung ausgeführt wird?
Danke.
Ich habe Code, der sowohl in Diensten als auch in VCL-Formanwendungen (Win32-Anwendungen) verwendet wird. Wie kann ich feststellen, ob die zugrunde liegende Anwendung als NT-Dienst oder als Anwendung ausgeführt wird?
Danke.
ANFANG DER BEARBEITUNG
Da dies immer noch Aufmerksamkeit zu bekommen scheint, habe ich beschlossen, die Antwort mit fehlenden Informationen und neueren Windows-Patches zu aktualisieren. Auf jeden Fall sollte der Code nicht einfach kopiert und eingefügt werden. Der Code dient nur als Beispiel, wie die Dinge gemacht werden sollten.
ENDE DER BEARBEITUNG:
Sie können überprüfen, ob der übergeordnete Prozess der SCM (Service Control Manager) ist. Wenn Sie als Dienst ausgeführt werden, ist dies immer der Fall und niemals der Fall, wenn Sie als Standardanwendung ausgeführt werden. Außerdem denke ich, dass SCM immer die gleiche PID hat.
Sie können dies wie folgt überprüfen:
type
TAppType = (atUnknown, atDesktop, atService);
var
AppType: TAppType;
function InternalIsService: Boolean;
var
PL: TProcessList;
MyProcessId: DWORD;
MyProcess: PPROCESSENTRY32;
ParentProcess: PPROCESSENTRY32;
GrandParentProcess: PPROCESSENTRY32;
begin
Result := False;
PL := TProcessList.Create;
try
PL.CreateSnapshot;
MyProcessId := GetCurrentProcessId;
MyProcess := PL.FindProcess(MyProcessId);
if MyProcess <> nil then
begin
ParentProcess := PL.FindProcess(MyProcess^.th32ParentProcessID);
if ParentProcess <> nil then
begin
GrandParentProcess := PL.FindProcess(ParentProcess^.th32ParentProcessID);
if GrandParentProcess <> nil then
begin
Result := SameText(string(ParentProcess^.szExeFile), 'services.exe') and
(SameText(string(GrandParentProcess^.szExeFile), 'winlogon.exe') or
SameText(string(GrandParentProcess^.szExeFile), 'wininit.exe'));
end;
end;
end;
finally
PL.Free;
end;
end;
function IsService: Boolean;
begin
if AppType = atUnknown then
begin
try
if InternalIsService then
AppType := atService
else
AppType := atDesktop;
except
AppType := atService;
end;
end;
Result := AppType = atService;
end;
initialization
AppType := atUnknown;
Die TProcessList ist wie folgt implementiert (nochmals: THashTable ist nicht enthalten, aber eine beliebige Hashtabelle sollte geeignet sein):
type
TProcessEntryList = class(TList)
private
function Get(Index: Integer): PPROCESSENTRY32;
procedure Put(Index: Integer; const Value: PPROCESSENTRY32);
public
property Items[Index: Integer]: PPROCESSENTRY32 read Get write Put; default;
function Add(const Entry: TProcessEntry32): Integer; reintroduce;
procedure Clear; override;
end;
TProcessList = class
private
ProcessIdHashTable: THashTable;
ProcessEntryList: TProcessEntryList;
public
constructor Create; reintroduce;
destructor Destroy; override;
procedure CreateSnapshot;
function FindProcess(const ProcessId: DWORD): PPROCESSENTRY32;
end;
implementation
{ TProcessEntryList }
procedure TProcessEntryList.Clear;
var
i: Integer;
begin
i := 0;
while i < Count do
begin
FreeMem(Items[i]);
Inc(i);
end;
inherited;
end;
... (Rest of the translation remains the same) ...
Wie wäre es, GetCurrentProcessId
mit EnumServicesStatusEx
abzugleichen?
Der Parameter lpServices
zeigt auf einen Puffer, der ein Array von ENUM_SERVICE_STATUS_PROCESS
-Strukturen empfängt. Der Abgleich erfolgt anhand der aufgelisteten Dienstprozess-ID: ServiceStatusProcess.dwProcessId
in dieser Struktur.
Eine weitere Option ist die Verwendung von WMI
zur Abfrage von Win32_Service
-Instanzen, bei denen ProcessId=GetCurrentProcessId
.
Ich bezweifle das
System.IsConsole
System.IsLibrary
wird Ihnen die erwarteten Ergebnisse liefern.
Alles, woran ich denken kann, ist, ein Anwendungs-Objekt als TObject zu übergeben an die Methode, wo Sie diese Unterscheidung treffen müssen und prüfen, ob der Klassenname des übergebenen Objekts ist ein
TServiceApplication
oder
TApplication
Das gesagt, es sollte kein Bedarf für Sie bestehen zu wissen, ob Ihr Code in einem Dienst oder einer GUI läuft. Sie sollten wahrscheinlich Ihr Design überdenken und den Aufrufer dazu bringen, ein Objekt zu übergeben, um mit den Nachrichten umzugehen, die Sie zeigen möchten (oder nicht zeigen möchten). (Ich nehme an, es geht darum, Nachrichten/Ausnahmen anzuzeigen, die Sie wissen möchten).
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.