Reading directory in delphi 7 gives nothing - file

I'm a delphi noob, and I simply try to read the the files in a directory (I will be doing sth with this files later).
I tried ouple methods, and nothing works - there is simply nothing outputed.
directoryPath := exePath + 'XML_out\'; //correct directory
wiadomosc := wiadomosc + sLineBreak + sLineBreak + 'FILES IN DIRECTORY:' + directoryPath; //will output correct directory
//first method
directoryEOFound:= False;
if FindFirst(directoryPath, faAnyFile, directoryRes) = 0 then
wiadomosc := wiadomosc + sLineBreak + 'DIRECTORY N)T FOUND' + sLineBreak //should save info about directory not found but return nothing
// exit //exit is killing app, like directory was not found.... but directory is there
else
while not directoryEOFound do begin
wiadomosc := wiadomosc + sLineBreak + directoryRes.Name; //gives nothing
directoryEOFound:= FindNext(directoryRes) <> 0;
end;
FindClose(directoryRes) ;
//second method
if FindFirst(directoryPath, faAnyFile, directoryRes) = 0 then try
repeat
if (directoryRes.Name = '.') or (directoryRes.Name = '..') then
continue;
wiadomosc := wiadomosc + sLineBreak + 'file: ' + directoryRes.Name; //gives nothing, i dont think its initiated
until FindNext(directoryRes) <> 0;
finally
SysUtils.FindClose(directoryRes);
end;
Neither method works, so maybe its a OS matter? (windows 7 64 bit) No errors in compilation offcourse.

You need to include a pattern to search for files. Replace
directoryPath := exePath + 'XML_out\';
with
directoryPath := exePath + 'XML_out\*';
The first block of code is odd. It appears to give up when FindFirst returns 0. But the 0 return value indicates success. So that condition is wrong. The second block of code looks reasonable.

Related

Delphi - Load files & folders to TreeView ( using IOUtils )

