C# 2010 is not loading delphi DLL - c#

I am facing a problem. I have written and win32 DLL in delphi 2009. Now I want to dynamically load that DLL from C# desktop application but LoadLibray function returns 0. Here is CSharp code, please can any body helps me why DLL is not loading?
public partial class Form1 : Form
{
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad, IntPtr hFile, uint dwFlag);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[DllImport("Kernel32.dll")]
private extern static Boolean CloseHandle(IntPtr handle);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
IntPtr ptr = IntPtr.Zero;
ptr = LoadLibrary("MyDLL.dll", IntPtr.Zero, 0);
if (ptr == IntPtr.Zero)
{
MessageBox.Show("DLL not laded");
}
}
}
}

You have the wrong signature for LoadLibrary. It should be:
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadLibrary(string dllname);
You had two spurious parameters and weren't capturing the error code.
Always check for errors when calling Win32 functions. In this case
IntPtr lib = LoadLibrary(dllname);
if (lib == IntPtr.Zero)
throw new Win32Exception();
Common failure modes include:
Mis-matched bitness.
DLL not found on DLL search path.
DLL's dependencies not resolved.

I can't tell you why that DLL is not loading as there is not enough information in the question.
Hint: Have you checked that your application is running in 32-bit or 64-bit appropriately for the DLL?
However, I can tell you how to get more information about the problem.
First, add the following to the attributes:
[DllImport("Kernel32.dll", SetLastError=true)]
^-----------------^
Then add this to your if-statement that handles the problem:
if (ptr == IntPtr.Zero)
throw new Win32Exception();
This should give you a more specific exception message indicating what the problem might be.

Related

LoadLibraryEx Function Probelem In C#

