Executing External Programs in pascal - pascal

I want to open a program with below code but I can't
program launchprogram;
uses
Classes, SysUtils, Process;
var
AProcess: TProcess;
begin
AProcess := TProcess.Create(nil);
AProcess.Executable:= 'C:\Program Files (x86)\oCam\oCam.exe';
AProcess.Parameters.Add('-h');
AProcess.Options := AProcess.Options + [poWaitOnExit];
AProcess.Execute;
AProcess.Free;
end.
How can I solve this problem?

See: http://wiki.freepascal.org/Executing_External_Programs
I tried this on a linux machine and it works fine
SysUtils.ExecuteProcess(UTF8ToSys('/full/path/to/binary'), '', []);
or better:
SysUtils.ExecuteProcess(UTF8ToAnsi('/full/path/to/binary'), '', []);
It is also supposed to work in MSWin

Here is an example of the use of TProcess on a linux machine:
enter code here
procedure TForm1.Button1Click(Sender: TObject);
VAR AProcess : TProcess;
begin
AProcess:= TProcess.Create(nil);
Aprocess.Executable:= '/usr/bin/mysqldump';
Aprocess.Parameters.Add('--user=root');
Aprocess.Parameters.Add('--password=any');
Aprocess.Parameters.Add('--result-file=/home/user/mydump.sql;
Aprocess.Parameters.Add('database1);
AProcess.Options := AProcess.Options + [poWaitOnExit,poUsePipes];
AProcess.Execute;
AProcess.Free;
end;
hope this will help you. I think the executable is not wright

Related

How to compile a Delphi source code file for execution from the command line with parameters?

I use Delphi 7 IDE. I want to run .exe from the command line with parameters (to be defined).
How can I know if my app is running with the CMD command?
How can I read the parameter with source code?
How can I know if my app is running with the CMD command?
You can't, nor do you ever need to. If your project is a console app, then the .exe is always run inside of a console window process. If the project is not a console app, then there is no console, but you can create one if needed using AllocConsole(). Any process, whether it is a console app or not, can receive command-line parameter, though.
How can I read the parameter with source code?
Use the ParamCount() and ParamStr() functions in the System unit, or the FindCmdLineSwitch() function in the SysUtils unit.
Or, use GetCommandLine() in the Windows unit and parse the raw command-line data yourself.
var
bHideForm = boolean ;
begin
bHideForm := False;
bHideForm := ParamCount > 0;
if bHideForm then
bMetadataExport := GetParamValue(C_MENU, sMetaDataMenu);
{--------------------- function GetParamValue ----------------------------- }
function GetParamValue(aParamName: string; out oParamValue: string): Boolean;
var
i: Integer;
s: string;
begin
Result := False;
for i := 1 to ParamCount do
begin
s := ParamStr(i);
Result := pos(aParamName, UpperCase(s)) = 1;
if Result then
begin
oParamValue := copy(s, length(aParamName)+2, MaxInt);
Exit;
end;
end;
end;
end;

Why no window is being shown despite no error or warnings

I am trying following code for a GUI to show 2 identical windows. I am using show rather than showmodal:
program RnTFormclass;
{$mode delphi}
uses
//cthreads, // for linux only.
Interfaces, Forms, StdCtrls;
type
RnTForm = class(TForm)
private
wnd: TForm;
btn: TButton;
public
constructor create;
procedure showit;
end;
constructor RnTForm.create;
begin
//Application.Initialize; //removed.
wnd := TForm.Create(Application);
with wnd do begin
Height := 300;
Width := 400;
Position:= poDesktopCenter;
Caption := 'LAZARUS WND';
end;
btn := TButton.Create(wnd);
with btn do begin
SetBounds(0, 0, 100, 50);
Caption := 'Click Me';
Parent := wnd;
end;
end;
procedure RnTForm.showit;
begin
wnd.Show;
end;
var
myform1, myform2: RnTForm;
begin
// create windows:
myform1 := RnTForm.Create;
myform2 := RnTForm.Create;
// show windows:
myform1.showit;
myform2.showit;
end.
I want two identical windows to show/open up. Though the program runs without any error or warning, not even one window is shown.
The program just terminates.
Where is the problem and how can it be solved? Thanks for your help.
Edit: As pointed out in the comments, Application.initialize is being called twice and not run. I have commented out Application.initialize and the code still does not open up any of the window. (It does open windows one by one if show is replaced by showModal).
Main question is how to keep window open after show?
Taking suggestions from comments, I got it working by following main method:
begin
Application.Initialize;
// create windows:
myform1 := RnTForm.Create;
myform2 := RnTForm.Create;
// show windows:
myform1.showit;
myform2.showit;
Application.run;
end.
Now both the windows appear and I can click and work on any of them.
However, on closing both the windows, the program still keeps running in background. An exit button with its click function needs to be added.

Varriable File Path in the Commandline Lazarus/Free Pascal

I want to execute an external program wich is called 'copy.bat' located at my desktop 'C:\Users\Jack\Desktop\RunProgram\lib\x86_64-win64'. If I want to run the Program on someone else´s Compter/ Account where 'copy.bat' is in the same folder it doesn´t work, because the username changes.
My question: is there any way to use a varriable username?
This is what I came up with but it doesn´t work...
var
Form1: TForm1;
Runprogram:TProcess;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
begin
RunProgram := TProcess.Create(nil);
RunProgram.CommandLine := '%USERPROFILE%\Desktop\RunProgram\lib\x86_64-win64\Copy.bat';
RunProgram.Execute;
RunProgram.Free;
end;
P.S. If I enter this path 'C:\Users\Jack\Desktop\RunProgram\lib\x86_64-win64\Copy.bat' it works.
You can use the Function "GetEnvironmentVariable"
userP := GetEnvironmentVariable(String('USERPROFILE'));
RunProgram.CommandLine := userP + '\Desktop\RunProgram\lib\x86_64-win64\Copy.bat';

Capture all commands output

I want to capture cmd.exe output and show it in a diffrent gui I am making. I want to make a command interpreter with extended functionality. The dir command works flawless, the problem ocurrs when I try to execute another process like ipconfig.
I don't see ipconfig output. Is there a workarround on that ?!
I use TProcess component from Lazarus (FreePascal)
proc := TProcess.Create(nil);
proc.Options:= [poUsePipes, poNoConsole];
proc.ShowWindow:= swoHIDE;
proc.Executable:= 'cmd';
Reading output thread:
if (Length(cmd) > 0) then
begin
cmd := cmd + #13#10;
proc.Input.Write(cmd[1], Length(cmd)); // here I write command from user
strikes := 0;
end
else
if proc.Output.NumBytesAvailable > 0 then
begin
while proc.Output.NumBytesAvailable > 0 do
begin
FillChar(buf, sizeof(buf), #0);
proc.Output.Read(buf, sizeof(buf) - 1);
data := data + buf;
end;
// data gets echoed to user
It works fine for me (I use FPC 3.1.1 & Lazarus 1.5 but I hope it does not matter):
proc.Options:= [poUsePipes];
proc.ShowWindow:= swoHIDE;
proc.Executable:= 'cmd';
...
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
var
cmd: String;
begin
if Key = #13 then
begin
Key := #0;
if not proc.Active then
proc.Active := True;
cmd := Edit1.Text + LineEnding;
proc.Input.Write(cmd[1], Length(cmd));
end;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
buf: array[0..65535] of Char;
begin
if proc.Output.NumBytesAvailable > 0 then
begin
while proc.Output.NumBytesAvailable > 0 do
begin
FillChar(buf, sizeof(buf), #0);
proc.Output.Read(buf, sizeof(buf) - 1);
Memo1.Lines.Add(buf);
end;
end;
end;
I guess that you just does not catch process output properly.
Good luck.
PS: If you need to create some windows console-like application, the best way, I think, is using Windows console API instead of cross-platform Lazarus components.
PPS: To emulate console look and behavior with Lazarus use CmdLine component.
In general it is smart to first check if the short examples don't solve the problem:
e.g.
uses process;
var s : ansistring;
begin
runcommand('ipconfig',['/all'],s);
writeln(s);
end.
works fine, and saves a whole lot of trouble. (FPC 2.6.2+ though)

Delphi, Windows: Best way to find whether web-browser is running?

What is the best way to find whether a web-browser is running?
Using Delphi XE2 and on Windows, I need to find whether the following web-browsers are currently running:
A) Mozilla Firefox
B) Apple Safari
C) Google Chrome
If found, the process will be terminated because the home page of the web-browser needs to be changed programmatically by modifying the web-browser configuration files (which is either not possible or could result in unpredictable results if done when the web-browser is running).
Does the output from the EnumWindows API function contain sufficient information needed to handle the above task? If yes, then are the window class names for each of the above web-browsers documented anywhere? If no, then which method is most reliable?
TIA.
Terminate a process without the user permission is not good practice, instead you must ask to the user if he wants terminate the app (in this case the web browser).
Now back to your question, you can detect if a app(webbroser) is running checking for the process name (firefox.exe, chrome.exe , safari.exe) using the CreateToolhelp32Snapshot method.
uses
Windows,
tlhelp32,
SysUtils;
function IsProcessRunning(const ListProcess: Array of string): boolean;
var
hSnapshot : THandle;
lppe : TProcessEntry32;
I : Integer;
begin
result:=false;
hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if hSnapshot <> INVALID_HANDLE_VALUE then
try
lppe.dwSize := SizeOf(lppe);
if Process32First(hSnapshot, lppe) then
repeat
for I := Low(ListProcess) to High(ListProcess) do
if SameText(lppe.szExeFile, ListProcess[i]) then
Exit(True);
until not Process32Next(hSnapshot, lppe);
finally
CloseHandle(hSnapshot);
end;
end;
and use like so
IsProcessRunning(['firefox.exe','chrome.exe','safari.exe'])
Now if you want a more reliable way you can search for the class name of the Window (using the FindWindowEx method) and then the PID of the process owner of the handle (using GetWindowThreadProcessId), from here you can use the PID of the process to resolve the name of exe.
{$APPTYPE CONSOLE}
uses
Windows,
tlhelp32,
SysUtils;
function GetProcessName(const th32ProcessID: DWORD): string;
var
hSnapshot : THandle;
lppe : TProcessEntry32;
begin
result:='';
hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if hSnapshot <> INVALID_HANDLE_VALUE then
try
lppe.dwSize := SizeOf(lppe);
if Process32First(hSnapshot, lppe) then
repeat
if lppe.th32ProcessID=th32ProcessID then
Exit(lppe.szExeFile);
until not Process32Next(hSnapshot, lppe);
finally
CloseHandle(hSnapshot);
end;
end;
function IsWebBrowserRunning(const ClassName, ExeName :string) : Boolean;
var
hWindow : THandle;
dwProcessId: DWORD;
begin
result:=False;
hWindow:= FindWindowEx(0, 0, PChar(ClassName), nil);
if hWindow<>0 then
begin
dwProcessId:=0;
GetWindowThreadProcessId(hWindow, dwProcessId);
if dwProcessId>0 then
exit(Sametext(GetProcessName(dwProcessId),ExeName));
end;
end;
begin
try
if IsWebBrowserRunning('MozillaWindowClass','firefox.exe') then
Writeln('Firefox is Running');
if IsWebBrowserRunning('{1C03B488-D53B-4a81-97F8-754559640193}','safari.exe') then
Writeln('Safari is Running');
if IsWebBrowserRunning('Chrome_WidgetWin_1','chrome.exe') then
Writeln('Chrome is Running');
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
readln;
end.

Resources