How can I properly organize the loading of a specific path of the file system (Windows) in TreeView?
For example:
load files & folders to TreeView (with IOUtils)
(*
tv_zapis: TTreeView
uses
System.IOUtils,
System.Types;
*)
procedure TF1.tb_ReDirectClick(Sender: TObject);
{ ReDirect ( Reorganization Directoris ) dirs & files to TTreeView }
procedure DFToTv(_Tv: TTreeView;
withNode: TTreeNode;
dfPath: string);
var
InsNode: TTreeNode;
Short_Name,
Short_EXT: string; // '*.txt' - delete
sPath: string;
arMask: TStringDynArray;
FilterTN: TDirectory.TFilterPredicate;
SO: TSearchOption;
s: TShiftState;
begin
sPath := Trim(dfPath);
SO := TSearchOption.soAllDirectories; // Search for All Directories in dir
FilterTN := // Filter for Find files
function(const Path: string; const SearchRec: TSearchRec): Boolean
var
nDir, // name Folder ( ! not full path )
sDF: string;
fAtts: TFileAttributes;
begin
nDir := TPath.GetFileName(Path); { Path Name - name of 'folder' }
sDF := IncludeTrailingPathDelimiter(Path) + SearchRec.Name ; // + '\' + SearchRec.Name
// Ignor find dir '_Setting'
if (SearchRec.Name = APL_nameS) or (nDir = APL_nameS)
then exit(False);
{ Browse a file and read its attributes }
fAtts := TPath.GetAttributes(sDF, False);
if (TFileAttribute.faDirectory in fAtts) then
begin
{ if path ' FOLDER ' }
Short_Name := SearchRec.Name;
// ??????????
InsNode := withNode.Parent;
if (InsNode = nil) then
begin
// ShowMessage( ' 1 ? ' );
// ??????????
//if (InsNode.Text = tNode.Text) then
InsNode := _Tv.Items.AddChild(withNode, Short_Name)
//else
// InsNode := _Tv.Items.AddChild(InsNode, Short_Name);
end
else
begin
ShowMessage( ' 2 ? ' );
// ??????????
InsNode := _Tv.Items.AddChild(InsNode, Short_Name);
end;
InsNode.ImageIndex := 1;
InsNode.SelectedIndex := 2;
Exit(True);
end
else
begin
{ if path ' File ' }
Short_EXT := AnsiUpperCase(ExtractFileExt(SearchRec.Name));
if (Short_EXT = '.TXT') then
Short_Name := ChangeFileExt(SearchRec.Name , '')
else
Short_Name := SearchRec.Name;
ShowMessage( ' 3 ? ' );
// ??????????
InsNode := _Tv.Items.AddChild(InsNode.Parent, Short_Name);
if (Short_EXT = '.TXT') then
begin
InsNode.ImageIndex := 3;
InsNode.SelectedIndex := 4;
end
else
begin
InsNode.ImageIndex := 5;
InsNode.SelectedIndex := 5;
end;
Exit(True);
end;
end;
{ FIND FOLDER & File }
arMask := TDirectory.GetFileSystemEntries(sPath, SO, FilterTN);
Application.ProcessMessages;
//Screen.Cursor := crDefault;
// ShowMessage(' All Good :))) ');
(*
ShowMessage( 'sDF - ' + '`' + sDF + '`' + sLineBreak + sLineBreak +
'Path - ' + Path + sLineBreak + sLineBreak +
'SearchRec.Name - ' + '`' + SearchRec.Name + '`' + sLineBreak
);
*)
end;
var
tNode: TTreeNode;
nodeChild: Boolean;
begin
if (DirectoryExists(APL_Files) = False) then Exit;
tv_zapis.Items.Item[0].Selected := True;
Screen.Cursor := crHourGlass;
tv_zapis.Items.BeginUpdate;
try
tv_zapis.Items.Clear;
tNode := tv_zapis.Items.AddChild(nil, 'Dominant_Folder');
begin
DFToTv (tv_zapis, tNode, APL_Files);
end;
finally
tv_zapis.Items.EndUpdate;
Screen.Cursor := crDefault;
end;
end;
Everything functions correctly, but the path does not display correctly on the TreeView (tv_zapis).

How to get the path to the file using backslash symbol and 2 dots ('\..')

