How to prevent a window from opening from another application? - c#

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

Related

switch application and assigning them to instance

I'm having problems with switching application and assigning them to a variable. This is what I have so far.
[DllImport("user32.dll")]
public static extern void SwitchToThisWindow(IntPtr hWnd, bool b);
Process[] procs = Process.GetProcessesByName("Excel");
foreach (Process proc in procs)
{
SwitchToThisWindow(proc.MainWindowHandle, false);
}
In the end I want to assign that Excel window to be assigned to xlApp. I tried:
xlAppl = SwitchToThisWindow(proc.MainWindowHandle, false); but obviously this won't work because the interface is a void. I tried looking at GetActiveWindow I was thinking of getting active window and assign it but it's return value is not an Object it's IntPtr.
Is there a way out of this?
There are a couple things I want to point out about what you have so far:
For SwitchToThisWindow MSDN states - [This function is not intended for general use. It may be altered or unavailable in subsequent versions of Windows.]. So I personally wouldn't use that one if I were you.
Your Process.GetProcessByName call is going to return all excel processes. Then you're going to try to bring each one to the foreground. Only the last one of course will actually be in the foreground, since they can't all be in the foreground. You should probably decide on a more accurate way of choosing which one you want.
You are assuming that MainWindowHandle is not IntPtr.Zero which is not a valid assumption in all cases. MainWindowHandle will only have a value once there is a visible window that has been rendered.
If I were you I'd try using the SetForegroundWindow and SetActiveWindow APIs instead.
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern bool SetForegroundWindow(
IntPtr hWnd
);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SetActiveWindow(
IntPtr hWnd
);
Guys i found the solution. Pretty simple here is the answer if anyone else is looking for this:
Excel.Application xlApp = (Excel.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");

SendMessage() only working when window is open, not when minimized

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.

Can WH_MOUSE catch global events?

I'm trying to develop a WPF C# application that captures mouse clicks even (especially) if it's in background in order to start another task.
On MSDN documentation ( http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx ) I can read that WH_MOUSE should have either a global or thread scope.
I instantiate my hook handle this way:
hHook = SetWindowsHookEx(WH_MOUSE,
MouseHookProcedure,
(IntPtr)0,
AppDomain.GetCurrentThreadId());
where MouseHookProcedure is the delegate of my callback function and WH_MOUSE value is 7 (following Winuser.h).
The code works but it can only catch local clicks (I just need WM_LBUTTONDOWN messages), the clicks inside the window. I need to catch clicks also outside the window, and when the window is in background.
I tried hooking to WH_MOUSE_LL (with a value of 14), but it's not working.
For the most part I followed this:
http://support.microsoft.com/kb/318804
with some changes since I am using WPF and not WinForms.
The documentation about Hooks is a bit confusing.
All in all I'd like to know:
Can WH_MOUSE detect mouse messages globally? If yes, what am I doing wrong?
Can I hook from a .NET C# code to a WH_MOUSE_LL? If yes, how?
Thanks in advance.
It's possible with WH_MOUSE_LL and you need it.
In my case I developed a global keyboard maybe this could help you.
I needed to call LoadLibrary in the third parameters.
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr LoadLibrary(string fileName);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, KeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
void MyFunction(){
[...]
SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, LoadLibrary("user32.dll"), 0);
}
Technically you should be able to have a global mouse hook implemented in C#. You would then pass zero as the last arguments to SetWindowsHookEx and your hook procedure must reside in a DLL, not an EXE. That's because the DLL will be injected into every process that has windows belonging to the same desktop as the hooking application. For this same reason writing global hooks in .NET is not actually recommended by most because it causes the CLR to be loaded into every desktop process, which can carry substantial overhead.

MFC-hosted WPF usercontrol how to close parent window on button press

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.

Alternative to GetWindowModuleFileName to get other processes ApplicationFileName?

In order to get the application name of the foreground Window (or the name of application file) I want to use GetActiveWindow with GetWindowModuleFileName.
I found a similar question relating to GetWindowText here
That implementation of GetWindowText works fine, but GetWindowModuleFileName only returns a value for visual studio (when I click inside the devenv) for all other applications it stays blank.
Any hint how I can find out what goes wrong? Might this have to do with permission/security of my application querying the applicationfilename of another process?
EDIT: http://support.microsoft.com/?id=228469 looks like this doesn't work under Win >=XP
Any alternatives how to get the application file name?
In order to get the application name of the foreground Window (or the name of application file) I want to use GetActiveWindow with GetWindowModuleFileName.
... querying the applicationfilename of another process ...
In my opinion your problem with use of GetActiveWindow() function. It is used for gathering information from the calling thread/process only. If calling thread is inactive GetActiveWindow return 0;
From MSDN:
GetActiveWindow Retrieves the window handle to the active window attached to the calling thread's message queue.
Try to use GetForegroundWindow() function instead of GetActiveWindow()
By chance do you have UAC turned off?
Starting with Vista, if your code touches an HWND in another process, your process needs to be run at the same privilege level.
In other words, if the window is hosted in a process running as administrator, your app must also run as administrator.
I found a workaround using this:
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
IntPtr handle = IntPtr.Zero;
handle = GetForegroundWindow();
uint processId;
if (GetWindowThreadProcessId(handle, out processId) > 0)
{
Console.WriteLine(Process.GetProcessById((int)processId).MainModule.FileName);
}

Categories