針對clickonce發佈後的程序,優化處理省略彈出層

 

 

 

 

 

 

 

 

 

 谷歌插件封裝:

1. VSCode新建文件目錄

2. 創建manifest.json文件

{
  "version": "1.0", //插件版本
  "manifest_version": 2, //版本號,由google指定爲2 ,必須是2
  "name": "插件名稱", //插件名稱
  "description": "插件描述", //插件描述
  "icons": { //插件圖標
    "128": "icons/header_128_128.png",
    "64": "icons/header_64_64.png",
    "48": "icons/header_48_48.png",
    "32": "icons/header_32_32.png",
    "16": "icons/header_16_16.png"
  },
  "background": {
    "persistent": true,
    "scripts": [ "background.js" ]
 },
  "permissions": [ "webRequest", "webRequestBlocking", "nativeMessaging", "http://*/*", "https://*/*" ],
  "update_url": "https://wwww.baidu.com",//插件更新地址
  "browser_action": {
    "default_icon": "icons/header_16_16.png", //插件圖標
    "default_popup": "index.html" //點擊圖標後彈出的html互動文件
  },
  "web_accessible_resources": [ "icons/header_16_16.png" ],
  "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'" //希望能在 Chrome 插件中使用 Vue 放開內容安全策略,纔可以使用evel,new Function等函數
}

3. 新增background.js

var nativeHostName = "客戶端APPName"; // 需要跟後端客戶端一致

// 根據配置文件連接到本地程序
var port = chrome.runtime.connectNative(nativeHostName); 
port.onDisconnect.addListener(() => {
  console.log(
    "連接到客戶端服務失敗: " + chrome.runtime.lastError.message
  );
  port = null;
});

// 點擊url地址鏈接後進行判斷,發現是打開clickonce的程序攜帶{clickonce:url}的參數發送到客戶端,客戶端會提前註冊到註冊表,找到註冊表的json文件,再調用json文件配置的客戶端地址
chrome.webRequest.onBeforeRequest.addListener(
  function (details) {
    if (details.url.indexOf(".application") != -1) {
      var el = document.createElement("a");
      el.href = details.url;
      if (el.pathname.match(/\.application$/)) {
        chrome.runtime.sendNativeMessage(nativeHostName, {
          clickonce: details.url,
        });
        return { redirectUrl: "javascript:void(0)" };
      }
    }
  },
  { urls: ["http://*/*", "https://*/*"] },
  ["blocking"]
);

// 下載啓動exe程序自動執行到註冊表,注意這裏的plugin.html,其實是一個插件下載頁面,進入後自動下載後端exe客戶端
chrome.runtime.onInstalled.addListener(function (details) {
  if (details.reason == "install" || details.reason == "update") {
    chrome.tabs.create({ url: chrome.extension.getURL("plugin.html") });
  }
});

4. 新增默認啓動頁面index.html

<html>
  <head>
    <title>Plugin</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <!--需要引用background後臺執行的js文件--> <script type="text/javascript" src="background.js"></script> </head> <body> <h3>插件初始化成功!</h3> </body> </html>

5. 新增plugin.html,

<html>
<head>
<title>Plugin</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<script type="text/javascript">
// 自動下載後端服務的插件
  window.onload = function() {
var anchorObj = document.body.children.namedItem('helper-download');
// {"clickonce":"http://域名/winform部署到iis的clickonce的app url地址"}
anchorObj.href = chrome.extension.getURL('/exe/c#封裝的註冊到註冊表地址的一個exe程序.exe');
var evt = document.createEvent("MouseEvents");
evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
var allowDefault = anchorObj.dispatchEvent(evt);
};
</script>
</head>
<body>
<h3>下載安裝插件!</h3>
</body>
</html>



6. c#封裝執行程序

