MFC application Assertion failed when linking with a regular DLL that uses MFC - dll

I'm migrating an old OWL application to MFC. there were a main library that has the main dialogs and controls , I started writing an alternative classes of MFC to the old OWL like TDialog[inherits from CDialogEx], TEdit..... I added all the needed classes from the OWL now my library build successfully.
I created a new MFC Application [to test the library], i exported a function [SowDialogue] from the dll to be used in the Application , I added the .lib of dll to the MFC application, I called the function to show a simple dialog , the build go successfully, but at the first start the application fail with the following message
I clicked retry and the break to get the line that caused the assertion it was that one
So the problem is with the resources. when i link with the library the MFC can't get the right resources module.
I thought it was because i use a regular dll that uses MFC and shares MFC objects, if i must use an MFC extension library. how can i convert regular library to MFC extension library.
Or any solution to this disaster after a long work
EDIT
this is the call stack, there are no exported functions in this, its all in the application the error come before calling anything from the dll
Solution
the problem was solved when i converted the dll to an MFC extension library, really i created a new mfc extension dll and cheated it's properties, the dll main, the stafx includes and preprocessors definisions
static AFX_EXTENSION_MODULE MFCExtensionDLL = { NULL, NULL };
extern "C" int APIENTRY DllMain( HINSTANCE hInst, DWORD fdwReason, LPVOID)
{
if (fdwReason == DLL_PROCESS_ATTACH)
{
TRACE0("MFCExtension.DLL Initializing!\n");
// Extension DLL one-time initialization
if (!AfxInitExtensionModule(MFCExtensionDLL, hInst))
return 0;
new CDynLinkLibrary(MFCExtensionDLL);
//My initialization code
return 1;
}
else if (fdwReason == DLL_PROCESS_DETACH)
{
// Terminate the library before destructors are called
AfxTermExtensionModule(MFCExtensionDLL);
// my finalization code
return 1;
}
}
the properties
in the properties of project->configuration properties->general Use of MFC = Use MFC in a Shared DLL
,
in the properties of project->configuration properties->C/C++->Preprocessor->Preprocessor Definitions->add _AFXEXT , make sure to delete _USERDLL if it exists

When using MFC in a .dll, you have to make sure that the .dll can find resource handles for things like strings and bitmaps in the .rc file. MFC maintains an internal state for each .dll that points to the resources for that .dll. When calling into that .dll from an application (or another .dll) you have to 'help' MFC get the internal state right or it will not be able to find your resource and will ASSERT.
I can't see the function immediately below the one in the call stack in your example, but if it is an exported function, the MFC state problem is likely what is going on.
Make sure you have put the AFX_MANAGE_STATE macro at the top of any functions accessible from outside (exported functions). That will go a long way to solving your problems.
Microsoft reference: http://msdn.microsoft.com/en-us/library/ba9d5yh5(v=vs.80).aspx

If you use resources or windows from a dll file, you can try this way. This code can be in the dll itself. Whenever the resource is created the current resource handle of the main process will be set as the dll's resource handle and use the handle.
After any window creation or resource change revert it back to the old value.
hdllresource = ::LoadLibrary(<dllfile containing the resource>);
hcurrentInst = AfxGetResourceHandle();
AfxSetResourceHandle(hdllresource );
//do your window creation or resource loading stuff
AfxSetResourceHandle(hdllresource);

Related

Interrupt installation when custom action returns error

