unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Windows,shellapi,Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
StdCtrls;
type
{ TForm1 }
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
public
end;
TMyThread = Class(TThread)
Private
fFileName :WideString;
Sh:ShellExecuteInfoW;
Public
procedure Execute Override;
Procedure CleanUp;
constructor Create(FileName:WideString);
End;
var
Form1: TForm1;
MyThread:TMyThread;
implementation
{$R *.lfm}
{ TForm1 }
Procedure TMyThread.Execute;
Begin
FillChar(Sh, SizeOf(Sh),0);
Sh.cbSize:= SizeOf(Sh);
Sh.fMask := SEE_MASK_NOCLOSEPROCESS;
Sh.lpVerb := WideString('RunAs');
Sh.LpFile := pWideChar(fFileName);
Sh.nShow := SW_SHOWNORMAL;
Form1.Caption := PWideChar(Sh.LpFile);
If ShellExecuteExW(@Sh)= True Then
Begin
While (WaitForSingleObject(Sh.hProcess, 1000) = WAIT_TIMEOUT)and(Not Terminated) Do;
if Terminated Then TerminateProcess(Sh.HProcess, 0);
End;
Synchronize(@CleanUp);
end;
Procedure TMyThread.Cleanup;
Begin
Form1.Button2.OnClick(Self);
end;
Constructor TMyThread.Create(FileName:WideString);
Begin
fFileName := FileName;
Inherited Create(True); //Suspend Thread, don't start yet.
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Button1.Enabled := false;
MyThread := TMyThread.Create('c:\Windows\System32\notepad.exe');
MyThread.FreeOnTerminate := True;
MyThread.Start;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
if (Assigned(MyThread))and(MyThread.Terminated= False) Then MyThread.Terminate;
MyThread := Nil;
Button1.Enabled := True;
end;
end.
There are other things you can add but this does work for me. for you, you'll need to change the code a bit to pass the correct file name you need.
I may have missed some other details in the ShellExecute setup but this is a good start for you.