I know how to detect already running browsers. Now, I want to know how to detect browser that is currently executing and I also want to know how to detect if new tab/window opens of some browser in c# winforms.
e-g
if user click on x browser; my program should tell x browser is running. now if user opens a new tab in that browser then my program should tell "tab opening in x browser".
I did research but could not find exact!
Thanks
There are two ways to do that, both of them use P/Invoke as there is no managed code for such thing :
Polling :
You program should call GetForegroundWindow periodically then GetWindowText and test if the open focused Window is a browser or not and that's also the active tab title (page title).
Event listening :
You should SetWinEventHook on a system-level event : EVENT_SYSTEM_FOREGROUND to detect the new focused window. You can then SetWinEventHook on an object-level EVENT_OBJECT_NAMECHANGE or EVENT_OBJECT_CREATE for every browser's window to detect tab changes.
Tips :
The client thread that calls SetWinEventHook must have a message loop in order to receive events.
For out-of-context events, the event is delivered on the same thread that called SetWinEventHook.
When you use SetWinEventHook to set a callback in managed code, [you should explicitly tell] the garbage collector not to move the callback.
While a hook function processes an event, additional events may be triggered, which may cause the hook function to reenter before the processing for the original event is finished. The problem with reentrancy in hook functions is that events are completed out of sequence unless the hook function handles this situation. For more information, see Guarding Against Reentrancy.
Related
I'm writing a program that monitors state. It launches main window (LoginForm) to ask for user credentials, then hides the form. After that LoginForm inits NotifyIcon and all the remaining work is being done with LoginForm hidden. I've implemented all the clean-up work in FormClosing event of LoginForm. During normal exit process everything works perfectly.
The problem is that the program sits in tray all the time and I tend to forget to exit it before shutting down windows - program doesn't save the state on shutdown event.
I've read through many forums and docs, and from what I've read events FormClosing/FormClosed + SessionEnding/SessionEnded must fire anyway. But it looks like they just don't fire. Can't even cancel shutdown in SessionEnding (with stupid e.Cancel=true) - program disappears without reaching the place.
I've made myself a small debugging library to write out debug information into a file with instant flashing of cache. I've added debug messages to all the events. When I try to log off user in Windows (same as shutting down) for a test - I see no events being triggered usually, just the program vanishes. No exceptions I could catch, no events, etc. When exitting program manually or through "taskkill /IM " - I see all the expected debug printout. What's even more interesting - sometimes the program does reach closing events and does proper clean-up job during Windows shutdown.
Wasted a few days on this already. Overriden WndProc as suggested in MS article - program doesn't reach WndProc as well (to ensure it comes first before closing the form). Tried instead of FormClosing event to override OnClosing of LoginForm - no luck. Added UnhandledException handler, Microsoft.Win32.SessionEnding, Microsoft.Win32.SessionEnded, Form.FormClosing, Form.FormClosed event handlers - no luck.
I suspect this is either a problem of hidden forms or that some kind of exception is happening during shutdown only (resources disposed?). How can I find why that's happening? Is there some simple way to simulate Windows shutdown for single application to make debugging in VS possible? I've tried RMTool - for some reason it fails to simulate shutdown and program just ignores it.
Update: Program uses System.Timers.Timer to regularly poll server for any changes.
I've done some research into this, basically, after Windows XP they altered the way that shutdowns were handled.
You cannot block or capture the shutdown event reliably using the form_closing events etc.
You must use a new API to do so. There is a complete example here: http://bartdesmet.net/blogs/bart/archive/2006/10/25/Windows-Vista-2D00-ShutdownBlockReasonCreate-in-C_2300_.aspx
You should be able to call the function to block shutting down (display a message such as 'saving changes...') and then save and exit your application in the background. Once your program quits, it should allow windows to continue shutting down.
I think windows is simply configured to automatically shutdown all applications regardless and hence the application has no chance to catch SessionEnding events and so on : have a look at http://www.addictivetips.com/windows-tips/disable-automatic-termination-of-applications-during-shutdown-in-windows-7/ or check your configuration at Computer Configurations > Administrative Templates > System > Shutdown Options.
I added a code for standard "Are you sure you want to exit?" message inside the this.Closing
event of my main window.
It works as expected for closing from the gui, however I would like to disable this check when the application is closed via Application.Shutdown().
There is no event in the Application fired before the window gets closed and the Shutdown method cannot be overriden.
How can I detect what invoked the closing of the window?
Disclaimer: I'd make this a comment rather than an answer if I could as it is a dirty hack (not a clean one). But if you really need something and no better solutions present itself I'll post it anyway to hopefully help...
If you're definitely not in a position to control / hook the parts of the code base that are calling application shutdown, then the possibility is to find something else that responds to the shutdown that you can trip before your window closes.
My (not so ideal) thought on that is to set up another hidden window (SO: Loading a WPF Window without showing it) that the user wont interact with but the application will close on shutdown.
In the closing event of that window you can set a flag to indicate the application is shutting down. Then in your main window's closing event you can react to that flag.
The big issue to tackle is configuring things so that the hidden window will always close before the Main Window(s) safely.
I did some limited tests with MainWindow.Xaml as the application Startupuri, and creating the hidden window from the application.onstartup event and found the hidden window would close first - but I wouldn't want to gaurantee that in all scenerios! Actually getting this working and tested adequately could be a lot of work - as I said it's a last restort dirty hack.
Who calls Application.Shutdown()? If you are in Charge of that just set a flag indicating that you did it and check for that flag in the Closing event handler.
Is it possible to utilize the sendInput function on windows that currently do not have focus, and maybe through the use of multithreading, sendinput to multiple minimized windows at the same time, or send input to one window while you're working on another window?
I'd like to do something like this in c#
thanks in advance.
You can only use SendInput to send input to the HWND with keyboard focus. Furthermore the window must be attached to the calling thread's message queue, so one cannot simply SetFocus either.
You'll need to get the window's thread id with GetProcessIdOfThread.
When you have the thread id you can use the AttachThreadInput function to attach your thread to the other threads input processing.
After all this you can probably use SetFocus and SendInput.
You'll probably want to detach your thread when you've sent your input.
To get access to these method you'll have to use P/Invoke for C# or C++/CLI. PInvoke.net is very handy as a reference. It will be a small chore importing all those functions, but when you are done you should be able to send input to whatever "window" you want.
Also as a side note, I'm not sure if you are aware of this, but in pure Win32 everything is regarded as a window, even a button. If you are unlucky you may have to send the input to the handle of the text control belonging to the notepad application.
That is not possible with SendInput. What you probably want to do is find the messages that were sent to the window by the OS when that particular event was performed then emulate them. You can use Spy++ to attach to the target window and perform your event. Then use SendMessage() and PostMessage() to reproduce the messages that were generated by your event. This will work fine for notepad.
If you do use this method, note that you need to send messages to notepad's child window which you can find with FindWindowEx() with a classname of "edit". For example to type text you could try WM_KEYDOWN. You should note that this method is not necessarily reliable:
http://blogs.msdn.com/b/oldnewthing/archive/2005/05/30/423202.aspx
I'm writing a program which creates no forms at all until one is required. The problem is, it's preventing shutdown from continuing automatically. I've seen discussions about adding an if to form closing events to check if it's due to shutdown, but as I've said, my program is meant to have no forms at all until required.
Is there any event or some other method that will allow me to know when my program should be closing itself to allow for Windows to shut itself down automatically? And it's not multithreaded.
You can use the SystemEvents class, to "listen to" users logging out, or shutting down.
If I understand the documentation correctly (and a deep study with Reflector confirms this):
The systemevents will spawn a new thread that receives the messages from windows (it has its own messagepump).
When an event is received, your code will be called, from the new thread. You should be aware of this.
You could always add a dummy form which you open minimized, with no icon on the taskbar - it won't have any visual impact, but will be sent the form closing event - where you could note the shutdown event, and presumably shut down/stop whatever else there is that your application is doing.
Handling the Microsoft.Win32.SystemEvents.SessionEnding event, and checking if it's an actual shutdown with System.Environment.HasShutdownStarted
I have this problem: I have an handler to the mainWindow of a certain application, and I want to simulate a keypress on that application...
I'm using sendMessage/postMessage api calls to do this. The reason why I don't use the .Net SendKeys function or the keybd_event of the win32 api, is that they simulate the keypress at a global level. In my case, the target application is not the top-active one (other application may be running in a higher z-level, hence covering the target app).
The problem with sendMessage and postMessage is that you must pass the handler of the exact childwindow where you want the key to be pressed. For example, in notepad, if I send the key to the handler of the mainWindow, nothing happens, I have to send the key to the handler of the child window that basically consists of the white canvas where you can write.
Obtaining the handler to the active child window is the problem. In the beginning, I was using the GetTopWindow or GetWindow(GW_CHILD) api calls, as it returns the most active child window. What I was doing was to keep calling the GetWindow(GW_CHILD) until I got a childwindow that had no more childWindows. This works ok for some applications like notepad or paint. However, in some cases (like firefox for example), it doesn't work. The reason for that is that the parent window has the whole firefox area, and its childwindow has the opened WebPage (like google). So, when I ask for the most active child window of the mainWindow, it returns the only child window it has, which is the one corresponding to the Webpage area. It only works if the active window is that one (like if the user is writing something on a textbox of a certain page). But if what is active is, let's say, the address bar, it doesn't work because the active window is not the child window but actually the parent... and I can't get this information programatically.
I actually found a way of doing this, using the GetGUIThreadInfo api call, using the following code:
// get thread of the main window handle of the process
var threadId = GetWindowThreadProcessId(firefox.MainWindowHandle, IntPtr.Zero);
// get gui info
var info = new GUITHREADINFO();
info.cbSize = (uint)Marshal.SizeOf(info);
if (!GetGUIThreadInfo(threadId, out info))
throw new Win32Exception();
// send the letter W to the active window
PostMessage(info.hwndActive, WM_KEYDOWN, (IntPtr)Keys.W, IntPtr.Zero);
And it works very well: If the address bar is active, it sends a "W" letter to the address bar. If the search textBox of google is active, it sends the "W" letter to it... Perfect! However, this method can't be used by me for a simple reason:
If the target application is not the active window of the operating system, the ThreadInfo structure comes empty. For example, if I'm targetting firefox, it works if firefox is active (the top-most application, the focused/active one), but if, let's say, notepad is on top of firefox, it doesn't work, it is unable to get the active window handler.
I know I can solve this by using the setForegroundWindow api call to activate the target application and then capture the handler of the active child-window but I didn't want to have to bring the target app to the foreground.
I've also tried other techniques like AttachThreadInput() and GetFocus() api calls, which also works, but has the same problem: If the target application is not the active windows application, it doesn't work.
So basically I need to find some way of getting the handler to the active childwindow of an application even if that application is not the top-active one.
Any ideas?
Thanks
You might want to check out the EnumChildWindows function.
If everything else fails, here is another idea: You might want to consider using a WH_CBT or a WH_CALLWNDPROC hooks to monitor which child window of the target thread has been focused last.
Install a CBT hook (WH_CBT) and listen for the HCBT_SETFOCUS notification.
Or use a WH_CALLWNDPROC hook and listen for the WM_SETFOCUS message.
Don't do much in the hook proc or you'll hog down the system resources. Just save the needed information and post yourself a custom message to process it later.