UrlDownloadToFile doesn't work in Delphi XE2? - delphi

I'm trying to download a file from the internet with Delphi XE2, but Nothing happens.
Here's my code:
uses URLMon;
...
procedure TForm1.Button1Click(Sender: TObject);
Const
SourceFile = 'http://www.google.com/intl/de/images/home_title.gif';
DestFile = 'c:\download\home_title.gif';
begin
UrlDownloadToFile(nil, PChar(SourceFile), PChar(DestFile), 0, nil);
end;
So my problem is: When I click the button, the program doesn't download the file.
I tried to download to another directory, I tried to download other files but nothing.
I can't get it to work.
What Am I doing wrong?
Please Help Me!

Your code works fine. Most likely the problem is a local one. Perhaps a problem with your network connection. Or perhaps the directory 'c:\download' does not exist.
To investigate your local problem, you'll need to make a note of the value returned by the function UrlDownloadToFile. It's an HRESULT and S_OK indicates success. Other values indicate failure. Once you know what the error code is, you should be able to track down your problem.
Having said that, UrlDownloadToFile doesn't seem to do a good job of returning meaningful error codes. For example, if you make DestFile be a path with non-existant folders, then the function still returns S_OK.

Related

Delphi: Unzipping Files using FlexCompress (3rd-Party-Component)

I am having trouble unzipping files using the Delphi 3rd Party component FlexCompress. Here is the Code, detailed explanation after the code:
MyZipReader := TFlexCompress.Create(myComponent);
MyZipReader.Name := 'MyReader';
MyZipReader.FileName := DataPath; //e.g. C:\Users\thisUser\AppData\Local\Temp\ThisTempFolder\ThisZip.zip
MyZipReader.OpenArchive(fmOpenRead);
MyZipReader.BaseDir := BasePath; //e.g. C:\Users\[...]\ThisTempFolder\UnzipHere\
MyZipReader.CreateDirs := TRUE;
MyZipReader.ExtractCorruptedFiles := TRUE;
MyZipReader.ExtractFiles := ('*.*');
MyZipReader.closeArchive;
All files will be extracted and placed accordingly, so that's OK.
BUT: All files are empty. No text no nothing.
I have no idea what I am doing wrong. If I extract an archive I packed with Flexcompress everything is OK but if I try this with an external archive this behaviour occurs. Is there some sort of switch I am missing? I would be grateful about every tip or idea! I also tried the options ReplaceReadOnly and overwriteMode. Did not help and I am out of Ideas. If anyone knows some sort of FlexCompress forum I would also appreciate a link, maybe I could find info there? Sadly componentAce does not seem to host something like this.
Edit(2021.12.14 - 1.17pm)
Extra information gathered in the process:
One should not set the ExtractCorruptedFiles property to TRUE. This will prevent the eventhandler from raising an exception within the extractFiles() procedure

How to resolve "Sevenzip: Error result (00000001) Incorrect function" using JCLcompression unit

