// this is my oldschool Execution function from MS-DOS now "Windownized" ;-)
// Similar as if you would execute anything on Command-Line
// Result will be greater than 31 on success
// if result is 4294967295/$FFFFFFFF than its a general error
// Example: if ExecuteCommandLine('C;\WINDOWS\TEMP\FILENAME.EXE', False) > 31 then Success := True else Success := False;
Function ExecuteCommandLine(
const cmdLine:
string;
const ShowConsole: Boolean): Cardinal;
const
flags:
array [Boolean]
of Integer = (SW_HIDE, SW_SHOWNORMAL);
var
cmdbuffer:
array [0..MAX_PATH]
of Char;
begin
Result := Cardinal($FFFFFFFF);
GetEnvironmentVariable('
COMSPEC', cmdBUffer, SizeOf(cmdBuffer));
StrCat(cmdbuffer, '
/C ');
StrPCopy(StrEnd(cmdbuffer), cmdLine);
Result := WinExec(cmdbuffer, flags[ShowConsole]);
end;
// this is my "ShellExecuteEx" implementation
// Example:
// to run something type
// ExecuteShell('C;\Windows\Temp\FileName.exe','Parameters',False,False);
// to run something type and wait that it finish type
// ExecuteShell('C;\Windows\Temp\FileName.exe','-Parameters',False,True);
// ShowConsole should only be activated for Console Programs
// Returned Value is either ErrorCode from ShellExecuteEx or Init/Exit Code from "Executable"
// if result is 4294967295/$FFFFFFFF than its a general error
function ExecuteShell(
const Executable, Commands:
String;
const ShowConsole, DoWait: Boolean): Cardinal;
var
ProcessInfo: TShellExecuteInfo;
begin
Result := Cardinal($FFFFFFFF);
FillChar(ProcessInfo, SizeOf(TShellExecuteInfo), #0);
with ProcessInfo
do
begin
cbSize:= SizeOf( TShellExecuteInfo );
fMask := SEE_MASK_NOCLOSEPROCESS
or SEE_MASK_FLAG_DDEWAIT;
Wnd := GetActiveWindow();
lpVerb := '
open';
(* lpVerb can be one of this:
'edit' Launches an editor and opens the document for editing.
'explore' Explores the folder specified by lpFile.
'find' Initiates a search starting from the specified directory.
'open' Opens the file, folder specified by the lpFile parameter.
'print' Prints the document file specified by lpFile.
'properties' Displays the file or folder's properties.*)
lpFile:= PChar(Executable);
lpParameters := PChar(Commands);
lpDirectory := PChar(ExtractFilePath(Executable));
if ShowConsole
then nShow := SW_SHOWNORMAL
else nShow := SW_HIDE;
end;
if ShellExecuteEx(@ProcessInfo)
then
begin
// if DoWait then WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
if DoWait
then while WaitForSingleObject(ProcessInfo.hProcess, 500) <> WAIT_OBJECT_0
do ProcessMessages;
if not GetExitCodeProcess(ProcessInfo.hProcess, Result)
then Result := Cardinal($FFFFFFFF);
// GetExitCodeProcess(ProcessInfo.hProcess, Result);
CloseHandle(ProcessInfo.hProcess);
end
else
begin
Result := GetLastError;
exit;
end;
end;
// this function execute any Associated Program with "Executable" as Input-Filename optional wait that it finish
// give back as Result the Init/Exit Code of Associated Program or Error Code from FindExecutable
// Example: ExecuteAssociated('ReadMe.txt', False, True);
// that would open "ReadMe.txt" in Editor and wait that Editor terminate
// ExecuteAssociated('ReadMe.html', False, False);
// that would open your Internet Browser with "ReadMe.html" and not wait
// ShowConsole should only be activated for Console Programs
// if result is 4294967295/$FFFFFFFF than its a general error
function ExecuteAssociated(
const Executable:
String;
const ShowConsole, DoWait: Boolean): Cardinal;
var
Prg:
string;
Security : TSecurityAttributes;
ProcessInfo: TProcessInformation;
StartupInfo: TStartupInfo;
begin
Result := Cardinal($FFFFFFFF);
SetLength(Prg, MAX_PATH);
Result := FindExecutable(PChar(Executable),
nil, PChar(Prg));
if Result > 32
then
begin
with Security
do begin
nLength := SizeOf(TSecurityAttributes);
lpSecurityDescriptor :=
nil;
bInheritHandle := False;
end;
SetLength(Prg, StrLen(PChar(Prg)));
FillChar(StartupInfo, SizeOf(TStartupInfo), #0);
with StartupInfo
do
begin
cb := SizeOf(TStartupInfo);
dwFlags := STARTF_USESHOWWINDOW
or STARTF_FORCEONFEEDBACK;
if ShowConsole
then wShowWindow := SW_SHOWNORMAL
else wShowWindow := SW_HIDE;
end;
if CreateProcess(PChar(Prg), PChar(Format('
%s %s', [Prg, Executable])), @Security, @Security, False, CREATE_NEW_CONSOLE
or NORMAL_PRIORITY_CLASS,
nil, PChar(ExtractFilePath(Executable)), StartupInfo, ProcessInfo)
then
begin
if DoWait
then while WaitForSingleObject(ProcessInfo.hProcess, 500) <> WAIT_OBJECT_0
do ProcessMessages;
// if DoWait then WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
if not GetExitCodeProcess(ProcessInfo.hProcess, Result)
then Result := Cardinal($FFFFFFFF);
// GetExitCodeProcess(ProcessInfo.hProcess, Result);
CloseHandle(ProcessInfo.hProcess);
CloseHandle(ProcessInfo.hThread);
end
else
Result := GetLastError;
end;
end;
// this function execute any Executable with Commands optional wait that it finish
// give back as Result the Init/Exit Code of Executable or Error Code from CreateProcess
// example:
// to execute a executable type
// ExecuteExe('C:\WINDOWS\TEMP\FILENAME.EXE','Parameters',False,False);
// to execute a executable and wait type
// ExecuteExe('C:\WINDOWS\TEMP\FILENAME.EXE','Parameters',False,True);
// ShowConsole should only be activated for Console Programs
// DoWait will AntiFreeze and Lock your visible GUI
// this way you could still Update Display in your Application (like a text scroller, or any graphic etc)
// SideEffect: All commands that you click/do/set while in DoWait mode,
// will be executed at once when DoWait is finished.
// if result is 4294967295/$FFFFFFFF than its a general error
// Result can be Init/Exit Code of Executable
function ExecuteExe(
const Executable:
String; Commands:
String;
const ShowConsole, DoWait: Boolean): Cardinal;
procedure WaitFor(processHandle: THandle);
var
Msg: TMsg;
ret: DWORD;
begin
repeat
ret := MsgWaitForMultipleObjects(1,
{ 1 handle to wait on }
processHandle,
{ the handle }
False,
{ wake on any event }
INFINITE,
{ wait without timeout }
QS_PAINT
or { wake on paint messages }
QS_SENDMESSAGE
{ or messages from other threads }
);
if ret = WAIT_FAILED
then Exit;
{ can do little here }
if ret = (WAIT_OBJECT_0 + 1)
then
begin
// if Msg.Message = WM_COMMAND then begin Msg.Message := WM_NULL end else
while PeekMessage(Msg, 0, WM_PAINT, WM_PAINT, PM_REMOVE)
do
// while PeekMessage(Msg, 0, WM_NULL, WM_USER, PM_REMOVE) do (* this would total un-freeze = DoWait would not lock GUI *)
DispatchMessage(Msg);
end;
until ret = WAIT_OBJECT_0;
end;
{ Waitfor }
var
Security : TSecurityAttributes;
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
begin
Result := Cardinal($FFFFFFFF);
if ((Length(Commands) > 1)
and(Commands[1]<>'
'))
then Commands := '
' + Commands;
with Security
do begin
nLength := SizeOf(TSecurityAttributes);
lpSecurityDescriptor :=
nil;
bInheritHandle := False;
end;
FillChar(StartupInfo, SizeOf(StartupInfo), #0);
StartupInfo.cb := SizeOf(StartupInfo);
StartupInfo.dwFlags := STARTF_USESHOWWINDOW
or STARTF_FORCEONFEEDBACK;
if ShowConsole
then StartupInfo.wShowWindow := SW_SHOWNORMAL
else StartupInfo.wShowWindow := SW_HIDE;
if CreateProcess(PChar(Executable), PChar(Commands), @Security, @Security, False, CREATE_NEW_CONSOLE
or NORMAL_PRIORITY_CLASS,
nil, PChar(ExtractFilePath(Executable)), StartupInfo, ProcessInfo)
then
begin
if DoWait
then WaitFor(ProcessInfo.hProcess);
if not GetExitCodeProcess(ProcessInfo.hProcess, Result)
then Result := Cardinal($FFFFFFFF);
// GetExitCodeProcess(ProcessInfo.hProcess, Result);
// if Result = 0 then Result := STATUS_PENDING;
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
end
else
Result := GetLastError;
end;
// this function will execute a console application
// give all console output back to "Output:PChar" parameter
// give back as Result the ExitCode of "Executable"
// ShowConsole should only be activated if you want to see a blank Console Window aslong Process is running
// WARNING: DO NOT EXECUTE CONSOLE APPLICATIONS THAT NEED KEYBOARD/MOUSE INPUT!!!
// if result is 4294967295/$FFFFFFFF than its a general error
Function ExecuteConsole(
const Executable:
String; Commands:
String;
const ShowConsole: Boolean;
var Output: PChar): Cardinal;
const
ReadBuffer = 4000;
var
Security : TSecurityAttributes;
ReadPipe,WritePipe : THandle;
StartupInfo : TStartUpInfo;
ProcessInfo : TProcessInformation;
Buffer : Pchar;
BytesRead : DWord;
AppRunning : DWord;
begin
Result := Cardinal($FFFFFFFF);
if ((Length(Commands) > 1)
and(Commands[1]<>'
'))
then Commands := '
' + Commands;
with Security
do begin
nLength := SizeOf(TSecurityAttributes);
lpSecurityDescriptor :=
nil;
bInheritHandle := True;
end;
if CreatePipe (ReadPipe, WritePipe, @Security, 0)
then
begin
Buffer := AllocMem(ReadBuffer + 1);
FillChar(StartupInfo,SizeOf(StartupInfo), #0);
StartupInfo.cb := SizeOf(StartupInfo);
StartupInfo.hStdOutput := WritePipe;
StartupInfo.hStdInput := ReadPipe;
StartupInfo.dwFlags := STARTF_USESTDHANDLES
or STARTF_USESHOWWINDOW;
if ShowConsole
then StartupInfo.wShowWindow := SW_SHOWNORMAL
else StartupInfo.wShowWindow := SW_HIDE;
if CreateProcess(PChar(Executable), PChar(Commands), @Security, @Security, True, CREATE_NEW_CONSOLE
or NORMAL_PRIORITY_CLASS,
nil, PChar(ExtractFilePath(Executable)), StartupInfo, ProcessInfo)
then
begin
repeat
ProcessMessages;
Apprunning := WaitForSingleObject(ProcessInfo.hProcess,100);
until (Apprunning <> WAIT_TIMEOUT);
// if DoWait then while WaitForSingleObject(ProcessInfo.hProcess, 500) <> WAIT_OBJECT_0 do ProcessMessages;
repeat
BytesRead := 0;
ReadFile(ReadPipe,Buffer[0], ReadBuffer, BytesRead,
nil);
Buffer[BytesRead]:= #0;
OemToChar(Buffer, Output);
until (BytesRead < ReadBuffer);
end;
FreeMem(Buffer);
if not GetExitCodeProcess(ProcessInfo.hProcess, Result)
then Result := Cardinal($FFFFFFFF);
// GetExitCodeProcess(ProcessInfo.hProcess, Cardinal(Result));
CloseHandle(ReadPipe);
CloseHandle(WritePipe);
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
end;
end;