CefSharp无法打开特定应用程序链接问题求助
实现WinForm+CefSharp浏览器打开外部应用(如Roblox)
你当前的CefSharp浏览器默认不会处理roblox://这类自定义协议链接,要实现点击这类链接启动本地应用,需要拦截浏览器的请求并手动处理,具体步骤如下:
1. 自定义请求处理器(拦截自定义协议)
创建一个继承自IRequestHandler的类,用来拦截浏览器请求,判断是否是需要跳转的自定义协议:
using CefSharp; using System.Diagnostics; public class CustomRequestHandler : IRequestHandler { // 可扩展需要支持的自定义协议前缀,比如Roblox的roblox://、Steam的steam://等 private readonly List<string> _customProtocols = new List<string> { "roblox://", "steam://" }; public bool OnBeforeBrowse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool isRedirect) { var url = request.Url; // 判断当前请求URL是否属于自定义协议 if (_customProtocols.Any(protocol => url.StartsWith(protocol, StringComparison.OrdinalIgnoreCase))) { try { // 启动外部应用,必须设置UseShellExecute=true让系统处理协议 Process.Start(new ProcessStartInfo(url) { UseShellExecute = true }); } catch (Exception ex) { // 处理启动失败的情况,比如提示用户未安装对应应用 MessageBox.Show($"无法启动应用:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } // 返回true取消浏览器的导航操作 return true; } // 返回false让浏览器正常处理请求 return false; } // 以下为IRequestHandler接口的默认实现,直接返回默认值即可 public bool OnOpenUrlFromTab(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture) => false; public void OnRenderProcessTerminated(IWebBrowser chromiumWebBrowser, IBrowser browser, CefTerminationStatus status) { } public bool OnCertificateError(IWebBrowser chromiumWebBrowser, IBrowser browser, CefErrorCode errorCode, string requestUrl, ISslInfo sslInfo, IRequestCallback callback) { callback.Dispose(); return false; } public void OnPluginCrashed(IWebBrowser chromiumWebBrowser, IBrowser browser, string pluginPath) { } public CefReturnValue OnBeforeResourceLoad(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback) { callback.Dispose(); return CefReturnValue.Continue; } public bool GetAuthCredentials(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback) { callback.Dispose(); return false; } public bool OnQuotaRequest(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, long newSize, IRequestCallback callback) { callback.Dispose(); return false; } public void OnProtocolExecution(IWebBrowser chromiumWebBrowser, IBrowser browser, string url, out bool allowExecution) { allowExecution = false; } public void OnRenderViewReady(IWebBrowser chromiumWebBrowser, IBrowser browser) { } public void OnResourceRedirect(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response, ref string newUrl) { } public bool OnResourceResponse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response) => false; public IResponseFilter GetResourceResponseFilter(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response) => null; public void OnResourceLoadComplete(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response, UrlRequestStatus status, long receivedContentLength) { } public void OnDownloadUpdated(IWebBrowser chromiumWebBrowser, IBrowser browser, DownloadItem downloadItem, IDownloadItemCallback callback) { } public void OnDownloadCompleted(IWebBrowser chromiumWebBrowser, IBrowser browser, DownloadItem downloadItem, IDownloadItemCallback callback) { } public bool OnProtocolDialog(IWebBrowser chromiumWebBrowser, IBrowser browser, string url, string title, string message, bool isAlert, IJsDialogCallback callback) { callback.Dispose(); return false; } public bool OnBeforeUnloadDialog(IWebBrowser chromiumWebBrowser, IBrowser browser, string messageText, bool isReload, IJsDialogCallback callback) { callback.Dispose(); return false; } public void OnResetDialogState(IWebBrowser chromiumWebBrowser, IBrowser browser) { } public void OnDialogClosed(IWebBrowser chromiumWebBrowser, IBrowser browser) { } }
2. 给浏览器绑定自定义处理器
在FrmMain_Load方法中,初始化ChromiumWebBrowser后添加设置代码:
private void FrmMain_Load(object sender, EventArgs e) { browser = new ChromiumWebBrowser(txtUrl.Text); browser.Dock = DockStyle.Fill; // 绑定自定义请求处理器 browser.RequestHandler = new CustomRequestHandler(); this.pContainer.Controls.Add(browser); browser.TitleChanged += Browser_TitleChanged; }
3. 注意事项
- 确保目标应用已安装,且系统已注册对应自定义协议(比如Roblox安装后会自动注册
roblox://) - 可根据需求扩展
_customProtocols列表,添加更多需要支持的协议
完整修改后的代码
using CefSharp; using CefSharp.WinForms; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Net; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Diagnostics; namespace Lunarium { public partial class FrmMain : Form { public FrmMain() { InitializeComponent(); } private void txtUrl_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)13) browser.Load(txtUrl.Text); } ChromiumWebBrowser browser; private void btnGo_Click(object sender, EventArgs e) { browser.Load(txtUrl.Text); } private void FrmMain_Load(object sender, EventArgs e) { browser = new ChromiumWebBrowser(txtUrl.Text); browser.Dock = DockStyle.Fill; // 绑定自定义请求处理器 browser.RequestHandler = new CustomRequestHandler(); this.pContainer.Controls.Add(browser); browser.TitleChanged += Browser_TitleChanged; } public void favicon() { Uri url = new Uri("https://" + new Uri(browser.Address).Host + "/favicon.ico"); try { Icon img = new Icon(new System.IO.MemoryStream(new WebClient().DownloadData(url))); this.Icon = img; } catch (Exception) { this.Icon = Properties.Resources.tempIcon; // 替换tempIcon为你自己的.ico图标 } } private void Browser_TitleChanged(object sender, TitleChangedEventArgs e) { this.Invoke(new MethodInvoker(() => { Text = e.Title; favicon(); })); } } public class CustomRequestHandler : IRequestHandler { // 支持的自定义协议列表 private readonly List<string> _customProtocols = new List<string> { "roblox://", "steam://" }; public bool OnBeforeBrowse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool isRedirect) { var url = request.Url; // 判断是否为自定义协议 if (_customProtocols.Any(protocol => url.StartsWith(protocol, StringComparison.OrdinalIgnoreCase))) { try { // 启动外部应用 Process.Start(new ProcessStartInfo(url) { UseShellExecute = true }); } catch (Exception ex) { MessageBox.Show($"无法启动应用:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } // 取消浏览器导航 return true; } // 正常处理请求 return false; } // 以下为接口默认实现 public bool OnOpenUrlFromTab(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture) => false; public void OnRenderProcessTerminated(IWebBrowser chromiumWebBrowser, IBrowser browser, CefTerminationStatus status) { } public bool OnCertificateError(IWebBrowser chromiumWebBrowser, IBrowser browser, CefErrorCode errorCode, string requestUrl, ISslInfo sslInfo, IRequestCallback callback) { callback.Dispose(); return false; } public void OnPluginCrashed(IWebBrowser chromiumWebBrowser, IBrowser browser, string pluginPath) { } public CefReturnValue OnBeforeResourceLoad(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback) { callback.Dispose(); return CefReturnValue.Continue; } public bool GetAuthCredentials(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback) { callback.Dispose(); return false; } public bool OnQuotaRequest(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, long newSize, IRequestCallback callback) { callback.Dispose(); return false; } public void OnProtocolExecution(IWebBrowser chromiumWebBrowser, IBrowser browser, string url, out bool allowExecution) { allowExecution = false; } public void OnRenderViewReady(IWebBrowser chromiumWebBrowser, IBrowser browser) { } public void OnResourceRedirect(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response, ref string newUrl) { } public bool OnResourceResponse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response) => false; public IResponseFilter GetResourceResponseFilter(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response) => null; public void OnResourceLoadComplete(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response, UrlRequestStatus status, long receivedContentLength) { } public void OnDownloadUpdated(IWebBrowser chromiumWebBrowser, IBrowser browser, DownloadItem downloadItem, IDownloadItemCallback callback) { } public void OnDownloadCompleted(IWebBrowser chromiumWebBrowser, IBrowser browser, DownloadItem downloadItem, IDownloadItemCallback callback) { } public bool OnProtocolDialog(IWebBrowser chromiumWebBrowser, IBrowser browser, string url, string title, string message, bool isAlert, IJsDialogCallback callback) { callback.Dispose(); return false; } public bool OnBeforeUnloadDialog(IWebBrowser chromiumWebBrowser, IBrowser browser, string messageText, bool isReload, IJsDialogCallback callback) { callback.Dispose(); return false; } public void OnResetDialogState(IWebBrowser chromiumWebBrowser, IBrowser browser) { } public void OnDialogClosed(IWebBrowser chromiumWebBrowser, IBrowser browser) { } } }
内容的提问来源于stack exchange,提问作者vvl1m
相关产品推荐
相关产品推荐

