Solved

ShellExecuteEx

Posted on 2002-05-20
7
310 Views
Last Modified: 2010-04-04
hi Experts,

I start a windows application (let's say notepad) using ShellExecuteEx.

From here, I get hProcess.

Now, having that much, how can I make a call activate the application and bring it to front?

graga
0
Comment
Question by:graga
7 Comments
 
LVL 9

Accepted Solution

by:
ginsonic earned 50 total points
ID: 7023334
0
 
LVL 20

Expert Comment

by:Madshi
ID: 7023363
The problem is: How do you know which main window belongs to the given hProcess? That's almost impossible to know, since for enumerating windows and that stuff you need the process *ID*, not the handle. And there is no documented way to get the process ID from the handle.

So you should forget about ShellExecuteEx and instead use CreateProcess. This way you get the process ID and can then call EnumWindows or EnumThreadWindows to find out the main window of the process. If you want to start a document rather than an executable, use FindExecutable prior to calling CreateProcess.

Regards, Madshi.
0
 
LVL 2

Expert Comment

by:Tasomia
ID: 7023396
Hi,

Try this:

function WinExecAndWait32(FileName: string; Visibility: Integer): Integer;
var
  zAppName: array[0..512] of Char;
  zCurDir: array[0..255] of Char;
  WorkDir: string;
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
  r: DWORD;
begin
  StrPCopy(zAppName, FileName);
  GetDir(0, WorkDir);
  StrPCopy(zCurDir, WorkDir);
  FillChar(StartupInfo, SizeOf(StartupInfo), #0);
  StartupInfo.cb          := SizeOf(StartupInfo);
  StartupInfo.dwFlags     := STARTF_USESHOWWINDOW;
  StartupInfo.wShowWindow := Visibility;
  if not CreateProcess(nil,
    zAppName, // pointer to command line string
    nil, // pointer to process security attributes
    nil, // pointer to thread security attributes
    False, // handle inheritance flag
    CREATE_NEW_CONSOLE or // creation flags
    NORMAL_PRIORITY_CLASS,
    nil, //pointer to new environment block
    nil, // pointer to current directory name
    StartupInfo, // pointer to STARTUPINFO
    ProcessInfo) // pointer to PROCESS_INF
    then Result := -1
  else
  begin
    r := WaitForInputIdle(ProcessInfo.hProcess, 1000);
    while r <> 0 do
    begin
      if r = $FFFFFFFF then RaiseLastWin32Error;
      r := WaitForInputIdle(ProcessInfo.hProcess, 1000);
      Sleep(50);
    end;
    Result := ProcessInfo.dwThreadId;
    CloseHandle(ProcessInfo.hProcess);
    CloseHandle(ProcessInfo.hThread);
  end;
end; { WinExecAndWait32 }

function EnumProc(aWnd: HWND; var wnd: HWND): BOOL; stdcall;
begin
  Result := True;
  if (GetWindowLong(aWnd, GWL_HWNDPARENT) = 0) and
    (IsWindowVisible(aWnd) or IsIconic(aWnd)) then
  begin
    Result := False;
    wnd := aWnd;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  threadID: DWORD;
  wnd: HWND;
  buf: array [0..255] of char;
begin
  threadID := WinExecAndWait32('notepad.exe', SW_SHOWNORMAL);
  if threadID = -1 then
  begin
    ShowMessage('Error....');
    Exit;
  end;
  Sleep(100);
  wnd := 0;
  EnumThreadWindows(threadID, @EnumProc, Integer(@wnd));
  memo1.Clear;
  memo1.Lines.Add(Format('Found window, handle: %d', [wnd]));
  GetClassname(wnd, buf, SizeOf(buf));
  memo1.Lines.Add(Format('Classname is %s', [buf]));
  SendMessage(wnd, WM_GETTEXT, SizeOf(buf), Integer(@buf));
  memo1.Lines.Add(Format('Caption is %s', [buf]));
end;
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 

Expert Comment

by:hashirviqas
ID: 7025769
It is really quite simple.

Try this

uses ShellApi;
...
ShellExecute(Handle, 'open',
  'c:\Windows\notepad.exe', nil, nil, SW_SHOWNORMAL);


If you wanted to open a file with notepad, then use this instead;

ShellExecute(Handle,'open',
  'c:\windows\notepad.exe','c:\mytext.txt',
  nil, SW_SHOWNORMAL);

As a matter of fact you can open up a site with the default web browser too

ShellExecute(Handle, 'open',
  'http://www.dawn.com',nil,nil, SW_SHOWNORMAL);


or how about if you want to send an email message with default mail client on your win 32 box;

var em_subject, em_body, em_mail : string;
begin
 em_subject := 'This is my subject line';
 em_body := 'my Message body text goes here';

 em_mail := 'mailto:me@me.com?subject=' +
   em_subject + '&body=' + em_body ;

 ShellExecute(Handle,'open',
   PChar(em_mail), nil, nil, SW_SHOWNORMAL);
end;

Let me know if you have other questions... Hope these examples help



0
 

Author Comment

by:graga
ID: 7025790
Hi Experts,

I'm just going now through your suggestions. I'll explain the scenario further:

I have a small menu system that can execute a number of different programs, both DOS and Windows.

When I select a program from the menu, this program is started.

When I select a program that has already been started, I want to find the program and bring it to front, rather than starting a new instance of the program.

To maintain a list of programs I have started, I keep a list of process ID's in a simple TList holding:

ProcessList: TList;

PProcess: ^AProcess
AProcess = record
           MenuOption: string;
           ProcessID: DWORD
           end;

Now, when a menu item is selected, I loop through my ProcessList looking for MenuOption selected.
When it is not there, I start the program.
If found, I check if the process is still running.
If running, I want to bring it to front, otherwise I remove entry from list, start the process and add the process to the list again.

So, my question summarises what I want to do:
- Start application
- Get some information from started application that I can use to activate it
- Activate application using the above information.

I hope this clarifies the problem.

I will raise points for working example.

graga
0
 
LVL 1

Expert Comment

by:pnh73
ID: 9006100
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

Accept answer from ginsonic

Please leave any comments here within the next seven days.
 
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!
 
Paul (pnh73)
EE Cleanup Volunteer
0
 
LVL 1

Expert Comment

by:pnh73
ID: 9010326
Thankyou for your response

Paul (pnh73)
EE Cleanup Volunteer
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now