1、日常工作中,登录内部系统往往需要输入用户名、密码、短信验证码,但是如果30分钟不操作,会自动退出,为避免频繁登录,可以使用c#写一个自动刷新指定网址页面的程序。找来找去,这个最好用
using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using System.Net.WebSockets; using Newtonsoft.Json; ///用这个命令行打开谷歌,然后在进入自己的地址 "C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222 --user-data-dir="C:\temp\chrome_debug" namespace shuxin { public class TabInfo { [JsonProperty("id")] public string Id { get; set; } [JsonProperty("url")] public string Url { get; set; } [JsonProperty("webSocketDebuggerUrl")] public string WebSocketUrl { get; set; } [JsonProperty("title")] public string Title { get; set; } } class Program { private const string TARGET_URL = "sd4a.com"; // 支持部分匹配,如包含 baidu.com private const int REFRESH_INTERVAL_MINUTES = 19; private static readonly HttpClient httpClient = new(); static async Task Main(string[] args) { Console.WriteLine("Auto-refresh for browser tabs started..."); Console.WriteLine($"Target URL pattern: {TARGET_URL}"); Console.WriteLine($"Refresh every {REFRESH_INTERVAL_MINUTES} minutes.\n"); while (true) { try { await RefreshTargetTabAsync(); } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); } await Task.Delay(TimeSpan.FromMinutes(REFRESH_INTERVAL_MINUTES)); } } static async Task RefreshTargetTabAsync() { // Step 1: 获取所有标签页 var tabsJson = await httpClient.GetStringAsync("http://localhost:9222/json"); var tabs = JsonConvert.DeserializeObject<List<TabInfo>>(tabsJson); // Step 2: 查找目标 URL(支持子路径) var targetTab = tabs.FirstOrDefault(t => t.Url != null && t.Url.Contains(TARGET_URL, StringComparison.OrdinalIgnoreCase)); if (targetTab == null) { Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] Target tab not found."); return; } Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] Found tab: {targetTab.Title} - {targetTab.Url}"); // Step 3: 通过 WebSocket 发送 Page.reload 命令 await ReloadPageViaCDP(targetTab.WebSocketUrl); Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] Page refreshed successfully."); } static async Task ReloadPageViaCDP(string webSocketUrl) { using var ws = new ClientWebSocket(); await ws.ConnectAsync(new Uri(webSocketUrl), CancellationToken.None); // 构造 CDP Page.reload 命令 var command = new { id = 1, method = "Page.reload", @params = new { } }; string json = JsonConvert.SerializeObject(command); var buffer = Encoding.UTF8.GetBytes(json); await ws.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None); // 可选:读取响应(非必须) var receiveBuffer = new byte[1024]; await ws.ReceiveAsync(receiveBuffer, CancellationToken.None); await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None); } } }2、如果想增加日志,可以这样写:
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Net.WebSockets; using Newtonsoft.Json; /// 启动Chrome命令:"C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222 --user-data-dir="C:\temp\chrome_debug" namespace shuxin { public class TabInfo { [JsonProperty("id")] public string Id { get; set; } [JsonProperty("url")] public string Url { get; set; } [JsonProperty("webSocketDebuggerUrl")] public string WebSocketUrl { get; set; } [JsonProperty("title")] public string Title { get; set; } } class Program { private const string TARGET_URL = "sd4a.com"; private const int REFRESH_INTERVAL_MINUTES = 19; private static readonly HttpClient httpClient = new(); private const string LogFilePath = @"c:\log.txt"; static async Task Main(string[] args) { // 初始化信息 LogAndPrint("Auto-refresh for browser tabs started..."); LogAndPrint($"Target URL pattern: {TARGET_URL}"); LogAndPrint($"Refresh every {REFRESH_INTERVAL_MINUTES} minutes.\n"); while (true) { try { await RefreshTargetTabAsync(); } catch (Exception ex) { LogAndPrint($"Error: {ex.Message}"); } await Task.Delay(TimeSpan.FromMinutes(REFRESH_INTERVAL_MINUTES)); } } static async Task RefreshTargetTabAsync() { // 获取所有标签页 var tabsJson = await httpClient.GetStringAsync("http://localhost:9222/json"); var tabs = JsonConvert.DeserializeObject<List<TabInfo>>(tabsJson); // 查找目标标签页 var targetTab = tabs.FirstOrDefault(t => t.Url != null && t.Url.Contains(TARGET_URL, StringComparison.OrdinalIgnoreCase)); if (targetTab == null) { LogAndPrint($"[{DateTime.Now:HH:mm:ss}] Target tab not found."); return; } LogAndPrint($"[{DateTime.Now:HH:mm:ss}] Found tab: {targetTab.Title} - {targetTab.Url}"); // 刷新页面 await ReloadPageViaCDP(targetTab.WebSocketUrl); LogAndPrint($"[{DateTime.Now:HH:mm:ss}] Page refreshed successfully."); } static async Task ReloadPageViaCDP(string webSocketUrl) { using var ws = new ClientWebSocket(); await ws.ConnectAsync(new Uri(webSocketUrl), CancellationToken.None); // 构造刷新命令 var command = new { id = 1, method = "Page.reload", @params = new { } }; var buffer = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(command)); await ws.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None); // 读取响应(可选) var receiveBuffer = new byte[1024]; await ws.ReceiveAsync(receiveBuffer, CancellationToken.None); await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None); } /// <summary> /// 统一处理:控制台输出 + 写入日志 /// </summary> private static void LogAndPrint(string message) { Console.WriteLine(message); try { // 追加写入日志,带完整时间戳 var logContent = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {message}{Environment.NewLine}"; File.AppendAllText(LogFilePath, logContent, Encoding.UTF8); } catch (Exception ex) { // 日志写入失败时仅提示,不影响主程序 Console.WriteLine($"Failed to write log: {ex.Message}"); } } } }3、可以通过 VBS 脚本调用 exe 程序并不弹出控制台窗口
创建一个.vbs文件,比如run_hidden.vbs,内容如下:然后双击执行即可。也可以设置成开机启动
' run_hidden.vbs ' 注意:替换为你实际的exe文件路径 Set WshShell = CreateObject("WScript.Shell") ' 写法1:三重双引号包裹路径(推荐,处理路径含空格的情况) WshShell.Run """C:\your\actual\path\shuxin.exe""", 0, False ' 写法2:如果路径没有空格,也可以直接写(不推荐,兼容性差) ' WshShell.Run "C:\your\actual\path\shuxin.exe", 0, False ' 释放对象(可选,VBS会自动回收,但显式释放更规范) Set WshShell = Nothing代码解析:
这是一个基于 Chrome DevTools Protocol (CDP) 实现自动刷新特定浏览器标签页的 C# 程序。让我详细分析其工作原理和用途:
主要功能
程序会定期(每19分钟)检查并刷新包含特定URL(如baidu.com)的Chrome标签页,防止网页因长时间不活动而过期或超时。
代码结构分析
1. 核心组件
TabInfo类:定义了浏览器标签页的数据结构
Main方法:程序主循环,定时执行刷新任务
RefreshTargetTabAsync方法:查找并刷新目标标签页
ReloadPageViaCDP方法:通过WebSocket发送刷新命令
2. 工作流程
启动要求:需要先用特定命令启动Chrome,启用远程调试
获取标签页列表:通过HTTP请求
http://localhost:9222/json获取所有标签页信息查找目标标签页:匹配包含
TARGET_URL的URL发送刷新命令:通过WebSocket连接发送
Page.reloadCDP命令循环执行:每19分钟重复上述过程
3. 关键技术点
Chrome远程调试:
bash
复制
下载
# 使用9222端口开启调试模式 chrome.exe --remote-debugging-port=9222 --user-data-dir="C:\temp\chrome_debug"
CDP通信:
通过WebSocket连接到
webSocketDebuggerUrl发送JSON格式的CDP命令
Page.reload命令会触发页面刷新
4. 潜在用途
保持登录状态:防止需要登录的网页会话过期
数据监控:保持监控页面实时更新
避免超时:防止长时间不操作导致的连接断开
5. 注意事项和潜在问题
安全问题:
csharp
复制
下载
// 远程调试端口暴露了浏览器控制权限 // 建议添加访问控制或身份验证
资源管理:
csharp
复制
下载
// HttpClient 是静态的,但未正确配置重试和超时 // 建议添加适当的异常处理和资源清理 private static readonly HttpClient httpClient = new();
改进建议:
错误处理增强:当前异常处理较简单,可能需要对特定异常做不同处理
配置灵活性:可将目标URL和间隔时间改为可配置参数
多个标签页支持:目前只处理第一个匹配的标签页
连接状态检查:添加WebSocket连接状态的验证
6. 依赖项
Newtonsoft.Json (JSON.NET) - 用于JSON序列化
System.Net.WebSockets - WebSocket通信
System.Text.Json - .NET内置JSON支持(虽然代码中使用了Newtonsoft)
这个程序实际上是一个简单的"防休眠"工具,通过模拟用户活动来保持网页的活跃状态。