How to extract dll from the resource - delphi

my application uses Bass.dll and i added it to the resource. I wanted it to be extracted before the application starts it chrash. how to void it?

XBasic3000, I think your problem is wich maybe you are using a external declaration like this
function Foo: integer; stdcall; external 'bass.dll';
so the OS cannot resolve the address of the function in the dll.
instead you must use the LoadLibrary() and GetProcAddress() functions after extracting the DLL, in this way you can avoid crashing by checking for the existance of the DLL.

I think that the solution to your problem is described by RPUZ or Chris Thornton (both up-voted). If extracting files to the hard drive causes you trouble, you should know that it is possible to load the DLL directly from memory instead.
Zarko Gajic explains at delphi.about.com.

If you extract the DLL, where do you put it? Your app isn't a setup app (setup.exe) which would have special privleges, so it cannot write to \windows\system32 or even \program files\yourapp under Vista/Windows7. Attempting to put it into the program directory will result in it being located elsewhere, via the VirtualStore. So you must verify FileExists('bass.dll') prior to attempting LoadLibrary().

Related

Trouble with Paths?

I have a problem where I am creating an Android app using Firemonkey in Delphi XE6. The app consists of a TWebBrowser and a button...nothing fancy.
I am TRYING to display an xhtml file that is located on my SD card.
I "think" I am doing all the right things like using "TPath.GetHomePath" and putting my file in this location. - and made sure the permissions are set in the project.
Being a seasoned developer, I know that I need to use "file://" so the browser knows it a local file, as I have done a million times in Delphi over the years, and even checking the help file which uses the example "WebBrowser1.Navigate('file://MyFile.pdf')"
So I construct my URL by doing :
AppPath := TPath.Combine(TPath.GetHomePath, 'myfile.xhtml');
I then go:
WebBrowser1.Navigate('file://'+AppPath);
When the navigation happens, it tells me the file doesn't exist, file:///data/data/com.embarcadero.WebBrowser/files/myfile.xhtml
I spotted the 3 /'s i.e. file:/// and thought I would just hard coded the path into a string and got the same problem saying the file doesn't exists and it reverting back to file:///
Can anyone see what I am doing wrong? its got me puzzled thats for sure! :-)
Thanks, Jeremy
Instead of
TPath.GetHomePath
i used
TPath.GetPublicPath
which leads me to /storage/emulated/0/Android/data/<myapp>/files/ folder (the one i need).
TPath.GetHomePath
gives me data/data/<myapp>/files/ which is not exists (i guess, maybe i need something like GetAbsolutePath).

gnugettext base directory for Delphi XE2

I am evaluating gnugettext for Delphi XE2. All seems to be OK except that it seems that we don't have translation directory(ies) choice : it is always "\locale\Lc_MESSAGES\".
As I need to share translation for some exe in the same application it's not very convenient. I looked in the sources and see :
BaseDirectory:=ExtractFilePath(ExecutableFilename);
OK, I may change the source but I don't like it.
Any elegant idea ?
You can use the provided bindtextdomain function to change the directory where your application looks for the dictionary files. The first parameter will normally be the string 'default', and the second parameter is the directory to go to. The actual dictionary files will still need to be in a subfolder of the specified directory (using the same \locale\LC_MESSAGES\ pattern), but this at least gives a convenient way of sharing translations across multiple programs.

How to write a file that is being read?