I'm using JCL version 2.4.1.4571 with Delphi XE3 and have had no luck decompressing archives. I've downloaded the dll's from JEDI's site and also tried using the 7z.dll (32bit) from 7-zip.org but either way I get the same error when I try to "ExtractAll"
See function below:
function TForm1.Decompress(FileName, DestDir: String): Boolean;
var
archiveclass: TJclDecompressArchiveClass;
Myarchive: TJclDecompressArchive;
begin
Decompress := False;
// Filename = name.7z or name.zip (simple test zips nothing fancy)
// DestDir = fully qualified path to an existing directory
archiveclass := GetArchiveFormats.FindDecompressFormat(FileName);
Try
if Assigned(archiveclass) then
Begin
Myarchive := archiveclass.Create(FileName);
if (Myarchive is TJclSevenZipDecompressArchive) then
Begin
try
Myarchive.ListFiles; { Fails without doing this first }
{ ExtractAll (AutocreateSubDir) must be set true if arc has directories or it will crash }
Myarchive.ExtractAll(DestDir, True);
Decompress := True;
except on E: EJclCompressionError do
Begin
ShowMessage(e.Message);
End;
end;
End
Else
ShowMessage('Not supported by 7z.dll');
End;
Finally
MyArchive.Free;
End;
end;
When I execute the MyArchive.ExtractAll line, I get an exception Sevenzip: Error result (00000001) Incorrect function. I based my code on code from others here on StackOverflow. Am I missing something I need to do first or is this a bug? I've replaced the extract line with MyArchive.ListFiles and get the same error (I saw that in an example here; however, I've yet to divine the purpose of ListFiles.
Compiling to 32bit target.
Edit: Created a series of different types of archives using 7-zip and tried to decompress each with my program. The first thing I discovered is that if the archive contains directories of files, ExtractAll will crash if you don't set the second parameter to True. I then tested archives with different compression methods.
.7z archive using LZMA2 Ultra compression gives the Hresult = 1 error
.zip archive using LZMA Ultra compression gives the Hresult = 1 error
.zip archives using flavors of Deflate or deflate64 all work fine.
It appears that the library doesn't handle LZMA compression at all. Since it makes no sense that the 7z.dll can't handle it, I'm guessing the problem is with the JEDI JCL code. I need to be able to compress/decompress .7z and .zip's using LZMA with this library or I could have just used the built in zip stuff to begin with. Any further suggestions would be appreciated.
I think that is a JCL implementation bug. 7z use COM interfaces, and returns HRESULT codes. JCL attemptes to translate them into error messages using SysErrorMessase(), but AFAIK it works only for Win32 error codes, not HRESULT. That way the return code S_FALSE gets mapped to ERROR_INVALID_FUNCTION (see http://issuetracker.delphi-jedi.org/view.php?id=6348).
My guess is that a 7z call is returning S_FALSE for some reason, because it encounters some issue when decompressing - and the error is deceiving.
See also Error Handling in COM.
Further Googling on this problem turned up http://sourceforge.net/p/jcl/mailman/message/21371812/
It appears "FindDecompressFormat doesn't find archive format if file name is not in lower case."
I tried changing the string I was passing to lowercase and I successfully decompressed an LZMA archive.
archiveclass := GetArchiveFormats.FindDecompressFormat(lowercase(FileName));
JEDI JCL would be a cool library if it had any documentation whatsoever - sad.
If you call TJclZipDecompressArchive with a filename that does not exist you will get the same not very helpful error message on the ListFiles function.
Moral of the story check if the file exists yourself before calling the api.

Getting file property details of a Word file

I'm trying to get sonme information from the details page of a file properties dialogue box.
For example:
I'm just after the two underlined dates for now.
I have searched and found some code in the thread here:
a thread on the Tek-Tips forums
and I've found other code around which looks very similar to the code in that thread.
I grabbed that code and made a little application to check it - the code in the button handler is:
procedure TfmMain.Button1Click(Sender: TObject);
var
fnp: string;
bb: boolean;
ss: string;
begin
fnp := 'c:\temp\aaaa.doc';
bb := IsNTFS(fnp);
if bb then
moOne.lines.add('Yes, it is NTFS')
else
moOne.lines.add('No, it is not NTFS');
ss := GetFileSummaryInfo(fnp);
moOne.lines.add(ss);
end;
The NTFS check works fine, my file system is reported as NTFS, but I get the following OLE error
Project raised exception class EOleSysError with message 'OLE error 80030002'
Stepping through, this occurs on the line:
OleCheck(PropSetStg.Open(FmtID_SummaryInformation,
STGM_READ or STGM_SHARE_EXCLUSIVE, PropStg));
in the code I linked to on the Embarcadero forums.
What am I doing wrong?
I'm using Delphi 5 on Win 7 64 bit.
That COM error code is STG_E_FILENOTFOUND. So, on the face of it, it would seem that the summary information property set does not exist for that document.
From what I can tell, the getter function in that code does not work, but the setter function does. So you are not doing anything, but I think the code you are trying to use does not work as advertised.
I have found some code that does work ... the example shows how to get the document title, subject, author, comment, revision, application, creation date and word count. I've tried it on a few MSWord documents and the information fetched is correct.
It can be found here:
fourm.sources.ru file details code thread

EIBInterBaseError 'unavailable database' when trying to create a Firebird database in Delphi

I'm trying to create a Firebird database during runtime. The procedure that I'm using to do this is this one:
procedure CreateDatabase(DBName: String);
var
IBDatabase1: TIBDatabase;
begin
IBDatabase1 := TIBDatabase.Create(Self);
try
IBDatabase1.DatabaseName := ChangeFileExt(DBName, '.fdb');
IBDatabase1.Params.Add('USER ''SYSDBA''');
IBDatabase1.Params.Add('PASSWORD ''masterkey''');
IBDatabase1.Params.Add('PAGE_SIZE 4096');
IBDatabase1.Params.Add('DEFAULT CHARACTER SET WIN1252');
IBDatabase1.CreateDatabase;
finally
IBDatabase1.Free;
end;
end;
I've achieved this without problems in any little project that I create to teste this function. However, if I try to run this code in the same machine, same Delphi, same everything, except that it is a different (and quite big) project, I get the following error on the IBDatabase1.CreateDatabase line:
First chance exception at $7579B9BC. Exception class EIBInterBaseError with message 'unavailable database'. Process xxx.exe (4144)
Anybody has any clues about this one? Maybe some way to debug this properly?
Thanks in advance.
EDIT
It seems to be something in my project file. I've managed to generate a new one and the problem is gone, but I'm afraid of being bitten by this in the future. What could possibilly cause this?
It wasn't my project file. It was an old GDS32.dll that was dropped in the same directory as the executable. Removing it solved the issue. Hope this might help someone with the same problem.

Too many open files

I get an EInOutError with message 'Too many open files' when executing this code block repeatedly for some time from a number of client threads:
var InputFile : Text;
...
Assign (InputFile, FileName);
Reset (InputFile)
try
// do some stuff
finally
CloseFile (InputFile);
end;
The number of client threads is approximately 10, so only 10 files can be open at any time. Is there any possibility that Delphi refuses to close files right away? Can I ensure that it does? Or am I making a mistake here? This is the only place where I open files and the try..finally block should guarantee that opened files get closed, shouldn't it?
REEDIT: forget the edit
I can only advise you to use the more "modern" facilities for dealing with files. I don't know whether there is a limit of open files using the Windows API, but I just tested and could easily open 1000 streams in parallel:
procedure TForm1.Button1Click(Sender: TObject);
var
Strs: TList;
i: integer;
begin
Strs := TList.Create;
try
for i := 1 to 1000 do begin
Strs.Add(TFileStream.Create('D:\foo.txt', fmOpenRead or fmShareDenyWrite));
end;
finally
FreeObjectList(Strs);
end;
end;
I have never understood why people still use untyped files instead of TStream and its descendants in new code.
Edit: In your comment you write that you only want to read plain text files - if so just create a TStringList and use its LoadFromFile() method.
You aren't running this on an older Windows 9x based computer, are you? If so, you might be running into a DOS filehandle problem.
Delphi closes immidiately in the CloseFile. Your example code seems to be correct.
Try again without anything between try and finally.
There IS a thread safety issue here although I can't see how it could cause the problem.
The problem is Reset uses the global FileMode variable.
As for client threads--are you sure they aren't leaking away on broken connections or something?
Might be useful to put some debug output alongside the Reset and the Close so you can see how long each thread has the file open for.
Do you really need threads? It sounds like they are causing you problems. Your code would be easier to debug without them.
This code should work just fine. There are no known problems related to using files from threaded code (as far as I know). We use such idioms fairly regularly and everything works fine.
I would suggest adding some logging code (before Assign and CloseFile) to see if a) close is executed and b) you really have only 10 threads running. Maybe your thread terminating logic is faulty and CloseFile never executes.

Resources