Solved

ShellExecute-Running app.

Posted on 1998-08-17
19
446 Views
Last Modified: 2010-04-04

I want to start an application from my Delphi app.To do that there are some API fucntions,(ShellExecute, ShellExecuteEx.)
the problem is that when I use the ShellExecuteEx, by using
WaitForSingleObject i can know that whether the launched app is terminated or not.(Because ShellExecuteEx give the handle of the application and a flag value which is SEE_MASKNOCLOSEPROCESS so that you can be informed when the app. is terminated).
  But ShellExecuteEx cannot be used in WINNT and my app must run on NT.
(In ShellExecute(which can be used on NT also.) there is no flag like SEE_MASKNOCLOSEPROCESS so you cannot call the WaitForSingleObject to understand the termination.)


Any help,

Later...
0
Comment
Question by:ms99y
[X]
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
  • 7
  • 4
  • 3
  • +4
19 Comments
 

Author Comment

by:ms99y
ID: 1336185

By the way, Does anybody know how to search the answers and questions in this site for a specific subject..

(There are lots of questions and given answers but how to search ???)

ms99y
Later
0
 
LVL 10

Expert Comment

by:viktornet
ID: 1336186
Hello ms99y...

Here is a funtion that will do it...
Function WinExecAndWait(Path : string; Visibility : word) : word;

var

  InstanceID : THandle;

  PathLen : integer;

begin

  { inplace conversion of a String to a PChar }

  PathLen := Length(Path);

  Move(Path[1],Path[0],PathLen);

  Path[PathLen] := #0;

  { Try to run the application }

  InstanceID := WinExec(@Path,Visibility);

  if InstanceID < 32 then { a value less than 32 indicates an Exec error }

     WinExecAndWait := InstanceID

  else

  begin

    Repeat

      Application.ProcessMessages;

    until Application.Terminated or (GetModuleUsage(InstanceID) = 0);

    WinExecAndWait := 32;

  end;

end;

Hope this is what you need
//Viktor Ivanov
0
 
LVL 3

Expert Comment

by:vladika
ID: 1336187
Try to use CreateProcess function
In the last parameter it return handles of process and primary thread

0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 10

Expert Comment

by:viktornet
ID: 1336188
Param :
  Visibility : SW_NORMAL, SW_HIDE, ........

Example call : WinExecAndWait('C:\Windows\desktop\cool.exe',SW_NORMAL);

You can remove the WinExec procedure ,and enter ShellExec instead. That would be better I think...

//Viktor Ivanov
0
 

Author Comment

by:ms99y
ID: 1336189

I will try your suggestions
  Thanx much

0
 

Author Comment

by:ms99y
ID: 1336190

I will try your suggestions
  Thanx much

0
 
LVL 10

Expert Comment

by:viktornet
ID: 1336191
If WinExec try to use ShellExec like this....
Don't forget to include the ShellAPI in the uses clause

Instead of having this line from the code I gave you before...
    InstanceID := WinExec(@Path,Visibility);
.use this one ....

InstanceID := ShellExec(0, 'open',PChar(Path),nil,nil, Visibility);

You can also have @Path instead of PChar(Path)... the way you prefer...
Hope this helps...

//Viktor Ivanov
0
 
LVL 10

Expert Comment

by:viktornet
ID: 1336192
I meant if WinExec doesn't work then try to use ShellExec

//Vik
0
 

Author Comment

by:ms99y
ID: 1336193
Hi Vect,


  In your code you make a call to GetModuleUsage WINAPI function wh,ch is obsolete and deleted. I will examine the CreateProcess  which  vladika suggested.


Later,
0
 
LVL 8

Expert Comment

by:ZifNab
ID: 1336194
ms99y,

Last 2 weeks, this Q'n is already answered several times :

PS. Don't use WinExec in 32bit programs! It's there for backworth compatability. Use CreateProcess instead!

Here is one of mine :

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;
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, ointer to STARTUPINFO }
    ProcessInfo) then Result := -1 { pointer to PROCESS_INF }
  else begin
    WaitforSingleObject(ProcessInfo.hProcess,INFINITE);
    GetExitCodeProcess(ProcessInfo.hProcess,Result);
  end;
end;

And here I refer to another, still open Q'n (although not really a Q'n, it's an answer on q'n which are frequently asked):

http://www.experts-exchange.com/topics/comp/lang/delphi/Q.10071798

About search : YES! It was needed! And NOW there IS a search engine, a small one, but heck it's good enough for now.
---> The home-page of E-E has now a search capability.

Regards, Zif.
0
 
LVL 4

Expert Comment

by:erajoj
ID: 1336195
What the ... are you talking about? :-)
ShellExecuteEx works in NT! (just tested it)

