Static linking SHFolder components - c++

I have a Win32 app developed in C++ Builder XE, which has worked great in the WinPE 2.x/3.0 environments for the past couple of years. I have made some significant changes over the past couple of months, but now that it's complete and I try to run it under WinPE I get the error message: The program can't start because SHFOLDER.DLL is missing from your computer.
Since I can't control the WinPE environment, and this dll isn't included in WinPE, my first thought is to try and statically link the necessary components. However, it appears the functionality offered by this dll is only available from the dll.
I haven't been able to find any useful information on this DLL, and unfortunately I don't know which functionality I added that now requires this DLL. I am hoping that someone has experience with this, and can help guide me toward statically linking the required components, or finding a workaround so that this app no longer requires the dll. Thanks!

shfolder.dll is used to get shell folder paths like the Desktop, My Documents, Windows directory, etc. It implements SHGetFolderPath() consistently along all versions of Windows due to differences of implementation between SHGetSpecialFolderPath(), SHGetFolderLocation(), SHGetKnownFolderPath(), etc.
MSDN explains it better:
This function is a superset of SHGetSpecialFolderPath, included with
earlier versions of the Shell. On systems that preceded those that
include Shell32.dll version 5.0 (Windows Millennium Edition (Windows
Me) and Windows 2000), SHGetFolderPath was obtained through
SHFolder.dll, distributed with Microsoft Internet Explorer 4.0 and
later versions. SHFolder.dll always calls the current platform's
version of this function. If that fails, it tries to simulate the
appropriate behavior. SHFolder.dll continues to be included for
backward compatibility, but the function is now implemented in
Shell32.dll.
The DLL itself is redistributable so you can include it for WinPE. You can also just use any one of the other functions, if they work for you and you don't need any of the special cases.

Related

DLL hell and deployment: best practice for native windows applications

