I'm having trouble executing this line of code in my MVC application:
IntPtr hModule = LoadLibrary(BondProbeSettings.AssemblyFilePath);
The problem is that hModule is always 0.
If I run the same code with the same value for BondProbeSettings.AssemblyFilePath but from a console application instead of the MVC app hModule is non-zero.
Are there any security issues I need to consider?
The signature for LoadLibrary is:
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
static extern IntPtr LoadLibrary(string lpFileName);
Change the declaration to:
[DllImport("kernel32.dll", CharSet = CharSet.Auto), SetLastError = true)]
static extern IntPtr LoadLibrary(string lpFileName);
And your code to:
IntPtr hModule = LoadLibrary(BondProbeSettings.AssemblyFilePath);
if (hModule == IntPtr.Zero) throw new System.ComponentModel.Win32Exception();
Now you'll know why it doesn't work.
Yep you need to run the site assembly in full trust. I haven't configured this myself but I reckon you need:
to GAC the dll (meaning it has to be strongnamed)
to perhaps configure the application pool in IIS (assuming IIS) to allow full trust (?)
I'm on linux so I can't really help you with screenshots right now
Related
I am running a Web API Asp.Net 4.6 app running in Any CPU mode (though I've also tried this specifying x64) and it makes a call to an unmanaged x64 C dll. This works fine when running within Visual Studio (using default IIS Express settings) though I get Windows Error 126 (The specified module could not be found.) when I deploy to another server and run in IIS or IIS Express even though I am sure that the path to the DLL is correct. Is there something else I can try?
My Native Methods Wrapper:
public static class NativeMethods
{
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr hModule);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll")]
public static extern uint GetLastError();
}
My Load DLL Method:
private static void LoadDll()
{
UnloadDLL(); //Unload the module first
if (string.IsNullOrEmpty(DllDirectory))
throw new ApplicationException("DPI DLL directory not specified.");
if (!File.Exists(DllPath))
throw new ApplicationException("Could not find DPI DLL.");
pDll = NativeMethods.LoadLibrary(DllPath);
//Fails Here
if (pDll == IntPtr.Zero)
throw new ApplicationException(string.Format("Failed to load library <{0}> (ErrorCode: {1})", DllPath, Marshal.GetLastWin32Error()));
}
Let me know if I can make anything else more clear, thanks!
Use Dependency Walker to get the list of module's dependencies (module with path DllPath). Also check do you need install Visual C++ Redistributable on the server.
By ikenread: Need to check unmanaged DLL compilation mode. If it compiled in Debug mode, it will be dependent on Debug versions of Visual C++ Redistributable dlls and they will be absent (most likely) on the production server.
This question already has answers here:
Target 32 Bit or 64 Bit native DLL depending on environment
(3 answers)
DllImport - An attempt was made to load a program with an incorrect format [duplicate]
(1 answer)
Closed 8 years ago.
The community reviewed whether to reopen this question 8 months ago and left it closed:
Original close reason(s) were not resolved
I want my C# application to conditionally run a native method, conditionally choosing to run either the x86 or the x64 version of the dll. Whenever I try to load the 32 bit dll I get the below error:
Unhandled Exception: System.BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
at <exeName>.MiniDumpMethods.MiniDumpWriteDumpX86(IntPtr hProcess, UInt32 processId, SafeHandle hFile, MINIDUMP_TYPE dumpType, IntPtr expParam, IntPtr userStreamParam, IntPtr callbackParam)
Background context: I want my binary to take a memory dump of a given process. Based on whether or not the process it's taking a memory dump of is 32 or 64 bit it'll choose to run the MiniDumpwriteDump method from the x86 or x64 version of dbghelp.dll.
I'm currently doing the following:
[SuppressUnmanagedCodeSecurity]
internal static class MiniDumpMethods
{
[DllImport("dbghelp.dll",
EntryPoint = "MiniDumpWriteDump",
CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Unicode,
ExactSpelling = true,
SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool MiniDumpWriteDump(
IntPtr hProcess,
uint processId,
SafeHandle hFile,
MINIDUMP_TYPE dumpType,
IntPtr expParam,
IntPtr userStreamParam,
IntPtr callbackParam);
[DllImport("dbghelpx86.dll",
EntryPoint = "MiniDumpWriteDump",
CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Unicode,
ExactSpelling = true,
SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool MiniDumpWriteDumpX86(
IntPtr hProcess,
uint processId,
SafeHandle hFile,
MINIDUMP_TYPE dumpType,
IntPtr expParam,
IntPtr userStreamParam,
IntPtr callbackParam);
}
Any idea how I can conditionally load either the x86 or the x64 version of the dll?
(Note: dbghelpx86.dll is the x86 version of dbghelp.dll that I renamed)
Thanks
You cannot load a 32 bit DLL into a 64 bit process. To support this you will have to have two different EXE's, one compiled as 64 bit and one compiled as 32 bit.
If you run the 64 bit process and encounter a 32 bit dump, you'll have to launch the 32 bit version of the EXE to process the dump file. Once it is processed you can use some sort of IPC (Interprocess Communication) mechanism to send the results back to the 64 bit process.
I know you are gonna hate me for that kind of question. But could somebody tell me what the following code is doing?
I mean there are some libraries loaded, i get that. plus there are some methods, still I don't get it.
F.e.:
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
Here is the code:
private static class API
{
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(
int idHook,
HookDel lpfn,
IntPtr hMod,
uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CallNextHookEx(
IntPtr hhk,
int nCode,
IntPtr wParam,
IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetModuleHandle(
string lpModuleName);
}
You do not have to explain it to me line for line. At least give me some reference where I can read it up, please.
Thx in advance!
This code is using P/Invoke to allow C# code to call several Win32 API functions related to Windows Hooks.
The posted code only defines the methods; it doesn't call them, so it doesn't do anything by itself. It just allows you to use the methods from other parts of your code.
Here's an older MSDN article explaining P/Invoke and what's going on. Hopefully this helps you.
What the code is doing is allowing your managed C# code to call unmanaged Win32 API functions.
Here's also a tutorial on MSDN that walks you through the P/Invoke process of creating code like your question has.
DllImport is used to call unmanaged code/API in .Net/Managed code. All the code you've posted is trying to work with the window object of Win32 API.
References:
DLLImport
Win32 API
Win32 API to .Net API map
Take a look at this. Your program somewhere is installing a hook into windows hook chain to monitor some events.
The dllimport attribute itself lets the program to invoke win32 api functions like the previous answer mentions.
I've noticed something very strange. I was trying to call the CRT function "putchar", and was unable to get it to work. So I double-checked that I wasn't missing something, and I copied the code directly from the P/Invoke tutorial on MSDN to see if it worked.
http://msdn.microsoft.com/en-us/library/aa288468%28VS.71%29.aspx
You'll notice that they import "puts".
So I tested the exact code copied from MSDN. It didn't work! So now I got frustrated. I've never had this problem before.
Then I just so happened to run WITHOUT debugging (hit ctrl+f5), and it worked! I tested other functions which output to the console too, and none of them work when debugging but all work when not debugging.
I then wrote a simple C dll which exports a function called "PrintChar(char c)". When I call that function from C#, it works even if I'm debugging or not, without any problems.
What is the deal with this?
The Visual Studio hosting process is capable of redirecting console output to the Output window. How exactly it manages to do this is not documented at all, but it gets in the way here. It intercepts the WriteFile() call that generates the output of puts().
Project + Properties, Debug tab, untick "Enable the Visual Studio hosting process". On that same page, enabling unmanaged debugging also fixes the problem.
It's a bad example, using the C-Runtime Library DLL to call puts. Keep reading the tutorial as there is good info there, but try making Win32 API calls instead.
Here is a better introduction to p/invoke: http://msdn.microsoft.com/en-us/magazine/cc164123.aspx
It's old, but the information is still good.
Edited
My explaination was wrong.
I went looking for a correct explaination and I discovered that the C-Runtime puts method and the .NET Framework Console.Write method differ in how they write to the console (Console.Write works where the p/invoke to puts does not). I thought maybe the answer was in there, so I whipped up this demonstration:
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
class Program
{
public static void Main()
{
int written;
string outputString = "Hello, World!\r\n";
byte[] outputBytes = Encoding.Default.GetBytes(outputString);
//
// This is the way the C-Runtime Library method puts does it
IntPtr conOutHandle = CreateFile("CONOUT$", 0x40000000, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
WriteConsole(conOutHandle, outputBytes, outputString.Length, out written, IntPtr.Zero);
//
// This is the way Console.Write does it
IntPtr stdOutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
WriteFile(stdOutputHandle, outputBytes, outputBytes.Length, out written, IntPtr.Zero);
// Pause if running under debugger
if (Debugger.IsAttached)
{
Console.Write("Press any key to continue . . . ");
Console.ReadKey();
}
}
const int STD_OUTPUT_HANDLE = -11;
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll", SetLastError = true)]
static extern int WriteFile(IntPtr handle, [In] byte[] bytes, int numBytesToWrite, out int numBytesWritten, IntPtr mustBeZero);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr CreateFile(string lpFileName, int dwDesiredAccess, FileShare dwShareMode, IntPtr securityAttrs, FileMode dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
static extern bool WriteConsole(IntPtr hConsoleOutput, [In] byte[] lpBuffer, int nNumberOfCharsToWrite, out int lpNumberOfCharsWritten, IntPtr mustBeZero);
}
Both of those successfully output under the debugger, even with the hosting process enabled. So that is a dead end.
I wanted to share it in case it leads someone else to figuring out why it happens -- Hans?
I am developing a Windows Mobile application using WM6 SDK. The application is a Managed code (using C#) & I would like to know the steps to be taken in order to call native functions.
Thanks for the help,
Abdel Olakara
http://www.pinvoke.net/
That should do it.
You need to first declare the native APIs as static extern using DLLImport and then use them like normal methods. Example:
[DllImport("user32.dll", ExactSpelling = true)]
internal static extern IntPtr SetTimer(IntPtr hWnd, IntPtr nIDEvent, int uElapse, IntPtr lpTimerFunc);