See Q.10071798 for an implementation.

/// John
0
 
LVL 8

Expert Comment

by:ZifNab
ID: 1336196
erajoj,

what the ... am I talking about :

1. They were talking of WinExec
2. Then about CreateProcess
3. My comment : gave example of Createprocess
                AND refered to your question-example : see comment! for ShellExecute
4. Think all is said.

Zif.
0
 
LVL 4

Expert Comment

by:erajoj
ID: 1336197
Hi Zif,
Not talking to you, talking to ms99y.
Don't believe everything the helpfiles say...

/// John
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1336198
erajoj,

my helpfile says, ShellExecuteEx DOES RUN with WinNT. Your helpfile must be an old version...    :-)

Madshi.
0
 

Author Comment

by:ms99y
ID: 1336199
Hi erajoj,

  In my help file it is saying that ShellExecuteEx does not run on NT. (But anyway I can make test..)

To Zif,
  I will try your code and Thanx.
0
 

Author Comment

by:ms99y
ID: 1336200
Hi erajoj,

  In my help file it is saying that ShellExecuteEx does not run on NT. (But anyway I can make test..)

To Zif,
  I will try your code and Thanx.
0
 

Author Comment

by:ms99y
ID: 1336201
Hi, Viktor instead of using WinExec it seems that using CreateProcess is more logical way.

Zif ,
thanks for your help, please send your comment as an answer

Later
0
 
LVL 1

Expert Comment

by:nrobin
ID: 1336202
procedure TForm1.Run (const Name: string);
var
      si   :TStartupInfo;
      pif  :TProcessInformation;
      ecp  :DWORD;
      Running:boolean;
      Path: Array [0..255] of char;
      ErrorCode: Integer;

begin
       FbWECreated := FALSE;
       SetCurrentDir (ExtractFilePath (name));

       ZeroMemory (@si, sizeof (TStartupInfo));
       si.cb := sizeof (TStartupInfo);
       si.lpTitle := StrAlloc (100);
       StrPCopy (si.lpTitle, 'Compiling the ' + eProject.Text + ' project...');
       si.dwFlags := STARTF_USESHOWWINDOW;
       si.wShowWindow := SW_MAXIMIZE;

       if CreateProcess (nil, PChar (Name), nil, nil, FALSE, NORMAL_PRIORITY_CLASS, nil, nil, si, pif) then
   begin
             RE.Lines.Add ('');
             RE.Lines.Add ('Executing compiler...');

     WaitForInputIdle (THandle (pif.hProcess), 10000);
     Running := TRUE;

      while Running do
      begin
        Application.ProcessMessages;
        GetExitCodeProcess (THandle (pif.hProcess), ecp);
        if ecp <> STILL_ACTIVE then
                              Running := false;

        Sleep (250);
                  end;

      if cbExecuteOutput.Checked then
      begin
        StrPCopy (path, eOutputFile.Text);
        ErrorCode := ShellExecute(Application.Handle, 'open', Path, '', '', SW_SHOW);
                  end;
                  LoadFile (TRUE);
             end
   else
end;

0
 
LVL 8

Accepted Solution

by:
ZifNab earned 90 total points
ID: 1336203

Hi ms99y,

Glad it work for you!

PS. Don't use WinExec in 32bit programs! It's there for backworth compatability. Use CreateProcess instead!

       Here is one of mine :

       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;
       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, ointer to STARTUPINFO }
           ProcessInfo) then Result := -1 { pointer to PROCESS_INF }
         else begin
           WaitforSingleObject(ProcessInfo.hProcess,INFINITE);
           GetExitCodeProcess(ProcessInfo.hProcess,Result);
         end;
       end;

       And here I refer to another, still open Q'n (although not really a Q'n, it's an answer on q'n which are frequently asked):

       http://www.experts-exchange.com/topics/comp/lang/delphi/Q.10071798

       About search : YES! It was needed! And NOW there IS a search engine, a small one, but heck it's good enough for now.
       ---> The home-page of E-E has now a search capability.

Regards, Zif.

Have fun.
0

Featured Post

On Demand Webinar - Networking for the Cloud Era

This webinar discusses:
-Common barriers companies experience when moving to the cloud
-How SD-WAN changes the way we look at networks
-Best practices customers should employ moving forward with cloud migration
-What happens behind the scenes of SteelConnect’s one-click button

Question has a verified solution.

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

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
I've attached the XLSM Excel spreadsheet I used in the video and also text files containing the macros used below. https://filedb.experts-exchange.com/incoming/2017/03_w12/1151775/Permutations.txt https://filedb.experts-exchange.com/incoming/201…

735 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