Delphi - Write/read files in a shared environment - delphi

I have some problems on files which are placed in a LAN: there is a single Delphi program (server) which should write some files, which can be only read by multiple Deplhi programs (clients).
I use these simple instructions in the server for writing (DataList is a TStrings):
Stream:=TFileStream.Create(filePath,fmOpenWrite or fmShareDenyWrite);
try
DataList.SaveToStream(Stream);
finally
Stream.Free;
end;
The clients check every 5 seconds if the file above is modified (by just checking the FileAge), and if modifications are occurred, they load the DataList in the following way:
try
Stream:=TFileStream.Create(filePath,fmOpenRead or fmShareDenyNone);
DataList.LoadFromStream(Stream);
finally
Stream.Free;
end;
Normally everything works perfectly, but sometimes it happens that the server or the client raise an exception because "the file is in use by other process".
I don't understand which is the problem: I tried many alternatives, but this can happen also with just the server and only one istance of the client running..
Any ideas?
Thanks!

By design, network file systems can't be trusted. At least, NFS (in Linux) and SMB (in Windows) have no proven lock feature: concurrent access is not safe.
You need to use a Client-Server protocol to ensure that shared data is safe. You can use TCP/IP, HTTP or any other mean.
I recommend using a true service implementation, like DataSnap, RemObjects or our Open Source mORMot.

Related

How to solve exception error when consuming Microsoft Sql Server Reporting Services (SSRS) 2005 from Delphi XE7

