TOpenDialog And Spaces - delphi

I have a project on Lazarus that I want to compile a source using gcc, for this I have a TOpenDialog called OpenDialog1 and a TProcess called AProcess.
I call gcc with this code:
procedure TFormMain.btCompileClick(Sender: TObject);
begin
if OpenDialog1.Execute then
begin
AProcess := TProcess.Create(nil);
try
AProcess.CommandLine := 'gcc.exe ' + OpenDialog1.FileName;
AProcess.Options := AProcess.Options + [poWaitOnExit, poUsePipes];
AProcess.Execute;
OutputMemo.Lines.BeginUpdate;
OutputMemo.Lines.Clear;
OutputMemo.Lines.LoadFromStream(AProcess.Output);
OutputMemo.Lines.EndUpdate;
finally
AProcess.Free;
end;
end;
end;
It compiles ok(the project on Lazzarus), but when I was testing it, by trying to compile the source test.c, that is located at C:\Documents and Settings\Nathan Campos\Desktop, I got this on OutputMemo:
'C:\Documents': No such file or directory
Then, OpenDialog1 isn't getting the full path with the spaces, or gcc can't locate it on the folder with spaces.
Any suggestion to help me on this?

It needs to be in quotes so spaces won't trip it up. So like this:
AProcess.CommandLine := 'gcc.exe "' + OpenDialog1.FileName + '"';
That should work.

Related

Delphi ini file reading

Im stuck and asking for your help te get a solution for reading my ini file back and placing that in my memo1 form with a button.
This is in my text file:
[Filename]
Work Time=03-10-2018 15:11
Here is some of the code im working with.
var
aWorkTime: string;
procedure TForm1.button2(Sender: TObject):
begin
Memo1.Lines.Clear;
IniFile := TIniFile.Create(GetCurrentDir+'\Filename.ini');
try
aWorkTime := IniFile.ReadString('Filename', 'Work Time', <'none'>);
finally
IniFile.Free;
end;
end
I hope that this is enough information if not please tell me what you are missing from me
Your use of GetCurrentDir is problematic. The current dir may change and doesn't have to be the same directory as where your .exe file resides. Rather use ExtractFilePath(Application.ExeName)
Also, instead of reading the items one by one, to read the entire .ini file into your memo, do something like:
procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.Lines.LoadFromFile(ExtractFilePath(Application.ExeName) + 'FileName.ini');
end;
If you only need the work time, then your code is almost there:
var
aWorkTime: string;
IniFile: TIniFile;
begin
Memo1.Lines.Clear;
IniFile := TIniFile.Create(ExtractFilePath(Application.ExeName) + 'FileName.ini');
try
aWorkTime := IniFile.ReadString('Filename', 'Work Time', '<none>');
Memo1.Lines.Add('Work Time=' + aWorkTime);
finally
IniFile.Free;
end;
end;

Save a TiniFile from application to iOS

I am very new to the iOS platform. I am trying to save an INI file for my application. The problem is that I can't get a path with write permission.
Here is my code:
ini := TIniFile.Create(GetHomePath + '/user.dat');
try
ini.WriteString('data','user',edtuser.Text);
ini.WriteString('data','descr',edt1.Text);
finally
ini.Free;
end;
I get an exception that the file can't be created. How can I get a writable path using Firemonkey?
Use TPath.GetDocumentsPath (and use TPath.Combine instead of concatenation, to remove the hard-coded /):
uses
System.IOUtils;
ini := TIniFile.Create(TPath.Combine(TPath.GetDocumentsPath, 'user.dat'));
Using TPath.GetDocumentsPath works across all supported platforms (Win32, Win64, OSX, iOS, and Android) transparently, and using TPath.Combine will automatically add the TPath.DirectorySeparatorChar, so you don't have to manually concatenate them.
If you prefer to do it yourself, though:
var
IniName: string;
begin
IniName := TPath.GetDocumentsPath + TPath.DirectorySeparatorChar + 'user.dat';
Ini := TIniFile.Create(IniName);
try
// Rest of code
finally
Ini.Free;
end;
end;
May be this or this can help you
uses INIFiles;
function TForm6.MyINIFilePath: string;
begin
// Result := GetHomePath + PathDelim + 'Library' + PathDelim+'My.ini';
Result := GetHomePath + PathDelim + 'Documents' + PathDelim+'MyD.ini';
end;

Why does FindFirst return file names that don't match the mask?

