AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Externes Programm mit ShellExecuteEx starten
Thema durchsuchen
Ansicht
Themen-Optionen

Externes Programm mit ShellExecuteEx starten

Ein Thema von schwa226 · begonnen am 7. Nov 2008 · letzter Beitrag vom 22. Jan 2009
Antwort Antwort
Seite 2 von 2     12   
schwa226

Registriert seit: 4. Apr 2008
400 Beiträge
 
#11

Re: Externes Programm mit ShellExecuteEx starten

  Alt 11. Nov 2008, 19:33
Delphi-Quellcode:

type

      PJobObjectBasicProcessIDList = ^TJobObjectBasicProcessIDList;
      TJobObjectBasicProcessIDList = Record
          NumberOfAssignedProcesses : DWORD;
          NumberOfProcessIdsInList : DWORD;
          ProcessIdList : Array[0..0] of ULONG;
      End;

const
  {$IFDEF UNICODE}
  AWSuffix = 'W';
  {$ELSE}
  AWSuffix = 'A';
  {$ENDIF UNICODE}

const

  JOB_OBJECT_ASSIGN_PROCESS = $0001;
  {$EXTERNALSYM JOB_OBJECT_ASSIGN_PROCESS}
  JOB_OBJECT_SET_ATTRIBUTES = $0002;
  {$EXTERNALSYM JOB_OBJECT_SET_ATTRIBUTES}
  JOB_OBJECT_QUERY = $0004;
  {$EXTERNALSYM JOB_OBJECT_QUERY}
  JOB_OBJECT_TERMINATE = $0008;
  {$EXTERNALSYM JOB_OBJECT_TERMINATE}
  JOB_OBJECT_SET_SECURITY_ATTRIBUTES = $0010;
  {$EXTERNALSYM JOB_OBJECT_SET_SECURITY_ATTRIBUTES}
  JOB_OBJECT_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED or SYNCHRONIZE or $1F ;
  {$EXTERNALSYM JOB_OBJECT_ALL_ACCESS}

//
// Extended Limits
//

  JOB_OBJECT_LIMIT_PROCESS_MEMORY = $00000100;
  {$EXTERNALSYM JOB_OBJECT_LIMIT_PROCESS_MEMORY}
  JOB_OBJECT_LIMIT_JOB_MEMORY = $00000200;
  {$EXTERNALSYM JOB_OBJECT_LIMIT_JOB_MEMORY}
  JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION = $00000400;
  {$EXTERNALSYM JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION}
  JOB_OBJECT_LIMIT_BREAKAWAY_OK = $00000800;
  {$EXTERNALSYM JOB_OBJECT_LIMIT_BREAKAWAY_OK}
  JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK = $00001000;
  {$EXTERNALSYM JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK}
  JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = $00002000;
  {$EXTERNALSYM JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE}

const

function CreateJobObjectA(lpJobAttributes: PSecurityAttributes; lpName: LPCSTR): THANDLE; stdcall;
{$EXTERNALSYM CreateJobObjectA}
function CreateJobObjectW(lpJobAttributes: PSecurityAttributes; lpName: LPCWSTR): THANDLE; stdcall;
{$EXTERNALSYM CreateJobObjectW}
function CreateJobObject(lpJobAttributes: PSecurityAttributes; lpName: LPCTSTR): THANDLE; stdcall;
{$EXTERNALSYM CreateJobObject}

function OpenJobObjectA(dwDesiredAccess: DWORD; bInheritHandle: BOOL; lpName: LPCSTR): THANDLE; stdcall;
{$EXTERNALSYM OpenJobObjectA}
function OpenJobObjectW(dwDesiredAccess: DWORD; bInheritHandle: BOOL; lpName: LPCWSTR): THANDLE; stdcall;
{$EXTERNALSYM OpenJobObjectW}
function OpenJobObject(dwDesiredAccess: DWORD; bInheritHandle: BOOL; lpName: LPCTSTR): THANDLE; stdcall;
{$EXTERNALSYM OpenJobObject}

function AssignProcessToJobObject(hJob, hProcess: THANDLE): BOOL; stdcall;
{$EXTERNALSYM AssignProcessToJobObject}