I try to use LoadLibraryEx Function to load a xxx.dll. In ASP.NET CORE Web - MVC application. It can return a right value. But in a ASP.NET Web - Web API application. It return 0x00000000.But GetLastError() return 0. Here is my demo code
CODE IN ASP.NET Web - Web API application
[DllImport("kernel32.dll")]
static extern uint GetLastError();
[DllImport("kernel32.dll", EntryPoint = "LoadLibraryEx", SetLastError = true)]
private static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags);
private static uint LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008;
private static void LoadWin32Library(string libPath)
{
IntPtr moduleHandle = LoadLibraryEx(libPath, IntPtr.Zero, LOAD_WITH_ALTERED_SEARCH_PATH);
uint code = GetLastError();
Console.WriteLine(code);
Console.WriteLine(moduleHandle);
if (moduleHandle == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());
}
// GET api/values
public IEnumerable<string> Get()
{
String lpFileName = "C:\\Program Files\\dotnet\\shared\\Microsoft.NETCore.App\\2.1.11\\System.dll";
LoadWin32Library(lpFileName);
return new string[] { "value1", "value2" };
}
CODE IN ASP.NET CORE Web - MVC
[DllImport("kernel32.dll")]
static extern uint GetLastError();
[DllImport("kernel32.dll", EntryPoint = "LoadLibraryEx", SetLastError = true)]
private static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags);
private static uint LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008;
private static void LoadWin32Library(string libPath)
{
IntPtr moduleHandle = LoadLibraryEx(libPath, IntPtr.Zero, LOAD_WITH_ALTERED_SEARCH_PATH);
uint code = GetLastError();
Console.WriteLine(code);
Console.WriteLine(moduleHandle);
if (moduleHandle == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());
}
public string Index()
{
String lpFileName = "C:\\Program Files\\dotnet\\shared\\Microsoft.NETCore.App\\2.1.11\\System.dll";
LoadWin32Library(lpFileName);
return "This is my default action...";
}
In fact. These two pieces of code are basically the same.But the results are completely different.So. If anybody can help me?
This isn't really an "answer" but it's too involved to be a comment.
You should never need to call LoadLibrary from managed code
There are three ways DLLs can get loaded into managed code:
Your program has a referenced to a managed assembly (in the References section under the project in Solution Explorer)
You call Assembly.Load (or one of the variants) from your code, loading in a managed assembly
You use P/Invoke to load an unmanaged DLL and execute a function within it (like how you are loading kernel32.dll and calling GetLastError or LoadLibraryEx in your code)
And, for completeness (and on the advice of #SeanSkelly), adding a fourth option that does involve LoadLibary(Ex), but with severe restrictions. This is definitely not a recommended option.
Use LoadLibary(Ex), but with the caveat that you have to do much of the work of (and mimic the actions of) the P/Invoke marshaler. You also can't use this with a managed DLL because GetProcAddress will always fail on a managed assembly.
I have a guess as to why you are getting success in one case and a failure in the other. In one case, you are loading in the same System.dll that the framework has already loaded, so it just returns a handle to the loaded DLL. In the other, you are loading a different version of System.dll. The unmanaged loader doesn't understand versioning and strong names the way Assembly.Load does, so it says "hey, I already have a System.dll and it doesn't match up, so I'm failing your request". But, this is just a guess.
But, it doesn't really matter, you don't need to do this.

PostMessage results in "...a call to pinvoke function has unbalanced the stack c#..."

In a 32bit managed app I use Proecess.Start to load a 64bit .Net app.
Following that I PostMessage() from the 32bit app to the 64bit app using the MainWindowHandle.
The problem is that when the PostMessage() is called I get the error "A call to PInvoke function 'xxxx::PostMessage' has unbalanced the stack..."
After pressing continue everything works fine.
I am using VS 2017.
If I convert the 32bit app to 64bit no problem.
Also I don't get the problem when run the 32bit app outside the VS.
Both apps are in C#.
Can I just uncheck the PInvokeStackImbalance in MDA or is it something that I should "worry" about?
Thank you
Following is the code in a form to start a client app, dock its main form and set the handle of the current form to the client app.
private const int SEND_HANDLE = WM_USER + 101;
[DllImport("user32.dll", EntryPoint = "PostMessageA", SetLastError = true)]
private static extern bool PostMessage(IntPtr hwnd, uint Msg, long wParam, long lParam);
private void DoDock()
{
ProcessStartInfo psi = new ProcessStartInfo("test.exe");
psi.Arguments = "";
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
pDocked = Process.Start(psi);
while (hWndDocked == IntPtr.Zero)
{
pDocked.WaitForInputIdle(1000);
Thread.Sleep(100);
pDocked.Refresh();
if (pDocked.HasExited)
return;
hWndDocked = pDocked.MainWindowHandle; //cache the window handle
}
PostMessage(hWndDocked, SEND_HANDLE, this.Handle.ToInt32(), 0);
}
This normally means that your pinvoke declaration is wrong. This website lists the correct declaration as:
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern bool PostMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

RegisterRawInputDevices returning false

I am using RegisterRawInputDevices of user32.dll to register the keyboard, but it's returning false. I am developing an Office add-in using VSTO and C#.
[StructLayout(LayoutKind.Sequential)]
public struct RAWINPUTDEVICE
{
[MarshalAs(UnmanagedType.U2)]
public UInt16 usUsagePage;
[MarshalAs(UnmanagedType.U2)]
public UInt16 usUsage;
[MarshalAs(UnmanagedType.U4)]
public int dwFlags;
public IntPtr hwndTarget;
}
[DllImport("User32.dll", SetLastError = true)]
public static extern bool RegisterRawInputDevices(RAWINPUTDEVICE[] pRawInputDevice,
UInt32 uiNumDevices, UInt32 cbSize);
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
public void Register()
{
IntPtr hwnd = FindWindow("PPTFrameClass", "Presentation1 - PowerPoint");
RegisterKeyboardDevice(hwnd);
}
public void RegisterKeyboardDevice(IntPtr hwnd)
{
const int RIDEV_INPUTSINK = 0x00000100;
RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[1];
rid[0].usUsagePage = Convert.ToUInt16(1);
rid[0].usUsage = Convert.ToUInt16(6);
rid[0].dwFlags = RIDEV_INPUTSINK;
rid[0].hwndTarget = hwnd;
if (!RegisterRawInputDevices(rid, Convert.ToUInt32(rid.Length),
Convert.ToUInt32(Marshal.SizeOf(rid[0]))))
{
throw new ApplicationException("Failed to register raw input device(s). " +
"Error code: " + Marshal.GetLastWin32Error());
}
}
But the same logic is working fine for VB.NET and COM-addins. Please correct me if I am going wrong.
You can call RegisterRawInputDevices only on windows that belong to the same process as your calling code.
I tested your code in an Excel C# VSTO addin as well as in an Excel C# COM addin and in both cases I could successfully call RegisterRawInputDevices on the Excel window itself and on a WPF test window, that was created from inside the addin, without any kind of error. (My version for this test was Excel 2016 64-bit.)
Unfortunately I don't have any kind of reference for this behavior but I think this is intentional by design, maybe because of security concerns as you could potentially hijack some other window and possibly act as a kind of keylogger or doing some other really bad stuff.
So your code does work perfectly but you have to use a window that belongs to the same process. And I think the difference to your VB.NET addin is that it's working because it's playing by this rule.

C# VisualStudio 2012 - FreeLibrary() blocks the application

I am using DLLImport LoadLibrary() and FreeLibrary() in C# on 3 DLL.
I can Load the 3 DLL without any problem, but at the end of my application where I am using my FreeLibrary, it doesn't go further and I have to manually stop it.
This is a WPF Application, and I must call the 3 DLLs because they need eachothers. I cannot use the "Add Reference" to add the DLL.
Here is the code :
public partial class MainWindow : Window
{
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr hModule);
public MainWindow()
{
InitializeComponent();
try
{
string pathDllOne = "dll/DllOne.dll";
string pathDllTwo = "dll/DllTwo.dll";
string pathDllThree = "dll/DllThree.dll";
IntPtr DllThreeLink = LoadLibrary(pathDllThree);
IntPtr DllTwoLink = LoadLibrary(pathDllTwo);
IntPtr DllOneLink = LoadLibrary(pathDllOne);
if (DllOneLink == IntPtr.Zero || DllTwoLink == IntPtr.Zero || DllThreeLink == IntPtr.Zero)
Console.WriteLine("WARNING : UNABLE TO FIND ONE OR MORE DLL");
else
Console.WriteLine("LOADING OK");
FreeLibrary(DllThreeLink);
FreeLibrary(DllTwoLink);
FreeLibrary(DllOneLink);
Console.WriteLine("END");
}
catch (Exception ex)
{
Console.WriteLine("ERROR : " + ex.Message);
}
}
}
The console clearly shows the "LOADING OK".
The problem happened when I call "FreeLibrary(DllOneLink);". It doesn't go further, so it doesn't show the "END" message.
Do you have any idea what may cause this?
Maybe when you do LoadLibrary some resource get loaded in the library and when you do FreeLibrary it hangs because library cannot be unloaded because of such resources still in use.
Maybe these libraries have a method to call for releasing their resources, before calling FreeLibrary.

Capture WindowClass #32770

I am new in C#, i've got some problem to capture any windows dialog show in my server. I need to know the message (caption and title) from windows dialog so i can write to my application log.
I know that i must find #32770 class windows, but i do not know how to enumwindows. In delphi 7, the code should use some functions like:
Enumwindows
EnumProcess
Enumchildwindows
Enumchildwindowsproc
Getwindowthreadprocessid
GetClassName
Getwindowtext
Is there any solution for this ?
You can use windows API in C# as well. You can find a lot information and examples of using here. And here is information about DllImport attribute.
You can try something like:
class Program
{
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
static void Main(string[] args)
{
var handle = IntPtr.Zero;
do
{
handle = FindWindowEx(IntPtr.Zero, handle, "#32770", null);
if (handle != IntPtr.Zero )
Console.WriteLine("Found handle: {0:X}", handle.ToInt64());
} while (handle != IntPtr.Zero);
Console.ReadLine();
}
}

Categories

Resources