I have a method that verifies a password in a .dll and it should return an error code on failure. It has the following prototype:
#define DllExport __declspec( dllexport )
extern "C" DllExport UINT TestPassword(MSIHANDLE hInstall);
I expect that when this method returns an error code (like ERROR_INSTALL_USEREXIT = 1602) the whole installation process will terminate (no other custom action following this one will be executed), but it doesn't.
Also, in Wix I have the following fragment:
<CustomAction Id='TestPassword' BinaryKey='TestPassword' DllEntry='TestPassword' Execute='immediate'
Return='check'/>
<Binary Id='TestPassword' SourceFile='DummyDll.dll'/>
Quick Link: Managed Code Custom Actions (below is for C++ native custom actions).
UPDATE: Some helpful links.
Hello WiX (minimal WiX Visual Studio Project). WiX quick start suggestions.
Debugging Custom Actions (for native code / C++ just attach debugger to msiexec.exe).
Microsoft Debugging Environments.
Dynamic Link Libraries.
Suspected causes:
Listing some suggestions at the top here.
1) Wrong C++ custom action code configuration, often forgetting to create a CA.def file to define dll exports. I also always use __stdcall (MSI is an old girl).
2) Wrong path to custom action dll in WiX markup (not valid dll in MSI).
3) Forgot to enable checking of error codes in the WiX markup (*.WXS) and then a CA does not end the setup. This looks correct in your case (Return='check').
4) Forgot to insert custom action in installation sequence.
There are a few more, can't think of them at the moment. Might add later... One that comes to mind is bitness problems (x86/64)...
File and runtime dependencies is a classic fallover cause.
Try to statically link whatever you can.
Deployment DLLs should be minimum dependencies for sure since they need to run on any system, in any language, in any state, in any OS version, et...
One of the few cases where static linking is really recommended and always the right choice.
Heads-Up: Avoid Licensing In Setup? I would recommend you put the license validation in your application instead of your setup. Here
are some thoughts on the matter:
Installer with Online Registration for Windows Application (recommended read).
Technical Issues:
FileName.def: I am no C++ expert, but do you have a FileName.def file in your project to declare the exported functions for the dll? If not - add one (steps / procedure below). Make sure it is in the right format (add via Visual Studio, I think it is UTF8 without BOM). Compile and check with Dependency Walker if all exports are correct:
Verify MSI File DLL: You should check the compiled MSI to verify it has the correct DLL inside it with the correct exports available. Hence; verify that the DLL has safely made it into the Binary table of the MSI:
Open your compiled MSI with Orca (or equivalent).
Binary table, double click the Data column for your DLL entry.
Select "Write binary to filename" and save to desktop (or somewhere else).
Use Dependency Walker (depends.exe) to verify that you have a valid DLL as illustrated in the image above. Common problem is that you see no exports at all (MyImmediateCA, MyTestFail, MyTestSuccess, etc...).
Verify the file- and product versions as well in file properties.
Error Processing: A custom action can be set to suppress errors. Your markup looks correct with the "Return attribute" set: (Return='check'). Your snippet:
<CustomAction Id='TestPassword' BinaryKey='TestPassword'
DllEntry='TestPassword' Execute='immediate' Return='check'/>
Sequencing: Also check that your sequencing is OK. Altogether you need to point to the binary table DLL, declare the custom action and then also insert it into the right sequence. Mock-up WiX markup:
<!--<Binary Id="CustomActions" SourceFile="$(var.TestDll.TargetPath)" />-->
<Binary Id="CustomActions" SourceFile="C:\TestDll.dll" />
<CustomAction Id="MyTestFail" BinaryKey="CustomActions" DllEntry="MyTestFail"/>
<CustomAction Id="MyTestSuccess" BinaryKey="CustomActions" DllEntry="MyTestSuccess"/>
<InstallExecuteSequence>
<Custom Action="MyTestSuccess" After="CostFinalize" />
<Custom Action="MyTestFail" After="MyTestSuccess" />
</InstallExecuteSequence>
C++ DLL: And the actual C++ DLL itself (remember the *.def file). Snippet in the bottom code segment from MSI API Custom Action Security:
Suggested steps for Visual Studio 2017:
Create new VC+ DLL Project - Dynamic-Link Library (DLL).
Dump the below code in the main *.cpp file (I avoid the dllmain.cpp).
Add the *.def file!
Right Click Source Files => Add => New Item... => Code => Module-Definition File (.def) => Any name should do... (only one def file allowed)
Add your export function names:
Mock-up:
LIBRARY
EXPORTS
MyTestFail
MyTestSuccess
MyImmediateCA
Close and re-open file to verify if there are any format errors. Select fix if a warning appears. UTF8 without BOM required I think.
#include "stdafx.h"
#include <windows.h>
#include <Msiquery.h>
#pragma comment(lib, "msi.lib")
UINT __stdcall MyTestFail(MSIHANDLE hInstall)
{
MessageBox(NULL, L"MyTestFail", L"MyTestFail", MB_OK);
return ERROR_INSTALL_FAILURE;
}
UINT __stdcall MyTestSuccess(MSIHANDLE hInstall)
{
MessageBox(NULL, L"MyTestSuccess", L"MyTestSuccess", MB_OK);
return ERROR_SUCCESS;
}
// I will leave in the below snippet from the MSI API - section "Custom Action Security". Above two test methods will do though...
UINT __stdcall MyImmediateCA(MSIHANDLE hInstall)
{
MessageBox(NULL, L"Test", L"Test", MB_OK);
// set up information for deferred custom action called MyDeferredCA
const TCHAR szValue[] = TEXT("data");
UINT uiStat = ERROR_INSTALL_FAILURE;
if (ERROR_SUCCESS == MsiSetProperty(hInstall, TEXT("MyDeferredCA"), szValue))
{
uiStat = MsiDoAction(hInstall, TEXT("MyDeferredCA"));
// clear CustomActionData property
if (ERROR_SUCCESS != MsiSetProperty(hInstall, TEXT("MyDeferredCA"), TEXT("")))
return ERROR_INSTALL_FAILURE;
}
return (uiStat == ERROR_SUCCESS) ? uiStat : ERROR_INSTALL_FAILURE;
}
Another answer on MsiGetProperty (retrieving property values). This is a little more complicated in C++ - with the buffers and all. Scroll down for source code.
Minimal Dependencies: In order to minimize dependencies you should eliminate the Visual C / C++ Runtime dependencies and any MFC
dependencies (don't use MFC if you can help it for file size and
performance reasons). If you use MFC, set it to use static linking -
also for ATL. And finally for the C/C++ runtime, see here:
Visual Studio 2010 MSVCR dependency removal?
(there are better links, but all I could find that I have time for
right now - just want to get this in there so it is not forgotten).
The Release mode C++ binary should now not depend on any MSVC runtime dlls:
Here is a screenshot of how the DLL depends on MSVC runtime dlls without this tweak - don't mind the red icons - this is the ancient dependency walker tool which is not updated for modern dependencies, but shows older-style dependencies perfectly:
Please note that debug-mode DLLs may depend on different files than the Release mode binaries. The Release mode binaries are the ones that are important. Obviously never distribute debug-mode binaries!