function TerminateJobObject(hJob: THANDLE; uExitCode: UINT): BOOL; stdcall;
{$EXTERNALSYM TerminateJobObject}

function IsProcessInJob(ProcessHandle, JobHandle: THANDLE; var Result_: BOOL): BOOL; stdcall;
{$EXTERNALSYM IsProcessInJob}

Function QueryInformationJobObject(hJob : THandle;
                        JobObjectInformationClass : TJobObjectInfoClass;
                        lpJobObjectInformation : Pointer;
                        cbJobObjectInformationLength : DWORD;
                        lpReturnLength : PDWORD) : Bool; StdCall;
                        External Kernel32 Name 'QueryInformationJobObject';

function CreateJobObjectA; external kernel32 name 'CreateJobObjectA';
function CreateJobObjectW; external kernel32 name 'CreateJobObjectW';
function CreateJobObject; external kernel32 name 'CreateJobObject' + AWSuffix;
function OpenJobObjectA; external kernel32 name 'OpenJobObjectA';
function OpenJobObjectW; external kernel32 name 'OpenJobObjectW';
function OpenJobObject; external kernel32 name 'OpenJobObject' + AWSuffix;
function AssignProcessToJobObject; external kernel32 name 'AssignProcessToJobObject';
function TerminateJobObject; external kernel32 name 'TerminateJobObject';
function IsProcessInJob; external kernel32 name 'IsProcessInJob';
  Mit Zitat antworten Zitat
nat

Registriert seit: 10. Nov 2005
216 Beiträge
 
RAD-Studio 2009 Pro
 
#12

Re: Externes Programm mit ShellExecuteEx starten

  Alt 12. Nov 2008, 01:23
also ich habe jetzt ma die o.g. vorgehensweise von Apollonius ausprobiert.
was ich (testweise) wollte ist eine datei mit dem windows öffnen-mit dialog öffnen
(rundll32.exe shell32.dll,OpenAs_RunDLL blabla.txt). der user wählt dann
ein programm aus (zum test notepad), bearbeitet die datei, und wenn das
programm beendet wird lädt mein programm die datei neu. da ich nich an irgendein
handle des vom user ausgewählten/gestarteten progamm komme, ich aber auf das ende
dieses programms warten möchte, habe ich das, wie oben in diesem thread beschrieben,
mit einem JobObject und einem IoCompletionPort gemacht.
klappt eigentlich auch ganz gut, bis auf eine kleinigkeit:

wie gesagt, zum test habe ich meien textdatei mit notepad geöffnet (über den öffnen-mit dialog).
in notepad habe ich dann über den öffnen-dialog eine andere datei geöffnet
(rechtsklick auf eine datei und dann z.B. senden an o.ä.). dies erzeugt dann einen
weiteren prozess der (logischerweise) dann ja auch zu dem jobobject gehört.
soweit ist ja auch alles ok.
wenn ich nun aber notepad schliesse, ist in dem job ja immer noch ein aktiver
prozess (das programm das über den öffnen dialog gestartet wurde).
der prozess (notepad) auf den ich warten wollte ist aber ja schon beendet.
von daher könnte mein programm ja nun "aufwachen" und mit seiner arbeit weiter
machen (textdatei neu laden). dies passiert nun aber erst, wenn der andere prozess auch
beendet wird (da ich auf ActiveProcesses = 0 teste).
kann ich nich irgendwie nur auf einen bestimmten prozess in dem jobobject warten
(den ich natürlich nachträglich erst auslesen muß, sprich nachdem der öffnen-mit
dialog das programm gestartet hat)?

ich hoffe ihr versteht was ich meine

edit:
ich habe es nun doch noch selber hingekommen (man muss nur ma in ruhe sdks lesen *g*).
wen es interessiert wie ichs gemacht hab:
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var
  Filename: String;
  pi: windows.TProcessInformation;
  hJob, hProc: THandle;
  aExitCode: Cardinal;
  InfoBasic: TJobObjectBasicAccountingInformation;
  InfoPIDs: TJobObjectBasicProcessIdList;
  Len: Cardinal;
  count: integer;
  PID: Cardinal;
