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

我一直在寻找,我还没有找到我将如何从C#中做到这一点。

我想要这样做,所以我可以告诉谷歌Chrome从我的C#应用​​程序前进后退打开新标签关闭标签打开新窗口关闭窗口

我使用WinAmp做了类似的事情

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

还有一些其他人。 但我不知道要发送什么消息或者如何找到传递给它的窗口,或者其他什么。

那么有人可以告诉我如何从C#向Chrome发送这6个命令吗? 谢谢

编辑:好的,我正在投票,所以也许我不够清楚,或者人们假设我没有试图自己解决这个问题。

首先,我对整个DllImport的东西不太满意。 我还在学习它是如何运作的。

几年前我在winamp找到了如何做同样的想法,我正在查看我的代码。 我做到了所以我可以跳过一首歌,回去,播放,暂停,并停止从我的C#代码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_windowNameWM_COMMAND

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

从http://dev.chromium.org/developers开始您的研究


编辑 :向窗口发送消息只是工作的一半。 窗口必须响应该消息并相应地采取行动。 如果该窗口不知道消息或根本不关心,则您无法通过发送窗口消息来控制它。

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

您在第一步中需要做的是找出Chromium是否支持某种远程控制以及这些机制是什么。

您可以使用Visual Studio的Spy ++轻松获取窗口名称,然后按CTRL + F,然后找到chrome。 我试过了,得到了

用于窗口的“Chrome_VistaFrame”。 网页的实际窗口是“Chrome_RenderWidgetHostHWND”。

就WM_COMMAND而言 – 你需要进行实验。 你显然想要发送按钮点击(我头顶的WM_MOUSEDOWN)。 由于后退,前进按钮不是他们自己的窗口,你需要弄清楚如何通过在某个x,y位置模拟鼠标点击来做到这一点,以便Chrome知道你正在做什么。 或者您可以发送等效于后退/前进的键盘快捷键,依此类推。

我刚才写的一个例子是trillian和winamp: 通过c#和winapi向windows发送消息

还有一些工具可以使用脚本语言将这种东西宏观化 – autoit是我用过的: autoit.com

好的,这就是我到目前为止所得到的…我知道我需要做什么,但这只是现在做的事情……

这是Spy ++的窗口,我锁定了Chrome_RenderWidgetHostHWND,然后单击键盘上的Back按钮。 这是我得到的: 替代文字

所以这是我的假设,我现在一直在玩这个,我只是无法弄清楚价值观

 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。 我不知道我是否做得对。 我在搜索谷歌获取WM_KEYDOWN值后得到的前两个值,有人使用&H100和&H101作为两个值。 我已经尝试了其他一些我见过的随机想法。 我只是想不出来。

哦,这是SendMessage方法

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

这是互操作常量的一个很好的站点:

的PInvoke

查找值的另一种方法是使用C#作为语言搜索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常量定义正在浮动,考虑到VK_ *是1字节0-255的值,而人们已经将它们作为特征)。

看起来与你的consts略有不同。 我认为你所追求的function是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窗口