Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

ShellExecuteEx

Posted on 2002-05-20
7
316 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
Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 

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

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
This video shows how to use Hyena, from SystemTools Software, to bulk import 100 user accounts from an external text file. View in 1080p for best video quality.
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

828 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