前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >chrome打开本地链接

chrome打开本地链接

作者头像
meteoric
发布2021-07-13 11:28:50
2.7K0
发布2021-07-13 11:28:50
举报
文章被收录于专栏:游戏杂谈

同事之前给我提了一个需求,想实现在网页里点击链接地址后直接打开指定的地址(路径是内网共享的目录,file://share.xx.com\x\x)。

浏览器因为有安全的限制,是无法访问 web 页面时,可以打开本地PC的目录。当你点击带有本地文件链接的超链接(file://),控制台上会报错:Not allowed to load local resource:

最开始在网上搜索了一下,有二个插件看上去似乎可以满足需求。

(1)Enable local file links

(2)Local Explore – File Manager on web browser

插件启用后,类似下面这种效果(跟他们想要的效果还是有区别)。

Local Explore,自定义了协议,然后呼起本地 exe,再打开资源管理器,是期望的效果。但是它最大的问题是:如果路径有中文,就乱码,无法正常使用。

它的原理倒是比较简单,修改超链接为 LocalExplore:file://xxxx,如果注册表添加了对该协议的监听,当浏览器访问该协议时,会触发指定的 exe 并传入相关的参数。

我要解决乱码问题,先处理浏览器扩展插件,再就是替换 exe 的实现就可以了。

(1)替换插件,解决因插件 escape 导致的乱码问题(注:不太能理解作者为啥要用 JSON.parse 处理一下)

对比了二个插件的实现,我准备在 Local Explore 插件的基础上进行精简。只留下必要的代码,然后通过开发者模式,加载进 chrome 的扩展程序里。

background.js 里的代码被我删光了,content.js 只进行一个操作,遍历文档所有超链接,然后修改其 href 属性。

代码语言:javascript
复制
$(document).ready(function() {
    var optOpenFolders = "true";
    var protocolStr = "LocalExplorer:";

    // var clickEventHandler = function(evt) {
    //     evt.preventDefault();

    //     chrome.extension.sendMessage({
    //         cmd: "click",
    //         data: this.href
    //     });
    // };

    $("a").each(function(i, e) {
        if (e.href !== undefined && e.href !== null && e.href !== "") {
            if (!e.href.match(/^file:\/\//)) {
                return;
            }

            if (e.href.match(/^file:\/\//)) {
                if (window.debug) console.log(e.href);

                e.href = protocolStr + e.href;
                if (e.target) e.target = "_self";
            }
            // $(e).off("click", clickEventHandler);
            // $(e).on("click", clickEventHandler);
        }
    });
});

manifest.json 也做了一点修改

代码语言:javascript
复制
{
    "update_url": "https://clients2.google.com/service/update2/crx",
    "version": "2021.7.6",
    "short_name": "Meteoric Local Explorer",
    "name": "Meteoric Local Explorer - File Manager on web browser",
    "description": "__MSG_extDescription__",
    "default_locale": "zh_CN",
    "icons": {
        "128": "icon/icon128.png",
        "32": "icon/icon32.png",
        "16": "icon/icon16.png"
    },
    "browser_action": {
        "default_icon": "icon/icon32.png",
        "default_title": "Meteoric Local Explorer"
    },
    "content_scripts": [{
        "matches": ["<all_urls>"],
        "js": ["jquery.js", "content.js"],
        "all_frames": false,
        "run_at": "document_start"
    }],
    "background": {
        "scripts": ["background.js"]
    },
    "options_page": "", // options.html
    "permissions": [
        "http://*/*",
        "https://*/*",
        "tabs"
    ],
    "manifest_version": 2
}

(2)替换 exe,支持打开中文链接

这里我直接用 C# 简单写了一个 exe,实现了基本的功能。为了精简 Release 版本生成的内容,我对几处设置作了简单的调整

(1)项目属性里面的,生成 –> 高级 –> 高级生成设置,输出 –> 调试信息,选择无,避免生成 pdb 文件;

(2)App.config 的文件属性,修改‘生成操作’为‘嵌入的资源’,避免生成 *.exe.config 文件;

这样生成的 Release 目录就是比较干净的了,只有一个叫 LocalExplorer.exe 的文件。替换掉安装在 C 盘里面的 exe(默认路径在:"C:\Program Files (x86)\LocalExplorer\LocalExplorer.exe" )

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace FriendTimesLocalExplorer
{
    class Program
    {
        static void Main(string[] args)
        {
            /*
            for (int i = 0, len = args.Length; i < len; i++)
            {
                // Get first param

            }
            */
            if (args.Length < 1)
            {
                MessageBox.Show("File Path is Empty", "System Tips", MessageBoxButtons.OK, MessageBoxIcon.Information);

                return;
            }

            string filePath = args[0];

            // escape
            filePath = Uri.UnescapeDataString(filePath).Replace("/", "\\");

            // delete protocol
            filePath = filePath.Replace("localexplorer:", "");
            filePath = filePath.Replace("file:", "");
                        // get right file path
            filePath = filePath.Substring(filePath.IndexOf('\\'));
            //Console.WriteLine(filePath);

            if (Directory.Exists(filePath) || File.Exists(filePath))
            {
                Process p = new Process();
                p.StartInfo.FileName = "explorer.exe";
                p.StartInfo.CreateNoWindow = true;
                p.StartInfo.UseShellExecute = false;

                // hidden
                p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

                p.EnableRaisingEvents = true;
                p.StartInfo.RedirectStandardError = true;

                if (File.Exists(filePath))
                {
                    p.StartInfo.Arguments = @"/select," + filePath;
                }
                else
                {
                    p.StartInfo.Arguments = filePath;
                }
                
                try
                {
                    p.Start();

                    // explorer.exe 异常结束时,会导致启动不断重启
                    p.WaitForExit();

                    if (p != null)
                    {
                        p.Close();
                        p.Dispose();
                        p = null;
                    }
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.ToString(), "System error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }                
            }
            else
            {
                MessageBox.Show("Not Found Path : \n" + filePath, "System error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }            
        }
    }
}

浏览器插件 和 exe 都进行替换后,就能实现点击链接调用本地exe,再通过 exe 打开指定的目录了。迅雷、QQ或其它客户端软件,基本上也是使用类似的原理,实现点击网页链接呼起本地的客户端应用程序(应用程序想干嘛就自己实现)

注意点击时,会弹出一个提示。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-07-06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档