Varriable File Path in the Commandline Lazarus/Free Pascal - lazarus

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';

Related

Loading an array of records back into a program from a file?

I am creating a program that moves through an array of records and save these student records to a file.
However I now wish to reload the data (StudentName,Class,Grade) back into the array and subsequently display them in a list box on another form.
I have tried a few methods but with no success.
This is the code that wrote the file:
unit NewStudent;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
ExtCtrls, studentdata;
{ TFormNewStudent }
Type
TFormNewStudent = class(TForm)
Button1: TButton;
ButtonAddStudent: TButton;
Button3: TButton;
ComboBoxPredictedGrade: TComboBox;
EditClass: TEdit;
EditName: TEdit;
procedure Button1Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure ButtonAddStudentClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ private declarations }
public
{ public declarations }
end;
Type
TPupil = Record
Name:String[30];
ClassGroup:String;
ComboBoxPredictedGrade:Integer;
end;
var
FormNewStudent: TFormNewStudent;
StudentRecArray : Array[1..30] of TPupil;
StudentNo:integer;
studentFile:TextFile;
implementation
{$R *.lfm}
{ TFormNewStudent }
procedure TFormNewStudent.Button1Click(Sender: TObject);
begin
FormStudentData.visible:=true;
FormNewStudent.visible:=false;
end;
procedure TFormNewStudent.Button3Click(Sender: TObject);
begin
FormStudentData.visible:=False;
FormNewStudent.visible:=True;
end;
procedure TFormNewStudent.ButtonAddStudentClick(Sender: TObject);
var
newStudent:string;
Begin
assignfile(studentFile,'G:\ExamGen\studentfile.txt');
StudentRecArray[StudentNo].Name:=EditName.text;
StudentRecArray[StudentNo].ClassGroup:=EditClass.text;
StudentRecArray[StudentNo].ComboBoxPredictedGrade:=ComboBoxPredictedGrade.ItemIndex;
append(studentFile);
newStudent:=(StudentRecArray[StudentNo].Name)+','+(StudentRecArray[StudentNo].ClassGroup)+','+(IntToStr(StudentRecArray[StudentNo].ComboBoxPredictedGrade));
writeln(studentFile,newStudent);
closefile(StudentFile);
StudentNo := StudentNo + 1;
end;
procedure TFormNewStudent.FormCreate(Sender: TObject);
begin
ComboBoxPredictedGrade.Items.Add('A');
ComboBoxPredictedGrade.Items.Add('B');
ComboBoxPredictedGrade.Items.Add('C');
ComboBoxPredictedGrade.Items.Add('D');
ComboBoxPredictedGrade.Items.Add('E');
ComboBoxPredictedGrade.Items.Add('U');
end;
end.
ScreenShot 1: StudentFile
ScreenShot 2: AddStudent Form
Answer given by Zamrony P. Juhara is correct, but your approach here may be not the most convenient. You define record which contains information about each student, then you write procedures to write this record to file and another one to read it. If you'll eventually change format of your record, you'll have to rewrite this code also. There are better ways, in my opinion.
You can define record containing only simplest members, like Ken White suggested:
TPupil = Record
Name:String[30];
ClassGroup:String[20]; //some convenient value
ComboBoxPredictedGrade:Integer;
end;
Such a record have fixed size and contains all needed information in itself (version with ClassGroup:String actually stores pointer to another area in memory where your string is), and then you can save and load it extremely easy:
var
myFile : File of TPupil;
procedure TFormNewStudent.ButtonAddStudentClick(Sender: TObject);
Begin
assignfile(studentFile,'G:\ExamGen\studentfile.txt');
StudentRecArray[StudentNo].Name:=EditName.text;
StudentRecArray[StudentNo].ClassGroup:=EditClass.text;
StudentRecArray[StudentNo].ComboBoxPredictedGrade:=ComboBoxPredictedGrade.ItemIndex;
append(studentFile);
Write(studentFile,StudentRecArray[StudentNo]); //THAT'S IT!
closefile(StudentFile);
inc(StudentNo);
end;
procedure TFormNewStudent.ReadFromFile;
begin
AssignFile(myFile,'G:\ExamGen\studentfile.txt');
Reset(studentFile);
StudentNo:=1;
while not Eof(studentFile) do begin
Read(studentFile,StudentRecArray[i]);
inc(StudentNo);
end;
end;
There is little drawback: file is not so readable as it was before, because Integer is saved exactly as 4-byte value, not its decimal representation.
There is much more interesting possibilities if you move from record to class, in that case you can use streaming system in a way as IDE saves forms to disc, in .dfm or .lfm files, so you'll be able to automatically save complex ierarchies of objects and load them back.
var
myFile : TextFile;
text : string;
lines : TStringList;
i : integer;
...
lines := TStringList.Create();
AssignFile(studentFile,'G:\ExamGen\studentfile.txt');
Reset(studentFile);
i:=1;
while not Eof(studentFile) do
begin
ReadLn(studentFile, text);
lines.CommaText := text;
studentRecArray[i].Name := lines[0];
studentRecArray[i].ClassGroup := lines[1];
studentRecArray[i].ComboBoxPredictedGrade := StrToInt(lines[2]);
inc(i);
end;
CloseFile(studentFile);
lines.Free();

