After reading quite a bit on the clipboard being blocked when trying to use it, I tried using OpenClipboard() directly, to capture the clipboard and be able to use it from my window.
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
[DllImport("user32.dll", SetLastError=true)]
private static extern bool OpenClipboard(IntPtr hWndNewOwner);
[DllImport("user32.dll", SetLastError=true)]
private static extern bool CloseClipboard();
private int idx = 0;
private void refresh_Tick(object sender, EventArgs e) {
switch (idx++) {
case 0:
OpenClipboard(Handle);
break;
default:
Clipboard.SetText(" ");
break;
}
}
}
When using SetText, I will get the infamous error:
A first chance exception of type 'System.Runtime.InteropServices.ExternalException' occurred in System.Windows.Forms.dll
Additional information: Requested Clipboard operation did not succeed.
So, the questions:
Does OpenClipboard() actually work?
What is the argument for OpenClipboard() for? The rest of the API does not need a handle to any window, so why does OpenClipboard()? In other words, the Clipboard is supposed to be shared between PROCESSES, not WINDOWS - but I don't see a way to lock it for my current process.
I can call OpenClipboard(IntPtr.Zero), which MSDN says:
If this parameter is NULL, the open clipboard is associated with the current task.
What is 'task' supposed to mean?
Does OpenClipboard() actually work?
OpenClipboard() works, but definitely not in the way you showed. It is a raw Win32 API. Here is an example of using it to copy string to clipboard (C/C++).
What is the argument for OpenClipboard() for?
To be honest, I'm not sure about this. Usually we just pass NULL aka IntPtr.Zero and let it associate with the current task. I guess it retrieves the thread that created the specified window, and then associates it with the clipboard.
What is task? Well here is my understanding. Back in Win16 days, instead of 'Thread' or 'Process', they used the terminology 'Task'. There was a function to GetCurrentTask().
Then the function is replaced by GetCurrentProcess() and GetCurrentThread().
Since it makes more sense that only one thread can access a shared resource at one time, I would say that 'Task' actually means 'Thread'.
The rest of the API does not need a handle to any window, so why does OpenClipboard()?
If my assumption above is correct, that is, only one thread can access Clipboard at a time, then chances are, Windows will use the thread/window you specified with OpenClipboard() previously, until you call CloseClipboard() or the thread/window becomes invalid. That's why you don't need to specify the HWND all the time.
In other words, the Clipboard is supposed to be shared between PROCESSES, not WINDOWS - but I don't see a way to lock it for my current process.
It locks, though I'm not sure about C# P/Invoke. If you have access to Win32/C development toolkit, compile and run the following code:
#include <conio.h>
#include <Windows.h>
int main()
{
OpenClipboard(GetForegroundWindow());
_getch();
return 0;
}
And see what happen if you use Clipboard in other program. :) Close the console window to restore.
Related
I want to detect in my C# code whenever the user presses the physical snapshot button in a webcam.
I discovered that the webcam's own software application has a dll (emDLL.dll) that contains various functions, and I used Dependency Walker to know if it includes an exported function that does what I want. And yes, it has one, whose unmangled name is int IsButtonPressed(void)
Reviewing various responses referred to this issue, I managed myself to write the C# code below to test that unmanaged DLL's function:
using System;
using System.Runtime.InteropServices;
class PlatformInvokeTest3
{
// EntryPoint is assigned with the mangled name of the exported unmangled function int CEM2800Prop::IsButtonPressed(void)
[DllImport(#"emDLL.dll", EntryPoint = "?IsButtonPressed#CEM2800Prop##QAEHXZ")]
[return: MarshalAs(UnmanagedType.I4)]
public static extern int IsButtonPressed();
public static void Main()
{
int Aux;
Aux = IsButtonPressed();
}
}
The problem is that when the code reaches the point when the function is called, appears an exception with the following error:
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
I need to know what is wrong in my code and if there are some way to call from within my C# code that emDLL.dll function.
Thanks to all.
I tested a lot. But I found no disadvantages of those 2!
But see the accepted answer.
I read here that calling GetLastError in managed code is unsafe because the Framework might internally "overwrite" the last error. I have never had any noticeable problems with GetLastError and it seems for me that the .NET Framework is smart enough not to overwrite it. Therefore I have a few questions on that topic:
in [DllImport("kernel32.dll", SetLastError = true)] does the SetLastError attribute make the Framework store the error code for the use of Marshal.GetLastWin32Error() ?
is there an example where plain GetLastError fails to give the correct result ?
do I really HAVE to use Marshal.GetLastWin32Error() ?
is this "problem" Framework version related ?
public class ForceFailure
{
[DllImport("kernel32.dll")]
static extern uint GetLastError();
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetVolumeLabel(string lpRootPathName, string lpVolumeName);
public static void Main()
{
if (SetVolumeLabel("XYZ:\\", "My Imaginary Drive "))
System.Console.WriteLine("It worked???");
else
{
// the first last error check is fine here:
System.Console.WriteLine(GetLastError());
System.Console.WriteLine(Marshal.GetLastWin32Error());
}
}
}
Producing errors:
if (SetVolumeLabel("XYZ:\\", "My Imaginary Drive "))
Console.WriteLine("It worked???");
else
{
// bad programming but ok GetlLastError is overwritten:
Console.WriteLine(Marshal.GetLastWin32Error());
try
{
using (new FileStream("sdsdafsdfsdfs sdsd ", FileMode.Open)) { }
}
catch { }
Console.WriteLine(GetLastError());
}
if (SetVolumeLabel("XYZ:\\", "My Imaginary Drive "))
Console.WriteLine("It worked???");
else
{
// bad programming and Marshal.GetLastWin32Error() is overwritten as well:
Console.WriteLine(GetLastError());
try
{
using (new FileStream("sdsdafsdfsdfs sdsd ", FileMode.Open)) { }
}
catch { }
Console.WriteLine(Marshal.GetLastWin32Error());
}
// turn off concurrent GC
GC.Collect(); // doesn't effect any of the candidates
Console.WriteLine(" -> " + GetLastError());
Console.WriteLine(" -> " + GetLastError());
Console.WriteLine(Marshal.GetLastWin32Error());
Console.WriteLine(Marshal.GetLastWin32Error());
// when you exchange them -> same behaviour just turned around
I don't see any difference! Both behave the same except Marshal.GetLastWin32Error stores results from App->CLR->WinApi calls as well and GetLastError stores only results from App->WinApi calls.
Garbage Collection seems not to call any WinApi functions overwriting the last error code
GetLastError is thread-safe. SetLastError stores an error code for each thread calling it.
since when would GC run in my threads ?
You must always use the Marshal.GetLastWin32Error. The main problem is the garbage collector. If it runs between the call of SetVolumeLabel and the call of GetLastError then you will receive the wrong value, because the GC has surely overwritten the last result.
Therefore you always need to specify the SetLastError=true in the DllImport-Attribute:
[DllImport("kernel32.dll", SetLastError=true)]
static extern bool SetVolumeLabel(string lpRootPathName, string lpVolumeName);
This ensures that the marhsallling stub calls immediately after the native function the "GetLastError" and stores it in the local thread.
And if you have specified this attribute then the call to Marshal.GetLastWin32Error will always have the correct value.
For more info see also "GetLastError and managed code" by Adam Nathan.
Also other function from .NET can change the windows "GetLastError". Here is an example which produces different results:
using System.IO;
using System.Runtime.InteropServices;
public class ForceFailure
{
[DllImport("kernel32.dll")]
public static extern uint GetLastError();
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetVolumeLabel(string lpRootPathName, string lpVolumeName);
public static void Main()
{
if (SetVolumeLabel("XYZ:\\", "My Imaginary Drive "))
System.Console.WriteLine("It worked???");
else
{
System.Console.WriteLine(Marshal.GetLastWin32Error());
try
{
using (new FileStream("sdsdafsdfsdfs sdsd ", FileMode.Open)) {}
}
catch
{
}
System.Console.WriteLine(GetLastError());
}
}
}
Also it seems that this is depended on the CLR which you are using! If you compile this with .NET2, it will produce "2 / 0"; if you switch to .NET 4, it will output "2 / 2"...
So it is depended on the CLR version, but you should not trust the native GetLastError function; always use the Marshal.GetLastWin32Error.
TL;DR
Do use [DllImport(SetLastError = true)] and Marshal.GetLastWin32Error()
perform the Marshal.GetLastWin32Error() immediately after a failing Win32 call and on the same thread.
Argumentation
As i read it, the official explanation why you need Marshal.GetLastWin32Error can be found here:
The common language runtime can make internal calls to APIs that overwrite the GetLastError maintained by the operating system.
To say it in other words:
Between your Win32 call which sets the error, the CLR may "insert" other Win32 calls which could overwrite the error.
Specifying [DllImport(SetLastError = true)] makes sure that the CLR retrieves the error code before the CLR executes any unexpected Win32 calls.
To access that variable we need to use Marshal.GetLastWin32Error.
Now what #Bitterblue found is that these "inserted calls" don't happen often - he couldn't find any. But that's not really surpising. Why? Because it's extremely difficult to "black box test" whether GetLastError works reliably:
you can detect unreliability only if a CLR-inserted Win32 call actually fails in the meantime.
failure of these calls may be dependent on internal/external factors. Such as time/timing, memory pressure, devices, state of computer, windows version...
insertion of Win32 calls by CLR may be dependent on external factors. So under some circumstances the CLR inserts a Win32 call, under others it doesn't.
behavior can change with different CLR versions as well
There's is one specific component - the Garbage collector (GC) - which is known to interrupt a .net thread if there's memory pressure and do some processing on that thread (see What happens during a garbage collection). Now if the GC were to execute a failing Win32 call, this would break your call to GetLastError.
To sum it up, you have a plethora of unknown factors which can influence the reliability of GetLastError. You'll most likely not find an unreliability problem when developing/testing, but it might blow up in production at any time. So do use [DllImport(SetLastError = true)] and Marshal.GetLastWin32Error() and improve your sleep quality ;-)
in [DllImport("kernel32.dll", SetLastError = true)] does the SetLastError attribute make the Framework store the error code for the use of Marshal.GetLastWin32Error() ?
Yes, as is documented in DllImportAttribute.SetLastError Field
is there an example where plain GetLastError fails to give the correct result ?
As documented in Marshal.GetLastWin32Error Method, if the framework itself (e.g. the garbage collector) calls any native method that sets an error value between your calls to the native method and GetLastError you would get the error value of the framework's call instead of your call.
do I really HAVE to use Marshal.GetLastWin32Error() ?
Since you can't ensure that the framework will never call a native method between your call and the call to GetLastError, yes. Also, why not?
is this "problem" Framework version related ?
It could definitely be (e.g. changes in the garbage collector), but it doesn't have to.
I am working on a project that requires implementing am unmanaged windows DLL. The DLL is used to communicate with a USB device. My code is in C# and WPF.
To initialize the DLL I call a function called:
InitTimerDll(Int32 wHandle, ref dllInitParams initParams);
When calling this function I have to pass a struct called dllInitParams and the Handle that the control is bound to.
I am using DllImport for function pointer as such:
[DllImport("myDll.dll")]
public static extern void InitTimerDll(Int32 wHandle, ref dllInitParams initParams);
Here is my struct:
public struct dllInitParams
{
public UInt16 simp;
public UInt16 simt;
}
All of the above are in a separate class called myDllInterface.cs. Here is how I call the InitTimerDll function from my WPF form:
public IntPtr Handle
{
get { return (new System.Windows.Interop.WindowInteropHelper(this)).Handle; }
}
private void initTime_Click(object sender, RoutedEventArgs e)
{
myDllInterface.dllInitParams initParams = new myDllInterface.dllInitParams();
initParams.simp = 0;
myDllInterface.InitTimerDll(this.Handle.ToInt32(), ref initParams);
}
The first part of the above code explains how I get the handle and the initTime_Click shows how I initialize the struct, call the initTimeDll function by passing the handle and the struct to it. I have copied the dll file in the directory that the code runs in. My code compiles just fine but it creates an error when I click on the initTime button.
Error:
An unhandled exception of type 'System.AccessViolationException' occurred in ProbeCTRL.exe
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Why is this happening?
Without knowing exactly what the InitTimerDll() function does with the 'this' pointer, I would focus on the params structure. Try adding a structure layout markup like the following:
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct dllInitParams
{
public UInt16 simp;
public UInt16 simt;
}
Also, double check that your structure is complete and accurate.
I found the problem. The code is fine the problem was the dll file, which was corrupted. A proper copy of the dll file took care of the problem. When using dll in your codes it is quite important to make sure you have accurate information, function calls, data types to passed and so on.
Thanks everyone for your help.
Have a look at the PInvoke tutorial: http://msdn.microsoft.com/en-us/library/aa288468%28v=vs.71%29.aspx
as Jim Gomes points out:
[StructLayout(LayoutKind.Sequential)]
or something similar is definitely important.
Also, you're only initializing one of the variables in your struct.
quick question. I want to find out if a DLL is present in the system where my application is executing.
Is this possible in C#? (in a way that would work on ALL Windows OS?)
For DLL i mean a non-.NET classic dll (a Win32 dll)
(Basically I want to make a check cause I'm using a DLL that may or may not be present on the user system, but I don't want the app to crash without warning when this is not present :P)
Call the LoadLibrary API function:
[DllImport("kernel32", SetLastError=true)]
static extern IntPtr LoadLibrary(string lpFileName);
static bool CheckLibrary(string fileName) {
return LoadLibrary(fileName) == IntPtr.Zero;
}
When using platform invoke calls in .NET, you could use the Marshal.PrelinkAll(Type) method:
Setup tasks provide early initialization and are performed
automatically when the target method is invoked. First-time tasks
include the following:
Verifying that the platform invoke metadata is correctly formatted.
Verifying that all the managed types are valid parameters of platform
invoke functions.
Locating and loading the unmanaged DLL into the process.
Locating the entry point in the process.
As you can see, it performs additional checks other than if the dll exists, like locating the entry points (e.g if SomeMethod() and SomeMethod2() actually exist in the process like in the following code).
using System.Runtime.InteropServices;
public class MY_PINVOKES
{
[DllImport("some.dll")]
private static void SomeMethod();
[DllImport("some.dll")]
private static void SomeMethod2();
}
Then use a try/catch strategy to perform your check:
try
{
// MY_PINVOKES class where P/Invokes are
Marshal.PrelinkAll( typeof( MY_PINVOKES) );
}
catch
{
// Handle error, DLL or Method may not exist
}
Actually it does not throw FileNotFoundException.
Also for that one needs to check in multiple places for path, for the LoadLibrary
There is a standard exception in .net the is derived from TypeLoadException, that is DllNotFoundException.
Best way is to wrap a method/PInvoke call in try..catch and handle the DllNotFoundException since .net will check for application path as well as any other paths set as part of PATH OS Environment variable.
[DllImport("some.dll")]
private static void SomeMethod();
public static void SomeMethodWrapper() {
try {
SomeMethod();
} catch (DllNotFoundException) {
// Handle your logic here
}
}
Call LoadLibrary.
http://msdn.microsoft.com/en-us/library/ms684175(VS.85).aspx
I'm assuming this is a PInvoke call?
If so the easiest way to make this determine if it's present is to make the call and catch the exception that results if the file does not exist.
[DllImport("some.dll")]
private static void SomeMethod();
public static void SomeMethodWrapper() {
try {
SomeMethod();
} catch (DllNotFoundException) {
// Do Nothing
}
}
The following code implements a simple singleton that ensures only 1 instance of my application can be run. However, if another instance is started, I need to be able to grab that instance's command-line arguments, pass them to the initial instance, then terminate the second instance.
The issue comes in when I'm attempting to get hold of the first instance of the application. Once I've found the handle of that instance's main form, I pass it to the Control.FromHandle() method, expecting to get back a MainForm. Instead, the return value is always null. (Control.FromChildHandle() gives the same result.)
Therefore, my question is simply: what am I doing wrong? And is this even possible in .NET?
public class MainForm : Form
{
[DllImport("user32")]
extern static int ShowWindowAsync(IntPtr hWnd, int nCmdShow);
[DllImport("user32")]
extern static bool SetForegroundWindow(IntPtr hWnd);
private Mutex singletonMutex;
private void MainForm_Load(object sender, EventArgs e)
{
bool wasCreated;
singletonMutex = new Mutex(false, Application.ProductName + "Mutex", out wasCreated);
// returns false for every instance except the first
if (!wasCreated)
{
Process thisProcess = Process.GetCurrentProcess();
Process[] peerProcesses = Process.GetProcessesByName(thisProcess.ProcessName.Replace(".vshost", string.Empty));
foreach (Process currentProcess in peerProcesses)
{
if (currentProcess.Handle != thisProcess.Handle)
{
ShowWindowAsync(currentProcess.MainWindowHandle, 1); // SW_NORMAL
SetForegroundWindow(currentProcess.MainWindowHandle);
// always returns null !!!
MainForm runningForm = (MainForm) Control.FromHandle(currentProcess.MainWindowHandle);
if (runningForm != null)
{
runningForm.Arguments = this.Arguments;
runningForm.ProcessArguments();
}
break;
}
}
Application.Exit();
return;
}
}
Single-instance apps are well supported by the .NET framework. Check this thread for an example that does exactly what you need.
Control.FromHandle isn't going to work because the control you're looking for is in another process (and therefore in another appdomain).
You already have the WindowHandle but it's use is limited to the Win32 API. Nothing from WinForms is going to work.
You can send (WM_) messages but it's hard to get data across.
Options
use something low-level with a
temp-file.
use remoting (WCF)
Try the following
var form = (Form)(Control.FromHandle(myHandle));
EDIT
Re-read your question and realized you are looking at a handle in another process. There is no way to convert a handle in another process to a Form instance in the current process. My solution will only work for handles in the same process.
The only way to get ahold of the Form instance is to use Remoting. But that will require cooperation on the part of both processes which does not appear to be what you are looking for.
You are really trying to implement a singleton application. There are a few examples in the Internet (sorry, haven't really tried myself), e.g.
http://www.codeproject.com/KB/cs/SingletonApplication.aspx
http://www.nathanm.com/csharp-wpf-singleton-application/
You can't call code in another process directly, you need to use some form of inter-process communication
If you are communication only between processes started by the same user on the same computer you can use window messages (using WinAPI PostMessage and overriding WndProc), otherwise I think remoting is the easiest to use in .net
I use the Microsoft.VisualBasic.dll library described in the thread that nobugz pointed to. Yes, you can use it in C#. You just override the OnStartupNextInstance and pass the command line into your program in whatever way works best for you.
This is a whole lot easier than messing around with the threads manually.