C++/clr adding a native c++ dll library

I am making a computer app in C++/CLR and I just hit the wall. I'm loading the dll using the loadlibrary function and I am able to call the functions too but when I try to send a parameter for example if my function is:
std::string msgbox(std::string str)
{
MessageBoxA (0,str.c_str(),"TiTle", MB_OK | MB_ICONINFORMATION);
return str;
}
In a native c++ app when I call the function after loadlibrary and getprocaddress
std:: tmp = msg ("String");
tmp becomes "String"; and I see a Message box with String as the message but if I use C++/CLR I get like some rubbish while printing the message content in the message box if I pass in a parameter and the tmp variable would contain some trash text too how can I just load it the same way as I am doing but without this trash in the way
This is the output and the source code too:
Source: https://uploadfiles.io/itm93
Error images: https://imgur.com/a/WM7MK4c
It looks like you are compiling your c++ dlls with gcc. You can't pass standard library types between DLLs/applications compiled against different standard libraries.
You either need to compile everything with visual studio (and the same runtime library, you can't mix debug/release or the static/shared runtimes) or only pass raw character pointers over dll boundaries.

How to add a property page to DirectShow filter

I have written an DirectShow-Filter *.ax to integrate a Hardware (Camera). All works fine with my filter.ax and there Transport Images to Skype success.
Now I am want to integrate a Dialog to handle the camera-options with UI.
In my Filter.ax is calling the function QueryInterface(REFIID riid, void **ppv)
when riid == IID_ISpecifyPropertyPages
I am have seen that the Dialog must be in a other DLL like Com ?
My try to open the Dialog directly works, but no windows Messages are incoming.
I must also write an MFC Dll they is starting by PropertyPage IIID ? My Propertypage is a large MFC Controles TabControl with some items. I can see it if i start the filter from MFC Test app. AfxInit I can't execute. (Wrong Lib versions I must use the directshow baseclass(knowledge example)
I don't now why my Dialog got no Messages, what is the right way ?
You don't need to implement a property page in a separate DLL (even though it is a possible).
DirectShow filter property pages are regular COM property pages implemented using ISpecifyPropertyPages. Property pages are separate COM objects implementing well known interfaces like IPropertyPage.
Windows SDK Ezrgb24 sample shows how to implement a simple transform filter and also features a property page (CEZrgb24Properties class). It should be a good start for a property page implementation for your filter.
If you prefer to implement the property page in a separate DLL, a typical way is to define a shared COM interface, the filter would implement it and reference the property page by its CLSID, the property page would query this interface from the filter instance and use it for configuration actions.

Why can't i reference to a method/property? VB.NET

Please take a look at the 2 photos i attached, i wish to call the methods from one project to another. Both projects are in the same solution. I have already made the reference to the project containing the method in the project i want to call the method.
http://postimg.org/image/m42dlc28r/
http://postimg.org/image/w03gkz80r/
In your main project, go to
Project -> Add Reference
In that window, click browse and find the compiled version of your other project (Probably in the Release or Debug folder)
In your main projects window add this to the very top of your code (even above your class declaration)
Imports SecondProjectRootNamespace
That should give you enough information on how to do what your trying to do, but if anything was unclear, I am going to need all the details to provide a more precise answer.
Also, make sure your methods/functions are NOT declared as private.
Private = Method is only visible from within the same class
Friend = Method is only visible from any class within the same assembly (same .exe or .dll or etc)
Public = Method has no access restrictions
There are a few others but those are the basics
Try to find the dll file of the method that you want, then add it as reference in the properties of your application

using Lame dll in Unity3d

I am trying to use LAME in Unity3d on OS X with Mono c#. I dragged the Lame_enc.dll in but when the wrapper tries to find it, it doesn't and i get
DllNotFoundException: Lame_enc.dll
Yeti.MMedia.Mp3.Mp3Writer..ctor (System.IO.Stream Output, WaveLib.WaveFormat InputDataFormat, Yeti.Lame.BE_CONFIG Mp3Config) (at Assets/Helping Libraries/Lame/Mp3Writer.cs:82)
The problem from what i see, it when i try to 'link' some static methods to the dll:
[DllImport("Lame_enc.dll")]
public static extern uint beInitStream(BE_CONFIG pbeConfig, ref uint dwSamples, ref uint dwBufferSize, ref uint phbeStream);
I know that in order to see dll, on Windows, the dll needs to be in the same folder as the .exe file, but Unity being a multiplatform solution, i don't know how i can tell it where it is.
I've placed the dll in my project root folder, in the Library, in the Editor, but no luck!
Just remove the ".dll",it will work well in Editor,but won't work on mobile phone.I removed the using xxx.window and some unused files,but still the output file xx.mp3 only has 44B.