Search code examples
c#automationpinvoke

Interact with a form using handle C#


I am trying to automate a dynamically appearing dialogue box. I need to pass text to it,s text field and then press a button over this. What I have tried so far.

 [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
        static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);

IntPtr handle= FindWindowByCaption(System.IntPtr.Zero, "Caption Of File");

I am getting the handle of dialogue box correctly.

List<IntPtr> childWindows=  GetChildWindows(handle);//To get the child controls in this dialogue box

Source

But when I try to cast it to control I get null.

foreach (IntPtr i in childWindows) 
{
    Control c = Control.FromHandle(i);
}

So can any body tell what is wrong.I am supposing that I shall cast handle to control and then interact with control properties(e.g: text).


Solution

  • enter image description here

    I've been using code like this sucessfully for years to perform single sign on to an application that prompts the user for their username/pwd/domain. The only caution is you need to know the control structure of the dialog you're targeting, but this is easily accomplished with Spy++ and rarely changes. Of course you will need to modify this code for the control structure of your window.

            [DllImport("user32.dll")]
            static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter,
                string lpszClass, string lpszWindow);
    
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, int wParam, string lParam);
    
            [DllImport("User32.Dll")]
            public static extern IntPtr PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
    
            private const uint WM_GETTEXTLENGTH = 0x000E;
            private const uint WM_SETTEXT = 0x000C;
            private const uint WM_GETTEXT = 0x000D;
            private const uint BM_CLICK = 0x00F5;
            private const uint WM_CLOSE = 0x0010;
    
            enum GetWindow_Cmd : uint
            {
                GW_HWNDFIRST = 0,
                GW_HWNDLAST = 1,
                GW_HWNDNEXT = 2,
                GW_HWNDPREV = 3,
                GW_OWNER = 4,
                GW_CHILD = 5,
                GW_ENABLEDPOPUP = 6
            }
    
    var dialog FindWindow("optionalClassNameHere", "Log On"); //Get the handle of the window
     var w3 = GetWindow(dialog , (uint)GetWindow_Cmd.GW_CHILD);  //I use GetWindow to walk the window controls
     var wUid = FindWindowEx(w3, IntPtr.Zero, "Edit", "");
     var w4 = GetWindow(wUid, (uint)GetWindow_Cmd.GW_HWNDNEXT);
     var wPwd = FindWindowEx(w4 , IntPtr.Zero, "Edit", "");
     var wOK = FindWindowEx(w3, IntPtr.Zero, "Button", "OK");
     SendMessage(wUid, WM_SETTEXT, 0, _WinDomain + "\\" + Username); //Send username to username edit control
     SendMessage(wPwd, WM_SETTEXT, 0, Password); //Send password to password edit control
     PostMessage(wOK, BM_CLICK, 0, 0); //Send left click(0x00f5) to OK button