I have a .EXE that performs several calculations and was implemented by another company. I do not have access to the source code of this executable and it is out of question trying to modify its behaviour.
My problem is:
I am writing a code in c# to call this EXE and read its file output. After the EXE is done with the calculation, it opens a MessageBox -> "Calculation Done", and only after clicking in a "OK Button" the output file is written. That really sucks, since it is necessary the user manually click with the mouse to close the MessageBox. I am wondering if it is possible to close this MessageBox programmatically?
I have googled it and my guess is that is it possible using MainWindowHandle, but I am not sure. Any help?
You can call FindWindow to locate your MessageBox, and then use SendMessage to send a close message
[DllImport("user32.dll")]
private static extern int SendMessage(int hWnd,uint Msg,int wParam,int lParam);
[DllImport("user32.dll", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindow(string lp1, string lp2);
public const int WM_SYSCOMMAND = 0x0112;
public const int SC_CLOSE = 0xF060;
IntPtr window = FindWindow(null, "MessageBox Title Here");
if (window != IntPtr.Zero)
{
SendMessage(window, WM_SYSCOMMAND, SC_CLOSE, 0);
}
Read more here
Related
I've been using SendMessage to send mouse clicks to a couple of windows. One being a game(everything works perfectly), but the other window, being a 3rd party tool for the game is having trouble with SendMessage. If the window is 'not minimized' everything works fine, don't matter if window is completely covered up by another. But if that same window is minimized then nothing happens, I checked with spy++ and the messages are indeed getting received but not being processed (correct term?). I've tried to solve this last couple days, doing both searches on here and Google alike, many of topics but nothing helped?
//MyImports
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
And this is how I have it wrapped
public static void LClick(string windowclass, int x, int y)
{
IntPtr WHandle = FindWindow(windowclass, null);
SendMessage(WHandle, (int)WMessages.WM_LBUTTONDOWN, (IntPtr)1, (IntPtr)MakeLParam(x, y));
SendMessage(WHandle, (int)WMessages.WM_LBUTTONUP, (IntPtr)0, (IntPtr)MakeLParam(x, y));
}
I have tried focus, activate. One thing that might be useful info is that the third party program is being loaded as module("Qt5QWindowIcon") of the game.
I tried PostMessage as well, and it does the same thing as SendMessage() same problem when minimized.
This game does allow for macroing and unattended macroing, Hints the third part tool designed to execute the macros (published by the creators) I'm just trying to simulate a mouse click on the program to start the macro.
I would just use SendInput, but the entire purpose of my program is to run in background.
I 've faced same problem .Please change assembly name and project name (Changed name not started with name on that you are throwing/posting windows message)then rebuild it and check it. Now you will able to debug.
I'm trying to get a legacy MFC application and a new WPF usercontrol to shut down a dialog window based on a button press in the WPF usercontrol. In essence, I would like some tips on how I can get the DoModal() function of MFC return.
For various reasons the dialog is a MFC CDialog started via DoModal, which hosts a single WPF component and nothing else. This component then has a button which will need to close the CDialog after doing some various tasks. This application is an.. exiting.. case of legacy and it's really hard to track control flow and where the actual message pumps driving this thing resides. It's also full of #defines that makes everything twice as difficult as it should be. I think I have identified the message pump, so I think I can insert something into that to make it close - if I can get to that from the WPF control.
I do not know how to send a windows message out from the usercontrol to the host, or how to get the HWND of the host from the usercontrol. I'm sure there is a way to get that, or another better way of communicating?
Is the correct approach to send a WM_CLOSE message to the parent HWND? Or perhaps I can send a WM_USER to the dialog pump and handle the actual closing there?
Try this. It should work for any WPF element (if it's a Visual), by finding it's containing HWND, tracing up the HWND tree until it finds the root parent, then sending that a WM_CLOSE message.
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
private static extern IntPtr GetParent(IntPtr hWnd);
//I'd double check this constant, just in case
static uint WM_CLOSE = 0x10;
private void CloseContainingWindow(Visual visual)
{
// Find the containing HWND for the Visual in question
HwndSource wpfHandle = PresentationSource.FromVisual(this) as HwndSource;
if (wpfHandle == null)
{
throw new Exception("Could not find Window handle");
}
// Trace up the window chain, to find the ultimate parent
IntPtr hWindow = wpfHandle.Handle;
while (true)
{
IntPtr parentHWindow = GetParent(hWindow);
if (parentHWindow == (IntPtr)0) break;
hWindow = parentHWindow;
}
// Now send the containing window a close message
SendMessage(hWindow, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
}
Declare a close event in the control. Raise the event when the close button is closed.
In your CDialog-derived class, subscribe to the event, then call EngDialog in the event handler.
WM_CLOSE should work, but you have to try it.
Another approach is to post a WM_COMMAND message to the parent dialog.
Sending a WM_USER looks too complicated.
I´m facing a problem when trying to close a Windows Explorer (not Internet Explorer) window through another application, using the "Process.CloseMainWindow()" method; because it doesn´t close the Explorer window, it tries to close the full Windows (Operative System), by the way, Windows XP.
The code is as follows:
[DllImport("user32.dll")]
static extern int GetForegroundWindow();
[DllImport("user32.dll")]
private static extern UInt32 GetWindowThreadProcessId(Int32 hWnd, out Int32 lpdwProcessId);
public String[] exeCommand()
{
try
{
//Get App
Int32 hwnd = 0;
hwnd = GetForegroundWindow();
Process actualProcess = Process.GetProcessById(GetWindowProcessID(hwnd));
//Close App
if (!actualProcess.CloseMainWindow())
actualProcess.Kill();
}
catch { throw; }
return null;
}
Suppose that the "actualProcess" is "explorer.exe"
Any help will be appreciated!!
Salutes!
I believe this is because the main window for explore is considered the shell. You can however kill the process, but windows will start it right back up.
I will prevent a window from iTunes to be opened.
I googled a lot but can't find an iTunes library that allows me to control such things, so I think I must get back to basics and close it after it opens, but how?
I think:
Tick a timer every 500 ms
Check if the window handle is opened
Close it
Is that possible?
How can I recognize a window from this application on other computers (I will give away my application)?
Language is C#.Net 2.0.
Yes it's an option to find the window and close it. However the user will still see it.
You can do the PInvoke method of FindWindow or use the C# ones (prefer those)
using System.Diagnostics;
Process[] processes = Process.GetProcessesByName("notepad");
foreach (Process p in processes)
{
p.CloseMainWindow();
}
From here
This is only for closing the top application, I dont know if you can find the subwindow with Process.
I know you can with PInvoke, see example here
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
or
[DllImport("user32.dll", EntryPoint="FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
Sure there are ways to do this, an approach I used before was based on the win32APIs, you'll want to look at the following:
FindWindow
SendMessage
In short you can use the timer, and when it fires use FindWindow (either using the window title bar, or the application "class") to get the handle, once you have that you SendMessage to the window of at least a WM_CLOSE or WM_DESTROY
I have used the following code to disable the control panel:
RegistryKey RegKey = Registry.CurrentUser.CreateSubKey(
#"Software\Microsoft\Windows\CurrentVersion\Policies\Explorer");
RegKey.SetValue("NoControlPanel", false, RegistryValueKind.DWord);
RegKey.Close();
The above code disables control panel only after restarting, I would like to apply the setting immediately without restarting. Please help me.
Try this...
private const int HWND_BROADCAST = 0xffff;
private const int WM_WININICHANGE = 0x001a, WM_SETTINGCHANGE = WM_WININICHANGE, INI_INTL = 1;
SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, INI_INTL);
[DllImport("user32.dll")]
private static extern int SendMessage(int hWnd, uint wMsg, uint wParam, uint lParam);
This will notify all applications that changes have been made to the registry, and those programs that accept the notification shuould reload their settings.
Note that not all applications may do this, but things like control panel should.
I haven't tested this, but I suspect you only have to close all your explorer.exe processes for this to take effect.
Note that the desktop and taskbar are provided by explorer.exe, so you'll need to start a new one after closing them all.
It's a bit hostile, because the user might have Explorer windows that they don't want to lose, so do it only if it's not going to annoy people. 8-)