I am trying to create a sample Delphi XE7 desktop app that will connect to SSRS 2005 web service but every time I try to call LoadReport web method, the following error is shown:
This is what I have done so far:
Create a desktop app.
Import WSDL for ReportExecution2005 and ReportService2005.
Create a button that call the web service based on the code shown
here. The web service locations as well as report are hardcoded for
simplicity purposes.
This is the code snippet from the link:
HTExec := tHttpRio.Create(nil);
rsExec := GetReportExecutionServiceSoap(False, ExecURL, HTExec);
// Load the selected report.
LRParams.Report := 'ReportName';
LoadParamsResponse := rsExec.LoadReport(LRParams); //here it fails
Note: I have already created a .NET win form app (VS2010 and VS2013) that consumes this web service without any issues, thus I know the web service and report to render are working OK. Sadly our requirements is for a Delphi solution, My educated guess is that the WSDL importer generated code is not correct and somebody out there may have come across with this issue before and know how to solve it.
I did a quick search for "http://schemas.microsoft.com/sqlserver/2005/06/30/reporting/reportingservices/LoadReport"
and found this.
If it applies to you as well, it may be the case you're calling the service on an incorrect URL, use the one with ReportExecution2005.asmxin it, not ReportService2005.asmx
(There's a lot more here)
To find out differences between the Delphi version and the working version, use a HTTP proxy (Fiddler2) to capture the SOAP HTTP traffic in both setups.
If you have no access to the working environment, use SoapUI to create SOAP requests.

Generate PDF using QuickReport from a Windows Service in Delphi

I'm writing a windows service using Delphi XE3. The service is going to read from a database, generate a pdf using quickreport 5.05.1.
I plan to generate the pdf using TQRPDFDocumentFilter.
Everything works fine in a normal VCL application, but when I implement it in a windows service the service hangs (without any exceptions) when I do a QuickRep.Prepare.
I have read that it is possible to use QuickReport in a windows service, but I do not know how. Any suggestions?
Where is the code:
procedure foo
var
pdfFilter: TQRPDFDocumentFilter;
begin
with TForm2.Create(Self) do
begin
ClientDataSet1.Open;
QuickRep1.Prepare;
pdfFilter := TQRPDFDocumentFilter.Create(GetApplicationFolder() + 'test.pdf');
try
QuickRep1.QRPrinter.ExportToFilter(pdfFilter);
finally
pdfFilter.Free;
ClientDataSet1.Close;
end;
end;
end;
Edit:
I have also tried turning off "show progress" on the QuickReport as suggested in another thread.
Writing some code to catch an exception reveals that it indeed throws one. The message is "There is no default printer currently selected".
So this leads me to believe that the local system user that the service is running under does not have any printers installed and that this is the problem.
I have resolved a similar problem (printing to a shared network printer from a Java server running as a Windows service) with these steps:
log on as the user who will run the service
install the printer
IIRC with Delphi applications, the printer name is not case sensitive (with Java it is).

Downloading fails from ftp server using TMS Webcopy software in Delphi xe3

Hi i am trying to use TMS software to download a file. But cannot seem to get the file to download.
i use the following code, and have written in an exception handler which keeps telling me that the URL cannot be found. Any help would be appreciated.
main.WebCopy1.Items.Clear;
with main.WebCopy1.Items.Add do
begin
FTPHost :=fHost;
FTPUserID := fusername;
FTPPassword := fPass;
URL := '\Setup\libmysql.dll';
Protocol := wpFTP;
CopyNewerOnly := true;
TargetDir := 'c:\Program Files\myfolder\';
end;
main.WebCopy1.Execute;
May i just add, i just tested the same code and url in another project that i had written and it worked.
Thank You
Things I would try:
use the debugger and check the code which connects and sends the HTTP request
check your HTTP server log file to see which resource has been requested
use a HTTP proxy (Fiddler) to intercept and analyze the HTTP traffic between the Delphi application and your HTTP server
extract the relevant part of the two projects, then diff their sources
(both with the working and the non-working application).
Sorry guys i found the problem. The connection was not set to passive.
I checked on the server and could not find that any connection was being made to the ftp account, and realized that the problem was not the path, it was the connection.
So i checked and saw the connection was set to passive, changed it an vualla, it worked.
So Now We know, For it to work passive must be set to true.
Thanks alot anyway guys

Launching application from a database

I have many users using my application. However if I do some update, which I put on the server, not all of them are willing to update it (they sometimes afraid of changes they do not want to accustom).
So I speculate, how to force them to launch the latest application. There are surely several ways how to do it, but I have heard, that it is possible to launch an application stored in a blob field of a database.
Does anybody knows how it can be accomplished? (I am using MySQL database)
thanx
Without judging on meaningful or nonsense ....
You could use uExecFromMem .....
There is a Memoryleak in this unit which can be fixed by adding:
ResumeThread(PI.hThread);
Result := PI.hThread;
FreeMem(pFile); // added here
end;
an example call using a TBlobField would be
var
ms:TMemoryStream;
begin
ms:=TMemoryStream.Create;
try
TBlobField(YouDBBlobField).SaveToStream(ms);
ms.Position := 0;
ExecuteFromMem(Application.ExeName,'',ms.Memory); // pointing to an existing executable
finally
ms.Free;
end;
end;
My advice is to use libraries.
You can have a small main executable file (some kind of "launcher"), which won't do nothing but launch external .dll fields. Just like a kernel does load modules at runtime (think about how Windows or Linux work).
Then you download an updated version of a .dll, stop and unload the old one, then load and initialize the new version.
Of course, your code has to be "clean", with proper startup and shutdown functions for each .dll.
But I suspect it would be much less error prone than ExecuteFromMem(). In this respect, good old load + execute of an .exe file (as Remy suggested) sounds like a much better option to me.

IMAP + TLS/SSL with Synapse?

I'm currently trying to add to a software the capability to list unread emails in the user's inbox using IMAP. After having no success at all using Indy10, I discovered Synapse which seemed better for what I needed, but I can't find a way to get it working.
My problem is with the login (thus I think with the SSL configuration). I can't find a working combination of "FullSSL", "Sock.SSL.SSLType" and "AutoTLS". Whenever I do the "Login()" function, it fails.
For the sake of testing, are any of you able to connect to Gmail's IMAP server using Synapse, and, if yes, how?
Having just done this myself, I might recommend that you just follow the simple example on the Synapse HowTo http://synapse.ararat.cz/doku.php/public:howto:smtpsend
The only other thing would be that you need to download the openssl dll's and place the in your project folder.
IMHO .... I would recommend that you also consider looking at CleverComponents.com at their IMAP4 with built in SSL (not requiring OpenSSL, which has some licensing restrictions) and is completely NON-Blocking sockets.
mfw is correct, but here's a clearer and more current answer.
Go to the page skamradt said and download the "Binaries" ZIP. From its Bin folder, copy these files into your EXE's folder:
libssl32.dll
libeay32.dll
In your DPR, add
uses ssl_openssl;
For GMail / port 587:
// support for upgrade session to TSL/SSL:
SMTP.AutoTLS := True ;
SMTP.FullSSL := False;
For other SMTP servers / port 465:
// support for TSL/SSL tunnel:
SMTP.AutoTLS := False;
SMTP.FullSSL := True ;
This might also work for POP / port 995. It's how I got Synapse to send mail securely in Delphi 7 + Synapse Release 40 (2012-04-23)
I suggest Mailbee IMAP ActiveX from AfterLogic.
I did the research when developing Gmail Keeper (a Gmail backup software), CleverComponnets' feature set seems good but their support is very badm they seem discontinued that promising component set, you can try to email them back and forth to see if there is anything changed since it's been a long time since I checked them last time, I indeed wish they continue their VCL.
On the other hand, afterlogic's support is really good, especially when the reasonable price is considered.
One-click to backup Gmail with labels to local disk (supports backup scheduling)
http://GmailKeeper.com
You need these libraries in your program:
libeay32.dll
ssleay32.dll

Resources