Reputation: 3056
Sometimes there is need to open new program (e.g. Windows Powerpoint presentation as slideshow can be opened by command line "powerpnt.exe /s
") from commandline, maximize this program and bring it in front of desktop as the first program the user can see and use. This happens by default if user directly enters command in the command prompt, because the command prompt is the active window.
But the question is - how to do this, if command line is executed from background process - e.g. from custom Windows service application of from the Windows Task Scehduler - in both cases the new windows is not brought as the first window.
At present I can imagine only quite hard solutions (whose drawback is that they required coding and they can not be used from Task Scheduler):
Maybe there is easier way?
Upvotes: 3
Views: 3709
Reputation: 10946
Create a batch file that opens the required program(s) and have the Task Scheduler run that.
The batch file will run as if a user entered the commands directly into the command prompt and you will get the desired result.
Upvotes: 0
Reputation: 2121
You can create a small (non-gui) launcher application that will call the new program for you (I know, that's what you've called the hard solution) and then schedule this launcher on the task scheduler.
This launcher application would have to create de process (CreateProcess function), and then get the Window Handle from the pID... with the window handle you can use SetForegroundWindow to do what you need, or call other functions for things like maximize, etc.
Since you tagged delphi, I'm posting a possible delphi implementation of that.
function WindowFromPID(pID: Cardinal; VisibleWindow: Boolean): Cardinal;
type
TProcData = record
pID: Cardinal;
pHandle: Cardinal;
VisibleWindow: Boolean;
end;
var
wPData: TProcData;
function EnumProc(Handle: HWND; var pProcData: TProcData): Bool; stdcall;
var pID: DWORD;
begin
Result := True;
if pProcData.VisibleWindow then
if not IsWindowVisible(Handle) then
Exit;
GetWindowThreadProcessId(Handle, @pID);
if pID = pProcData.pID then begin
if GetWindow(Handle, GW_OWNER) = 0 then begin
pProcData.pHandle := Handle;
Result := false;
end;
end;
end;
begin
wPData.pHandle := 0;
wPData.pID := pID;
wPData.VisibleWindow := VisibleWindow;
EnumWindows(@EnumProc, Integer(@wPData));
while (wPData.pHandle = 0) do begin
Sleep(50);
EnumWindows(@EnumProc, Integer(@wPData));
end;
Result := wPData.pHandle;
end;
procedure RunAndGetWindowHandle(const FileName, Params: String; const WindowState: Word): Cardinal;
var
SUInfo: TStartupInfo;
CmdLine: String;
ProcInfo: TProcessInformation
begin
CmdLine := '"' + Filename + '"' + Params;
FillChar(SUInfo, SizeOf(SUInfo), #0);
with SUInfo do begin
cb := SizeOf(SUInfo);
dwFlags := StartF_UseShowWindow;
wShowWindow := WindowState;
end;
if not CreateProcess(Nil, PChar(CmdLine), nil, nil, False, Create_New_Console Or Normal_Priority_Class, nil, PChar(ExtractFilePath(Filename)), SUInfo, ProcInfo) then
raise Exception.Create('Error running process');
if WaitForSingleObject(ProcInfo.hProcess, 50) <> WAIT_TIMEOUT then
raise Exception.Create('Error running process!');
CloseHandle(ProcInfo.hThread);
while Result = 0 do begin
Sleep(50);
Result := WindowFromPID(ProcInfo.dwProcessId, true);
end;
end;
...
var WindowHandle: Cardinal;
begin
WindowHandle := RunAndGetWindowHandle("powerpnt.exe", " /s", SW_SHOWNORMAL);
SetForegroundWindow(WindowHandle);
end;
Hope that's what you need.. sorry if it's not.
Best Regards.
Upvotes: 4