internal static class Program
    {
        /// <summary>
        /// 應用程序的主入口點。
        /// </summary>
        [STAThread]
        static void Main()
        {
            string text = NativeClickOnce.OpenStandardStreamIn();
      
            if (!string.IsNullOrEmpty(text))
            {
                if (text.StartsWith("{\"clickonce\":\"") && NativeClickOnce.StartClickOnce(text))
                {
                    NativeClickOnce.OpenStandardStreamOut("{\"result\":\"OK\"");
                }
                return;
            }

            string[] commandLineArgs = Environment.GetCommandLineArgs();
            if (commandLineArgs.Length <= 1)
            {
                Install.Installer();
                return;
            }
            if (commandLineArgs[1].Equals("/Uninstall"))
            {
                Install.Uninstall();
                return;
            }
            Install.Installer();
        }
    }
 public class NativeClickOnce
    {
        public static bool StartClickOnce(string URI_Native)
        {
            string str = URI_Native.Substring("{\"clickonce\":\"".Length, URI_Native.Length - "{\"clickonce\":\"".Length - "\"}".Length);
            new Process
            {
                StartInfo = new ProcessStartInfo("PresentationHost.exe", "-LaunchApplication " + str)
            }.Start();
            return true;
        }

        public static string OpenStandardStreamIn()
        {
            Stream stream = Console.OpenStandardInput();
            byte[] array = new byte[4];
            stream.Read(array, 0, 4);
            int num = BitConverter.ToInt32(array, 0);
            string text = "";
            for (int i = 0; i < num; i++)
            {
                text += (char)stream.ReadByte();
            }
            return text;
        }

        public static void OpenStandardStreamOut(string stringData)
        {
            int length = stringData.Length;
            Stream stream = Console.OpenStandardOutput();
            stream.WriteByte((byte)(length & 255));
            stream.WriteByte((byte)(length >> 8 & 255));
            stream.WriteByte((byte)(length >> 16 & 255));
            stream.WriteByte((byte)(length >> 24 & 255));
            // 成功與否
            Console.Write(stringData);
        }
    }
 public class Install
    {
   private static string GooleExtID
= "這個是插件安裝後的ID,跟註冊後的json文件裏面的要一致"; private static string AppName = "要跟js寫一致";//跟js通信 ,必須字母小寫,否則會報錯 private static string InstallDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Menarva\\Plugin"); private static string jsonInstall = Path.Combine(Install.InstallDir, "plugin.json"); public static void Installer() { try { Directory.CreateDirectory(Install.InstallDir); string text = Path.Combine(Install.InstallDir, Assembly.GetExecutingAssembly().ManifestModule.ScopeName); File.Copy(Assembly.GetExecutingAssembly().Location, text, true); string[] value = new string[] { "{{", " \"name\": \"{0}\",", " \"description\": \"{1}\",", " \"path\": \"{2}\",", " \"type\": \"stdio\",", " \"allowed_origins\": [\"chrome-extension://{3}/\"]", "}}" }; string format = string.Join("\n", value); File.WriteAllText(Install.jsonInstall, string.Format(format, new object[] { AppName, "Plugin for Chrome", text.Replace("\\", "\\\\"), Install.GooleExtID })); Registry.SetValue($"HKEY_CURRENT_USER\\Software\\Google\\Chrome\\NativeMessagingHosts\\{AppName}", null, Install.jsonInstall); string keyName = "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + Assembly.GetExecutingAssembly().ManifestModule.ScopeName; Registry.SetValue(keyName, "Comments", "Plugin for Chrome"); Registry.SetValue(keyName, "DisplayName", "Plugin for Chrome"); Registry.SetValue(keyName, "DisplayIcon", text); Registry.SetValue(keyName, "Publisher", "Menarva Ltd"); Registry.SetValue(keyName, "NoModify", 1); Registry.SetValue(keyName, "NoRepair", 1); Registry.SetValue(keyName, "UninstallString", text + " /Uninstall"); MessageBox.Show("Plugin for Chrome successfully!"); } catch (Exception ex) { MessageBox.Show("Plugin Installer error:" + ex.Message); } } public static void Uninstall() { try { Registry.CurrentUser.DeleteSubKeyTree($"Software\\Google\\Chrome\\NativeMessagingHosts\\{AppName}"); Registry.CurrentUser.DeleteSubKeyTree("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + Assembly.GetExecutingAssembly().ManifestModule.ScopeName); File.Delete(Install.jsonInstall); MessageBox.Show("Plugin for Chrome\", \"The plugin was uninstalled successfully!"); ProcessStartInfo startInfo = new ProcessStartInfo { Arguments = string.Format("/C choice /C Y /N /D Y /T 3 & rd /S /Q \"{0}\"", Install.InstallDir), WindowStyle = ProcessWindowStyle.Hidden, CreateNoWindow = true, FileName = "cmd.exe" }; Process.Start(startInfo); } catch (Exception ex) { MessageBox.Show("Plugin Uninstall error:"+ex.Message); } } }

7. 打包成一個exe程序

7.1 安裝依賴包ILMerge

 7.2 自動生成的就是一個exe,如果依賴了多個dll,需要配置,百度參考ILMerge的其他文檔

7.3 將exe拖動到Vue的插件開發文件目錄裏面

 7.4 安裝瀏覽器插件,點擊加載已解壓的擴展程序,選擇當前Vs Code開發的項目目錄地址

 7.5 注意安裝後查看擴展程序ID是否跟C#程序的GooleExtID是否一致,必須要一致纔可以,否則會報錯,這裏程序會下載c#寫的exe程序,需要點擊註冊,註冊成功後即可使用

 7.6 也可以使用打包的方式進行,選擇項目目錄,進行打包,打包後會生成2個文件,一個*.crx文件,一個*.pem文件,*.crx文件可以直接拖動到瀏覽器進行安裝,注意安裝之前需要開啓開發者模式

 

7.7 *.crx安裝後會提示如下,以及ID不可控,這裏需要注意。暫時沒有找到解決辦法

 

7.8 然後就可以通過a標籤點擊跳轉到click once部署的winform、wpf程序進行直接打開exe程序

let herf = `${url}/APPClient/*****.application?攜帶參數傳遞到winfrom/wpf`;
window.open(herf, '_parent');
// _blank 、_self 、_parent、_top
<a href="clickOnce部署的APP地址/參數" target="_parent">打開xxx系統</a>

 7.9 安裝後可以查看註冊表地址

地址:計算機\HKEY_CURRENT_USER\SOFTWARE\Google\Chrome\NativeMessagingHosts\你的AppName

點擊右側默認的屬性,會顯示存儲的json位置

7.10 打開json位置如下:

地址:C:\Users\29561\AppData\Local\Menarva

該位置下面有你的exe程序,一個json文件

7.11 json文件內容如下

{
  "name": "你的AppName",
  "description": "Plugin for Chrome",
  "path": "C:\\Users\\29561\\AppData\\Local\\Menarva\\Plugin\\xxxPlugin.exe",
  "type": "stdio",
  "allowed_origins": ["chrome-extension://你的插件ID,必須要跟瀏覽器安裝後看到的擴展程序的ID一致/"]
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章