2

In my windows application on button click, I need to refresh all opened Chrome browser instances or at least the Active tab on my machine.

My code below:

 [DllImport("user32.dll")]
 static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);
 private void btnGetBrowserProcess_Click(object sender, EventArgs e)
    {
       const UInt32 WM_KEYDOWN = 0x0100;
       const int VK_F5 = 0x74;

        Process[] procsChrome = Process.GetProcessesByName("chrome");
        foreach (Process chrome in procsChrome)
        {
            if (chrome.MainWindowHandle != IntPtr.Zero)
            {
               PostMessage(chrome.MainWindowHandle, WM_KEYDOWN, VK_F5, 0);
            }
        }
}

This works fine with IE and Mozilla but doesn't work with Chrome

asif iqbal
  • 45
  • 2
  • 8

1 Answers1

1

Try using SendInput command instead. Unfortunately that means you need to add bit more code to set things up and you will also need to set focus on the chrome window before the keypress can be sent.

The two required external functions are:

    [DllImport("user32.dll")]
    static extern bool SetForegroundWindow(IntPtr hWnd);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern uint SendInput(uint numberOfInputs, INPUT[] inputs, int sizeOfInputStructure);

Then the required structs are:

    /// <summary>
    /// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646270(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    internal struct INPUT
    {
        public uint Type;
        public MOUSEKEYBDHARDWAREINPUT Data;
    }

    /// <summary>
    /// http://social.msdn.microsoft.com/Forums/en/csharplanguage/thread/f0e82d6e-4999-4d22-b3d3-32b25f61fb2a
    /// </summary>
    [StructLayout(LayoutKind.Explicit)]
    internal struct MOUSEKEYBDHARDWAREINPUT
    {
        [FieldOffset(0)]
        public HARDWAREINPUT Hardware;
        [FieldOffset(0)]
        public KEYBDINPUT Keyboard;
        [FieldOffset(0)]
        public MOUSEINPUT Mouse;
    }

    /// <summary>
    /// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646310(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    internal struct HARDWAREINPUT
    {
        public uint Msg;
        public ushort ParamL;
        public ushort ParamH;
    }

    /// <summary>
    /// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646310(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    internal struct KEYBDINPUT
    {
        public ushort Vk;
        public ushort Scan;
        public uint Flags;
        public uint Time;
        public IntPtr ExtraInfo;
    }

    /// <summary>
    /// http://social.msdn.microsoft.com/forums/en-US/netfxbcl/thread/2abc6be8-c593-4686-93d2-89785232dacd
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    internal struct MOUSEINPUT
    {
        public int X;
        public int Y;
        public uint MouseData;
        public uint Flags;
        public uint Time;
        public IntPtr ExtraInfo;
    }

Then finally change your click event as such:

private void btnGetBrowserProcess_Click(object sender, EventArgs e)
{
        Process[] procsChrome = Process.GetProcessesByName("chrome");
        foreach (Process chrome in procsChrome)
        {
            if (chrome.MainWindowHandle != IntPtr.Zero)
            {
                // Set focus on the window so that the key input can be received.
                SetForegroundWindow(chrome.MainWindowHandle);

                // Create a F5 key press
                INPUT ip = new INPUT { Type  =1};
                ip.Data.Keyboard = new KEYBDINPUT();
                ip.Data.Keyboard.Vk = (ushort)0x74;  // F5 Key
                ip.Data.Keyboard.Scan = 0;
                ip.Data.Keyboard.Flags = 0;
                ip.Data.Keyboard.Time = 0;
                ip.Data.Keyboard.ExtraInfo = IntPtr.Zero;

                var inputs = new INPUT[] { ip };

                // Send the keypress to the window
                SendInput(1, inputs, Marshal.SizeOf(typeof(INPUT)));

                // probably need to set focus back to your application here.
            }
        }
}

I've tried this out for myself and the current Chrome tab that I had opened refreshed successfully. I built this example using the following as references:

Unfortunately I don't have an explanation as to why PostMessage is not working for Chrome, but I suspect it will have something to do with the way in which it has been built.

Community
  • 1
  • 1
Adrian Sanguineti
  • 2,455
  • 1
  • 27
  • 29
  • Thanks for this excellent code, i am able to set focus on chrome browser, and its working fine even if browser is minimized, i need one more favour from you, is there any way by which i can refresh all the tabs of a browser including IE and Mozilla – asif iqbal Oct 17 '14 at 06:35
  • 1
    The only way I can think of doing that through the win32 api is sending a Ctrl+Tab key press following by an F5, but there would be no way of reliably knowing how many times this will need to be done without prior knowledge, as each browser implements their tabs differently and this information is unlikely accessible. If you want to be any more advanced than the example above, then you probably should look at creating browser extensions that will allow your application to talk to the browsers and do the actions you require. – Adrian Sanguineti Oct 17 '14 at 07:28
  • Now i am able to refresh all browser tabs by sending Ctrl+Tab following by f5, thanks for sugession – asif iqbal Oct 21 '14 at 07:18
  • Here is code SendKeys.SendWait("^{TAB}"); PostMessage(hWnd, WM_KEYDOWN, VK_F5, 0); – asif iqbal Oct 21 '14 at 07:20
  • Now the problem is that , this code is not running while i am creating windows service, it is unable to find browser process. please help – asif iqbal Oct 22 '14 at 06:38
  • Why are you running it as a Windows Service? What are your trying to achieve by this? It's sounding more like writing browser extensions (or use one of the many that already exist) will be easier to solve your problem. – Adrian Sanguineti Oct 22 '14 at 08:22
  • i need to refresh all the browsers on client machine on which he is displaying third party website wheer we don't have any rights. on the basis of any data change in our application, we have to refresh it by windows service. – asif iqbal Oct 22 '14 at 09:21
  • The problem is that i am not able to find "MainWindowHandle" in windows service, if any how i can get "MainWindowHandle" my problem will be solved. – asif iqbal Oct 22 '14 at 09:26
  • 1
    Ok I would say it would have something to the security context of the account that your Windows Service is being executed under. It may not be able to access the MainWindowHandle simply because it doesn't have the permission to. – Adrian Sanguineti Oct 22 '14 at 10:03
  • 1
    My recommendation is to post a new question on stackoverflow asking if there is a way to solve problem since it is different to your original question. That way you could get more answers than just from me. Don't forget to provide detail and context of the problem so that people have a enough information to help you. – Adrian Sanguineti Oct 22 '14 at 10:04
  • Thanks for your time , this is purely security context of the account, now i will create exe of windows application and try to perform desired task by it. Thanks again You are a star. – asif iqbal Oct 22 '14 at 10:42