I'm making a program in visual c++. The program relies on some dll files, which I don't want to place in system32. Now the dll files is in the same folder as my .exe, but i would like to move them to a sub folder. The problem is, if I move the files, my application fails to start and comes with this error message:
MyProgram.exe - Unable to Locate Component
This application has failed to start because myDll.dll was not found. Re-installing the application may fix the problem.
I have had the same problem before, where if found a solution, which included adding something to the registry, but i forgot how it worked, and now I can't find the guide again.
Can someone please help me?
There is more than one way to solve this problem. As other mentioned you can modify search path for your application in registry. Sometimes, you don't have rights to write to the registry, or you cannot do it for other reasons, then you can set dll path explicitly, the WinAPI function for that is SetDllDirectory, see MSDN.
Sounds like you're after the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths key. See here for complete information. In short, a string called Path points to a DLL search path. For example if your application was called "MyApp" a .reg file like this would do the trick:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppPaths\MyApp.exe]
#="C:\\Program Files\\MyCompany\\MyApp\\MyApp.exe"
"Path"="C:\\Program Files\\MyCompany\\MyApp\\DLLs"
I believe this is the article you are looking for:
http://www.codeguru.com/Cpp/W-P/dll/article.php/c99
Each application can now store it own path the registry under the following key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths
The use the application path, set a key for your application, using ONE.EXE from the example above:
HKEY_LOCAL_MACHINE...\CurrentVersion\App Paths\ONE.exe
Set the (Default) value to the full path of your executable, for example:
C:\Program Files\ONE\ONE.exe
Add a sub-key named Path
Related
VS2017, SDK/WDK, C++ project
we have a c++ solution (driver) that is shared across developers via Team Foundation Services - visualstudio.com (now called azure devops?).
When I perform a get latest source code, and want to rebuild the solution I get two MSB3030 errors:
"Could not copy the file "C:\path of my colleague his file" because it was not found."
I found it strange that I saw on one of the two errors a path of my colleague his pc. He works on C:\ I'm working on E:\
Unloading the project, I saw he path being set here:
<ItemGroup>
<FilesToPackage Include="C:\path of my colleague\foo.xml" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<PackageRelativeDirectory>
</PackageRelativeDirectory>
</FilesToPackage>
We cannot get this solution to build because of the MSB3030. First we have to clean the specific projects individually, rebuild it, then build another project etc.. a few steps to perform manually in the correct order , trial and error, drinking coffee, throwing bananas to the pc and praying that a monkey outputs the code correctly.
Has anyone seen somehting similar regarding MSB3030 errors?
On my pc I see the path of my colleague, but he doesn't see my path (strange!).
C:\Program Files (x86)\Windows
Kits\10\build\WindowsDriver.common.targets(1699,5): error MSB3030:
Could not copy the file 'C:...' because it was not found.
I've set the Any CPU to x64 because it doesn't make any sense for c++.
C++ Windows Driver MSB3030 could not copy the file '' because it was not found
The reason for this issue is that the path of the ItemGroup is an absolute path in the project file:
<ItemGroup>
<FilesToPackage Include="C:\path of my colleague\foo.xml" ...>
...
</FilesToPackage>
</ItemGroup>
Regardless of whether your colleague has added this file to source control, when you pull the code from the TFS server to your local and put the code in a different local folder, the absolute path will bring you a lot of trouble, you need to manually check the code on the TFS server for this file and you need to modify the absolute path of this file in your project. But this problem will reappear after your colleague updates after you submit your code. Because an absolute path cannot be assigned to two different paths C:\ and E:\.
To resolve this issue, you need to change the absolute path to a relative path in the source code. Generally, we prefer to add this file to the Solution/Project folder, then use the MSBuild Macros $(SolutionDir)/$(ProjectDir) to specify it.
Check Common macros for build commands and properties for some more details.
Hope this helps.
I'm getting this error when I try to run my app:
I checked and there is no reason that I can see that it wouldn't be able to find libnlopt-0.dll. Here it is (note GlassModelCalcualator is the DLL that uses libnlopt-0.dll), in the GlassModelCalcualatorDLL folder:
and in the debug folder of GlassModelCalcualatorDLL:
I have a different program that has a console which uses GlassModelCalcualator.dll and that also has this issue. To fix that, I had to put libnlopt-0.dll in the Debug folder of GlassModelCalcualator.
I'm assuming this is not the same problem here since you can clearly see that libnlopt-0.dll is in GlassModelCalcualator's Debug folder.
Any ideas?
Windows will follow a hierarchical order when searching for dll's.
You could place your dll in the same directory as the exe or even in the Windows system folders (only if you're absolutely sure you want to keep this dll forever as there's no cleanup)
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682586(v=vs.85).aspx
Update Sorry, guys, I was incorrectly determined the problem. All is working, error was in "other program logic". Please delete or close the question.
Qt5 is designed to load libeay32.dll and ssleay32.dll on program start before any instruction in main() (because it is static).
(Details: it is located in qtbase\src\network\ssl\qsslsocket_openssl_symbols.cpp:
static QPair<QSystemLibrary*, QSystemLibrary*> loadOpenSslWin32()
)
Issue:
my program starts with not its exe dir as working directory
libeay32.dll and ssleay32.dll resides in its exe dir
user cannot install OpenSSL in system dir
user cannot change PATH variable
I cannot recompile Qt, i.e. ship program with static Qt compiled with openssl-linked
Qt loads searches dlls in this order (from qtbase\src\corelib\plugin\qsystemlibrary.cpp):
Application path.
System libraries path.
Trying all paths inside the PATH environment variable.
No. 1 is Application path, but in fact it does not search there.
My program:
int main()
{
// at this point Qt5 already checked and tried to load the DLLs
// so this:
ChangeCurrentWorkingDirectoryToExeDir(); // some function to change cwd to current exe dir
// does not work :-(
// ... other program logic ..
}
How to force Qt5 to reload OpenSSL DLLs after changing working directory?
May be someone already faced this problem...
Update Sorry, guys, I was incorrectly determined the problem. All is working, error was in "other program logic". Please delete or close the question.
QSystemLibrary::load is called with onlySystemDirectory = false for SSL, so QFileInfo(qAppFileName()).path() is the first place where the DLLs are searched. Search order:
application dir
system path (e.g. C:\Windows\System32)
all paths in PATH
I don't find documentation for that, but in our software, Qt finds SSL libeay32.dll and ssleay32.dll when they are in the same directory as the application .exe, given that
the .dll files are not in PATH
the .dll files are not in the working directory
no qt.conf exists
If you have a qt.conf, the default library value might apply, which is .\lib.
Library search orders are discussed on MSDN at Dynamic-Link Library Search Order.
There's a few ways to handle loading libraries, but it sounds like most of them won't apply.
Its not clear to me why you can call ChangeCurrentWorkingDirectoryToExeDir, but you can't call SetDllDirectory. I'm probably missing something obvious.
It seems like your last option is to create an Qt.exe.local file. This is called Dynamic-Link Library Redirection, and will cause the linker to load the DLL specified in the local file.
i have made a MFC-based game and my project includes images and sounds. Now i want to create an installer setup in order to distribute it.
i have used the resources by providing their exact path in e.g
img->Load(L"C:\\Users\\Ad33l's\\Desktop\\block mania\\block mania\\res\\db.png");
MCIWndCreate(NULL, NULL,WS_POPUP|MCIWNDF_NOPLAYBAR|MCIWNDF_NOMENU,L"C:\\Users\\Ad33l's\\Desktop\\block mania\\block mania\\res\\tick.wav");
1.Can someone tell me any way to avoid Hard-coding the actual resource path as these resource files will not be present at this same exact path in other computers ?
2.Also guide me to handle these resource files during the creation of standalone SETUP (i am using advance installer )
(as an actual answer).
Do not use absolute path, always use relative path; relative to your EXE file is one solution.
The EXE path can be found using GetModuleFileName.
char appPath[MAXFILENAMELEN];
GetModuleFileName(NULL, appPath, MAXFILENAMELEN);
(addendum) appPath name is misleading, it contains the full name of the application; you need to extract the path from the full application name.
We do something like this:
(edit to make it compilable in unicode)
TCHAR applicationPath[MAX_PATH];
GetModuleFileName(NULL, applicationPath, MAX_PATH);
CString sSoundFile(applicationPath);
PathRemoveFileSpec(sSoundFile.GetBuffer());
sSoundFile.ReleaseBuffer();
From there, you can do something like (pseudocode-ish):
img.Load( appPath + "//Images//db.png" );
You can have a variable that saves the directory they want to install your program in. After they choose the directory they want to install it in, go off of that. Or you can also use system folders like the appdata folder
A first solution would be to configure your setup project to install the installation files under the DesktopFolder\block mania\block mania\res. Then, you can access within your application the current user Desktop location and append to it the remaining fix location (block mania\block mania\res).
Another solution would be to configure the setup project to create registries at install time which will store the paths of the installation files. Then, your application could read the installation paths from registry.
Finally you could also create at install time environment variables containing the paths of the installation file and, then use within your application the environment variables to access the installed files locations.
I have not yet found a definitive answer about this. I am trying to have access to files in subfolders from my .EXE. When I have asked before, people tell me to use the absolute location i.e. "c:/game/info/" if I wanted to access something in /info/
But it is completely unreasonable for me or anyone to assume that someone is going to use their program from the same directory. What if the user only has a D drive? That sort of thing.
So my question is: how can I access a file in a subdirectory from my executable without relying on the entire path?
Your title says "Windows", so I'll give a WinAPI-specific answer.
On Windows, you can find your application directory with GetModuleFileName(NULL, ...), and PathRemoveFileSpec. Then PathAppend will make the full path to your data files.
Or you can store the data inside you .exe file as Win32 resources, so they never get separated.
Please note that this approach generally works only for read-only access to data files. If you try to write files in your application directory, you might be blocked by ACLs (depending on install location and local security settings of the computer).
Use GetModuleFileName (Retrieves the fully-qualified path for the file that contains the specified module. The module must have been loaded by the current process.)
char strExePath [MAX_PATH];
GetModuleFileName (NULL, strExePath, MAX_PATH);
You'll then need to extract the folder path (someone has already posted how to do that), and combine your path.
Make or use an installer that asks the user where to install the executable and writes that path to the registry in a well-known location for later reference.
if you use:
#include <fstream>
ifstream stream("file");
it will be working. "file" is file in directory with your exe. Of course if you want go up or down in folders hierarchy use "..\file" or "folder\file"