I pass the parameter value '*1.dat' to FindFirst, still the first file that the FindFirst() routine return is 46checks5.dat, very consistently.
Is this a known problem?
vpath:=trim(vpath);
result:=true;
try
res:=findfirst(vpath+'\'+vmask,faarchive,search); //vmask = *1.dat
try
while res=0 do
begin
vlist.add(search.name); //searchname returned is 46checks5.dat!!!
res:=findnext(search);
end;
finally
findclose(search);
end;
except
result:=false;
end;
The reason is that the file has a "long" name, i.e. with more than 8 characters. For such files Windows also creates "short" names, that usually are created in the form longna~1.dat and this short name is found via *1.dat wildcard.
You can easily reproduce the same behaviour in command prompt in an empty directory:
C:\TEMP>echo. > 46checks5.dat
C:\TEMP>dir /x *1.dat
Volume in drive C has no label.
Volume Serial Number is 5C09-D9DE
Directory of C:\TEMP
2011.04.15 21:37 3 46CHEC~1.DAT 46checks5.dat
1 File(s) 3 bytes
The documentation for FindFirstFile(), which is the underlying API for FindFirst states:
The search includes the long and short
file names.
To workaround this issue, then, rather than using Delphi's wrapper to FindFirstFile(), call the Win32 API FindFirstFileEx(). Pass FindExInfoBasic to the fInfoLevelId parameter.
You have something else wrong.
I created a folder C:\Temp\Test, and put three files in it:
TestFile1.txt
TestFile2.txt
TestFile3.txt
I then dropped a TMemo on a new blank form in a new project, and added this code to the 'FormCreate' event:
procedure TForm1.FormCreate(Sender: TObject);
var
sPath: string;
sFile: string;
SR: TSearchRec;
begin
sPath := 'C:\Temp\Test';
sFile := '*1.txt';
Memo1.Lines.Clear;
if FindFirst(sPath + '\' + sFile, faArchive, SR) = 0 then
begin
try
repeat
Memo1.Lines.Add(SR.Name);
until FindNext(SR) <> 0;
finally
FindClose(SR);
end;
end;
end;
When the form was shown, the TMemo showed exactly one file, TestFile1.txt, just as I would expect.

How am I supposed to use JEDI's JCLCompression to create a 7z archive?

I am trying to create a 7z archive of certain files using Delphi 2009.
The code below seems to work, but all of the items in the resulting 7z file are of zero size. All of the file names that are in the archive are correct, but they shouldn't be zero size.
How can I add files properly to a 7z archive using JCLCompression?
var
fname, archiveFileName: string;
arch: TJclUpdateArchive;
archiveclass: TJCLUpdateArchiveClass;
sr: TSearchRec;
begin
fname := GetDesktop + 'Support.7z';
archiveclass := GetArchiveFormats.FindUpdateFormat(fname);
if not Assigned(archiveclass) then
raise Exception.Create('Could not determine the Format of ' + fname);
arch := archiveclass.Create(fname);
try
with arch do
begin
if FindFirst(uFolder + '*.*', faAnyFile, sr) = 0 then
begin
repeat
AddFile(ExtractFileName(sr.Name), sr.Name);
until FindNext(sr) <> 0;
FindClose(sr);
end;
Compress;
end;
finally
arch.free;
end;
end;
Never, ever, having jused JCLCompression my answer may wel be totally wrong, but don't you have to specify the folder somewhere ? You are only adding the filenames.

Using 7-Zip from Delphi?

I would like to use the 7-Zip DLLs from Delphi but have not been able to find decent documentation or examples. Does anyone know how to use the 7-Zip DLLs from Delphi?
As of release 1.102 the JEDI Code Library has support for 7-Zip built into the JclCompression unit. Haven't used it myself yet, though.
Expanding on Oliver Giesen's answer, as with a lot of the JEDI Code Library, I couldn't find any decent documentation, but this works for me:
uses
JclCompression;
procedure TfrmSevenZipTest.Button1Click(Sender: TObject);
const
FILENAME = 'F:\temp\test.zip';
var
archiveclass: TJclDecompressArchiveClass;
archive: TJclDecompressArchive;
item: TJclCompressionItem;
s: String;
i: Integer;
begin
archiveclass := GetArchiveFormats.FindDecompressFormat(FILENAME);
if not Assigned(archiveclass) then
raise Exception.Create('Could not determine the Format of ' + FILENAME);
archive := archiveclass.Create(FILENAME);
try
if not (archive is TJclSevenZipDecompressArchive) then
raise Exception.Create('This format is not handled by 7z.dll');
archive.ListFiles;
s := Format('test.zip Item Count: %d'#13#10#13#10, [archive.ItemCount]);
for i := 0 to archive.ItemCount - 1 do
begin
item := archive.Items[i];
case item.Kind of
ikFile:
s := s + IntToStr(i+1) + ': ' + item.PackedName + #13#10;
ikDirectory:
s := s + IntToStr(i+1) + ': ' + item.PackedName + '\'#13#10;//'
end;
end;
if archive.ItemCount > 0 then
begin
// archive.Items[0].Selected := true;
// archive.ExtractSelected('F:\temp\test');
archive.ExtractAll('F:\temp\test');
end;
ShowMessage(s);
finally
archive.Free;
end;
end;
7 Zip Plugin API
http://www.progdigy.com/?page_id=13
Zip and 7z with NO DLL, try out Synopse:
http://synopse.info/forum/viewtopic.php?pid=163
Delphi now has native, cross platform zip support with TZipFile in XE2:
How to extract zip files with TZipFile in Delphi XE2 and FireMonkey
If you intend to use 7Zip only for zip and unzip take a look at the TZip component.
I have written a small wrapper for my own purposes, which you can find in the Zipper.pas file, feel free to reuse.
I tried many solutions and had problems, this one worked.
Download https://github.com/zedalaye/d7zip
Copy 7z.dll and sevenzip.pas to your project diroctory and add sevenzip.pas to your project.
Then you can use this to unzip:
using sevenzip;
procedure Unzip7zFile (zipFullFname:string);
var
outDir:string;
begin
with CreateInArchive(CLSID_CFormat7z) do
begin
OpenFile(zipFullFname);
outDir := ChangeFileExt(zipFullFname, '');
ForceDirectories (outDir);
ExtractTo(outDir);
end;
end;
Usage:
Unzip7zFile(ExtractFilePath(Application.ExeName) + 'STR_SI_FULL_1000420.7z');

Resources