C# Dll - export functions - c#

I am trying to create a c# dll with a few exportable functions. Then I want a C++/unmanaged program to load that .dll and call a particular exported function inside the dll.
I'am using Robert Giesecke's Unmanaged Exports. But it doesn't seem to work.
I ran the unmanaged program in a debugger and it successfully does "LoadLibrary()", but when it tries to "GetProcAddress(test_start)" the call fails and returns zero.
This is my c# code:
using System.Runtime.InteropServices;
using RGiesecke.DllExport;
using etc...;
namespace test_dll
{
public class Class1
{
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllExport("test_start", CallingConvention = CallingConvention.Cdecl)]
public static void test_start()
{
MessageBox.Show("It works","YES");
}
}
}
The .dll builds fine and the CPU match (x86), but the unmanaged program can't get the export function address once the c# dll has been loaded.
Its pretty basic right now, but I'm just trying to get it to work. I'll need the imports later on.
Any help please, the documentation for the nuget package is quite thin. Thanks

Hey so actually I was doing it perfectly fine.
Weirdly Robert Giesecke's Unmanaged Exports ignores the first export??
So any exports I created below that one worked and was recognised.
I checked with CFF explorer to see the valid exports, and all but the first one was there. So I just left a blank export on top.

Related

DLLImport is showing my current directory in another user machine

I am new to PInvoke, I wanted to update my system volume using C#, I got one C++ dll and I have to just Import that DLL and use the methods to update the volume.
In C# I have written :
public const String DllName = "ChangeVolumeWindows.dll";
[DllImport(DllName, CharSet = CharSet.Auto)]
public static extern void SetSystemVolume(double newVolume, VolumeUnit vUnit);
I have put my dll into the exe path.
It is working fine for my pc , but when I package the app and send it to another machine I getting error " DLL not found "
I have observed that DLLImport is looking for path of my pc, which is not correct
For example:
I have put my dll in C:/User/ABC/Source/App/bin/debug/ChangeVolumeWindows.dll
in some another machine also it is looking for the same path instead of taking dll from C:/User/AnotherMachineUser/Source/App/bin/debug/ChangeVolumeWindows.dll
Can some one suggest where my code is going wrong.
I have tried to put my dll inside the project and the rebuild. Still I am facing the same issue.
Try this:
My.Application.Info.DirectoryPath("\folders\ChangeVolumeWindows.dll")

Unmanaged Exports not showing up in DLL

I have a new project and a test class, method below:
[ComVisible(true)]
[DllExport("Heartbeat2", CallingConvention = CallingConvention.StdCall)]
public static void Heartbeat2(){
//Do stuff here
}
Im using Unmanaged Exports (RGiesecke.DllExport) latest in DotNet 4.6...when running Nirsofts viewer, I do not see my method in the dll http://www.nirsoft.net/utils/dll_export_viewer.html)
I have the platform target to x86 also...what am I doing wrong? I plan on using this in a ruby 1.8.1 program using Win32API
Giesecke's Unmanaged Exports works fine using VS2015, but not in VS2017 or VS2019.
Try downloading VS2015 Community and try your example there.
Be sure you are building for X64 or X86, not Any CPU.
The Unmanaged Exports should generate a DLL, plus a LIB and RES file.
You can check whether the DLL was modified by checking it with one of several fine .Net decompilers, my current favourite is https://www.jetbrains.com/decompiler/

Debugging a failure to access libleveldb with C# on OSX

A C# project I'm interested in uses leveldb via a PInvoke 'wrapper' that works fine on both Windows and Linux but throws the following error on OSX.
src/tcmalloc.cc:331] Attempt to free invalid pointer 0x7f83cb954a00
A minimal example to reproduce the error with is
using System;
using System.Runtime.InteropServices;
namespace leveldb_test2
{
internal static class Native {
[DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr leveldb_options_create();
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("before");
IntPtr handle = Native.leveldb_options_create();
Console.WriteLine("after");
}
}
}
What I've tried
Manually building leveldb
Leveldb was initially installed via homebrew. Not knowing if they do anything magical, I also did a manual build which gave me the same error.
Verifying the method signature
The method signature used with DllImport seems ok, as it's identical to what's used in a wrapper project I found: leveldb-sharp (fwiw; I tried using that project, same error)
Note that original export from leveldb is
extern leveldb_options_t* leveldb_options_create();
I also created my own dll with the same signature and that worked fine. This also confirmed for me that I can correctly enforce which exact library file is being loaded to avoid it using some broken version somewhere else on my system.
Verifying library exports
I dumped the exports using nm to make sure no name mangling is going on, seems fine.
I can also access the library successfully with ctypes in Python.
Try older versions of leveldb
I tried all older versions up to 1.15 from September 2014. All give the same error.
What's next
Ideally, I'd like to be able to debug the native side. However, unlike with Visual Studio on Windows, the OSX Visual Studio Community Edition doesn't have the "Enable native code debugging" option described here. So my question is
How would I go about debugging the native side while initiated from C#?
I believe the latter part of this question is important, because as said before it works fine when initiated from Python. Any tips/hints/help are much appreciated!
PS: a bonus would be the solution to getting the wrapper to work.

