DllImport is not found C++ - dllimport

I am having trouble with using the DllImport function!
using namespace System;
using namespace System::Runtime::InteropServices;
[DllImport("user32.dll")]
It will show me no attribute when run. I am using a Windows Form with C++. And I am really noob with WindowsForms.
namespace Projekt3{
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Collections::Generic;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
using namespace System::Runtime::InteropServices;
using namespace System::Threading::Tasks;
using namespace System::IO;
using namespace std;
public ref class next : public System::Windows::Forms::Form
{
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(String sClassName, String sAppName);
[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
public:
next(void)
{
InitializeComponent();
//
//TODO: Konstruktorcode hier hinzufügen.
//
}
public: enum fsmodifiers
{
NOMOD = 0x0000,
ALT = 0x0001,
CTRL = 0x0002,
SHIFT = 0x0004,
WIN = 0x0008,
};

Your code works perfectly well, in so far as we can see it. For example, this program
using namespace System;
using namespace System::Runtime::InteropServices;
[DllImport("user32.dll")]
extern int MessageBox(System::IntPtr hwnd, System::String^ text, System::String^ caption,
unsigned int uType);
int main(array<System::String ^> ^args)
{
MessageBox((System::IntPtr)0, "foo", "bar", 0);
return 0;
}
produces the expected message box.
It is very much worth pointing out that using p/invoke from C++/CLI seems like a very pointless exercise. You can link to unmanaged code directly. It would be much more natural for this C++/CLI program to be written like so:
#include <Windows.h>
int main(array<System::String ^> ^args)
{
MessageBoxA(0, "foo", "bar", MB_OK);
return 0;
}

Related

C26434 Function xxx hides a non-virtual function

Take this simple code:
void CRestoreSettingsDlg::OnSize(UINT nType, int cx, int cy)
{
CResizingDialog::OnSize(nType, cx, cy);
m_gridBackupLog.ExpandLastColumn();
}
Why is it being flagged?
C26434 Function 'CRestoreSettingsDlg::OnSize' hides a non-virtual function 'CRestoreDialogDlg::OnSize'.
As you can see, I call the base class method.
Declarations and Definitions
CRestoreSettingsDlg:
public:
afx_msg void OnSize(UINT nType, int cx, int cy);
void CRestoreSettingsDlg::OnSize(UINT nType, int cx, int cy)
{
CResizingDialog::OnSize(nType, cx, cy);
m_gridBackupLog.ExpandLastColumn();
}
CResizingDialog:
public:
afx_msg void OnSize(UINT nType, int cx, int cy);
void CResizingDialog::OnSize(UINT nType, int cx, int cy)
{
CDialogEx::OnSize(nType, cx, cy);
Invalidate(TRUE);
}
The boilerplate base class (afxwin.h) appears to have:
protected:
afx_msg void OnSize(UINT nType, int cx, int cy);
_AFXWIN_INLINE void CWnd::OnSize(UINT, int, int)
{ Default(); }
Inheritance
class CRestoreSettingsDlg : public CResizingDialog
class CResizingDialog : public CDialogEx
C26434 warning documentation links to C.128 C++ Core Guidelines Rule. It explains that to enforce correct usage of virtual functions, non-virtual function hiding should produce a warning.
However, with MFC message maps, you have to name your message handler as specified in macro, OnSize in this case, and, since message handlers already dispatched by a virtual function (that is hidden in *_MESSAGE_MAP() macros), message handler by themselves don't have to be virtual.
So it may be seen as a false alarm. Or maybe seen as violation of the above mentioned C.128 rule by MFC itself. No surprise - MFC is decades older than these guidelines.
So I guess you can go ahead and suppress it for all afx_msg functions. Maybe redefine afx_msg to include __pragma(warning(suppress(...))), or just have suppression around afx_msg block.
Some options for suppression (Godbolt's compiler explorer demo):
#define afx_msg // this is normally defined by MFC
struct base
{
afx_msg void OnSize(){}
};
struct derived1 : base
{
afx_msg void OnSize() {} // produces C26434
};
// Suppression by adding some code:
struct derived2 : base
{
#pragma warning(push)
#pragma warning(disable:26434)
afx_msg void OnSize() {}
#pragma warning(pop)
};
struct derived3 : base
{
[[gsl::suppress(c.128)]] afx_msg void OnSize() {}
};
// Suppression by redefining MFC macro -- dirty but less intrusive:
#undef afx_msg
#define afx_msg __pragma(warning(suppress:26434))
struct derived4 : base
{
afx_msg void OnSize() {}
};
#undef afx_msg
#define afx_msg [[gsl::suppress(c.128)]]
struct derived5 : base
{
afx_msg void OnSize() {}
};

Call a Form method from a different thread (Invoke)

I've got a WinForm running on my main thread and a while(true) loop running on a separate thread. Each loop of that while(true) creates a new System::String^ and I want to paste that String into a TextBox on my UI.
My file structure includes GUI.h, GUI.cpp, and Other.cpp.
GUI.h contains all the automatically created code for the main (and only) Form. It also has some Get, Set, and ButtonClick methods.
//GUI.h
#pragma once
#include <string>
#include <vector>
#include <cliext\vector>
#include <conio.h>
#include <list>
#include <iostream>
extern void BufferRecieveLoop();
namespace GUI_Example_Receive {
static bool loopFlag = true;
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
using namespace System::Threading;
/// <summary>
/// Summary for GUI
/// </summary>
public ref class GUI : public System::Windows::Forms::Form
{
public:
GUI(void)
{
InitializeComponent();
}
std::vector<std::string> CollectText();
void ContinueNormally(); // Object^);
void DisableAllTextboxes();
void EnableAllTextboxes();
protected:
/// <summary>
/// Clean up any resources being used.
/// </summary>
~GUI()
{
if (components)
{
delete components;
}
}
private:
//Labels
//GroupBoxes
//Buttons
//SaveFile
public:
//TextBoxes
System::Windows::Forms::TextBox^ consoleTextBox;
private:
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
void InitializeComponent(void)
{
//automatically made, lightly edited
}
#pragma endregion
public:
void SetConsoleTextBoxText(System::String^ input)
{
this->consoleTextBox->Text = input;
this->consoleTextBox->Refresh();
}
void ClearConsoleTextBoxText()
{
this->consoleTextBox->Clear();
}
delegate void MyDelegate(System::String ^ str);
void ClearAndSetConsoleTextBoxText(System::String ^ input)
{
/***************************************************
if (InvokeRequired)
{
this->BeginInvoke(gcnew MyDelegate(this, &ClearAndSetConsoleTextBoxText), { input });
}
***************************************************/
ClearConsoleTextBoxText();
SetConsoleTextBoxText(input);
}
System::Void startButton_Click(System::Object^ sender, System::EventArgs^ e)
{
loopFlag = true; //able to loop through ContinueNormally()
ContinueNormally(); //method in GUI.cpp
}
};
//https://social.msdn.microsoft.com/Forums/vstudio/en-US/4da834f0-d8f8-4abb-a655-ef9e99d51eb2/how-to-create-a-global-object-of-a-ref-class-type?forum=vcgeneral
ref struct Globals {
static GUI ^gui; //using Globals::gui everywhere to access the one Form
};
}
Gui.cpp contains code to Run() the form, start a thread, and loop forever.
//GUI.cpp
void BufferRecieveLoop()
{
while (true)
{
size_t bytes_read = multicast.Receive(buffer, Example::MTU_SIZE);
incoming.Process(buffer, bytes_read, endian); //method in Other.cpp
}
}
void GUI::ContinueNormally()
{
System::Threading::Thread ^loopThread = gcnew System::Threading::Thread(gcnew System::Threading::ThreadStart(BufferRecieveLoop));
loopThread->Start();
loopThread->Join();
}
static void Start()
{
Globals::gui = gcnew GUI;
System::Windows::Forms::Application::Run(Globals::gui);
}
int __cdecl main(int argc, char* argv[])
{
System::Windows::Forms::Application::EnableVisualStyles();
System::Windows::Forms::Application::SetCompatibleTextRenderingDefault(false);
Start();
return 0;
}
Other.cpp creates a String^ and calls a method within GUI.h to change the text in a textbox.
//Other.cpp
void Process(const DIS::Pdu& packet)
{
System::String^ sysStr2 = "stuff";
GUI_Example_Receive::Globals::gui->ClearAndSetConsoleTextBoxText(sysStr2);
//GUI_Example_Receive::Globals::gui->BeginInvoke(gcnew MyStringDelegate(GUI_Example_Receive::Globals::gui, &GUI_Example_Receive::GUI::ClearAndSetConsoleTextBoxText), { sysStr2 });
}
I don't know where to properly Invoke my methods. Nor do I know how to Invoke my methods. A lot of what I've found is C# and hasn't worked for me.
Do I invoke from Other.cpp or inside the method being called in GUI.h?
In case anyone else has issues with this in the future and, like me, doesn't find many c++ code examples, I'll post my solution.
In my GUI.h file, I've got a method to SetConsoleTextBoxText(). This is usable only by the thread which owns consoleTextBox. Therefore, any other thread which trys to call that method will need to Invoke() the method (which is to relinquish control back to the owning thread).
//GUI.h
delegate void MyDelegate(System::String ^ text);
void SetConsoleTextBoxText(System::String^ input)
{
if (this->consoleTextBox->InvokeRequired) //is a thread other than the owner trying to access?
{
MyDelegate^ myD = gcnew MyDelegate(this, &GUI::SetConsoleTextBoxText);
//GUI is the ref class. Replace with wherever your function is located.
this->Invoke(myD, gcnew array<Object^> { input }); //Invoke the method recursively
}
else
{
//Normal function of this method. This will be hit after a recursive call or from the owning thread
this->consoleTextBox->Text = input;
this->consoleTextBox->Refresh();
}
}

Bring Window To Foreground When MainWindowHandle Is 0

The following code brings the window to the foreground, if the MainWindowHandle is not 0.
How can I bring a window to the front that has MainWindowHandle = 0?
This is for the Microsoft Excel - Compatibility Checker window that shows a GUI but does not have an icon in the task bar and has MainWindowHandle = 0.
I have no other instances of Excel running.
Add-Type #"
using System;
using System.Runtime.InteropServices;
public class Tricks {
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
}
"#
$excel = (Get-Process | Where-Object { $_.ProcessName -eq 'EXCEL' }).MainWindowHandle
[void] [Tricks]::SetForegroundWindow($excel)
In Windows Task Manager, I can right click on 'Microsoft Excel - Compatibility Checker' and click on "Bring To Front" and that works. How can I mimic this functionality in Powershell?
Thanks to IInspectable for pointing me in the right direction.
This code gets the real MainWindowHandle value:
$TypeDef2 = #"
using System;
using System.Text;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace Api
{
public class WinStruct
{
public string WinTitle {get; set; }
public int MainWindowHandle { get; set; }
}
public class ApiDef
{
private delegate bool CallBackPtr(int hwnd, int lParam);
private static CallBackPtr callBackPtr = Callback;
private static List<WinStruct> _WinStructList = new List<WinStruct>();
[DllImport("User32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumWindows(CallBackPtr lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
private static bool Callback(int hWnd, int lparam)
{
StringBuilder sb = new StringBuilder(256);
int res = GetWindowText((IntPtr)hWnd, sb, 256);
_WinStructList.Add(new WinStruct { MainWindowHandle = hWnd, WinTitle = sb.ToString() });
return true;
}
public static List<WinStruct> GetWindows()
{
_WinStructList = new List<WinStruct>();
EnumWindows(callBackPtr, IntPtr.Zero);
return _WinStructList;
}
}
}
"#
Add-Type -TypeDefinition $TypeDef2 -Language CSharpVersion3
$excelInstance = [Api.Apidef]::GetWindows() | Where-Object { $_.WinTitle.ToUpper() -eq "Microsoft Excel - Compatibility Checker".ToUpper() }
So now using this correct value, I can call the SetForegroundWindow() function:
Add-Type #"
using System;
using System.Runtime.InteropServices;
public class Tricks {
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
}
"#
[void] [Tricks]::SetForegroundWindow($excelInstance.MainWindowHandle)
I wrote a detailed blog about this on my website.
I've put up a full example on GitHub of how to create an Excel file, edit it and run the above code in a different thread which you have to do because the Excel popup blocks the main thread.

Hello World for Pinvoke and Native Calls

I am trying to do a very basic hello world for Pinvoke and native calls.
I create a single solution with 2 projects (one for the dll and one for the universal windows app)
So I end up with a project heirachy like this
There is one method in my dll (file NativeCalls.cpp):
#include "pch.h"
#include "NativeCalls.h"
#include <stdio.h>
MYAPI void print_line(const char* str) {
printf("%s\n", str);
}
On the C# side of things I have my NativeCalls.cs file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace MSSurfaceHubMonitoring
{
public static class NativeCalls
{
[DllImport("NativeCalls.dll")]
private static extern void print_line(string str);
public static void sayHelo()
{
print_line("Hello, PInvoke!");
}
}
}
At this point I will build and run it but get an error that it cannot find the dll
However I believe it to be the dependency and not the dll it self. I have changed the output directory of the dll to be in the root of where the UW app runs from (\bin\x86) so it really should be finding it. So like I said I think its the dependencies and not the actual dll.
Here is what I see in Dependency Walker
But I have installed all c++ packages I can get my hands on so I dont understand how to get the missing dependencies. Plus this is just a hello world, why do I need all these libraries.
FYI
My dll project is NOT referenced by the UW app. Im not sure thats needed or not? I dont think so though since this a runtime thing, so as long as the dll is there it should find it and read it. But regardless if I do try to add the project as a reference I get this error:
The biggest help to me was finding these method declarations (not even in the class)
extern "C" {
__declspec(dllexport) int getPageSize()
{
SYSTEM_INFO siSysInfo;
GetSystemInfo(&siSysInfo);
return siSysInfo.dwPageSize;
}
}
extern "C" {
__declspec(dllexport) Windows::Foundation::Collections::IMap<Platform::String^, int> ^getSystemInfo()
{
SYSTEM_INFO siSysInfo;
GetSystemInfo(&siSysInfo);
IMap<String^, int> ^ret =
ref new Platform::Collections::Map<String^, int>;
ret->Insert("oemId", siSysInfo.dwOemId);
ret->Insert("cpuCount", siSysInfo.dwNumberOfProcessors);
ret->Insert("pageSize", siSysInfo.dwPageSize);
ret->Insert("processorType", siSysInfo.dwProcessorType);
ret->Insert("maxApplicationAddress", siSysInfo.lpMinimumApplicationAddress);
ret->Insert("minApplicationAddress", siSysInfo.lpMaximumApplicationAddress);
ret->Insert("activeProcessorMask", siSysInfo.dwActiveProcessorMask);
return ret;
}
but in the end I was creating wrappers for things I didnt need to. in c# you can directly call the native methods without the need for a seperate dll or component project.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Monitoring
{
public static class NativeCallsWrapper
{
private static SYSTEM_INFO sysInfo = new SYSTEM_INFO();
private static MEMORYSTATUSEX mem = new MEMORYSTATUSEX();
[DllImport("kernel32.dll", SetLastError = false)]
public static extern void GetSystemInfo([In, Out] SYSTEM_INFO Info);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool GlobalMemoryStatusEx([In, Out] MEMORYSTATUSEX lpBuffer);
static NativeCallsWrapper()
{
GetSystemInfo(sysInfo);
GlobalMemoryStatusEx(mem);
}
[StructLayout(LayoutKind.Explicit)]
public struct SYSTEM_INFO_UNION
{
[FieldOffset(0)]
public UInt32 OemId;
[FieldOffset(0)]
public UInt16 ProcessorArchitecture;
[FieldOffset(2)]
public UInt16 Reserved;
}
public struct SYSTEM_INFO
{
public SYSTEM_INFO_UNION CpuInfo;
public UInt32 PageSize;
public UInt32 MinimumApplicationAddress;
public UInt32 MaximumApplicationAddress;
public UInt32 ActiveProcessorMask;
public UInt32 NumberOfProcessors;
public UInt32 ProcessorType;
public UInt32 AllocationGranularity;
public UInt16 ProcessorLevel;
public UInt16 ProcessorRevision;
}
[StructLayout(LayoutKind.Sequential)]
public class MEMORYSTATUSEX
{
public uint dwLength;
public uint dwMemoryLoad;
public ulong ullTotalPhys;
public ulong ullAvailPhys;
public ulong ullTotalPageFile;
public ulong ullAvailPageFile;
public ulong ullTotalVirtual;
public ulong ullAvailVirtual;
public ulong ullAvailExtendedVirtual;
public MEMORYSTATUSEX()
{
this.dwLength = (uint)Marshal.SizeOf(typeof(MEMORYSTATUSEX));
}
}
public static GeneralStatistics getGeneralStatistics()
{
GeneralStatistics generalStatistics = new GeneralStatistics();
generalStatistics.numberOfProcesses = (int)sysInfo.NumberOfProcessors;
generalStatistics.memoryTotal = mem.ullTotalPhys / 1048;
generalStatistics.memoryInUse = (mem.ullTotalPhys - mem.ullAvailPhys) / 1048;
return generalStatistics;
}
}
}

error C2664 cannot convert parameter 1 from 'std::string (__thiscall ClassName::* )(std::string)' to 'std::string (__cdecl *)(std::string)

I'm making a unmanaged application to handle an event fired in c# here.
FYI:: I want to handle a custom event when my Name property in C# class is changed.
I have gone through the following links:
Explanation about passing pointer to member function as parameter
Something similar to my problem.But couldn't understand the solution
Now,
In NativeApp.cpp,I have a member function which is passed as a function pointer as parameter in a method present in the c++/CLI wrapper
//NativeApp.cpp
std::string Class1::FunctionToBePointed(std::string msg)
{
return msg;
}
void Class1::NativeMethod()
{
UnmanagedWrapperClass* unmanagedWrapperClass=new UnmanagedWrapperClass();
unmanagedWrapperClass->WrapperMethod(&Class1::FunctionToBePointed,"Hello")
}
In Wrapper.h,
//Wrapper.h
class __declspec(dllexport) UnmanagedWrapperClass
{
boost::signals2::signal<void(std::string)>signalEvent;
void WrapperMethod(std::string (*GetCallBack)(std::string),std::string value);
}
When I call the WrapperMethod from NativeApp.cpp,
I subscribe my EventHandlerWrapper to a c# event
connect the function pointer to my boost signal signalEvent.
Set the Name property of the CSharp Class
When the Name Property is set, c# event is fired, EventHandlerWrapper method in Wrapper.cpp is executed.Looks like this::
void EventHandlerWrapper(string value)
{
if(signalEvent.connected())
{
signalEvent(value);
}
For some reasons I can't make my FunctionToBePointed(std::string) method as a non-member function.
P.S:: All ears for any other design approach.
In your real use-case can you simply make FunctionToBePointed a static method?
static std::string Class1::FunctionToBePointed(std::string msg)
{
return msg;
}
If yes your code should work.
The reason is that instance methods are implicitly called with an hidden this pointer, this is the thiscall calling convention, whereas static methods simply use the cdecl convention because they don't work on any instance.
EDIT:
A sample with Boost::bind:
The MyClass C# class:
using System;
using System.ComponentModel;
public class MyClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = delegate{};
private string name;
public string Name
{
get
{
return name;
}
set
{
if (name != value)
{
name = value;
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
}
}
The C++/CLI wrapper:
Wrapper.h:
class WrapperPrivateStuff;
class __declspec(dllexport) UnmanagedWrapperClass
{
private: WrapperPrivateStuff* _private;
public: void changeIt(std::string newName);
public: void WrapperMethod(boost::function<std::string(std::string)> GetCallBack);
public: UnmanagedWrapperClass();
};
Wrapper.cpp:
#using "MyClass.dll"
#include <boost/signals2.hpp>
#include <boost/bind.hpp>
#include "Wrapper.h"
#include <msclr\auto_gcroot.h>
#include <msclr\marshal_cppstd.h>
#include <msclr\event.h>
class WrapperPrivateStuff
{
public: boost::signals2::signal<void(std::string)>signalEvent;
public: msclr::auto_gcroot<MyClass^> a;
public: void EventHandlerWrapper(System::Object^, System::ComponentModel::PropertyChangedEventArgs^ args)
{
this->signalEvent(msclr::interop::marshal_as<std::string>(a->Name));
}
public: WrapperPrivateStuff()
{
a = gcnew MyClass();
a->PropertyChanged += MAKE_DELEGATE(System::ComponentModel::PropertyChangedEventHandler, EventHandlerWrapper);
}
BEGIN_DELEGATE_MAP(WrapperPrivateStuff)
EVENT_DELEGATE_ENTRY(EventHandlerWrapper, System::Object^, System::ComponentModel::PropertyChangedEventArgs^)
END_DELEGATE_MAP()
};
void UnmanagedWrapperClass::changeIt(std::string newName)
{
this->_private->a->Name = msclr::interop::marshal_as<System::String^>(newName);
}
UnmanagedWrapperClass::UnmanagedWrapperClass()
{
this->_private = new WrapperPrivateStuff();
}
void UnmanagedWrapperClass::WrapperMethod(boost::function<std::string(std::string)> GetCallBack)
{
_private->signalEvent.connect(GetCallBack);
}
And the native application, test.cpp:
#include <iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include "Wrapper.h"
class Class1
{
private: std::string name;
public: Class1(std::string name)
: name(name)
{
}
public: std::string FunctionToBePointed(std::string msg)
{
std::cout << "Hey it's " << name << "! Got: " << msg << std::endl;
return msg;
}
};
int main(void)
{
UnmanagedWrapperClass wrapper;
Class1 class1("Ed");
wrapper.WrapperMethod(boost::bind(&Class1::FunctionToBePointed, &class1, _1));
wrapper.changeIt("azerty");
return 0;
}
Result:
>test.exe
Hey it's Ed! Got: azerty
I have a more generic solution but it is really ugly. :(
Let me know if this fix your issue...

Resources