I have a project that I converted from Visual Studio 2003 .NET to Visual Studio 2010. It's NOT a .NET project; it's Visual C++ (unmanaged).
The DLL pulls in additional DLLs. If I link an executable with this DLL, then the executable dies during the initialization of the DLL. (I can tell, there are constructors for static objects that are being called, and I can see their operation.) I've removed ALL VS 2010-created DLLs from my path, except for one of them, which causes the error. Replacing that one with the VS.NET-created version allows the program to run.
Since I'm not getting any useful information, I decided to write a test application that doesn't directly link to the DLL, but instead uses LoadLibrary to load the library. The idea was that I could use GetLastError() to help figure the issue with the library. No go; I get an error code -529697949, which isn't a Windows error code at all! (If I change the DLL to the VS.NET-created version, the program loads the DLL properly.)
I used the Dependency Walker (www.dependencywalker.com) to check the DLL, and it tells me that "At least one delay-load dependency module was not found," highlighting IESHIMS.DLL and WER.DLL. I am seeing no other error with that tool. Running it on the VS.NET-created DLL shows the same two warnings, so I figure this is a red herring.
static void showMessage(const wchar_t *wmsg)
{
std::wcout << wmsg << std::endl;
::MessageBox(NULL, wmsg, TEXT("Message"), MB_OK);
}
static void testLoadLibrary(const wchar_t *lib)
{
::SetLastError(0L);
::SetErrorMode(0);
std::wstringstream wss;
wss << "LoadLibrary: " << lib;
showMessage(wss.str().c_str());
HINSTANCE LoadME = ::AfxLoadLibrary(lib);
if (LoadME == NULL) {
DWORD dw = ::GetLastError();
wss << "Failed: Error code " << dw;
showMessage(wss.str().c_str());
ErrorExit(lib, dw);
} else {
wss << "LoadLibrary of " << lib << " succeeded.";
showMessage(wss.str().c_str());
::FreeLibrary(LoadME);
}
}
Finally, I ran Process Monitor (sysinternals.com) to monitor the test program, looking at all entries with Path containing the string "dll." I don't see anything particularly informative in this list--no idea why the DLL is failing to load.
If I use LoadLibraryEx with DONT_RESOLVE_DLL_REFERENCES, the library loads, so this really looks like a dependency issue, which is why I'm surprised that the dependency walker isn't being particularly helpful.
I've tried this on Windows 2008 R2 and Windows 2003; same behavior.
Any suggestions?
There is an OS tool to help diagnose problems like this. Download the SDK or DDK and use gflags.exe to set 'Show Loader Snaps' (+sls) for the process. That should reveal why the DLL load fails.
The loader snaps output will appear in the debugger output window.
Martyn
Related
I want to load a C++ dll in C# (VS2012, C++ dll also created in VS2012 C++) that in C++ dll I've used a shared library generated by MATLAB with using of deploytool.(My configuration in both C# and C++ programs is x64 and shared library also generated in 64-bit version of MATLAB).
I've used following codes to load library and then I've recieved error code 1008 :
[DllImport("kernel32.dll",CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr LoadLibrary(string libname);
...
IntPtr handle = LoadLibrary("libName.dll");
if(handle == IntPtr.Zero)
{
int errorCode = Marshal.GetLastWin32Error();
//at this point error code will be 1008.
}
Help me to resolve that, please!
Thanks in advance.
Good chance the failure isn't directly in libName.dll but rather in one of its dependencies. There are quite a few tools that diagnose such dll loading problems:
Process monitor file system activity, can show you if a dll is sought but not found.
Dependency walker's 'profile' option can show you which dependent dll failed to load.
The most powerful tool AFAIK: 'Show Snaps' checkbox in gflags (bundled with debugging tools for windows). It activates a windows-loader-built-in tracing facility, that shows you not only who failed to load but also why exactly. Some more details and screenshots here.
I have just downloaded MinGW 64 bit for Windows (I'm not quite used to Linux) on http://sourceforge.net/projects/mingw-w64/?source=dlp
When I compile the following code, I get no errors:
#include <iostream>
int main()
{
std::cout << "Code 64 bit :D !" << std::endl;
return 0;
}
Also, when I execute the program in Code::Blocks, eveything works perfectly (using cb_console_runner.exe). The problem occurs when I execute my program outside Code::Blocks. I get the error "The application couldn't start properly (0xc000007b)". By the way, I translated the error from french. Do you have any idea what is the problem or how I can debug this? Oh I forgot: I don't get any errors when code is empty (i.e. when int main(){return0;}).
Thank you!
I've seen this happen here and there when GCC's standard C++ library (libstdc++) (or libgcc as well) is not in your %PATH%. Furthermore, this may also be the case that you have a mismatched version (i.e. a 32 bit version) of the same DLL in your path. Use something like Dependency Walker to determine this.
This doesn't happen when your program is empty since you are not using any symbols from the standard C++ library and thus it is not linked with your application. However when you use std::cout that references a symbol defined in the C++ library and thus it must be linked.
So I recently got Visual Studio 2012. I converted a Visual Studio 2010 solution to a Visual Studio 2012 project. It was working before I converted it.
I have this line of code:
this->Text = global::ProjectName + " (" + global::Type.ToString() + ") - Path Creator 2.0";
where global::Type is:
ref class global {
public:
static Rct3PathType Type;
...
};
...and Rct3PathType is:
enum class Rct3PathType {
Basic = 0x02060206,
Extended = 0x05060506,
Queue = 0x01070107
};
I get an error at compile time where ever I have called global::Type.ToString() saying "error C2228: left of '.ToString' must have class/struct/union". Considering this all compiled completely well BEFORE switching to Visual Studio 2012, I'm not sure what the issue is! :(
Also, when I try to run the last successful build (which was built with Visual Studio 2010), I get runtime error at startup saying "The program can't start becayse MSVCR100D.dll is missing from your computer." I know this probably doesn't relate to the issue at hand, but does anyone know why this may be happening as well?
Thanks for your help,
Alex
"error C2228: left of '.ToString' must have class/struct/union": enum class is also the syntax for a C++11 enum. To make it a C++/CLI enum, give it an accessibility specifier, which is not allowed on a C++11 enum. In other words, private enum class or public enum class will change it from a C++11 enum to a C++/CLI enum. This wasn't a problem in VS2010 because it doesn't support C++11 enums.
"The program can't start because MSVCR100D.dll is missing from your computer.": VS2012 uses a different C runtime than VS2010. MSVCR100D is the Microsoft Visual C Runtime version 10.0, Debug version. This DLL is installed with VS2010, there is no other way to get it. If you have an old Release build, you can get the runtime redistributable from Microsoft (x86 or x64), and install that to make it run. (That will be MSVCR100.dll, no "D" at the end.)
After building in Release mode, I am seeing exceptions which didn't occur in Debug mode. When debugging the release build, it looks like string references are not being passed correctly from the EXE (our application) to the DLL which is receiving the string reference.
Our EXE code looks like this:
string contents = "handle_message(): received=" + msg->encode();
LOG4CXX_DEBUG(logger, contents);
The LOG4CXX_DEBUG is going to log4cxx.dll, whose code looks like this:
CharMessageBuffer& CharMessageBuffer::operator<<(const std::basic_string<char>& msg) {
if (stream == 0) {
buf.append(msg);
} else {
*stream << msg;
}
return *this;
}
Looking at the Call Stack in the debugger, when I navigate down to the frame which has our source, I can see that contents is a valid string with size=583, capacity=838.
In the frame inside the log4cxx.dll (the next frame above in the stack) the string reference shows size=838, capacity=363113231 (and the values are all garbage).
Both our app and log4cxx.dll were compiled on the same machine, using the same runtime settings (/MD), but different versions of Visual Studio. The log4cxx dll was compiled using Visual Studio 2008 and our application was compiled using Visual Studio 2010. Running dumpbin on the 2 objects shows:
Our App (EXE)
MSVCP100.dll
MSVCR100.dll
log4cxx.dll (DLL)
MSVCP90.dll
MSVCR90.dll
Is this problem due to the fact that they are using different runtime versions?
If you pass non-POD (plain old datatypes) between DLL/EXE boundaries (like STL string or CRT FILE pointers) you must use the same shared CRT.
In your case, you must recompile all DLLs/LIBs with the same compiler!
See also: I can pass std::string for a Dll and what i can do with DLL´s?
The implicit question is:"Is there a way to pass data, hopefully using string and other STL containers, to DLLs of another version of visual studio either previous or later than the one that I'm using?".
Aside from using POD, there are probably three approaches: shared memory, sockets( to local host ) and MSMQ. All of these methods require additional extensive programming, but the deeper answer is found in how the interface is changing the input parameter.
I have found a possible solution to the string passing problem on the internet. It removes one layer of corruption; cast a pointer to the container to a uint and pass the uint. Dereference the uint to the pointer and the object is revealed. Beware, auto_ptrs are usually deleted in this process, so don't use them. If the passed object is still offset incorrectly( this happened to me with VS08 passing to a VS13 ), then pass the c_str() of the string instead. It's certainly inelegant, but we need to know all the alternatives. See "HowTo: Export C++ classes from a DLL" in Code Project( Nov 22, 2012 ).
I am trying libvips for visual studio 2012, starting with a simple example at
http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/vipsmanual/vipsmanualse1.html#x6-60001.1.1
#include <iostream>
#include <vips/vips>
int
main (int argc, char ⋆⋆argv)
{
if (argc != 3)
{
std::cerr << "usage: " << argv[0] << " infile outfile\n";
return (1);
}
try
{
vips::VImage fred (argv[1]);
fred.invert ().write (argv[2]);
}
catch (vips::VError e)
{
e.perror (argv[0]);
}
return (0);
}
What I did was:
Download and extract libvips at http://www.vips.ecs.soton.ac.uk/supported/7.34/win32/
Add to VC++ Directories->Include directories as vips-dev-7.34.1\include (vips-dev-7.34.1 is the extracted folder)
Add to VC++ Directories->Library directories as vips-dev-7.34.1\lib
Add a system path entry as vips-dev-7.34.1\bin
Basically because there are not much guide on using libvips with visual studio, so I applied the procedure that I used for OpenCV. The guide only say "All you need to do is include . This will get all of the include you need". Aparrently there are much more than that.
Upon building, the first error is "Unable to find header file "glib-object.h". Essentially, vips/vips call glib-objects "include which lies inside a subfolder of include \include\glib-2.0\glib-objects.h. I searched for a way to make VS search for all subfolders within the main include folder, it seems that such "recursive search" is not possible in VS. One has to point exactly to the folder containing header file and I may need to add all of the subfolders manually. So I tried adding vips-dev-7.34.1\include\glib-2.0 to VC++ Directories->Include directories. But then glib-objects.h calls for another glibconfig.h which is nowhere to be found within the include folder and subfolders.
Have someone sucessfully make libvips work with VS? Can you give me some advices if I miss something.
I'm the libvips maintainer. Sorry, it's very difficult to use the pre-built libvips binaries with VS, for various reasons (see below). I think your options are to use mingw instead, to cross-compile from linux (this is what I do), or to rebuild libvips yourself from source using VS (perhaps a week's work for an experienced dev?). There are some notes on the vips website about this issue.
The libvips.dll on the website has been cross-compiled from linux using mingw. It's set up for a linux-style build system with pkg-config, so you will have a lot of compiler flags to figure out in VS, and it's built against msvcrt.dll, the Windows C runtime, rather than msvcrtXX.dll, the VS runtime, so you will have endless annoying compatibility problems unless you also build against the Windows runtime.
Unfortunately VS no longer supports building against the Windows runtime. They have an internal tool which does support this mode, but it's not publicly available. I read somewhere you can coax the DDK compiler into doing this, but it's also not supported.
CoApp is an interesting project (partly supported by Microsoft) that is attempting to make building software on Windows less painful, but it's still in beta. You could maybe ask if they have a libvips packaged up for VS, or are considering making one.