Access Violation ShellExecute in delphi7

I am using ShellExecute the same way given below, to open a txt file in Delphi7, it gives me access violation in module BORdbk70.dll.
Not sure what this issue is? I have added ShellApi in uses list.
//sAddr := 'www.google.com';
Above line does not gives any error but also not redirect to browser and
ShellExecute returns result as "5 = Windows 95 only: The operating system denied access to the specified file"
sAddr := 'c:\text\info.txt';
res := ShellExecute(Handle, nil, PChar(sAddr), nil, nil, SW_SHOW);
showmessage(inttostr(res));
This example that I wrote for you, working good (without error). I tested with Delphi7 on Windows 8.1
You must know what is default application to open *.txt files in your Operation System. That application will try open your file. On my system for *.txt default application is Notepad++ and this example opened file info.txt in Notepad++
Full source (pas) code:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ShellApi;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
sAddr : String;
res : Integer;
begin
sAddr := 'c:\text\info.txt';
res := ShellExecute(Handle, 'open', PChar(sAddr), nil, nil, SW_SHOW);
showmessage(inttostr(res));
end;
end.
This example working good with admin and normal user rights.
var
file:string;
exe_start_map:string;
begin
exe_start_map:=(ExtractFileDir(Application.ExeName));
file:=exe_start_map+'\samplefile.txt';
ShellExecute(handle,'open',pchar(file),'','',SW_SHOWnormal);
end;
you must add ShellApi in uses list

Stored procedure Text saving in Delphi

I need to create stored procedure into oracle from delphi with TQuery.
But the SQL.text is difficult to uunderstand.
Is there any way to store direct text as pl/SQL with out quotes?
'create or replace '+
'function WholeTableRecovery(i_tablname IN varchar) return varchar '+
'as '+
Is it possible with resource file
Thanks in advance
Since you are using Delphi 2010 in the tags (I have no Delphi 7 here to test), a comfortable method would be storing the SQLs in separate textfiles, together with a RC file containing the directives for the resource compiler.
The RC files will contain the names of the resource you want to use together with the filenames containing the SQLs you want to store. The content for the example would look like this:
My_First_Speaking_ResourceName RCDATA "MyFirstSQL.sql"
My_Second_Speaking_ResourceName RCDATA "MySecondSQL.sql"
There is no need to call BRCC32 directly if you include the resource containing RC and resulting RES :
{$R 'MySQLResources.res' 'resources\MySQLResources.rc'}
You might wrap the usage of TResourceStream for your convenience, the way shown in the example would use Strings you might also work with the stream directly as mentioned by TLama MyQuery.SQL.LoadFromStream(rs);
implementation
{$R *.dfm}
{$R 'MySQLResources.res' 'resources\MySQLResources.rc'}
function LoadSqlResource(resourceName: string): string;
var
rs: TResourceStream;
sl: TStringList;
s : string;
begin
sl := TStringList.Create;
try
rs := TResourceStream.Create(hinstance, resourceName, RT_RCDATA);
try
rs.Position := 0;
sl.LoadFromStream(rs);
Result := sl.Text;
finally
rs.Free;
end;
finally
sl.Free;
end;
end;
procedure CallOneSql(Q:TADOQuery;ResourceName:String);
begin
Q.SQL.Text := LoadSqlResource('My_First_Speaking_ResourceName');
Q.ExecSQL;
end;
With a call like CallOneSql(MyQuery,'My_First_Speaking_ResourceName');
Make sure to create the project, not just compile if you made changes on the RC or the SQL files.

Delphi FTP upload Access violation

