I have a ServerCom DLL that comes from Fortran. I generate automatically using tlbimp a MyFortran.dll from the ServerCom.dll that can be referenced directly from C#.
In a C# Class Library I have referenced MyFortran.dll.
I created a console application that use the MyFortran.dll and generated the correct manifest (in order to have a free-interopt COM environment).
It works perfectly in the console application.
Now, I wrote a simple NUnit test and I got a COM Exception.
System.Runtime.InteropServices.COMException
: Retrieving the COM class factory for
component with CLSID
{0FB0F699-4EF8-4732-B98E-C088825E3912}
failed due to the following error:
80040154 Class not registered
(Exception from HRESULT: 0x80040154
(REGDB_E_CLASSNOTREG)).
How can I solve this?
Thanks,
Adrien.
You can use Activation Context API's to achieve this. This blog post gives all the details.
Here's a summary.
Paste the following code into your project (thanks to Spike McLarty for this):
/// <remarks>
/// Code from http://www.atalasoft.com/blogs/spikemclarty/february-2012/dynamically-testing-an-activex-control-from-c-and
/// </remarks>
class ActivationContext
{
static public void UsingManifestDo(string manifest, Action action)
{
UnsafeNativeMethods.ACTCTX context = new UnsafeNativeMethods.ACTCTX();
context.cbSize = Marshal.SizeOf(typeof(UnsafeNativeMethods.ACTCTX));
if (context.cbSize != 0x20)
{
throw new Exception("ACTCTX.cbSize is wrong");
}
context.lpSource = manifest;
IntPtr hActCtx = UnsafeNativeMethods.CreateActCtx(ref context);
if (hActCtx == (IntPtr)(-1))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
try // with valid hActCtx
{
IntPtr cookie = IntPtr.Zero;
if (!UnsafeNativeMethods.ActivateActCtx(hActCtx, out cookie))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
try // with activated context
{
action();
}
finally
{
UnsafeNativeMethods.DeactivateActCtx(0, cookie);
}
}
finally
{
UnsafeNativeMethods.ReleaseActCtx(hActCtx);
}
}
[SuppressUnmanagedCodeSecurity]
internal static class UnsafeNativeMethods
{
// Activation Context API Functions
[DllImport("Kernel32.dll", SetLastError = true, EntryPoint = "CreateActCtxW")]
internal extern static IntPtr CreateActCtx(ref ACTCTX actctx);
[DllImport("Kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool ActivateActCtx(IntPtr hActCtx, out IntPtr lpCookie);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool DeactivateActCtx(int dwFlags, IntPtr lpCookie);
[DllImport("Kernel32.dll", SetLastError = true)]
internal static extern void ReleaseActCtx(IntPtr hActCtx);
// Activation context structure
[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
internal struct ACTCTX
{
public Int32 cbSize;
public UInt32 dwFlags;
public string lpSource;
public UInt16 wProcessorArchitecture;
public UInt16 wLangId;
public string lpAssemblyDirectory;
public string lpResourceName;
public string lpApplicationName;
public IntPtr hModule;
}
}
}
Every time you need to create a COM object (COMObject in this example), wrap the call that creates it in a lambda function, and pass that to UsingManifestDo, like this:
object CreateManifestDependantCOMObject()
{
object myCOMObject = null;
ActivationContext.UsingManifestDo(pathToManifestFile, () => myCOMObject = new COMObject());
return myCOMObject;
}
Yes, this doesn't work. The registry-free COM manifest needs to be embedded in the EXE that uses the COM server. Easy enough for your console app. Not easy when you use NUnit because the EXE is now the unit test runner. You can't/shouldn't mess with it. Hard to do anyway because there are a bunch of them.
Just don't bother, this is a deployment detail that's not relevant for the testing you want to do. Just register the server with regsvr32.exe on the machine that executes the tests and be done with it.
Check out this answer:
How to do registration-free COM in a plug-in architecture
Eugene indicates that this is possible in one of two ways:
1. embed the manifest in the dll and compile with ISOLATION_AWARE_ENABLED
2. use context activation APIs
Related
I've got a vaguely Java background and just installed Visual Studio Community 2015. Playing about with it so have a console app up and running and wanted to use above function after attaching to a different Console. Trouble is I have no idea about the appropriate declaration for this function - can someone tell me what it should be in this instance but also a good pointer for me in future so I can work it out on my own. The IDE doesn't seem to help much
using System.Runtime.InteropServices;
namespace ConsoleStuff
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetConsoleHistoryInfo();
static void Main(string[] args)
{
GetConsoleHistoryInfo(); // <-- PInvokeStackImbalance occurred
}
}
}
You should declare it like this:
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool GetConsoleHistoryInfo(ref CONSOLE_HISTORY_INFO ConsoleHistoryInfo);
You will need the CONSOLE_HISTORY_INFO type too for this to work:
[StructLayout(LayoutKind.Sequential)]
public struct CONSOLE_HISTORY_INFO
{
uint cbSize;
uint HistoryBufferSize;
uint NumberOfHistoryBuffers;
uint dwFlags;
}
A lot of useful PInvoke information can be found at PInvoke.net. You should however double check it against the MSDN to see if it fits.
I have hooked QtGui4.dll's unmanaged function QPainter::drawTextItem(const QPointF &p, const QTextItem &ti); using EasyHook in C#. I have wrapped the QPointF and QTextItem classes into managed structs and can get the data from these parameters by marshaling them. However, I would like to call member functions of the unmanaged QPainter class using managed code, so I am trying to wrap the QPainter class into a managed class. I have access to the unmanaged code for testing purposes, but will not have access to it in production. I have looked at the memory layout of the unmanaged classes QPainter and QPaintDevice. The QPainter class is just a single pointer and the QPaintDevice class is just two pointers (one for the virtual function table). I tried following the techniques in this blog, but when I call the wrapped QPainter::device() method just to see if I can get a pointer, my target (unmanaged, hooked) application crashes with either an access violation error (Access violation reading location 0x00000078) or an argument exception error (EEArgumentException at memory location 0x003786f4), depending on whether my wrapped QPainter class uses a sequential layout or not, respectively. I don’t expect someone to correct all the source code, but I was hoping if someone could point out some of the mistakes I am making in my approach. By the way, this is the first time I've ever posted a question on Stack Overflow because I usually find the answers to my problems from one or more existing questions. I apologize for the long question, but I tried to simplify the problem as much as possible without leaving out potentially relevant information. Thanks in advance for your help.
Memory Dump:
class QPainter (size = 4):
(0) d_ptr
class QPaintDevice (size = 8):
(0) {vfptr}
(4) painters
Unmanaged Code (qpainter.h):
class QPainter
{
QPainter();
explicit QPainter(QPaintDevice *);
~QPainter();
QPaintDevice *device() const; // trying to call this function
void drawTextItem(const QPointF &p, const QTextItem &ti); // hooked function
// class has additional functions, but left out for brevity
}
Managed Hook (hook.cs):
[DllImport("QtGui4.dll", CharSet = CharSet.Unicode, SetLastError = true,
CallingConvention = CallingConvention.ThisCall,
EntryPoint = "?drawTextItem#QPainter##QAEXABVQPointF##ABVQTextItem###Z")]
public static extern void QPainter_drawTextItem(IntPtr obj, IntPtr pt, IntPtr ti);
[UnmanagedFunctionPointer(CallingConvention.ThisCall, CharSet = CharSet.Unicode,
SetLastError = true)]
delegate void D_QPainter_drawTextItem(IntPtr obj, IntPtr pt, IntPtr ti);
static unsafe void QPainter_drawTextItem_Hooked(IntPtr obj, IntPtr pt, IntPtr ti)
{
QTextItem qti = (QTextItem)Marshal.PtrToStructure(ti, typeof(QTextItem));
QPointF qpt = (QPointF)Marshal.PtrToStructure(pt, typeof(QPointF));
QPainter painter = (QPainter)Marshal.PtrToStructure(obj, typeof(QPainter));
__QPaintDevice* pd = painter.device(); // ERROR
QPainter_drawTextItem(obj, pt, ti);
}
Managed Wrapper (wrap.cs):
[StructLayout(LayoutKind.Sequential, Size=8)]
public unsafe struct __QPaintDevice
{
public IntPtr *vfptr;
public IntPtr painters;
};
[StructLayout(LayoutKind.Sequential, Size=4)]
public unsafe struct __QPainter
{
public IntPtr d_ptr;
};
// When the following line is included, I get this error:
// Access violation reading location 0x00000078.
// When the following line is excluded, I get this error:
// EEArgumentException at memory location 0x003786f4.
[StructLayout(LayoutKind.Sequential)] // is this useful?
public unsafe class QPainter : IDisposable
{
private __QPainter* _this;
private __QPaintDevice* _pd;
[DllImport("QtGui4.dll", EntryPoint = "??0QPainter##QAE#XZ",
CallingConvention = CallingConvention.ThisCall)]
private static extern int _QPainter_Constructor(__QPainter* ths);
[DllImport("QtGui4.dll",
EntryPoint = "??0QPainter##QAE#PAVQPaintDevice###Z",
CallingConvention = CallingConvention.ThisCall)]
private static extern int _QPainter_Constructor(__QPainter* ths,
__QPaintDevice* pd);
[DllImport("QtGui4.dll", EntryPoint = "??1QPainter##QAE#XZ",
CallingConvention = CallingConvention.ThisCall)]
private static extern int _QPainter_Destructor(__QPainter* ths);
[DllImport("QtGui4.dll",
EntryPoint = "?device#QPainter##QBEPAVQPaintDevice##XZ",
CallingConvention = CallingConvention.ThisCall)]
private static extern __QPaintDevice* _device(__QPainter* ths);
public QPainter()
{
_this = (__QPainter*)Marshal.AllocHGlobal(sizeof(__QPainter));
_QPainter_Constructor(_this);
}
public QPainter(__QPaintDevice* pd)
{
_this = (__QPainter*)Marshal.AllocHGlobal(sizeof(__QPainter));
_pd = (__QPaintDevice*)Marshal.AllocHGlobal(sizeof(__QPaintDevice));
_QPainter_Constructor(_this, pd);
}
public void Dispose()
{
_QPainter_Destructor(_this);
Marshal.FreeHGlobal((IntPtr)_this);
Marshal.FreeHGlobal((IntPtr)_pd);
_this = null;
_pd = null;
}
public __QPaintDevice* device()
{
return _device(_this);
}
};
Inside a C# Console application, I'm importing a native C++ DLL methods. for example:
[DllImport("MyDll.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
public static extern int MyMethod(IntPtr somePointer);
When executed, MyMethod() is printing output to the Console, which I would like to be hidden.
Assuming I can't change the DLL, how can I still suppress it's output?
Modified from http://social.msdn.microsoft.com/Forums/vstudio/en-US/31a93b8b-3289-4a7e-9acc-71554ab8fca4/net-gui-application-native-library-console-stdout-redirection-via-anonymous-pipes
I removed the part where they try to redirect it because if you read further, it says they were having issues when it was called more than once.
public static class ConsoleOutRedirector
{
#region Constants
private const Int32 STD_OUTPUT_HANDLE = -11;
#endregion
#region Externals
[DllImport("Kernel32.dll")]
extern static Boolean SetStdHandle(Int32 nStdHandle, SafeHandleZeroOrMinusOneIsInvalid handle);
[DllImport("Kernel32.dll")]
extern static SafeFileHandle GetStdHandle(Int32 nStdHandle);
#endregion
#region Methods
public static void GetOutput(Action action)
{
Debug.Assert(action != null);
using (var server = new AnonymousPipeServerStream(PipeDirection.Out))
{
var defaultHandle = GetStdHandle(STD_OUTPUT_HANDLE);
Debug.Assert(!defaultHandle.IsInvalid);
Debug.Assert(SetStdHandle(STD_OUTPUT_HANDLE, server.SafePipeHandle));
try
{
action();
}
finally
{
Debug.Assert(SetStdHandle(STD_OUTPUT_HANDLE, defaultHandle));
}
}
}
#endregion
}
and usage sample:
[DllImport("SampleLibrary.dll")]
extern static void LetterList();
private void button1_Click(object sender, EventArgs e)
{
ConsoleOutRedirector.GetOutput(() => LetterList());
}
The only way you can hope to do this is to redirect the standard output whenever you call into the DLL. I've never attempted this and have no idea whether or not it works.
Use SetStdHandle to direct standard output to some other place. For example a handle to the nul device would do. If you need to restore the original standard output handle after calls to the DLL return, that takes another call to SetStdHandle.
You'll need to jump through these hoops for each and every call to the DLL. Things would get even more complex if you have threads and/or callbacks.
I have a C# application which needs to import a function from a C++ dll. I use DLLImport to load the function. It works fine in English and Chinese environment, but it always raise 'Module not found' exception in French operating system.
The code snapshot:
[DllImport("abcdef.dll", CallingConvention = CallingConvention.StdCall)]
public static extern string Version();
Note that letters in the name of module have been replaced but the name itself is in the same format and the same length.
And a screenshot:
Any ideas?
I have tried all methods you proposed, however the problem still exists.
Here is an alternative way which could avoid that error. It uses Win32 APIs to load the library and find the address of the function, then invoke it. Demo code follows:
class Caller
{
[DllImport("kernel32.dll")]
private extern static IntPtr LoadLibrary(String path);
[DllImport("kernel32.dll")]
private extern static IntPtr GetProcAddress(IntPtr lib, String funcName);
[DllImport("kernel32.dll")]
private extern static bool FreeLibrary(IntPtr lib);
private IntPtr _hModule;
public Caller(string dllFile)
{
_hModule = LoadLibrary(dllFile);
}
~Caller()
{
FreeLibrary(_hModule);
}
delegate string VersionFun();
int main()
{
Caller caller = new Caller("abcdef.dll");
IntPtr hFun = GetProcAddress(_hModule, "Version");
VersionFun fun = Marshal.GetDelegateForFunctionPointer(hFun, typeof(VersionFun)) as VersionFun;
Console.WriteLine(fun());
return 0;
}
}
I know the title is bit confusing for my question.
Let me explain:-
There are some DLLs written by my seniors and I use them in C# as follows:
Say, Existing DLL name is SeniorDLL and I want to use function SeniorFunc from that DLL.
What I do is:-
private delegate int SeniorFunc(IntPtr Blah);
[DllImport("kernel32")]
public extern static IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32", CharSet = CharSet.Ansi)]
public extern static IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
SeniorFunc fp_Senior;
and in function where I want to use this function, Before first function call I write:
IntPtr handle;
handle = IntPtr.Zero;
handle = LoadLibrary("<DLL Path>");
IntPtr fPtr = GetProcAddress(handle, "SeniorFunc");
fp_Senior = (SeniorFunc)Marshal.GetDelegateForFunctionPointer(fPtr, typeof(SeniorFunc));
and then I use this function via fp_Senior(<Parameter>);
Now I want to create such DLL for me in C# by which I'll be able to call functions from DLL.
Currently I created a DLL but I have create an instance of class in DLL and then have to access like ClassInstance.MyFunction(<Parameters>);
How can I get directly function calls without creating an instance?
In other words, (I don't know I am correct or wrong) How can I create APIs??
Thanks!!
You don't need an instance here, everything can be static. Something like this, with the necessary error checking added:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
internal static class NativeMethods {
public static void SeniorFunc(IntPtr arg) {
if (fp_Senior == null) lookUpSenior();
fp_Senior(arg);
}
private static void lookUpSenior() {
loadSenior();
IntPtr addr = GetProcAddress(SeniorModule, "seniorfunc");
if (addr == IntPtr.Zero) throw new Win32Exception();
fp_Senior = (SeniorFuncDelegate)Marshal.GetDelegateForFunctionPointer(addr, typeof(SeniorFuncDelegate));
}
private static void loadSenior() {
if (SeniorModule == IntPtr.Zero) {
SeniorModule = LoadLibrary("mumble.dll");
if (SeniorModule == IntPtr.Zero) throw new Win32Exception();
}
}
private static IntPtr SeniorModule;
private delegate int SeniorFuncDelegate(IntPtr Blah);
private static SeniorFuncDelegate fp_Senior;
[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
private extern static IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32", CharSet = CharSet.Ansi, SetLastError = true)]
public extern static IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
}
The point of keeping lookupSenior in a separate method is to allow SeniorFunc() to get inlined so it is fast. If you know you'll always use these functions in your program then you can also write a static constructor for the class and do the lookup there. Saves the null check but makes an exception a bit harder to interpret.
There is no such a thing as a method outside a class in C#. So if you must call a method, you have to specify the class name.
The difference with the DLLs you are currently using is that those DLLs are written in C/C++ or other non-.NET language which does not enforce a strict object-oriented approach like C# does.
Thus, nothing forces you to create an instance of a class when calling a method from a .NET library. If a method is declared as static, you can call it directly through ClassName.MethodName().