My application reads a TextFile of floating point numbers slowly. From time to time circumstances change and the file has to be rewritten. Some example code:
procedure TAMI_Column_Selector.read_continuously (file_name: string);
var infile: TextFile;
f: Double;
begin
AssignFile (infile, file_name);
Reset (infile);
try
while not EOF (infile) do
begin
Read (infile, f);
process (f); // this may take quite some time, seconds or even minutes
end; // while
finally
CloseFile (infile);
end; // try..finally
end; // read_continuously //
How can I write a file that is open for reading? More specifically:
how can I write a file that is open for reading?
how to prevent a crash when the application tries to read a file that at that moment
is being written
how does my application know that the file has been rewritten?
I think I could solve the first to questions be reading the file into memory and read that (is there a TextFile that can be written to and read from memory)? Then still remains how I can test a file has been written over.
Anyone having an (elegant) solution to this problem?
Thanks in advance.
Using Delphi XE on windows 7
To write to a file that's also open for reading, there's generally not anything special the writer needs to do. If everyone else who has the file open has allowed writing to the file, then the intended writer can open the file for writing, write to the file, and close it. If the others haven't allowed writing to the file, then the intended writer won't be allowed to open the file in the first place, and there's nothing it can do about it.
How to open a file for reading while also allowing writing depends on the opening method being used. With CreateFile, the dwDesiredAccess parameter is the usual GENERIC_READ, and the dwShareMode parameter is FILE_SHARE_READ or FILE_SHARE_WRITE. If you're using a TFileStream, then the mode parameter of the constructor should be fmOpenWrite or fmShareDenyNone. If you're using AssignFile and Reset, then you'd need to set the FileMode global variable, but that doesn't support any sharing modes, so you can't use Pascal-style I/O.
Reading a file that is at the same time being written does not inherently cause a crash. It certainly doesn't cause problems at the OS level. If your program crashes, it's because it wasn't written to anticipate reading failures. When you read something, check the API result to confirm that you read as many bytes as you requested. You can also have the reading and writing applications communicate with each other. You might use a synchronization object to serialize access to the file, or the writer might send the reader a signal to indicate that the file has changed, and that the previous read might not be accurate anymore. It's up to you to work the details.
If the reader is going to keep a copy of the file in memory, then it probably doesn't need to bother sharing write access. Instead, it can open the file and only share read access, make a copy of the file in memory, and the close the file. The writer can then open the file without any worries of trampling on the reader process because there's nothing to trample. It can notify the reader that something changed, and the reader can either reload the entire file or just load the part that changed. (The writer will have to tell the reader which part changed, though; there's no other way for the reader to detect that without reading the entire file and seeing how it differs from the memory copy.)
Another way to keep writes from interfering with reads is to use transactions. Transactional NTFS is being phased out, though. Microsoft has published a list of alternatives, so you can try to find something that matches your needs.

Cannot send info from dll to exe with WM_COPYDATA

I am trying to send a record from one dll to one exe.
The dll is an Outlook add-in I wrote, the exe is my main application.
I used this example to succesfully send a record from exe to exe, but when I try to do the same from dll to exe it doesn't work.
Note: please open the link and there you find the code I am using. That code is for an EXE sender application and a EXE sender application. This works.
If I put the sender code inside a dll the example doesn't work anymore.
Could you suggest a solution?
Assuming that you can make it work with a string (which remains to be seen), you could simply serialize your record to a string (CSV, possibly using a weird delimiter like ~), send as a string (PAnsiChar or PWideChar), then de-serialze back into the record at the other end. This isn't as elegant as what you want, but absolutely, positively, will work.

IsUPXCompressed Problem

The function to determine if an exe file has been compressed (written by RRUZ) is excellent except I found a problem with the code. If the function IsUPXCompressed is called then you try to run upx, UPX can not save the file it modifies. There is something not sharing rights correctly in the function. I have tested this for several hours. If I do not call the method then UPX can write the files with no problem. If you call it then try to run UPX it will not save the file. UPX reports an IOException Permission denied error when trying to write the file.
Can anyone spot something wrong in the code that would cause this problem?
I posted this again because after 24 hours no one seem to see my posts about it at its original locastion: Method to determine if an exe file has been compressed with UPX
Thank-you
#RRUZ's code doesn't close either the file mapping or the file handle used to create it.
After the end of the for.. loop in the code, add the following two three lines:
UnmapViewOfFile(pBaseAddress);
CloseHandle(hFileMap);
CloseHandle(hFile);
No need to test them first, as the prior code exited if either of the function calls to open the handles doesn't succeed. (There should probably be try..finally protection of the two opening calls, but I'll leave that to RRUZ to correct in his original post.)

Resources