Call Unmanaged Code from SSIS Script Task

I have Business Intelligence -> Integration Services Project where I have SSIS Packages -> Script Task. I need to call from Script Task Unmanaged code using DllImport. Since I don't know where code for Script Task is stored during run-time I can't call my unmanaged dll.
Example code below for Script Task:
using System; // Console
using System.Runtime.InteropServices; // DllImport
class App
{
[DllImport("lib.dll", CallingConvention = CallingConvention.Cdecl)]
extern static int next(int n);
static void Main()
{
Console.WriteLine(next(0));
Dts.TaskResult = (int)ScriptResults.Success;
}
}
You can find more about Script Task here
Question: How to call Unmanaged Code from SSRS Package -> Script Task?
SSIS won't load dll's by location, even managed dll's. You have to GAC them, http://microsoft-ssis.blogspot.com/2011/05/referencing-custom-assembly-inside.html . I would therefore expect you to have to COM register your unmanaged dll, https://technet.microsoft.com/en-us/library/bb490985.aspx .
Make sure to copy c/c++ dll into "C:\Program Files\Microsoft SQL Server\120\DTS\Binn" which will be loaded when managed code calls DllImport
NOTE: 120 is version specific make sure to copy to the correct version that you have.

Resolving native libraries inside WinRT package

Consider the following solution structure: Windows Store C# application + 2 native libraries PInvokeServer and PInvokeServer1. Native libraries code:
// PInvokeServer1
PINVOKESERVER1_API int TestFunction1(void)
{
return 5;
}
// PInvokeServer
PINVOKESERVER_API int TestFunction(void)
{
return TestFunction1();
}
Both functions are extern C. PInvokeServer depends on PInvokeServer1 (using linker dependencies). PInvokeServer.dll and PInvokeServer1.dll are added to C# project with build action Content, so they are part of the application package. C# declarations:
const string dllName = #"Native\PInvokeServer.dll";
const string dllName1 = #"Native\PInvokeServer1.dll";
[System.Runtime.InteropServices.DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
public static extern int TestFunction();
[System.Runtime.InteropServices.DllImport(dllName1, CallingConvention = CallingConvention.Cdecl)]
public static extern int TestFunction1();
Case 1, doesn't work (module not found):
TestFunction();
Case 2, works:
TestFunction1();
Case 3, works:
TestFunction1();
TestFunction();
Case 1: When PInvoke tries to load PInvokeServer.dll, it cannot resolve native runtime dependency, PInvokeServer1.dll is not loaded, and I get Module not found exception. Placing PInvokeServer1.dll, for example, to System32 directory doesn't help.
Case 2: PInvoke is able to load PInvokeServer1.dll directly.
Case 3. Once PInvokeServer1.dll is loaded, PInvokeServer.dll can be loaded successfully as well.
Im my real program I have native C library depending on several other libraries. All these libraries are added to C# Store application package. But high-level library cannot be loaded, because PInvoke fails to load dependencies. The only way I can think about is to load low-level libraries using LoadLibrary PInvoke call, and finally use PInvoke call to high-level library. Is there better way?
In a desktop application you could use AddDllDirectory or SetDllDirectory to modify the search path. But in a Windows Store application these functions are not available to you. So I see two options:
Put the two DLLs in the same directory as the executable. This is, by some distance, the simplest and safest solution. The executable's directory is always the first location searched and so you can be sure that the right DLLs will be loaded.
Before calling any function in either DLL, call LoadLibrary passing the absolute path to the DLLs to load them into the process. Load PInvokeServer1 before PInvokeServer. Change your p/invoke declarations to specify just the DLL filename. That is, remove the Native directory from the p/invoke declaration. By calling LoadLibrary explicitly, you make sure that the two DLLs are loaded into the process. Then subsequent calls to p/invoke functions will result in the already loaded DLLs being used.

Categories