C#-从C#应用程序向Google Chrome发送消息

时间:2020-03-06 14:51:56  来源:igfitidea点击:

我一直在搜索,但是还没有找到如何从C#中做到这一点。

我想要这样做,以便可以告诉Google Chrome从我的C应用程序中前进,后退,打开新选项卡,关闭选项卡,打开新窗口和关闭窗口。

我使用WinAmp做过类似的事情

[DllImport("user32", EntryPoint = "SendMessageA")]
private static extern int SendMessage(int Hwnd, int wMsg, int wParam, int lParam);

和其他一些。但是我不知道要发送什么消息,或者如何找到将其传递给哪个窗口,等等。

有人可以告诉我如何将这6条命令从C#发送到Chrome吗?谢谢

编辑:
好的,我被否决了,所以也许我不够清楚,或者人们以为我没有尝试自己解决这个问题。

首先,我对整个DllImport东西不太满意。我仍在学习这一切的运作方式。

几年前,我发现如何在winamp中实现相同的想法,并且我正在查看自己的代码。我做到了,这样我就可以跳过歌曲,返回,播放,暂停和停止Ccode中的winamp。我从导入开始:

[DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr FindWindow([MarshalAs(UnmanagedType.LPTStr)] string lpClassName, [MarshalAs(UnmanagedType.LPTStr)] string lpWindowName);
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern int SendMessageA(IntPtr hwnd, int wMsg, int wParam, uint lParam);
    [DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    public static extern int GetWindowText(IntPtr hwnd, string lpString, int cch);
    [DllImport("user32", EntryPoint = "FindWindowExA")]
    private static extern int FindWindowEx(int hWnd1, int hWnd2, string lpsz1, string lpsz2);
    [DllImport("user32", EntryPoint = "SendMessageA")]
    private static extern int SendMessage(int Hwnd, int wMsg, int wParam, int lParam);

然后,我发现使用此代码的代码将这些常量用于我发送的消息。

const int WM_COMMAND = 0x111;
    const int WA_NOTHING = 0;
    const int WA_PREVTRACK = 40044;
    const int WA_PLAY = 40045;
    const int WA_PAUSE = 40046;
    const int WA_STOP = 40047;
    const int WA_NEXTTRACK = 40048;
    const int WA_VOLUMEUP = 40058;
    const int WA_VOLUMEDOWN = 40059;
    const int WINAMP_FFWD5S = 40060;
    const int WINAMP_REW5S = 40061;

我将通过以下方式获取hwnd(向其发送消息的程序):

IntPtr hwnd = FindWindow(m_windowName, null);

然后我会向该程序发送一条消息:

SendMessageA(hwnd, WM_COMMAND, WA_STOP, WA_NOTHING);

我认为我会为Google Chrome做类似的事情。但是我不知道其中的一些值应该是什么,我四处搜寻试图找到答案的方法,但是我做不到,这就是为什么我在这里问。所以我的问题是如何获取以下值:

m_windowName和WM_COMMAND

然后,不同命令的值,前进,后退,新选项卡,关闭选项卡,新窗口,关闭窗口?

解决方案

在http://dev.chromium.org/developers上开始研究

编辑:向窗口发送消息只是工作的一半。窗口必须响应该消息并采取相应措施。如果该窗口不知道消息或者根本不在乎,则我们没有机会通过发送窗口消息来控制它。

我们正在查看有关如何远程控制Winamp的实现细节。发送消息只是做到这一点的一种方式,也是Winamp开发人员选择的方式。我们正在使用的那些消息是用户定义的消息,仅对Winamp具有特定的含义。

第一步,我们需要了解Chromium是否支持某种远程控制以及这些机制是什么。

我们可以使用Visual Studio的Spy ++并按CTRL + F,然后找到镶边,轻松获得窗口名称。我试了一下

" Chrome_VistaFrame"用于外出窗口。包含网页的实际窗口是" Chrome_RenderWidgetHostHWND"。

就WM_COMMAND而言,我们需要进行实验。我们显然会希望发送按钮点击(我的头顶上方是WM_MOUSEDOWN)。由于后退,前进按钮不是它们自己的窗口,因此我们需要弄清楚如何通过在特定的x,y位置上模拟鼠标单击来做到这一点,以便chrome知道我们在做什么。或者,我们可以将等效的键盘快捷键发送给后退/前进等。

我之前写的一个示例使用trillian和winamp做到了这一点:通过cand winapi将消息发送到Windows

还有一些工具可以将这种情况宏化,使用脚本语言autoit是我使用过的一种:autoit.com

好的,这就是我到目前为止所拥有的...我有点知道我需要做的事,但这只是现在要做的事情...

这是Spy ++的窗口,我锁定到Chrome_RenderWidgetHostHWND并单击键盘上的"后退"按钮。这是我得到的:

所以这是我的假设,而我一直以来一直在玩这个游戏,我只是无法弄清楚这些价值。

IntPtr hWnd = FindWindow("Chrome_RenderWidgetHostHWND", null);
SendMessage(hWnd, WM_KEYDOWN, VK_BROWSER_BACK, 0);
SendMessage(hWnd, WM_KEYUP,   VK_BROWSER_BACK, 0);

现在,我只是不知道该如何设置WM_KEYDOWN / UP值或者VK_BROWSER_BACK / FORWARD值...
我尝试了这个:

const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
const int VK_BROWSER_BACK = 0x6A;
const int VK_BROWSER_FORWARD = 0x69;

我从刚刚显示的图像中获得的后两个值是这两个键的ScanCodes。我不知道我是否做对了。我在Google搜索WM_KEYDOWN值后得到的前两个值,有人用&H100和&H101作为这两个值。我尝试了其他一些随处可见的随机想法。我只是想不通。

哦,这是SendMessage方法

[DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, uint lParam);

这是互操作常量的绝佳站点:

品客

查找值的另一种方法是使用Cas语言搜索koders.com,以获取WM_KEYDOWN或者所需的常量:

Koders.com搜索

&H值看起来像来自VB(6)。 pinvoke和koders都返回VK_BROWSER_FORWARD的结果,

private const UInt32 WM_KEYDOWN        = 0x0100;
private const UInt32 WM_KEYUP          = 0x0101;

public const ushort VK_BROWSER_BACK = 0xA6;
public const ushort VK_BROWSER_FORWARD = 0xA7;
public const ushort VK_BROWSER_REFRESH = 0xA8;
public const ushort VK_BROWSER_STOP = 0xA9;
public const ushort VK_BROWSER_SEARCH = 0xAA;
public const ushort VK_BROWSER_FAVORITES = 0xAB;
public const ushort VK_BROWSER_HOME = 0xAC;

(有趣的是,考虑到VK_ *是1字节0-255的值,并且人们已经将它们设为uint,VK常数有多少错误的定义在浮动着呢?)。

看起来与const略有不同。我认为我们要使用的功能是SendInput(但我没有尝试过),因为它是一个虚拟键。

[DllImport("User32.dll")]
private static extern uint SendInput(uint numberOfInputs, [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] KEYBOARD_INPUT[] input, int structSize);

有关参数的说明:

参数

  • nInputs-pInputs数组中的结构数。
  • pInputs-指向INPUT结构数组的指针。每个结构代表一个要插入键盘或者鼠标输入流的事件。
  • cbSize-指定INPUT结构的大小(以字节为单位)。如果cbSize不是INPUT结构的大小,则该函数将失败。

这需要一个KEYBOARD_INPUT类型:

[StructLayout(LayoutKind.Sequential)] 
public struct KEYBOARD_INPUT
{ 
    public uint type; 
    public ushort vk; 
    public ushort scanCode; 
    public uint flags; 
    public uint time; 
    public uint extrainfo; 
    public uint padding1; 
    public uint padding2; 
}

最后是一个样本,我还没有测试它是否可行:

/*
typedef struct tagKEYBDINPUT {
    WORD wVk;
    WORD wScan;
    DWORD dwFlags;
    DWORD time;
    ULONG_PTR dwExtraInfo;
} KEYBDINPUT, *PKEYBDINPUT;
*/
public static void sendKey(int scanCode, bool press)
{
        KEYBOARD_INPUT[] input = new KEYBOARD_INPUT[1];
        input[0] = new KEYBOARD_INPUT();
        input[0].type = INPUT_KEYBOARD;
        input[0].vk = VK_BROWSER_BACK;

    uint result = SendInput(1, input, Marshal.SizeOf(input[0]));
}

另外,我们还需要使用SetForegroundWindow将Chrome窗口聚焦