Newsgroups : Borland : borland.public.delphi.rtl.win32 : 2007 Aug : CreateProcess / Application not started to the foreground
| Subject: | CreateProcess / Application not started to the foreground |
| Posted by: | "Adrien Reboisson" (nospam@nospam.com) |
| Date: | Thu, 9 Aug 2007 09:49:14 |
Hi,
I'm trying to figure out WHY sometimes when I CreateProcess an
application, it's main window is not shown on foreground, but behind the
current maximized window.
Okay, I think it's related to the more complex way I use CreateProcess
here - but anyway, I don't understand why sometimes it works and
sometimes it does not work.
Say I've 3 applications :
- The first one is launched maximized ("application 1").
- The second one is launched without any GUI ("application 2"). It's a
kind of "proxy application", which receives requests from "application
1" through a named pipe. A typical request contains the name of the app
to run, the parameters and the local user which have to be impersonated,
if any. This application runs elevated and use
CreateProcess/CreateProcessWithLogonW according to the kind of the
request it receives.
- The third one is the application to run ("application 3"). Not much to
say about it. A regular Delphi Win 32 application.
So we have the following calling chain :
"Application 1" -- named pipe --> "Application 2" --
CreateProcess/CreateProcessWithLogonW --> " Application 3"
The first time "application 1" runs "application 3" through "application
2", all works just fine. Before executing various actions, a modal
dialog is displayed by App 2, and this dialog is displayed in front of
the maximized window belonging to App 1. Fine. Perfect.
But, the other times (why ?), the dialog shown by "application 2" is
displayed BEHIND "application 1". So, in short, the guy behind the
screen gets puzzled since he clicked on a button, and nothing happens.
He has to minimize the application to find the modal dialog in order to
validate it. Of course, the average user will never do that and will
just send to me a bug report : "hey, your application does nothing !"
So, do have you ever experienced this kind of problem ? I currently use
Delphi 2007 - I think the bug wasn't present with D7... I tried to use
MainFormOnTaskBar := True without any result. The hidden dialog is
displayed modaly, before calling Application.Run() in "application 3",
it may be linked with the way Delphi processes messages ? Anyway, it's
the same behaviour on XP and Vista.
There is the code I use to run the process in "application 2" :
function SetWinPos(Handle: HWND; LParam: Longint): Bool; stdcall;
begin
Result := SetWindowPos(Handle, HWND_TOP, 0,0,0,0, SWP_NOMOVE or
SWP_NOSIZE or
SWP_NOACTIVATE or SWP_SHOWWINDOW);
end;
class function TThRequestWrapper.InternalCreateProcess(
const AHandle: Cardinal;
const AAppPath, AAppParameters, AUser, APassword: string;
AEnableImpersonation: Boolean): Boolean;
var
wUsername, wDomain, wPassword, wApp, wParameters: WideString;
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
LUser, LDomain: string;
LSecurityAttributes: TSecurityAttributes;
PSecurityDescriptor: PSECURITY_DESCRIPTOR;
begin
PSecurityDescriptor := AllocMem(SECURITY_DESCRIPTOR_MIN_LENGTH);
InitializeSecurityDescriptor(PSecurityDescriptor,
SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(PSecurityDescriptor, True, nil, False);
LSecurityAttributes.nLength := SizeOf(LSecurityAttributes);
LSecurityAttributes.lpSecurityDescriptor := PSecurityDescriptor;
LSecurityAttributes.bInheritHandle := True;
FillChar(StartupInfo, SizeOf(StartupInfo), 0);
StartupInfo.cb := SizeOf(StartupInfo);
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow := SW_SHOW;
try
if not GetCurrentUserAndDomain(LUser, LDomain) then
AEnableImpersonation := False;
if (AEnableImpersonation) and (not ((SameText(LUser, AUser)))) then
begin
wUsername := AUser;
wDomain := '.';
wPassword := APassword;
wApp := AAppPath;
wParameters := AAppParameters;
Result := CreateProcessWithLogonW(pwidechar(wUsername),
pwidechar(wDomain),
pwidechar(wPassword),
LOGON_WITH_PROFILE,
pwidechar(wApp),
pwidechar(wParameters),
CREATE_DEFAULT_ERROR_MODE,
nil,
nil,
StartupInfo,
ProcessInfo);
end else
begin
Result := CreateProcess(PChar(AAppPath),
PChar(AAppParameters),
@LSecurityAttributes,
nil,
True,
NORMAL_PRIORITY_CLASS,
nil,
nil,
StartupInfo,
ProcessInfo
);
end;
if not Result then
MessageBox(AHandle, PChar(Format(strCannotStartTask,
[SysErrorMessage(GetLastError())])), nil,
MB_ICONERROR)
else
begin
WaitForInputIdle(ProcessInfo.hProcess, 15000); { Wait
initialization }
EnumThreadWindows(Processinfo.dwThreadid, @SetWinPos, 0); { Make
app foreground -- useful hack ??? }
while WaitForSingleObject(ProcessInfo.hProcess, 500) =
WAIT_TIMEOUT do;
CloseHandle(ProcessInfo.hProcess);
CloseHandle(ProcessInfo.hThread);
end;
finally
FreeMem(PSecurityDescriptor);
end
end;
Any hint greatly appreciated.
Best regards,
A.R.