I am currently encoutering a very strange problem. In one of my applications I use OpenSSL and Indy in order to create a secure TCP connection to a host. I wanted to test if the application (and Indy) are recognizing if the OpenSSL-libraries are missing. Those libraries are placed inside the application folder.
The strange thing is that my application still works fine even though I have removed the libraries. I also removed OpenSSL itself from my computer and searched for any other appearance of the OpenSSL-libraries. There are no OpenSSL-libraries on my computer.
So what is going on? I call the Load() method from IndyOpenSSLHeader in order to load the libraries and guess what...they are loading perfectly. How can this be? There are no libraries on my computer ^^
Btw I did NOT set up a custom library path. I am using the default one which - as far as I know - should be the application folder.
I am using Delphi XE5 and Indy 10 for me application.
What is wrong here?
Thanks in advance!
If you are on iOS then Indy links to OpenSSL statically. On any other platform, there is no possible way that Indy can successfully use OpenSSL SSL/TLS without loading its library files first, so they have to be getting loaded from somewhere you missed. If you are running on Windows, use Process Explorer to see where they are actually being loaded from.
Indy defaults to using the OS search path to load external libraries. The OS defaults to looking in the app's folder, but it can also look in other places as well. You can use Indy's IdOpenSSLSetLibPath() function to specify where you want OpenSSL loaded from (there is a similar function for ZLib - IdZLibSetLibPath()). This is good to ensure your app loads the libraries only from your app's folder and nowhere else, in case someone maliciously deletes the libraries from your app's folder in an attempt to trick it into loading the libraries from another path on the OS's search path. It is also good for testing purposes if you just want to see how your app reacts when the libraries are missing, without having to actually delete them.
They may be statically linked into your binary.
Also, there is a lot of places where SSL libraries could be.
See this article (Search Order for Desktop Applications):
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682586%28v=vs.85%29.aspx
Related
Update: It turned out that there was something with installing Delphi 10.4 CE that broke my app (thanks, DelphiCoder!); specifically, it was something in the Windows Registry that was broken. After using ProcessMonitor to ensure no Delphi 10.4 (aka 21.0) was being invoked, I ended up cleaning out the registry of all 10.4 references, rebuilding completely (not clear if this was needed or not), and lo and behold, it works again! I'm adding this update in case someone in a similar situation finds this question - remember to back up your registry first and be careful!
Original Post: I created several DLLs with Matlab Compiler 10 years ago, with C wrappers, to make them available with Delphi. Once I got them working, they always worked - until today! The code in the C wrapper initialization function in question is in the code box below; the "Could not initialize library" is printed to the console when I run my Delphi app.
mclmcrInitialize();
if (!mclInitializeApplication(NULL, 0)) {
fprintf(stderr, "Could not initialize application\n");
}
if (!libMyDllInitialize()) {
fprintf(stderr, "Could not initialize library\n");
}
The problem is that this has never happened before, over all the probably 10 years since we first wrote these! My machine has the correct version of the 32-bit 2021a MCR installed, as it has for several years; I've installed this on numerous machines from Windows XP up to Windows 10, The DLLs were last built 5 - 7 years ago; anyway, I don't have access to the Matlab compiler anymore. The only thing that has changed is my app, but not anywhere near where this DLL initialization code is called; also, when the problem first happened, my app was working, then didn't -without any changes. Finally, I went back a few days and rebuilt my app, and it still fails.
So I am really stuck, and need some advanced help in debugging DLL startup issues on Windows. I tried looking in the Windows Event Logger, but nothing appears to show up there. Logs to check? A setting in the Registry that somehow got hosed? Wrong phase of the moon? How does one debug loading/initializing a formerly working DLL when forced to treat it as a black box? Help!
How does one debug loading/initializing a formerly working DLL [...]?
I think there is no definitive answer to your question.
This is how we have gone about debugging the loading/initializing of DLLs and applications and may help you:
We regularly work with systems where we have no source code for the DLLs (and often we don't have any source code for the applications either). We experience DLL conflicts quite regularly. When testing why applications don't start as expected we have found the use of Sysinternal's Process Monitor by Mark Russinovich invaluable.
This will show you system level activity. You can filter for your process and then you will see all file, registry, thread and network activity (although thread and network are quite limited). If the DLL has dependencies then the system tries to find those and so you will be able to discover all dependent DLLs and COM interfaces (by seeing the registry lookups for that interface) that it's looking for. Process Monitor will show if the resource is not found or if access is denied.
Slightly more difficult to discover is if one of the dependencies exists but the export table has changed (so the functions have different signatures or export ordinals). There are ways to check that (by looking at the export and import tables) but generally (if you have access to a working environment) it's enough to check the filesize, timestamp (and the VERSIONINFO resource if there is one) between DLLs.
I am using Synapse in a small software (created with Delphi 7) for HTTPS requests. SSL libraries (libeay32.dll/ssleay32.dll) are saved in software resources, so when it opens the dll files are copied to the Windows temp folder. I also use SetDllDirectory pointing to temp folder, so application can "see" the libraries.
For long time, few users were complaining about error 500, so I decided do dig the issue. Discovered that there is another software that record old version of SSL libraries in the Windows system folder, and my software are trying to use them.
Looking in Synapse source I see it calls LoadLibrary without specifying the library path, so I tried to add temp folder to Windows environment path (SetEnvironmentVariable) as suggested in this post Delphi LoadLibrary Failing to find DLL other directory - any good options?, but no success :(
I also tried to load the libraries myself using LoadLibraryEx, with the LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR flag, but again the issue persists...
Please, someone have an idea what is going on and how to solve?
PS. Sorry, english is not my native language
In my application (build with Delphi XE8) I use the IdHTTP component. When I tried to run the application, the following exception was thrown: 'Could not load SSL library'.
I solved this issue by downloading the OpenSSL library from this site
http://thundaxsoftware.blogspot.nl/2014/09/cannot-load-ssl-library-using-delphi-xe7.html
If I'm correct: the files 'libeay32.dll' and 'ssleay32.dll' are needed.
But it only works for me. A friend of mine, who also uses this application, got the same error ("Could not load SSL library").
I want others to be able to download my application without them having to download the OpenSSL library seperately.
Is it possible to include these two files into my application?
For example by adding a folder to the directory location of the application? If so, how can I make the application find these files when it needs them?
I hope you can help me! (My apologies for the bad English)
You should bundle the DLLs (and any other necessary files) with your application in an installer. The installer can then install the DLLs in the same folder as your application executable, and your app will be able to find them when it's run. It also makes it much easier for your users to get the files into the proper locations by simply running Setup.exe (or YourAppSetup.exe).
There are several products that will create the installer for you, including the free (written in Delphi) Inno Setup.
The cleanest way to handle this is to deploy the SSL DLLs to the same directory as your executable file.
Assuming that you do not specify a location for the libraries, Indy will default to using the system DLL search order. And the executable file's directory is the top of that search order. So your DLL files will be found.
By supplying these libraries your app is isolated from other applications. That avoids so-called DLL hell where multiple applications share libraries but all have different version requirements.
I have two PCs both with XE2. I thought that I had installed identically on both but have problems installing 3rd party packages on one while the other is just fine.
I want the same on both anyway. The easist would probably just to "migrate" the working set-up by moving in into my Dropbox folder. Can I do that? If so, how?
If not, can I (easilly) backup my registry settings on one machine and then import them on the other?
I suppose I could just sort out the problem on the one PC, but am not having much luck so far. I would rather invest the time in only having one Delphi setup. And since I am moving lots of other stuff to DropBox anyway ...
The tool for this is now built into Delphi XE8 and higher.
It's found here:
C:\Program Files (x86)\Embarcadero\Studio\20.0\bin\migrationtool.exe
Online documentation:
http://docwiki.embarcadero.com/RADStudio/Rio/en/Settings_Migration_Tool
Install CnPack wizards from http://www.cnpack.org
From the CnPack toolbar select IDE Config Backup/Restore (image below) and save this file somewhere safe
Copy the components to the second delphi machine . Keep the exact same directory structure.
I store my components as follows this helps backing up, moving etc., but you can use your own structure
D:\components_bds\DCU
D:\components_bds\BPL
D:\components_bds\ComponentsThemselves
Use the restore config file from CnPack to restore your components on the new machine
This is also useful if your testing components that you plan to remove later and keeping a backup of your installation incase something goes wrong you can save time with new delphi installation if hard drive dies. Keep a copy on flashdrive or somewhere safe
You may compare/diff the config file created by cnPack using a tool like Beyond Compare and see what the differences are to find out why third party components give problems on one of the machines. It may be a Delphi registry/installation problem or a problem in the paths of the thirdparty components. Components need to be installed in an order perhaps it did not find the needed dcu or dll it depends on.
I don't know of any way to do so with DropBox. Here's an old post I made (related to Delphi 7, but with correction of registry keys still applicable) in the CodeGear newsgroups; hopefully it will help.
(It probably goes without saying, but back up the existing registry settings on the destination machine before starting by using RegEdit and exporting them, just in case. You'll at least be able to get back to the point you're at now if something goes wrong by deleting the imported entries and then importing the saved ones.)
You can't, without some difficulty anyway. (Especially if you have
third party components installed, as they may have placed files in the
%SYSTEM% folder you may not know about.)
You may be able to (for going from the old computer to the new
computer running the same exact version of Windows!) by exporting the
registry keys under HKCU\Software\Embarcadero and
HKLM\Software\Embarcadero from the old machine, and then after
installing Delphi on the new machine (in the exact same folder
location) importing that registry file.
Many of the compiler, linker, and other settings are configured on a
per-project basis, and should transfer over when you move your source
code to the new machine.
Third-party components are a problem, as I mentioned above. You may be
able to get away with using the registry export/import if you copy
each third-party component set from the old computer into exactly
the same location on the new machine before importing the registry
file. You'll probably have to track down some .BPL files that end up
in the $(BDS)\Bin and possibly other folders under the $(BDS)
tree; the IDE will tell you about missing stuff when you try and start
it. Make sure you answer "Yes " when asked if you want to try and load
it again next time!
Most of my development is hobby stuff or wannabe releases. Instead of dying trying to move my XE2 Pro from my Dell Inspiron N7110 Win 7 machine to my new Win 10 SSD machine, I'm seriously thinking of switching to Lazarus. I've used Lazarus 2.x with Indy 10, ZeosLib, and Firebird and successfully created a working distributed internet system. I also created Lazarus version of my XE2 Blackjack program. When compared to XE2, Lazarus (IMO) has only two weakness and neither are deal breakers for me. BTW, I have successfully duplicated Lazarus (with all installed components) from one machine to another simply by copying and pasting the Lazarus directory and it works. Try that with Delphi.
Sam
I have this unusual requirement from a client, and I am not quite sure how to proceed.
My client needs to select a folder from his computer in IE and POST the files within that folder to the server. I was thinking of an ActiveX control. Could you point me to the right way? Thank you.
It's a bit of a tricky question; You can certainly upload files using WinHttp or WinInet (forget which works better for it) but you could run into issues with proxy settings.
If I were you I'd write a plugin using FireBreath, which would then work on all major browsers instead of just IE (works both as an ActiveX control and as a NPAPI plugin). There is a library for FireBreath that though poorly documented allows you to upload files via HTTP using libcurl and openssl, or you could figure out how to do it with WinInet/WinHTTP (do some google searches, several possible leads come up).