delphi - unelevated program starts an elevated updater, updater should wait for finishing of program -
i have 2 apps, program.exe , updater.exe, both written in delphi5. program runs without admin-rights (and without manifest), updater has manifest "requireadministrator" because must able write @ program-folder update program.exe.
the problem launch updater , let him wait until program closed. i've found different ways @ web, none works (in cases 1st app starts 2nd app , wait ending of 2nd app, in case 2nd app should wait ending of 1nd app).
updater should wait, thats easy
updater.exe
{$r manifest.res} label.caption:='wait program.exe closing'; repeat sleep(1000); until file not open programhandle := read handle file waitforsingleobject(programhandle,infinite); label.caption:='program.exe closed'; updates
way 1
starting updater createprocess:
program.exe
fillchar(siinfo, sizeof(siinfo), 0); siinfo.cb := sizeof(siinfo); saprocessattributes.nlength := sizeof(saprocessattributes); saprocessattributes.lpsecuritydescriptor := nil; saprocessattributes.binherithandle := true; sathreadattributes.nlength := sizeof(sathreadattributes); sathreadattributes.lpsecuritydescriptor := nil; sathreadattributes.binherithandle := true; if createprocess(nil, pchar('updater.exe'), @saprocessattributes, @sathreadattributes, true, normal_priority_class, nil, pchar(extractfilepath(application.exename)), siinfo, piinfo) begin duplicatehandle(getcurrentprocess, getcurrentprocess, piinfo.hprocess, @myhandle, process_query_information, true, duplicate_same_access) write myhandle in file end; close program
doesn't anything, works when updater has no manifest requireadministrator into. if run program explizit admin-rights, works too.
way 2 starting updater shellexecuteex:
program.exe
fillchar(info, sizeof(info), chr(0)); info.cbsize := sizeof(info); info.fmask := see_mask_nocloseprocess; info.lpverb := pchar('runas'); info.lpfile := pchar('update.exe'); info.lpdirectory := nil; info.nshow := sw_restore; shellexecuteex(@info); myhandle:=openprocess(process_all_access, false, getcurrentprocessid()))); write myhandle in file close program
doesnt' work, myhandle has different value each time run procedure (without restarting program), updater can't work it.
so have no idea how start updater.exe , write handle of program.exe in file.
im not familiar these parts of programing ... has idea proplem?
your code not working because handle table per process, means second process have same handle pointing kernel object. below, there 1 of many possible solutions:
when creating process 2, pass pid of process 1 parameter:
procedure createupdater; var info: tshellexecuteinfo; begin fillchar(info, sizeof(tshellexecuteinfo), 0); info.cbsize := sizeof(tshellexecuteinfo); info.fmask := see_mask_nocloseprocess; info.lpverb := pchar('runas'); info.lpfile := pchar('update.exe'); info.lpparameters := pchar(inttostr(getcurrentprocessid)); info.lpdirectory := nil; info.nshow := sw_restore; shellexecuteex(@info); //note: missing error checking! end;
inside updater, wait process1 terminate:
procedure waitforandclose; var pid: string; ahandle: cardinal; ret: longbool; exitnumber: dword; begin pid:= paramstr(1); if pid <> '' begin ahandle:= openprocess(process_query_information, false, strtoint(pid)); //note: missing error checking! try repeat ret:= getexitcodeprocess(ahandle, exitnumber); //note: missing error checking! sleep(1000); //define time poolling until (exitnumber <> still_active); closehandle(ahandle); end; //terminate process; application.terminate; end; end;
you can use waitforsingleobject
avoid polling:
waitforsingleobject(ahandle, infinite); //note: missing error checking!
but need synchronize access open process:
ahandle:= openprocess(synchronize, false, strtoint(pid)); //note: missing error checking!
note: there no error checking here. should read docs , check errors.
note 2: i attention fact leaking handle. when use see_mask_nocloseprocess
caller responsible close handle of calee. in case think don't need mask @ all. remove it.
Comments
Post a Comment