begin
  Filename := IncludeTrailingPathDelimiter(ExtractFilePath(Paramstr(0)))+'text.txt';
  Memo1.Lines.SaveToFile(Filename);

  if not RunProcess('rundll32.exe shell32.dll,OpenAs_RunDLL ' + Filename, SW_SHOW, pi) then
    raise Exception.CreateFmt('"%s" konnte nicht gestartet werden', [Filename]);

  try
    hJob := CreateJobObject(nil, nil);
    if not AssignProcessToJobObject(hJob, pi.hProcess) then
      raise Exception.Create(SysErrorMessage(GetLastError));

    WaitForSingleObject(pi.hProcess, INFINITE);

    count := 0;
    repeat
      Sleep(100);
      if not QueryInformationJobObject(hJob, JobObjectBasicAccountingInformation, @InfoBasic, sizeof(InfoBasic), @Len) then
        raise Exception.Create(SysErrorMessage(GetLastError));
      count := InfoBasic.ActiveProcesses;
    until count >= 1;


    if not QueryInformationJobObject(hJob, JobObjectBasicProcessIdList, @InfoPIDs, sizeof(InfoPIDs), @Len) then
      raise Exception.Create(SysErrorMessage(GetLastError));

    if InfoPIDs.NumberOfProcessIdsInList <= 0 then
      raise Exception.Create('Prozess nicht gefunden!');

    PID := InfoPIDs.ProcessIdList[0];
    hProc := OpenProcess(SYNCHRONIZE, false, PID);
    if hProc = 0 then
      raise Exception.Create('Kann Prozess nicht öffnen');

    try
      WaitForSingleObject(hProc, INFINITE);
      Memo1.Lines.LoadFromFile(Filename);
    finally
      CloseHandle(hProc);
    end;
  finally
    CleanUpHandles(pi);
    CloseHandle(hJob);
  end;
end;
der code ist nicht grade optimiert. wie gesagt, ist nur zum test gewesen.
wenn ich was falsch gemacht hab oder es anders besser geht bin ich
aber für kritik offen!
soweit ich das sehen kann geht das in diesem fall hier so ganz gut.
das ganze muß man dann vll nur ma in n thread packen damit die
anwendung nicht "einfriert".
  Mit Zitat antworten Zitat
schwa226

Registriert seit: 4. Apr 2008
400 Beiträge
 
#13

Re: Externes Programm mit ShellExecuteEx starten

  Alt 22. Jan 2009, 17:57
Habe jetzt dazu noch eine Frage!

Ich habe ja ein Programm, dass ich dem Job zuweise. Dieses Programm (start.exe) startet eine andere program.exe und beendet sich sofort wieder.

Im Job ist ersichtlich wenn alle Child Processe beendet wurden. Das funktioniert!

Nun möchte ich über die ThreadID aber das Handle von dem Fenster haben.

Ich bekomme bei CreateProcess ja die ThreadID, aber die "start.exe" beendet sich anscheinend so schnell wieder, dass ich über die ThreadID nichts herausbekomme.

Bei einem anderen Programm z.B. Notepad.exe funktoniert das ja ohne Probleme.

Kann ich irgendewie die ThreadIDs die in einem Job sind herausfinden? Oder die ThreadID die die start.exe erzeugt, wenn dieprogram.exe gestartet wird!?
  Mit Zitat antworten Zitat
Apollonius

Registriert seit: 16. Apr 2007
2.325 Beiträge
 
Turbo Delphi für Win32
 
#14

Re: Externes Programm mit ShellExecuteEx starten

  Alt 22. Jan 2009, 18:09
Du kannst dir mit QueryInformationJobObject die Prozess-IDs besorgen. Mit der ToolHlp-API kannst du dir dann alle Threads in einem Prozess ausgeben lassen.
Wer erweist der Welt einen Dienst und findet ein gutes Synonym für "Pointer"?
"An interface pointer is a pointer to a pointer. This pointer points to an array of pointers, each of which points to an interface function."
  Mit Zitat antworten Zitat
schwa226

Registriert seit: 4. Apr 2008
400 Beiträge
 
#15

Re: Externes Programm mit ShellExecuteEx starten

  Alt 22. Jan 2009, 18:37
Danke!

Habe es gerade probiert und es geht!

Nun bekomme ich eine ThreadID die richtig zu sein scheint!
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:38 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz