A company produces a device with an ethernet connector. I have one of their devices and they gave me a .lib file and some .h files so I can connect and communicate with their device. Works fine, I'm glad.
Then the company produced a new version of their device. I also have this newer device and again they gave me some files so I can connect and communicate with it: this time a .lib file, a .dll file and some .h files.
So much for the background. Now, the problem:
I wrote a simple test application in MS Visual C++ 6.0 to see what happens, when I try to connect to the new device with the old interface: the connect() method provided (using the old .lib file) immediately returns 0 (Could not connect). Makes sense, I agree!
But, when I wrap that .lib file in a .dll file and try the same scenario again, I don't get an immediate result, it takes 42 seconds until I get the 0 result!
The wrapper works fine when I try to connect to the older device, no problem at all.
This is the first project where I have to wrap up a .lib file in a .dll file (I did that so I can use it in C#), so I don't know too much about this topic. All I know is, that I'm passing along values from the original method calls to the wrapper ... How can there be such a delay? It must happen somewhere in the Wrapping, but I have no clue. Networking shouldn't be the problem, because without wrapper I get the result immediately. Maybe something about Threading or DLLs?
I was hoping someone could enlighten me here ...
I didn't post any specific code, because I wouldn't know what is relevant here. If you need more information, please let me know!
EDIT:
In C# I have a class MyDLLImport:
class MyDLLImport
{
[DllImport("Old_Interface_MSVC++GeneratedDLL.dll")]
public static extern int Connect();
[DllImport("Old_Interface_MSVC++GeneratedDLL.dll")]
public static extern int Disconnect();
...
}
In another C# class I access these methods directly, like:
MyDLLImport.Connect();
The .lib and .h files I wrapped up in the Old_Interface_MSVC++GeneratedDLL.dll file like this:
Old_Interface_MSVC++GeneratedDLL.cpp:
#include "stdafx.h"
#include "Old_Interface_MSVC++GeneratedDLL_Class.h"
#include "Old_Interface_MSVC++GeneratedDLL.h"
#include <string.h>
#include <iostream>
BOOL APIENTRY DllMain( HANDLE 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;
}
ALibClass MyDLL::client;
int MyDLL::Connect()
{
int ret;
ret = MyDLL::client.Connect();
if(!ret)
{
std::cerr << "Could not connect" << std::endl;
return false;
}
return true;
}
void MyDLL::Disconnect()
{
MyDLL::client.Disconnect();
}
...
/////////////////////////////////
// exported functions
int Connect()
{
return MyDLL::Connect();
}
void Disconnect()
{
MyDLL::Disconnect();
}
Then, there is the header file for the previous .cpp file, Old_Interface_MSVC++GeneratedDLL.h:
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
// added by myself to prevent export warnings
#pragma warning( disable: 4251 )
/////////////////////////////////////////////
//exported general methods
extern "C" MYDLL_API int Connect();
extern "C" MYDLL_API void Disconnect();
...
And finally the class header file Old_Interface_MSVC++GeneratedDLL_Class.h:
#include "lib_header_file.h"
class MyDLL
{
private:
static ALibClass client;
public:
static int Connect();
static void Disconnect();
...
}
I hope I have added all relevant code parts. If you need more information, let me know!
Related
I have written a C++ dll with one published method which simply starts another program with a defined parameter. This method is called from a C# WinForms application.
The published method is triggered from the C# application on a button click. The 2nd application is starting, as intended, but in addition a Windows Console window is opening which outputs nothing.
I want to suppress the console window, but I can't figure out how to do this.
When the application I run is terminated, the console window also terminates.
This is what my header and source of the C++ dll looks like:
launcher.h
#pragma once
#ifdef ILJ16_EXPORTS
#define LAUNCHER_EXPORT __declspec(dllexport)
#else
#define LAUNCHER_EXPORT __declspec(dllimport)
#endif // ILJ16_EXPORTS
const char* startParam = "--Q7t0elSDASCrpHQ";
extern "C" LAUNCHER_EXPORT void startProcess();
launcher.cpp
#include "pch.h"
#include "launcher.h"
#include <process.h>
#include <stdio.h>
void startProcess()
{
char command[256 + 1];
snprintf(command, sizeof(command), "Test.exe %s", startParam); //Test.exe is the application which has to be started
int retCode = system(command);
}
In my C# WinForms project I have written the following code
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
[DllImport("ilj16.dll", EntryPoint = "startProcess")]
public static extern void startProcess();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
startProcess();
}
}
}
Instead of startprocess, consider using CreateProcess with STARTUPINFO.wShowWindow set to SW_HIDE.
CreateProcess
Creates a new process and its primary thread. The new process runs in the security context of the calling process
From reading the windows documentation it appears that the system(const char*) call opens a cmd.exe prompt and then executes the string.
system documentation
The system function passes command to the command interpreter, which executes the string as an operating-system command. system uses the COMSPEC and PATH environment variables to locate the command-interpreter file CMD.exe. If command is NULL, the function just checks whether the command interpreter exists.
From a quick google it looks like the best way to solve this is to use _popen, CreateProcessA, or you could try to hide/close the cmd.exe using something like this.
Also, if your C++ dll is only opening another program, you could eliminate the need for a dll and do it all in C# with this C# class. In the first example at that link there is a simple solution:
using (Process myProcess = new Process())
{
myProcess.StartInfo.UseShellExecute = false;
// You can start any process, HelloWorld is a do-nothing example.
myProcess.StartInfo.FileName = "C:\\HelloWorld.exe";
myProcess.StartInfo.CreateNoWindow = true;
myProcess.Start();
// This code assumes the process you are starting will terminate itself.
// Given that is is started without a window so you cannot terminate it
// on the desktop, it must terminate itself or you can do it programmatically
// from this application using the Kill method.
}
I want to read the Device Descriptor of a USB Serial port (not just the VID/PID -- mainly so I can get the bcdDevice, iProduct, and iManufacturer) so I can know if the USB serial port is capable of what I want it to do (we have a couple of modems in the field, and one of them is much more reliable at half-duplex).
I don't want to use libusbdotnet because I don't want my users to have to figure out ahead of time what to filter for to get the ports I'm interested in.
I see how to do it with C; looking on the USBView application, we're going to need to use the SetupAPI to enumerate the controllers (SetupDiEnumDeviceInfo), then the hubs, and then query the hubs with IOCTL to get what is on each port.
I think I have to do this this way because I can't figure out a mapping from COM13 -> \.\USB#ROOT_HUB30#4&2a9d917a&0&0#{f18a0e88-c30c-11d0-8815-00a0c906bed8}.. is there a better/easier way to get the filename I need for the ioctl, rather than go through them all and filter them?
I've also tried making the usbview application into a C DLL and tried to make a wrapper around that, but I can't get my homegrown DLL to compile properly...
I tried adding this to the enum.c from usbview just as a starting point
typedef struct
{
PSTR Name;
PSTR path;
int port;
} USBDevice;
USBDevice USBDevices[255] = { 0 };
int ndevices;
extern __declspec(dllexport) int GetDevices(PSTR filter)
{
//Enumerate it all and filter for "COM%"
//Store the data in the USBDevice array.
}
extern __declspec(dllexport) PSTR DeviceName(int i)
{
return USBDevices[i].Name;
}
extern __declspec(dllexport) PSTR DevicePath(int i)
{
return USBDevices[i].path;
}
extern __declspec(dllexport) void FreeList(void)
{
char* foo;
int i;
for (i = 0; i<ndevices; i++)
{
free(USBDevices[i].Name);
free(USBDevices[i].path);
}
ndevices = 0;
}
extern __declspec(dllexport) PUSB_COMMON_DESCRIPTOR GetDevuceInfo(PSTR path, int port)
{
//I didn't want to figure out how to marshal this.
}
extern __declspec(dllexport) PSTR GetDevuceInfoValue(PSTR path,int port, int selector)
{
//Open Hub, send IOCTL to it, get data, filter that, return the interesting bit.
}
But I can't load the resulting DLL into my C# project (it crashes when run - even before the window appears). Looking at the DLL, it appears that it is garbage (walking the DLL causes the walker to crash). so... I'm not sure what I'm doing wrong there, so I was going to translate the enum.c into C# pinvoke-style and roll with that, but it seems like a lot of work, especially if there's a simpler way to get the COM14 -> \.\USB#ROOT_HUB30#4&2a9d917a&0&0#{f18a0e88-c30c-11d0-8815-00a0c906bed8} [Port1] link...
So... Is there a lot of work ahead of me, or is there a simpler way to get the linkage (I've tried from the registry, but it doesn't seem to have the mapping).
It looks like that is the approved way (EnumerateDevices, CM_GetParent, Munge it to a valid path, then ask the Hub to get the data). I've made a C program to do the dirty work and it works like a charm. I think I'll wrap it in a DLL and post it to CodeProject.
Warning though... even if you do a DeviceIOControl, windows does not re-query your device. It only queries your device at Plug-In.
But at least you can find the "Manufacturer String" so you can tell your USB port from all the similar ones that are plugged in. Then again, you can get that from SetupAPI, so... I don't know what it really buys you.
I have a third-party Windows app that supports a C plugin/driver (see spec below) to be a passive data receiver once initialized. Now I found a C# package that does the data gathering and Pushing. The only missing piece here is a bridge between the C dll and the C# dll.
The data flow is like this: When the app is launched, it loads and calls the C dll which contains several exported functions including an init function. In this init function, I like to establish a call to the C# to setup some network connection and prepare for incoming data. Once that done, according to the driver spec, the C# dll will gather data and stream it to the receiving driver. To accommodate this, I have two thoughts (you may come up with more):
1) to wrap the C# with C++/Cli and call the expose C#-like methods from the driver. Declare an object with gcroot, then instantiate it with gcnew then call the method(s). Tried that and I got stackoverflowexception. I am new to this mix-mode programming and can't figure out why that happened.
2) to wrap the C dll in some way (like using C++/Cli to import the C functions then interact with the C# data streamer) to be callable from C#. What is the best way to do this?
I have done some reading and it seems C++/Cli is the easy route but I am open to other not so complicated options as well. What are the project settings I have to add/modify to make it work should I choose C++/Cli or any way you suggest?
As I am new to tackle this kind of problem, any samples or related links are helpful. So I appreciate if you could demonstrate how things work one way or the other.
Here is piece of the skeletal C# dll referenced (other methods are omitted):
public class Client
{
public Client()
{
//reset();
}
public void test()
{
Console.WriteLine("test");
}
/// <summary>
/// Connect connects the Client to the server.
/// Address string has the form host:port.
/// </summary>
public void Connect(string address)
{
Disconnect();
// validate address
int sep = address.IndexOf(':');
if (sep < 0)
{
throw new ArgumentException("Invalid network address");
}
// set host and port
host = address.Substring(0, sep);
toPort(ref port, address.Substring(sep + 1));
// connect
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(host, port);
rw.Set(socket, CLIENT_DEFAULT_BUFFER_SIZE);
}
/// <summary>
/// Disconnect disconnects the Client from the server.
/// </summary>
public void Disconnect()
{
backlog.Clear();
try
{
if (Connected)
{
write("close");
}
}
catch (Exception e)
{
}
//reset();
//rw.Close();
}
}
Here is the skeletal spec of the C dll:
//APIs
#ifdef __cplusplus
extern "C"{
#endif
#define DLL __declspec(dllexport)
////////////////////////////////////////////////////////////////////////////
// Initialization: do some prep for receiving data from C#
// params:
// hWnd handle
// Msg message
// nWorkMode work mode
// return:
// 1 true
// -1 false
DLL int Init(HWND hWnd, UINT Msg, int nWorkMode);
// Quitting and closing
// Param:
// hWnd same handle as Init
// return:
// 1 true
// -1 fals
DLL int Quit(HWND hWnd);
#ifdef __cplusplus
}
#endif
To call C functions in an external DLL, you can use C++/CLI as you've already mentioned, or use P/Invoke (Platform Invoke).
With P/Invoke, you define a static extern method in your C# assembly then decorate it with appropriate attributes. After that, you can call the method as per any other C# method, and the .NET Framework plumbing will handle the loading of the DLL and marshalling the method parameters back and forth.
For example:
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, uint pvParam, uint fWinIni);
The method is declared with the static and extern keywords, and decorated with the DllImport attribute which identifies the DLL that contains the C function. That's generally the minimum you will need.
The hardest part is determining which C types map to which .NET types for the method parameters and return type: this is a bit of a black art! If you visit pinvoke.net you can see how the Windows APIs have been translated, which may help. Searching the web for "pinvoke" should also turn up a number of useful resources.
At the moment, I can get a list of running processes with a main window using System.Diagnostics.Process.GetProcesses() and executing a simple LINQ query.
Then, I can import user32.dll and the SetWindowPos function and I manipulate other processes' window parameters.
Ok, it works. Now I'd like to select a window of a process, let's say calc.exe, by clicking it. In other words, I'd like to obtain a Process object (and then the MainWindowHandle) with a hook that catches the process name when I click on its window.
How can I achieve this?
I don't know how this is done in C#, but you have also tagged this question WinAPI so I can help there. In WinAPI, it can be done like so:
#include <stdio.h>
#include <Windows.h>
#include <Psapi.h>
#pragma comment(lib, "Psapi.lib")
int main(void)
{
/* Hacky loop for proof of concept */
while(TRUE) {
Sleep(100);
if(GetAsyncKeyState(VK_F12)) {
break;
}
if(GetAsyncKeyState(VK_LBUTTON)) {
HWND hwndPt;
POINT pt;
if(!GetCursorPos(&pt)) {
wprintf(L"GetCursorPos failed with %d\n", GetLastError());
break;
}
if((hwndPt = WindowFromPoint(pt)) != NULL) {
DWORD dwPID;
HANDLE hProcess;
GetWindowThreadProcessId(hwndPt, &dwPID);
hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, dwPID);
if(hProcess == NULL) {
wprintf(L"OpenProcess failed with error: %d\n", GetLastError());
} else {
wchar_t lpFileName[MAX_PATH];
DWORD dwSize = _countof(lpFileName);
QueryFullProcessImageName(hProcess, 0, lpFileName, &dwSize);
wprintf(L"%s\n", lpFileName);
CloseHandle(hProcess);
}
}
}
}
return EXIT_SUCCESS;
}
Example result:
In this case, I am simply polling to get the mouse click. A more proper way would be to use some sort of windows hook.
As Mike Kwan said, you'll be better of writing a hook though both approaches have their own drawbacks, but bjarneds already did a good work on this. Have a look # DotNET Object Spy. It's written in C# and will serve for your needs and more.
You should also note that using hooks are becoming redundant by the day. Depending on what you want to do, other winapis like GetForegroundWindow might serve better.
I try to load a simple DLL compiled with GCC in cygwin into a C#.NET application. The DLL looks like this
#ifndef __FOO_H
#define __FOO_H
#if _WIN32
#define EXPORT extern "C" __declspec(dllexport)
#else //__GNUC__ >= 4
#define EXPORT extern "C" __attribute__((visibility("default")))
#endif
EXPORT int bar();
#endif // __FOO_H
The function bar() just returns 42.
I compiled and linked the DLL with
g++ -shared -o foo.dll foo.cpp
Now I want to load this super simple DLL into a C# WinForms application.
public partial class Form1 : Form
{
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32", SetLastError = true)]
static extern IntPtr LoadLibrary(string lpFileName);
public delegate IntPtr Action2();
unsafe public Form1()
{
InitializeComponent();
IntPtr pcygwin = LoadLibrary("cygwin1.dll");
IntPtr pcyginit = GetProcAddress(pcygwin, "cygwin_dll_init");
Action init = (Action)Marshal.GetDelegateForFunctionPointer(pcyginit, typeof(Action));
init();
}
unsafe private void button1_Click(object sender, EventArgs e)
{
IntPtr foo = LoadLibrary("foo.dll"); // CRASH ... sometimes
IntPtr barProc = GetProcAddress(foo, "bar");
Action2 barAction = (Action2)Marshal.GetDelegateForFunctionPointer(barProc, typeof(Action2));
IntPtr inst = barAction();
}
}
Now the strange thing is: sometimes it works and sometimes it doesn't. When it doesn't work it crashes when it loads foo.dll. I run it in debug mode but I don't even get an exception. The debugger just stops as if I stopped it myself!
I also tried to load foo.dll in the same stack frame where I load cygwin1.dll. Same thing!
Any hints why this happens and what I can do to make it work?
Update 1: We use the latest cygwin and Visual Studio 2010.
Update 2: An assumption is that it has to with timing and garbage collection. It seems to me that the time between loading cygwin1.dll and loading foo.dll matters. The shorter the time between the two LoadLibrary calls the more likely it seems to work.
Update 3: If loading foo.dll succeeds the first time it succeeds always during a session. I can click button1 as often as I want.
Note: LoadLibrary("foo.dll") does not simply fail to load foo.dll. That'd be nice. I crashes and the debugger stops working. Not even an exception is thrown. AND it does not crash always. Sometimes it works!
Look at the "UPDATED" part of my old answer about the close problem. I recommend you to to compile your DLL with respect of MinGW tools instead of CygWin tools. If nothing is changed in the since the time the requirement "Make sure you have 4K of scratch space at the bottom of your stack" makes CygWin DLLs incompatible to .NET. I don't know how to realized the requirement in a .NET application.
You should try process monitor from msft. This is most likely being caused by a failure to load a dependent dll. Process monitor will show you what dll and why it is not loading.
Try the following...
[DllImport("kernel32", CharSet=CharSet.Unicode)]
static extern IntPtr LoadLibrary(string lpLibFileName);
maybe even use
[DllImport("kernel32", CharSet=CharSet.Unicode, SetLastError=true)]
and check for return values from both your calls to LoadLibrary and GetProcAddress before trying to use them.