C#实现Edge窗口复用:在现有标签页跳转而非新建标签
问题描述
运行以下C#代码时,首次输入URL会打开Edge访问对应网站,但再次输入不同URL时,Edge会新建标签页打开。希望复用已打开的Edge窗口,在现有标签页直接跳转新URL,而非新建标签页。
原代码:
while (true) { Console.WriteLine("Enter a URL"); string strURL = Console.ReadLine(); Process pWeb = new Process(); pWeb.StartInfo.UseShellExecute = true; pWeb.StartInfo.FileName = "microsoft-edge:"+ strURL; pWeb.Start(); }
可行实现方案
方案一:通过Windows API操控Edge窗口
借助Windows API定位Edge主窗口与地址栏控件,模拟输入URL并触发跳转,无需额外配置。
实现步骤
- 引入必要命名空间:
using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Text;
- 定义Windows API函数:
[DllImport("user32.dll", SetLastError = true)] private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll", SetLastError = true)] private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern bool SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, string lParam); [DllImport("user32.dll")] private static extern bool SetForegroundWindow(IntPtr hWnd); private const uint WM_SETTEXT = 0x000C; private const uint WM_KEYDOWN = 0x0100; private const int VK_RETURN = 0x0D;
- 编写跳转逻辑:
static void NavigateInExistingEdge(string url) { // 查找Edge主窗口(类名随Edge版本可能变化,可通过Spy++工具获取最新值) IntPtr edgeWindow = FindWindow("Chrome_WidgetWin_1", null); if (edgeWindow == IntPtr.Zero) { // 未找到Edge窗口时,新建窗口打开URL Process.Start(new ProcessStartInfo("microsoft-edge:" + url) { UseShellExecute = true }); return; } // 定位Edge地址栏控件 IntPtr addressBar = FindWindowEx(edgeWindow, IntPtr.Zero, "Chrome_OmniboxView", null); if (addressBar == IntPtr.Zero) { // 找不到地址栏时,fallback到新建窗口 Process.Start(new ProcessStartInfo("microsoft-edge:" + url) { UseShellExecute = true }); return; } // 激活窗口、设置地址栏URL、模拟回车跳转 SetForegroundWindow(edgeWindow); SendMessage(addressBar, WM_SETTEXT, IntPtr.Zero, url); SendMessage(addressBar, WM_KEYDOWN, (IntPtr)VK_RETURN, IntPtr.Zero); }
- 修改原循环调用该方法:
while (true) { Console.WriteLine("Enter a URL"); string strURL = Console.ReadLine(); NavigateInExistingEdge(strURL); }
方案二:使用Edge DevTools协议控制已打开实例
利用Edge支持的DevTools协议,通过WebSocket连接已打开的Edge实例,发送命令让现有标签页跳转。
实现步骤
- 先启动带远程调试端口的Edge实例(可手动启动或代码中检测启动):
start msedge.exe --remote-debugging-port=9222
- 编写C#控制逻辑:
using System; using System.Collections.Generic; using System.Net.Http; using System.Net.WebSockets; using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using System.Diagnostics; static async Task NavigateWithDevTools(string url) { using var httpClient = new HttpClient(); // 获取已打开页面的调试信息 var response = await httpClient.GetAsync("http://localhost:9222/json"); if (!response.IsSuccessStatusCode) { // 无调试端口的Edge实例,新建窗口打开URL Process.Start(new ProcessStartInfo("microsoft-edge:" + url) { UseShellExecute = true }); return; } var pages = JsonSerializer.Deserialize<List<JsonElement>>(await response.Content.ReadAsStringAsync()); if (pages == null || pages.Count == 0) { Process.Start(new ProcessStartInfo("microsoft-edge:" + url) { UseShellExecute = true }); return; } // 获取第一个页面的WebSocket调试地址 var webSocketDebuggerUrl = pages[0].GetProperty("webSocketDebuggerUrl").GetString(); if (string.IsNullOrEmpty(webSocketDebuggerUrl)) { Process.Start(new ProcessStartInfo("microsoft-edge:" + url) { UseShellExecute = true }); return; } // 通过WebSocket发送跳转命令 using var ws = new ClientWebSocket(); await ws.ConnectAsync(new Uri(webSocketDebuggerUrl), CancellationToken.None); var command = new { id = 1, method = "Page.navigate", @params = new { url = url } }; var jsonCommand = JsonSerializer.Serialize(command); var buffer = Encoding.UTF8.GetBytes(jsonCommand); await ws.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, CancellationToken.None); await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "操作完成", CancellationToken.None); }
- 修改原循环调用该异步方法:
while (true) { Console.WriteLine("Enter a URL"); string strURL = Console.ReadLine(); NavigateWithDevTools(strURL).Wait(); }
内容的提问来源于stack exchange,提问作者Pryach
相关产品推荐
相关产品推荐