I'm trying to get a handle on which DLLs my native mode C++ win32 application uses. This isn't always obvious - I can link a library but it's somewhat more difficult to find out which system DLLs are needed, particularly if they're system DLLs.
As a case in point, I recently sent a test build to a remote member of my team who's running an older version of windows.
his machine complained about
'api-ms-win-core-misc-l1-1-0.dll' being missing (I assume this had something to do with my using 'GetSystemTime' and related functions but that's part of my problem: how do I tell?) but seeing as this is a windows system file, how can I package up an installer that will ensure these files are installed?
Also, I've used dependency walker and 'listdlls.exe' to find all the DLLs used by my program but dependency walker can't load that DLL and 'listdlls' seems to silently ignore it, so I can't find their location in order to redistribute them (which feels like the wrong approach anyway).
My question therefore is what's the current best practice to:
comprehensively determine all the system DLLs that are used by my
application
write an installer that ensures these libraries are
installed on a users machine
Find out which redistributable installers are needed from a given list of DLLS
I would have thought that installing a visual studio redistributable
package (e.g.
https://support.microsoft.com/en-gb/help/2977003/the-latest-supported-visual-c-downloads)
would be enough. To my knowledge, the team member has installed this
but still gets DLL issues.

Distributing DbgHelp.DLL

My application relies on DBGHELP.DLL functions, especially the information about the loaded DLLs by the target processes. However, many times it fails on Windows versions lower to Vista (you know XP is still there!). Looked around and found that installed/present DBGHELP.DLL on the target system is old, and doesn't support many new features (For example, few flags of MiniDumpWriteDump are not supported in older versions).
This page mentions about the DbgHelp versions and vaguely mentions about distributing the DBGHELP.DLL (and other DLLs). DLLs shipped with OS must not be shipped (agreed, and no issues about it). Then it says latest DLL out of "Debugging Tools For Windows" should be shipped.
My question is: Which version can be/should be shipped with the application? Pick the latest one and assume it will work in lowest OS (XP)? Of course, I won't ship Debug version of this DLL. The "DbgHelp versions" page doesn't mention about supportability for specific OSes - so we may assume that even latest version will be supported on XP.
I would put the DLL in the application directory itself, and may conditionally call functions like SetDllDirectory. If needed, the DLL itself and/or any functions of DBGHELP.DLL may be loaded dynamically.
Related:
SymInitialize failed with error 2147483661
https://groups.google.com/forum/#!topic/microsoft.public.windbg/9V6sbsu8_js
One of the missing file error occurs as the file is deleted or corrupted. There is a different approach to its fix on the different windows versions. If you certainly need to fix dbghelp.dll missing error you need to install Microsoft Direct X follow the step-by-step method from installation of it.

Statically link with Microsoft CRT, and OpenMP

I’m developing some Windows software that's sometimes used in embedded-like scenarios. That’s not uncommon for my users to have a dedicated Win7 or Win8 PC they never update, not even connect to the Internet. Users plug those PC to a specific industrial hardware, and use that system for one job only.
My software includes components I've written in Visual C++. I include CRT in my MSI packages using appropriate installer merge modules.
Unfortunately, for a PC that never updated, that doesn’t work: today I got a bug report, the app crashes on startup saying “can’t start because api-ms-win-crt-stdio-l1-1-0.dll is missing from your computer”
This answer suggests static link to CRT.
Did that. But some parts of my C++ code rely on OpenMP for parallelism.
Dependency walker shows me the DLL I’m building depends on vcomp140.dll even when compiled with Multi-threaded (/MT) runtime library settings.
Also it shows vcomp140.dll only depends on kernel32.dll and user32.dll.
Can I just place that single DLL, vcomp140.dll, in the installation folder? Will it work on offline Windows 7 PC?
Based on the VS2015 Redistribution List I would say that copying that file would be indeed what you need to do and would work fine (if you used VS2015 to build your app). Take care to copy the proper dll based on arm/x86/x64.
Just to make it clear, it is not possible to statically link openmp with Visual Studio. Only two things you can do:
Remove openmp (and compile with /MT /MTd)
deploy vcomp140.dll (or VC redistributable) with your application

Are there any registry entries that indicate whether a specific C Run-Time is already installed?

I've been looking online and at my registry and I think not, but it would be nice if we could get a definitive answer on here.
Just the run time, as in for re-use on the client side.
I see it is possible for VC10, http://blogs.msdn.com/b/astebner/archive/2010/05/05/10008146.aspx, but prior to that we need to call the MsiQueryProductState API. Perhaps just give all the clients MSVCR100.DLL already?
The most common practice is to install the CRT your application was built with, regardless.
I think this practice comes from the v90 and lower CRTs, because there were multiple versions of each redistributable that could be installed, and though MSVCR90.DLL exists on the system, it may not be the version your application uses.
I believe this was changed with the v100 CRT, and now Microsoft guarantees that newer versions of the CRT will be usable in place of an older version, but I would still attempt to install the CRT your application was linked with.
It is still possible to do a private install of the Dll's into the application's folder. I recently installed 3 different version of the VC9 runtime when I was setting up my Visual Studio Express environments. All show up in Control Panel and appear to be readily removable.
For that reason I believe the current best practise to be to perform a private install (I think that is the terminolgy MS uses) of the required DLL's (for managed code you need the managed DLL and the native version) in tha app's folder.

Want to run a program on some unknown system

I have been working on a VS 2005 project and have successfully generated an exe file which works fine on my system. However when I tried to run it on some other pc it didnt run. It throws up the error message "the system cannot run the specified program". Can someone tell me how to make my code immune to such message i.e. system independent?
platform used: Windows XP, VS 2005
the extension of all my code files is cpp but I know only c and thats what I wrote inside them.
I have seen before exe created on Windows Sp1 not working on SP2 and problems such as that.
This should help you perhaps.
I've seen this when you run on a different version of Windows that doesn't have some DLL you depend on. The easiest thing to do is statically link the C runtime (that's the usual culprit) and use depends.exe to see if there are any others.
You will almost certainly need to create an installer that installs your executable and any non-OS-included DLL's it relies upon. It is not always possible or desirable to statically link all dependencies. You can in many cases simply copy the DLL's to the same folder as the executable.
By default, even the C/C++ standard library is provided by a DLL. While the MSVCRT.DLL used by VC++ 6 is included with the OS since later editions Win95, the MSVCRT required by VS2005 is not included with XP installations (other versions I do not know). The run-time support is included VC redistributes package. You may need to arrange for your installer to include that installation, or you could be more selective is you know your dependencies.
Some Win32 API calls if you are using them are dependent on the OS version (check the documentation), but if you built and rin it on XP, it should normally work of any subsequent version of Windows. You need to define various API version macros if you want to extend support to earlier versions of Windows (which seems unlikley).
You might need to install the VS 2005 redistributables on the other machines, depending on how you have compiled your program.