Reputation: 6344
I am writing a C# application which calls a function within an DLL written using unmanaged code.
For the most part, the calls work fine and the called functions return an integer value specifying either success, or a handful of error codes. However, for a couple of the error codes, the DLL also seems to pop up a message box providing some further information regarding the error.
I have no way of knowing if this is going to occur for a given funciton call or not, and would rather not hassle the user with these message boxes, as sometimes I am calling this function thousands of times in a batch process and I would rather not have the user have to press "OK" for however many failures there happen to be.
If there is any way to either determine that a message box was shown after a given call, or alternatively generally disable or disallow any windows or forms to be displayed during a given call? It seems unlikely, but I thought I'd ask at any rate.
Thanks, Mr M
Upvotes: 1
Views: 2617
Reputation: 97696
Would it be practical for you to run this code from inside a Windows service?
Services aren't allowed to show GUI (you used to be able to opt into allowing a service to show GUI, but MS has been phasing this out). I don't know for sure, but I think calls to MessageBox() and the like may simply return immediately when you call them from a non-interactive service.
Upvotes: 0
Reputation: 3892
Investigate low level Win API calls, they may offer a solution for you.
For example, using Spy++ can reveal window names which then you can search for and close. Then using the WINDOWS API callouts...
using System.Runtime.InteropServices;
// Get a handle to an application window.
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
private static extern IntPtr FindWindow(string lpClassName,
string lpWindowName);
// Activate an application window.
[DllImport("USER32.DLL")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
Then in a background thread, write a process that looks for these windows and closes them.
//Some PsuedoCode, note loop should have a cancel condition!
while (true)
{
//Get a handle.
handle = FindWindow(windowClassName, windowName);
//We found the window, close it
if (handle != IntPtr.Zero)
{
//Send Close Command
SetForegroundWindow(handle);
SendKeys.SendWait("%{F4}");
}
//Wait 200ms seconds before trying again
System.Threading.Thread.Sleep(200);
}
You might be able to do some type of hackish solution like this in your application.
Note, you will have to store the windowClassName(s) and windowName(s) in some sort of config file or hardcode them in your application.
Upvotes: 2
Reputation: 754665
There's really no way to prevent an arbitrary (non-managed) DLL from popping up UI if it feels the need to do so.
One ugly work around though is to try and close the window immediately after it pops up. The way I would do this would be to
This is by no means a bullet proof process but it may help you work around this problem.
Upvotes: 1
Reputation: 48596
As you suspect, you're not going to be able to suppress popups from code you haven't written, unless the calls have a specific parameter that would do that for you. Are the message boxes associated with particular error codes?
There are programs available that will monitor your computer for particular windows and click buttons on them when they appear, though of course requiring the users to run that as well is a bit of burden. [EDIT: Joe pointed out that you could do this yourself on a separate thread. Also an option.]
There are always going to be trade-offs when working with dependencies, and you have to balance the dependency's usefulness and necessity with what compromises it might require you to make.
Upvotes: 2