I'm trying to upload a file .txt in my web space, but then the problems start, the code I tried is this:
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
IdExplicitTLSClientServerBase, IdFTP, StdCtrls;
procedure TForm1.Button1Click(Sender: TObject);
var
FTP:tidftp;
begin
FTP.Host:='website.altervista.org';
FTP.Username:='website';
FTP.Password:='password';
FTP.Port:=25;
FTP.Connect;
FTP.Put('C:\Users\user\Desktop\text.txt');
FTP.Quit;
end;
I'm not getting any error, but when I start the program and I click on the button, I get an error:
and immediately after another:
and the button disappears.
Why? Thanks!
You have to instantiate the TIdFTP object for your local variable FTP before you access it. So try to use this:
procedure TForm1.Button1Click(Sender: TObject);
var
FTP: TIdFTP;
begin
FTP := TIdFTP.Create(nil);
try
FTP.Host := 'serioussamhd.altervista.org';
FTP.Username := 'serioussamhd';
FTP.Password := 'password';
FTP.Port := 21;
FTP.Connect;
FTP.Put('C:\Users\user\Desktop\text.txt');
FTP.Quit;
finally
FTP.Free;
end;
end;
You must create the instance of the tidftp first.
var
FTP:tidftp;
begin
FTP:=Tidftp.Create(nil); //create the instance
try
FTP.Host:='siteweb.altervista.org';
FTP.Username:='siteweb';
FTP.Password:='password';
FTP.Port:=25;
FTP.Connect;
FTP.Put('C:\Users\user\Desktop\text.txt');
FTP.Quit;
finally
FTP.Free;
end;
end;

Delphi: Minimize application to systray

I want to minimize a Delphi application to the systray instead of the task bar.
The necessary steps seem to be the following:
Create icon which should then be displayed in the systray.
When the user clicks the [-] to minimize the application, do the following:
Hide the form.
Add the icon (step #1) to the systray.
Hide/delete the application's entry in the task bar.
When the user double-clicks the application's icon in the systray, do the following:
Show the form.
Un-minimize the application again and bring it to the front.
If "WindowState" is "WS_Minimized" set to "WS_Normal".
Hide/delete the application's icon in the systray.
When the user terminates the application, do the following:
Hide/delete the application's icon in the systray.
That's it. Right?
How could one implement this in Delphi?
I've found the following code but I don't know why it works. It doesn't follow my steps described above ...
unit uMinimizeToTray;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ShellApi;
const WM_NOTIFYICON = WM_USER+333;
type
TMinimizeToTray = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure CMClickIcon(var msg: TMessage); message WM_NOTIFYICON;
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
var
MinimizeToTray: TMinimizeToTray;
implementation
{$R *.dfm}
procedure TMinimizeToTray.CMClickIcon(var msg: TMessage);
begin
if msg.lparam = WM_LBUTTONDBLCLK then Show;
end;
procedure TMinimizeToTray.FormCreate(Sender: TObject);
VAR tnid: TNotifyIconData;
HMainIcon: HICON;
begin
HMainIcon := LoadIcon(MainInstance, 'MAINICON');
Shell_NotifyIcon(NIM_DELETE, #tnid);
tnid.cbSize := sizeof(TNotifyIconData);
tnid.Wnd := handle;
tnid.uID := 123;
tnid.uFlags := NIF_MESSAGE or NIF_ICON or NIF_TIP;
tnid.uCallbackMessage := WM_NOTIFYICON;
tnid.hIcon := HMainIcon;
tnid.szTip := 'Tooltip';
Shell_NotifyIcon(NIM_ADD, #tnid);
end;
procedure TMinimizeToTray.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caNone;
Hide;
end;
end.
If it still works, it's probably easiest to use JVCL's TJvTrayIcon to handle it automatically.
I would recommend using CoolTrayIcon. The author has already worked out all the issues involved with tray icons. Its free with source and examples and very debugged.
http://subsimple.com/delphi.asp
Instead of Application.BringToFront; use SetforegroundWindow(Application.Handle);
In the following text I'll be referring to the step numbers mentioned in the question:
The following solution is without any additional components. It's very easy to implement.
Step #1:
Just use the application's main icon (see following code).
Step #2:
procedure TForm1.ApplicationEvents1Minimize(Sender: TObject);
begin
Shell_NotifyIcon(NIM_ADD, #TrayIconData);
Form1.Hide;
end;
Step #3:
procedure TForm1.TrayMessage(var Msg: TMessage);
begin
if Msg.lParam = WM_LBUTTONDOWN then begin
Form1.Show;
Form1.WindowState := wsNormal;
Application.BringToFront;
Shell_NotifyIcon(NIM_DELETE, #TrayIconData);
end;
end;
Step #4:
procedure TForm1.FormDestroy(Sender: TObject);
begin
Shell_NotifyIcon(NIM_DELETE, #TrayIconData);
end;
Necessary code in interface part:
uses
[...], ShellApi;
const
WM_ICONTRAY = WM_USER + 1;
type
TForm1 = class(TForm)
[...]
procedure TrayMessage(var Msg: TMessage); message WM_ICONTRAY;
end;
The only problem: The application can be minimized to the systray only once. The next time you want to minimize it, nothing will happen. Why?
Source: delphi.about.com

Resources