none
Why my 32 bit WPF .NET app can't find 32 bit dll RRS feed

  • Question

  • It is quite nice opportunity to combine C++ with C# , but if the app runs... (Solution in VS2017  WPF app ( .NET Framework), added project: Visual C++ -> Windows Desktop -> Windows Desktop Wizard -> dll)

    ...may be some VS settings in addition I need?

    The ERROR: System.DllNotFoundException: 'Unable to load DLL 'SomeAssemblerFunctions.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)'

    Why my 32 bit WPF .NET app can't find 32 bit dll?

    I use p/Invoke, not C++/CLI.

    Thanks in advance

    MyClass.cpp:

    int MyClass::Foo_1()  
    {  
        __asm  
      {  
        mov eax, 0  
      }
    }  
    void MyClass::SetFoo_1()  
    {  
      resultEAX = new int;  
      int a = -1;  
      try  
      {  
        a = Foo_1();  
      }  
      catch (int e) { }  
      if (a == 0) {  
      *resultEAX = 0;  
      }  
      else {  
        *resultEAX = 1;  
      }  
    }  

    MyClass.h:

    #ifndef MYCLASS_H  
    #define MYCLASS_H  
    class __declspec(dllexport) MyClass {  
    public:  
        int * resultEAX ;  
        int Foo1();  
        void SetFoo_1();  
        int  GetEAX();  
    };  
    #endif  

    MyClassCaller.h:

    extern "C" {  
    #endif  
    __declspec(dllexport) MyClass* Create();  
    __declspec(dllexport) void Dispose(MyClass* a_pObject);  
    __declspec(dllexport) void SetFoo_1(MyClass* a_pObject);  
    __eclspec(dllexport) int GetEAX(MyClass* a_pObject);  
    #ifdef __cplusplus
    }  
    #endif  

    MyClassCaller.cpp:

    Graphics* Create()  
    {  
      return new MyClass();  
    }  
    
    void Dispose(MyClass * a_pObject)  
    {  
      if (a_pObject != NULL)  
      {  
        delete a_pObject;  
        a_pObject = NULL;  
      }  
    }  
    
    void SetFoo_1(MyClass * a_pObject)  
    {  
      if (a_pObject != nullptr)  
      {  
        a_pObject->SetFoo_1();  
      }  
    }  
    
    int GetEAX(MyClass * a_pObject)  
    {  
      if (a_pObject != NULL)  
      {  
         return a_pObject->GetEAX();  
      }  
      return 0;  
    }  

    And I call the class from WPF.NET using managed C# code:

    IntPtr pMyClass = MyClassHandling.Create();  
    Int32 a = 0;  
    Int64 b = 0;  
    long c = 0;  
    long rslt = 0;  
    
    try  
    {  
      MyClassHandling.SetFoo_1(pMyClass);  
      if (Environment.Is64BitOperatingSystem)  
      {  
        //"SysWOW64" 
        b = MyClassHandling.GetEAX(pMyClass);  
       //…… 
      }  
      else  
      {  
        //"system32" 
        a = pMyClassHandling.GetEAX(pGraphics);  
        //… 
      }  
    
    MyClassHandling.Dispose (pGraphics); 
    pMyClass = IntPtr.Zero;  
    
    [DllImport("SomeAssemblerFunctions.dll")]  
    static public extern IntPtr Create();  
    [DllImport("SomeAssemblerFunctions.dll")]  
    static public extern void Dispose(IntPtr pGraphicsObject);  
    [DllImport("SomeAssemblerFunctions.dll", EntryPoint = "SetGraphicMode1")]  
    static public extern void SetFoo_1(IntPtr pGraphicsObject);  
    [DllImport("SomeAssemblerFunctions.dll", EntryPoint = "GetEAX")]  
    static public extern int GetEAX(IntPtr pGraphicsObject);



    Tuesday, May 14, 2019 8:30 AM

All replies

  • Hi Jovannaj,

    Welcome to the MSDN forum.
    According to your description, your issue is about the C# development and our forum is to discuss the VS extension, I will help you move this thread to the appropriate forum for a better support, thank you for your understanding.

    Best regards,
    Lance


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, May 15, 2019 6:11 AM
  • Hi Jovannal,

    Thank you for posting here.

    Based on your description, you want to solve the error that "Unable to load dll".

    The possible reason is that you don't put the dll in the right place. As usual, we could put it in the following path.

    WPFApp1\bin\Debug\SomeAssemblerFunctions.dll

    After checking it, if the problem exists, please feel free to let us know.

    Best Regards,

    Jack


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, May 15, 2019 7:29 AM
    Moderator
  • Dear Jack,

    thanks for the answer. 

    But there is a strange behavior of the app. I replaced assembler functions with some simple functions, to reduce the probable cause of the error. Tried thousand versions but the situation is:

    -the app runs on my PC only;

    -if I copy-paste the both files: CsAppWPF.exe and PInvoke_Class_Core_Win32DesktopDLL.dll to another PC , also on a virtual machine, the app hanging...and stop working.

    Windows throws a message: A problem caused the program to stop working correctly. Windows will close the program...

    Here is my Solution: GitHub > VanyaBenovska > P_Invoke-Win32DesktopDLL_and_Cs.NET-WPF


    Thanks.

    King regards,

    Vanya

    Thursday, June 13, 2019 11:48 AM
  • Your logic is incorrect for detecting x64. You are asking if the OS is x64. That has nothing to do with whether your process is x64 or not. An x64 OS can run both x86 and x64 code. Your app is just looking at the OS.

    Second issue is that your app determines the bitness of your code. You said your app is compiled for x86 therefore none of the x64 stuff matters, it'll never use it. That is good because your C++ DLL should be x86 as well. If your app is Any CPU and your DLL x86 then it wouldn't load on an x64 OS anyway.

    Lastly I don't really understand why you're checking for x64 anyway. In the x64 version you call GetEAX with a pointer to your MyClass which was originally created by calling Create. This lines up with the native code you provided. However on an x86 machine GetEAX on some "p" version that you didn't post. You also are passing some non-MyClass object. Since you didn't post any of that native code my gut instinct is it is calling native code incorrectly and therefore blows up.

    Take away - remove all the x64 logic as it doesn't apply here. See if your problem goes away. If it doesn't then post the relevant native and managed code that isn't working. Also go to Event Viewer and capture the error log that is generated. Alternatively when WER pops up that something went wrong grab the technical details. The callstack and error are most important.


    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, June 13, 2019 2:07 PM
    Moderator
  • Dear Michael,

    thank you for the answer. Yes, you are right, no need for OS check. I corrected it and also wrapped my functions in a class.

    But my code / or Visual Studio settings I've done are not correct. Problems are as mentioned: 

    -the app runs on my PC only;

    -if I copy-paste the both files: CsAppWPF.exe and .dll to another PC , also on a virtual machine, the app hanging...and stop working.

    (you can check my VS settings from the Solution, I've published it on:  GitHub > VanyaBenovska > P_Invoke-Win32DesktopDLL_and_Cs.NET-WPF)

    Tried a lot of versions, but it is the same: the app hangs if I start it from a virtual machine. Please help.

    MyClass.h:

    #ifndef MYCLASS_H #define MYCLASS_H class __declspec(dllexport) MyClass { public: int resultEAX ; int Foo_1(); int Foo_2(); void SetFoo_1(); void SetFoo_2(); int GetEAX(); }; #endif

    MyClassCaller.h:

    #pragma once
    #include "MyClass.h"      
    
    #ifdef __cplusplus
    
    extern "C" {
    #endif
    
    	 __declspec(dllexport) MyClass* Create();
    	 __declspec(dllexport) void Dispose(MyClass* a_pObject);
    	 __declspec(dllexport) void SetFoo_1(MyClass* a_pObject);
    	 __declspec(dllexport) void SetFoo_2(MyClass* a_pObject);
    	 __declspec(dllexport) int GetEAX(MyClass* a_pObject);
    
    #ifdef __cplusplus
    }
    #endif

    dllmain: generated authomatically:

    // dllmain.cpp : Defines the entry point for the DLL application.
    #include "stdafx.h"
    
    BOOL APIENTRY DllMain( HMODULE hModule,
                           DWORD  ul_reason_for_call,
                           LPVOID lpReserved
                         )
    {
        switch (ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
        }
        return TRUE;
    }
    
    

    MyClass.cpp:

    #include "stdafx.h"
    
    #include <iostream>
    
    
    #include "MyClass.h"
    
    
    int MyClass::Foo_1()
    {
    	__asm
    	{
    		mov eax, 9
    	}
    }
    
    int MyClass::Foo_2()
    {
    	__asm
    	{
    		mov eax, 8
    	}
    }
    
    void MyClass::SetFoo_1()
    {
    	try
    	{		
    		this->resultEAX = Foo_1();
    	}
    	catch (int e)
    	{
    		this->resultEAX = 0;
    	}
    }
    
    void MyClass::SetFoo_2()
    {
    	try
    	{
    		this->resultEAX = Foo_2();		
    	}
    	catch (int e)
    	{
    		this->resultEAX = 3;
    	}
    }
    
    int MyClass::GetEAX()
    {
    	return this->resultEAX;
    }
    

    MyClassCaller.cpp:

    #include "stdafx.h"
    
    #include "MyClassCaller.h"
    
    MyClass* Create()
    {
    	return new MyClass();
    }
    
    void Dispose(MyClass* a_pObject)
    {
    	if (a_pObject != NULL)
    	{
    		delete a_pObject;
    		a_pObject = NULL;
    	}
    }
    
    void SetFoo_1(MyClass* a_pObject)
    {
    	if (a_pObject != nullptr)
    	{
    		a_pObject->SetFoo_1();		 
    	}
    }
    
    void SetFoo_2(MyClass* a_pObject)
    {
    	if (a_pObject != nullptr)
    	{
    		a_pObject->SetFoo_2();
    	}
    }
    int GetEAX(MyClass* a_pObject)
    {
    	if (a_pObject != NULL)
    	{
    		return a_pObject->GetEAX();
    	}
    	return 0;
    }

    Thanks.

    Kind regards,

    Vanya


    Friday, June 14, 2019 2:53 PM
  • Firstly, you need to xcopy the entire output directory for your app, not just the EXE and DLL. The entire `bin\debug` (or wherever you output your code) needs to be copied. This includes other dependencies and the config files. Without that your app won't run.

    Please post the error information as I mentioned in the earlier post. The exact error message along with the callstack will help to quickly narrow this done. Most likely the issue is with the VM configuration. This is especially true if it is a baseline OS VM and/or you're calling to external network resources.




    Michael Taylor http://www.michaeltaylorp3.net

    Friday, June 14, 2019 3:00 PM
    Moderator
  • ups, and my C#  WPF  .NET code:

    using System;
    using System.Runtime.InteropServices;
    using System.Windows;
    
    
    namespace CsAppWPF
    {
        public static class ClassFromDllWithSomeAssemblerFunctions
        {
            [DllImport("PInvoke_Class_Core_Win32DesktopDLL.dll"
                 //  , EntryPoint = "??4MyClass@@QAEAAV0@$$QAV0@@Z"
                 // , CallingConvention = CallingConvention.Cdecl
                 , CallingConvention = CallingConvention.StdCall
                )]
            static public extern IntPtr Create();
    
            [DllImport("PInvoke_Class_Core_Win32DesktopDLL.dll"
                // , EntryPoint = "??4MyClass@@QAEAAV0@$$QAV0@@Z"
                // , CallingConvention = CallingConvention.Cdecl
                , CallingConvention = CallingConvention.StdCall
                )]
            static public extern void Dispose(IntPtr pMyClass);
    
            [DllImport("PInvoke_Class_Core_Win32DesktopDLL.dll"
                //   , EntryPoint = "??4MyClass@@QAEAAV0@$$QAV0@@Z"
                // , CallingConvention = CallingConvention.Cdecl
                , CallingConvention = CallingConvention.StdCall
                )]
            static public extern void SetFoo_1(IntPtr pMyClass);
    
            [DllImport("PInvoke_Class_Core_Win32DesktopDLL.dll"    
               //  , EntryPoint = "??4MyClass@@QAEAAV0@$$QAV0@@Z"
               // , CallingConvention = CallingConvention.Cdecl
               , CallingConvention = CallingConvention.StdCall
               )]
            static public extern void SetFoo_2(IntPtr pMyClass);
    
            [DllImport("PInvoke_Class_Core_Win32DesktopDLL.dll"
                //    , EntryPoint = "?GetEAX@MyClass@@QAEHXZ"
                // , CallingConvention = CallingConvention.Cdecl
                , CallingConvention = CallingConvention.StdCall
                )]
            static public extern int GetEAX(IntPtr pGraphicsObject);
        }
    
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                txbResult_ASM_Foo_1.Text = "Waiting to press 'Start'";
            }
    
            void OnClickStart(object sender, RoutedEventArgs e)
            {
                IntPtr p1_MyClass = ClassFromDllWithSomeAssemblerFunctions.Create();     
                long rslt = 0;
                try
                {
                    ClassFromDllWithSomeAssemblerFunctions.SetFoo_1(p1_MyClass);
                    rslt = ClassFromDllWithSomeAssemblerFunctions.GetEAX(p1_MyClass);
                    txbResult_ASM_Foo_1.Text = rslt.ToString();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    MessageBox.Show(ex.GetType().ToString());
                    txbResult_ASM_Foo_1.Text = "Error";
                }
                ClassFromDllWithSomeAssemblerFunctions.Dispose(p1_MyClass);
    
                IntPtr p2_MyClass = ClassFromDllWithSomeAssemblerFunctions.Create();
                try
                {
                    ClassFromDllWithSomeAssemblerFunctions.SetFoo_2(p2_MyClass);
                    rslt = ClassFromDllWithSomeAssemblerFunctions.GetEAX(p2_MyClass);
                    txbResult_ASM_Foo_2.Text = rslt.ToString();
                }
                catch (Exception ex)
                {
                    //MessageBox.Show(ex.Message);  //Unable to find an entry pointnamed "SetFoo_2" in DLL "MyClassCppAssembler.dll"
                    //MessageBox.Show(ex.GetType().ToString()); //SystemEntryPointNotFound Exception
                    txbResult_ASM_Foo_2.Text = "Error";
                }
                ClassFromDllWithSomeAssemblerFunctions.Dispose(p2_MyClass);
            }
        }
    }
    

    Friday, June 14, 2019 3:02 PM
  • Dear Michael,

    thank you for your answer. I copied all files from bin\debug directory, but my app still doesn't run and hanging... The app is running ok on my pc, but if I start it on a virtual machine - it doesn't. Would you  help me please?

    Thanks.

    Kind regards

    Vanya

     

    Monday, June 17, 2019 9:09 AM
  • You haven't posted the error your getting or anything yet. Please post that because we cannot possibly guess what is going wrong here. If you're getting the WER dialog then post the technical details. If you get no error then look in the event viewer. If you still aren't seeing anything then put Process Explorer on the machine, run the app and then click option to get a crash dump file that you can load into VS.

    Also bear in mind that the VM you're running your app on needs the correct version of .NET Framework installed. Your native DLL will need the correct version of the C++ runtime installed along with any other third party components it requires. Have you confirmed that all of this is properly installed on the VM?


    Michael Taylor http://www.michaeltaylorp3.net

    Monday, June 17, 2019 1:41 PM
    Moderator
  • Dear Michael,

    thank you for your advises. I entered in the C++ header peace of code for 1/WER:

    MyClass.h

    #ifndef MYCLASS_H

    #define MYCLASS_H

    #include <errorrep.h>

    EFaultRepRetVal ReportFault(

           LPEXCEPTION_POINTERS pep,

           DWORD                dwOpt

    );

    class __declspec(dllexport) MyClass

    {

    public:     

           int resultEAX ;

           int Foo_1();

           int Foo_2();

           void SetFoo_1();

           void SetFoo_2();

           int  GetEAX();

    };

    #endif

    But  I am not sure if it is enough Microsoft to receive crash information.

    2/The ERROR message: CsAppWPF has stopped working;    A problem caused the program to stop working corectly. Windows will close the program..

    3/Registry Editor-on the Virtual Machine: NET Framework Setup>NDP>v4>Full>Relase> (394254)

    On my PC: Registry Editor-on the Virtual Machine: NET Framework Setup>NDP>v4>Full>Relase> (461808)

    4/ 

    ERROR - Event Viewer when app ran on a Virtual Machine:

    Faulting application name: CsAppWPF.exe, version: 1.0.0.0, time stamp: 0x84bae582

    Faulting module name: KERNELBASE.dll, version: 10.0.10586.0, time stamp: 0x5632da1c

    Exception code: 0xe0434352

    Fault offset: 0x000bd8a8

    Faulting process id: 0xfa0

    Faulting application start time: 0x01d52828340fc799

    Faulting application path: \\store\Developers\Vanya_Benovska\exe__Microsoft-WER-Debug\CsAppWPF.exe

    Faulting module path: C:\Windows\SYSTEM32\KERNELBASE.dll

    Report Id: 8a815906-3fd0-41d8-98a6-f99d013392ed

    Faulting package full name: Faulting package-relative application ID

    5/ERROR - Event Viewer when app ran on another PC, without installed Visual Studio on it:

    Faulting application name: CsAppWPF.exe, version: 1.0.0.0, time stamp: 0xb1b35808

    Faulting module name: KERNELBASE.dll, version: 10.0.17763.475, time stamp: 0x9877ee8b

    Exception code: 0xe0434352

    Fault offset: 0x0011c762

    Faulting process id: 0x2198

    Faulting application start time: 0x01d5280b691c01f0

    Faulting application path: C:\Users\olga.mladenova\Desktop\exe-Microsoft-Debug\CsAppWPF.exe

    Faulting module path: C:\windows\System32\KERNELBASE.dll

    Report Id: 0f6954e5-96df-4313-8852-c9ec808f4963

    Faulting package full name: Faulting package-relative application ID

    But if I install Visual Studio on another PC (where the app crashing, ) after VS installation, the app stops crashing.

    Please help finding the problem..

    Kind regards,

    Vanya




    • Edited by JovannaJ Friday, June 21, 2019 12:48 PM
    Friday, June 21, 2019 12:39 PM
  • Quick test, compile your solution in Release mode and then try running it remotely. If it works then the issue is you're trying to run a debug app on a non debug machine.

    For .NET this doesn't matter but for C++ it relies on the C++ runtime. The runtime ships as both debug and release versions. Debug versions are not redistributable and are installed as part of VS. Non-VS machines won't have them. If you try to use a C++ binary compiled against the debug version of the runtime then it will fail. 

    Compiling and running in release mode solves this issue. If your app still doesn't run then verify the version of the C++ runtime you rely on is installed. The Depends tool is useful for figuring this out.

    If you really need to debug your app then you'll have to temporarily copy the debug DLLs to the remote machine. They are available under `<vsdir>\vc\redist\msvc\<version>\debug_nonredist`. Copy each of the DLLs you rely on from the appropriate bitness folder to the output directory on the remote machine. Then you can run your app. Note that these binaries cannot be redistributed so you cannot ship debug versions of your app.


    Michael Taylor http://www.michaeltaylorp3.net

    Friday, June 21, 2019 2:09 PM
    Moderator
  • Dear Michael,

    thank you for guiding. But the app still doesn't run on a virtual machine. I done:

    1/ build the both projects (Win32 dll and WPF.NET) in Release mode.

    2/ Target framework: .NET Framework 4.6.1;

    Installed versions:

    Microsoft Visual C++ 2008 Redistributable –x64  9.0.30729.4148

    Microsoft Visual C++ 2008 Redistributable –x64  9.0.30729.6161

    Microsoft Visual C++ 2008 Redistributable –x86  9.0.30729.4148

    Microsoft Visual C++ 2008 Redistributable –x86  9.0.30729.6161

    Microsoft Visual C++ 2010 Redistributable –x64  10.0.40219

    Microsoft Visual C++ 2010 Redistributable –x86  10.0.40219

    Microsoft Visual C++ 2010 Redistributable –x86  12.0.30501

    Microsoft Visual C++ 2017 Redistributable –x64  14.16.27029

    Microsoft Visual C++ 2017 Redistributable –x86  14.16.27029

    3/Dependency Walker ERROR: At least one file was not a 32-bit or 64-bit Windows module.

    Module: PINVOKE_CLASS_CORE_WIN32DWSKTOPDLL.IOBJ:  ERROR: No DOS or PE signature found. This file is not a valid 32-bit or 64-bit Windows module.

    Please guide me to next.

    Kind regards,

    Vanya

    Wednesday, June 26, 2019 9:10 AM
  • Where is this PINVOKE thing coming from? IOBJ isn't a DLL which seems to indicate an issue with your native code.

    Michael Taylor http://www.michaeltaylorp3.net

    Friday, June 28, 2019 9:49 PM
    Moderator
  • Dear Michael,

    Dear All,

    first, many thanks to Michael who helped me a lot to discover where the problem comes from. I would like to share it in case somebody has the same app-problems:
    1/check the .NET Framework version: on Visual Studio - project-set-version must be the same as .NET Framework version installed on the machine you run the app. (if app ver.4.0, must be at least 4.0:  latest versions include ver.4.0, is it?)
    2/Install on the machine you run the app - Microsoft Visual C++ 2015 Redistributable Update 3 RC 
    (Microsoft Visual C++ 2015 Redistributable installs run-time components of Visual C++ libraries. These components are required to run C++ applications that are developed using Visual Studio 2015 Update 3 RC and link dynamically to Visual C++ libraries. )

    Michael, thanks again!

    Have nice, nice days!!
    Friday, July 5, 2019 8:36 AM