我需要模拟输入,为什么HtmlElement.Focus不起作用?

问题描述 投票:0回答:1

我正在尝试编写一个应该未检测到的Web机器人,因此我不使用InnerText属性,而是尝试模拟按键。要做到这一点,我需要关注一个<input>元素,但焦点切换到另一个文本字段,甚至在element.Focus()调用之后。

我也试过使用element.InvokeMember("click");,但它也不起作用。

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
    }

    [DllImport("User32.dll")]
    public static extern int SendMessage(IntPtr hWnd, int uMsg, IntPtr wParam, IntPtr lParam);

    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

    public const Int32 WM_CHAR = 0x0102;
    public const Int32 WM_KEYDOWN = 0x0100;
    public const Int32 WM_KEYUP = 0x0101;
    public const Int32 VK_RETURN = 0x0D;

    IntPtr BrowserHandle
    {
        get
        {
            var hwnd = _browser.Handle;
            hwnd = FindWindowEx(hwnd, IntPtr.Zero, "Shell Embedding", null);
            hwnd = FindWindowEx(hwnd, IntPtr.Zero, "Shell DocObject View", null);
            hwnd = FindWindowEx(hwnd, IntPtr.Zero, "Internet Explorer_Server", null);
            return hwnd;
        }
    }

    readonly Random _rnd = new Random();

    private void Form1_Load(object sender, EventArgs e)
    {
        _browser.Navigate("https://...");
        _browser.DocumentCompleted += _browser_DocumentCompleted;
    }

    private async void _browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        if (e.Url.AbsoluteUri != "https://...") return;
        var inputs = _browser.Document.GetElementsByTagName("input");
        {
            var el = inputs.OfType<HtmlElement>().FirstOrDefault(x => x.GetAttribute("className").Contains("login"));
            await SendTextAsync(el, "sdfoj30jfoigjdlsgfdgd");
        }
    }

    async Task SendTextAsync(HtmlElement element, string text)
    {
        for (var i = 0; i < text.Length; i++, await Task.Delay(_rnd.Next(0, 500)))
        {
            if (_browser.Document.ActiveElement != element)
            {
                element.Focus(); // doesn't work
                if (_browser.Document.ActiveElement != element)
                {
                    element.InvokeMember("click"); // either
                    if (_browser.Document.ActiveElement != element)
                    {
                        element.Focus();
                        await Task.Delay(_rnd.Next(50, 250)); // anyway
                    }
                }
            }

            var c = text[i];
            SendCharacter(c, BrowserHandle);
        }
    }

    static void SendCharacter(char character, IntPtr hWnd)
    {
        var key = new IntPtr(character);
        SendMessage(hWnd, WM_KEYDOWN, key, IntPtr.Zero);
        SendMessage(hWnd, WM_CHAR, key, IntPtr.Zero);
        SendMessage(hWnd, WM_KEYUP, key, IntPtr.Zero);
    }
}

我希望这段代码能够填充登录文本字段,但是它会在那里写入一些字符,而其他字符则会转到密码文本字段。

c# dom webbrowser-control bots
1个回答
0
投票

解决方案是每次使用GetElementsByTagName查找元素而不是重用引用。

© www.soinside.com 2019 - 2024. All rights reserved.