In Delphi program I use ExtractFileDir function for getting parent folder and this code works correctly:
Fmain.frxReport1.LoadFromFile(ExtractFileDir(ExtractFileDir(ExtractFileDir(ExtractFilePath(ParamStr(0)))))+'\FastReports\report1.fr3');
How can I modify it and get parent folder's path with using "\.." as it is realised in Delphi sample program
Update:
I wrote this code:
setcurrentdir('../../');
s1:=getcurrentdir();
frxReport1.LoadFromFile(s1+'\FastReports\report1.fr3');
but I want one-line(as my code with ExtractFileDir ) and well-readable code to replace my code.
I have a function which absolutize a relative path.
To absolutize a path, you need to know the base path.
I the case of Delphi you show, the paths are relative to the project directory.
Once you have an absolute path, you can apply ExtractFilePath several times to go up in the directory levels.
Let's take an example: You have a relative path "....\SomeFile.txt". This path is relative to the base path "C:\ProgramData\Acme\Project\Demo". The complete path is: "C:\ProgramData\Acme\Project\Demo....\SomeFile.txt". Then the absolute path result of AbsolutizePath will be "C:\ProgramData\Acme\SomeFile.txt".
Note that Absolutize path take care of ".." (parent directory), "." (Current directory) and drive specification (Such as C:).
function AbsolutizePath(
const RelPath : String;
const BasePath : String = '') : String;
var
I, J : Integer;
begin
if RelPath = '' then
Result := BasePath
else if RelPath[1] <> '\' then begin
if (BasePath = '') or
((Length(RelPath) > 1) and (RelPath[2] = ':')) then
Result := RelPath
else
Result := IncludeTrailingPathDelimiter(BasePath) + RelPath;
end
else
Result := RelPath;
// If there is no drive in the result, add the one from base if any
if (Length(Result) > 1) and (Result[2] <> ':') and
(Length(BasePath) > 1) and (BasePath[2] = ':') then
Insert(Copy(BasePath, 1, 2), Result, 1);
// Delete "current dir" marker
I := 1;
while TRUE do begin
I := Pos('\.\', Result, I);
if I <= 0 then
break;
Delete(Result, I, 2);
end;
// Process "up one level" marker
I := 1;
while TRUE do begin
I := Pos('\..\', Result, I);
if I <= 0 then
break;
J := I - 1;
while (J > 0) and (not CharInSet(Result[J], ['\', ':'])) do
Dec(J);
// Check if we hit drive delimiter and fix it
if (J = 2) and (Result[J] = ':') then
J := 3;
Delete(Result, J + 1, I - J + 3);
I := J;
end;
end;

Delphi: Timer in Service Stops my FileReader

I am writing a Service that has a Timer which should check every 60 seconds if a Line has a particular number. Here is the code of the timer:
procedure TConnectionChecker.Timer2Timer(Sender: TObject);
var
myFile: TextFile;
sLine: string;
fileOpenLog: TStreamWriter;
fileOpenLogName, fileOpenLogPathName: string;
begin
ExePath := TPath.GetDirectoryName(GetModuleName(HInstance));
filename:= 'restult.txt';
filePath:= TPath.Combine(exePath, 'OutputFile');
filePathName:= TPath.Combine(filePath, filename);
fileOpenLogName:= 'Log_fileOpen.txt';
serviceLogPath:= TPath.Combine(exePath, 'LogFiles');
fileOpenLogPathName:= TPath.Combine(serviceLogPath, fileOpenLogName);
fileOpenLog := TStreamWriter.Create(TFileStream.Create(fileOpenLogPathName, fmCreate or fmShareDenyWrite));
if not FileExists(filePathName) then
begin
fileOpenLog.WriteLine('File not found');
TServiceThread.Current.Terminate;
fileOpenLog.Free;
end;
fileOpenLog.WriteLine('File found');
try
AssignFile(myFile, filePathName);
Reset(myFile);
fileOpenLog.WriteLine('File opened');
while NOT eof(myFile) do
begin
PingWorkedAufrufe:= PingWorkedAufrufe + 1;
readln(myFile, sLine);
fileOpenLog.WriteLine('Read Line: ' + sLine);
checkIfPingWorked(sLine);
end;
fileOpenLog.WriteLine('EOF');
finally
CloseFile(myFile);
end;
fileOpenLog.Free;
end;
And here is the code of my Procedure: checkIfPingWorked:
procedure TConnectionChecker.checkIfPingWorked(ALine: String);
var
AValue, StartOfLineToFind: String;
checkIfPingWorkedLog: TStreamWriter;
checkIfPingWorkedLogName, checkIfPingWorkedLogPathName: string;
begin
ExePath := TPath.GetDirectoryName(GetModuleName(HInstance));
StartOfLineToFind:= ' Pakete: Gesendet =';
ip:= '...';
fileName:= 'restult.txt';
filepath:= TPath.Combine(exePath, 'OutputFile');
filepathname:= TPath.Combine(filepath, fileName);
serviceLogPath:= TPath.Combine(exePath, 'LogFiles');
checkIfPingWorkedLogName:= 'Log_checkIfPingWorked.txt';
checkIfPingWorkedLogPathName := TPath.Combine(serviceLogPath, checkIfPingWorkedLogName);
checkIfPingWorkedLog := TStreamWriter.Create(TFileStream.Create(checkIfPingWorkedLogPathName, fmCreate or fmShareDenyWrite));
checkIfPingWorkedLog.WriteLine('Zeilen werden überprüft');
if Pos(StartOfLineToFind, ALine) = 1 then
begin
AValue:= Copy(ALine, 39, 1);
if AValue = IntToStr(5) then
checkIfPingWorkedLog.WriteLine('Success')
else
begin
checkIfPingWorkedLog.WriteLine('Error');
//Writing E-Mail...
//Authentifizierung
IdSMTP1.AuthType := TIdSMTPAuthenticationType.satDefault;
//Benutzerdaten für Authentifizierung
IdSMTP1.Username := '...';
IdSMTP1.Password := '...';
//Server-Daten
IdSMTP1.Host := '...';
IdSMTP1.Port := ...;
IdSMTP1.Connect;
try
IdMessage1.From.Address := '';
IdMessage1.Recipients.EMailAddresses := '';
//IdMessage1.CCList.EMailAddresses := '';
//IdMessage1.BCCList.EMailAddresses := '';
IdMessage1.Subject := '--AUTOMATISCHE BENACHRICHTIGUNG--';
IdMessage1.Body.Text := 'Der PC mit der IP: ' + ip + ' konnte nicht mehr erreicht werden';
IdSMTP1.Send(IdMessage1);
finally
IdSMTP1.Disconnect;
end;
checkIfPingWorkedLog.WriteLine('Email sent');
TServiceThread.Current.Terminate;
end;
end;
checkIfPingWorkedLog.Free;
end;
But I can only read the first two lines and then it stops.
Important to say is that I originally wrote this as a normal Program. And it worked fine. Now I am converting it into a Windows Service.
The Problem was, that I created everywhere and everytime new Log Files.
Now I Create one Log file on Service Create:
procedure TConnectionChecker.ServiceCreate(Sender: TObject);
var
logFilePathName, logFileName, exePath, logFilePath: String;
begin
ExePath := TPath.GetDirectoryName(GetModuleName(HInstance));
logFileName:= 'log_connectionTest.txt';
logFilePath:= TPath.Combine(exePath, 'logFile');
logFilePathName:= TPath.Combine(logFilePath, logFileName);
if not TDirectory.Exists(logFilePath) then
TDirectory.CreateDirectory(logFilePath);
swLogFile:= TStreamWriter.Create(TFileStream.Create(logFilePathName, fmCreate or fmShareDenyWrite));
end;
And I made a procedure where I ask for 2 params (destination and text) and write the line to the Log file.:
procedure TConnectionChecker.WriteToLog(destination, Text: string);
begin
swLogFile.WriteLine('[' + DateTimeToStr(now) + '] ' + destination + ' schreibt: ' + text);
end;
Finally I can call it in every procedure:
WriteToLog('checkIfPingWorked', 'Success')

intermittent problem with automatic file upload

I have written some code in Delphi/Pascal to upload a file to a website. To accomplish it, I run the code below in a thread immediately before I click the upload button. The thread looks for the windows upload file dialog and fills it in.
It works most of the time. Occasionally but with some frequency, it does not work. What is happening is that I am entering the full filename with path into the upload dialog. For some reason, sometimes windows will remove the path from the filename. Since the given filename (without the path) does not exist in the directory that windows is currently in, the upload fails.
For example, I am uploading "c:\uploads10\123.pdf", Windows will (sometimes) truncate the filename to "123.pdf" which does not exist in whatever directory the upload dialog defaults to, so the upload fails.
This has been driving me crazy for a while. Can someone tell me how to fix it?
for Looper := 1 to 2 do
begin
UploadDialogHandle := FindWindow('#32770', 'Choose File to Upload');
if UploadDialogHandle = 0 then
Sleep(100)
else
begin
SetFileUploadDialogPosition(UploadDialogHandle);
break;
end;
end;
if UploadDialogHandle = 0 then
exit;
for Looper := 1 to 1 do
begin
// Find the child ComboBoxEx32 window
UploadDialogFileEditHandle := FindWindowEx(FileUploadDialogHandle, 0,
'ComboBoxEx32', '');
if UploadDialogFileEditHandle = 0 then
Sleep(100)
else
break;
end;
if UploadDialogFileEditHandle = 0 then
exit;
for Looper := 1 to 1 do
begin
// Find the child ComboBox window
UploadDialogFileEditHandle := FindWindowEx(UploadDialogFileEditHandle, 0,
'ComboBox', '');
if UploadDialogFileEditHandle = 0 then
Sleep(100)
else
break;
end;
for Looper := 1 to 1 do
begin
// Find the child Edit window
UploadDialogFileEditHandle := FindWindowEx(UploadDialogFileEditHandle, 0,
'Edit', '');
if UploadDialogFileEditHandle = 0 then
Sleep(100)
else
break;
end;
if UploadDialogFileEditHandle = 0 then
exit;
Result := False;
if (UploadDialogHandle = 0) or (UploadDialogFileEditHandle = 0) or
(FileUploadButtonHandle = 0) then
exit;
StrPCopy(aUploadFileName, FileNameString);
SendMessage(UploadDialogFileEditHandle, WM_SETTEXT, SizeOf(aUploadFileName),
Integer(#aUploadFileName));
Sleep(200);
SendMessage(UploadDialogFileEditHandle, WM_GETTEXT, SizeOf(FileEditContents),
Integer(#FileEditContents));
if (StrComp(aUploadFileName, FileEditContents) = 0) then
SendMessage(FileUploadButtonHandle, BM_CLICK, 0, 0);

How to send a file AND other POST data with Synapse

Delphi used: 2007.
Hello,
I have a simple web page with two text input and one file input. Now, for the form to be sent, both the text inputs and the file input have to be filled. With Synapse, I know how to upload a file (HttpPostFile) and how to post data (HttpMethod). However, I don't know how to do both.
After looking at the source code of Synapse, I guess I have to "format" my data with boundaries or something like that. I guess I should have one boundary for my input file and another boundary for my text inputs. I found an article on the subject, but it's about sending email attachments. I tried to reproduce what they said with Synapse, with no results.
Code for HttpPostFile:
function HttpPostFile(const URL, FieldName, FileName: string;
const Data: TStream; const ResultData: TStrings): Boolean;
var
HTTP: THTTPSend;
Bound, s: string;
begin
Bound := IntToHex(Random(MaxInt), 8) + '_Synapse_boundary';
HTTP := THTTPSend.Create;
try
s := '--' + Bound + CRLF;
s := s + 'content-disposition: form-data; name="' + FieldName + '";';
s := s + ' filename="' + FileName +'"' + CRLF;
s := s + 'Content-Type: Application/octet-string' + CRLF + CRLF;
WriteStrToStream(HTTP.Document, s);
HTTP.Document.CopyFrom(Data, 0);
s := CRLF + '--' + Bound + '--' + CRLF;
WriteStrToStream(HTTP.Document, s);
HTTP.MimeType := 'multipart/form-data; boundary=' + Bound;
Result := HTTP.HTTPMethod('POST', URL);
if Result then
ResultData.LoadFromStream(HTTP.Document);
finally
HTTP.Free;
end;
end;
Thank you.
Your code is close. You are only sending your file field but not your text fields. To do all three, try this instead:
function HttpPostFile(const URL, InputText1FieldName, InputText1, InputText2FieldName, InputText2, InputFileFieldName, InputFileName: string; InputFileData: TStream; ResultData: TStrings): Boolean;
var
HTTP: THTTPSend;
Bound: string;
begin
Bound := IntToHex(Random(MaxInt), 8) + '_Synapse_boundary';
HTTP := THTTPSend.Create;
try
WriteStrToStream(HTTP.Document,
'--' + Bound + CRLF +
'Content-Disposition: form-data; name=' + AnsiQuotedStr(InputText1FieldName, '"') + CRLF +
'Content-Type: text/plain' + CRLF +
CRLF);
WriteStrToStream(HTTP.Document, InputText1);
WriteStrToStream(HTTP.Document,
CRLF +
'--' + Bound + CRLF +
'Content-Disposition: form-data; name=' + AnsiQuotedStr(InputText2FieldName, '"') + CRLF +
'Content-Type: text/plain' + CRLF +
CRLF);
WriteStrToStream(HTTP.Document, InputText2);
WriteStrToStream(HTTP.Document,
CRLF +
'--' + Bound + CRLF +
'Content-Disposition: form-data; name=' + AnsiQuotedStr(InputFileFieldName, '"') + ';' + CRLF +
#9'filename=' + AnsiQuotedStr(InputFileName, '"') + CRLF +
'Content-Type: application/octet-string' + CRLF +
CRLF);
HTTP.Document.CopyFrom(InputFileData, 0);
WriteStrToStream(HTTP.Document,
CRLF +
'--' + Bound + '--' + CRLF);
HTTP.MimeType := 'multipart/form-data; boundary=' + Bound;
Result := HTTP.HTTPMethod('POST', URL);
if Result then
ResultData.LoadFromStream(HTTP.Document);
finally
HTTP.Free;
end;
end;
If you switch to Indy, you can use its TIdMultipartFormDataStream class:
function HttpPostFile(const URL, InputText1FieldName, InputText1, InputText2FieldName, InputText2, InputFileFieldName, InputFileName: string; InputFileData: TStream; ResultData: TStrings): Boolean;
var
HTTP: TIdHTTP;
Input: TIdMultipartFormDataStream;
Output: TMemoryStream;
begin
Result := False;
try
Output := TMemoryStream.Create;
try
HTTP := TIdHTTP.Create;
try
Input := TIdMultipartFormDataStream.Create;
try
Input.AddFormField(InputText1FieldName, InputText1);
Input.AddFormField(InputText2FieldName, InputText2);
Input.AddFormField(InputFileFieldName, 'application/octet-stream', '', InputFileData, InputFileName);
HTTP.Post(URL, Input, Output);
finally
Input.Free;
end;
finally
HTTP.Free;
end;
Output.Position := 0;
ResultData.LoadFromStream(Output);
Result := True;
finally
Output.Free;
end;
except
end;
end;
I also use synapse in my projects. To be make my work simple and faster with Synapse, I wrote THTTPSendEx class, that gives fast speed of using and minimum of code and more features.
Currently it's a beta version.
It's views like Indy.
Create THTTPSendEx class.
Create methods OnBeginWork, OnWork, OnWorkEnd from it prototypes(see pas file), and assign it to created class. Thats all what you need, and just call GET, POST functions of the class.
I also implement multipart-fomdata for fast file posting in this format as TMultipartFormDataStream class.
With it you can easy write files and fields.
Example of using:
var
HTTP:THTTPSendEx;
Data:TMultipartFormDataStream;
sHTML:string; //Recived HTML code from web
begin
HTTP:=THTTPSEndEx.Create;
Data:=TMultipartFormDataStream.Create;
try
Data.AddFile('myFile','Path to the local file(No UNC paths)');
Data.DataEnd;
if HTTP.Post('URL HERE',Data,sHTML) then
begin
//Connection established
//Check HTTP response
if HTTP.IsSuccessfull then //HTTP returns "200 OK" code.
begin
ShowMessage('File successfully posted to the server.');
end;
end else
begin
ShowMessage('Can not establish a connection to the server...'+#13+'Network is not avaliable or server socket does not exist.');
end;
finally
FreeAndNil(HTTP);
FreeAndNil(Data);
end;
end;
You can see it at my web-site.
If you have any ideas for this, please write it's as a comment to project page.
Sorry for mistakes in english.

Resources