草庐IT

c# - 在不重启应用程序的情况下处理 URL 协议(protocol)

coder 2024-05-31 原文

我的问题都是关于 URL 协议(protocol)的。

我已经注册了一个名为 mcm 的 URL 协议(protocol),但我注意到每次我从任何网络浏览器运行它时,都会创建一个新的应用程序实例。有没有办法在已经运行的实例中处理协议(protocol)请求?

例如,当 uTorrent 使用 torrent 协议(protocol)时,它会立即处理请求,而无需再次运行该应用程序。我真的找不到任何有趣的东西,所以我在这里问...

这是我用来注册协议(protocol)的代码:

private static void RegisterUrlProtocol()
{
    UnregisterUrlProtocol();

    RegistryKey rKey = Registry.ClassesRoot.OpenSubKey(UrlProtocol, true);
    if (rKey == null)
    {
        rKey = Registry.ClassesRoot.CreateSubKey(UrlProtocol);
        rKey.SetValue("", "URL: MazCraft Protocol");
        rKey.SetValue("URL Protocol", "");

        rKey = rKey.CreateSubKey(@"shell\open\command");
        rKey.SetValue("", "\"" + Application.ExecutablePath + "\" %1");
    }

    if (rKey != null)
    {
        rKey.Close();
    }
}

读取参数的代码:

private static bool CheckForProtocolMessage()
{
    string[] arguments = Environment.GetCommandLineArgs();

    if (arguments.Length > 1)
    {
        string[] args = arguments[1].Split(':');
        args[1] = args[1].Replace("//", "");

        if (args[0].Trim().ToUpper() == "MCM" && args.Length > 1)
        {
            string[] actionDetail = args[1].Split('=');

            if (actionDetail[0].Trim().ToUpper() == "INSTALL" && actionDetail.Length > 1)
            {
                string id = actionDetail[1].Trim().Replace("/", "");

                Funcs.ID = id;

                return true;
            }
        }
    }

    return false;
}

任何帮助将不胜感激:) 问候。

最佳答案

您可以使用 Mutex 来检测已在运行的应用程序实例,并通过命名管道将数据发送到现有实例。

希望以下示例对您有所帮助。 您可以将命名管道对象(在本例中为字符串)换成您喜欢的任何可序列化对象。

命名管道.cs

    namespace SingleInstanceNP
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO.Pipes;
    using System.Runtime.Serialization.Formatters.Binary;
    using System.Threading;
    using System.IO;


    public class NamedPipe<T> : IDisposable
    {
        #region Attribute and Properties

        private string _pipeName;
        private NamedPipeServerStream _pipeServer;
        private bool _disposed;
        private Thread _thread;
        private bool _started;

        #endregion

        #region Constructors

        public NamedPipe(NameTypes pipeType)
        {
            _disposed = false;
            _started = false;
            _pipeName = pipeType.ToString();
            _thread = new Thread(Main);
            _thread.SetApartmentState(ApartmentState.STA);
            _thread.Name = "NamePipe: " + pipeType.ToString() + " Thread";
            _thread.IsBackground = true;
        }

        ~NamedPipe()
        {
            Dispose();
        }

        #endregion

        #region Events

        public delegate void Request(T t);
        public event Request OnRequest;

        #endregion

        #region Public Methods

        public static void Send(NameTypes pipeType, T t)
        {
            using (var npc = new NamedPipeClientStream(".", pipeType.ToString(), PipeDirection.Out))
            {
                var bf = new BinaryFormatter();
                npc.Connect();
                bf.Serialize(npc, t);
            }
        }

        public static T Recieve(NameTypes pipeType)
        {
            using (var nps = new NamedPipeServerStream(pipeType.ToString(), PipeDirection.In))
            {
                return Recieve(nps);
            }
        }

        public void Start()
        {
            if (!_disposed && !_started)
            {
                _started = true;
                _thread.Start();
            }
        }

        public void Stop()
        {
            _started = false;

            if (_pipeServer != null)
            {
                _pipeServer.Close();
                // disposing will occur on thread
            }
        }

        public void Dispose()
        {
            _disposed = true;
            Stop();

            if (OnRequest != null)
                OnRequest = null;
        }

        #endregion

        private void Main()
        {
            while (_started && !_disposed)
            {
                try
                {
                    using (_pipeServer = new NamedPipeServerStream(_pipeName))
                    {
                        T t = Recieve(_pipeServer);

                        if (OnRequest != null && _started)
                            OnRequest(t);
                    }
                }
                catch (ThreadAbortException)
                { }
                catch (System.IO.IOException iox)
                {
                    Console.WriteLine("ERROR: {0}", iox.Message);
                    Thread.Sleep(TimeSpan.FromSeconds(30));
                }
                catch (Exception ex)
                {
                    Console.WriteLine("ERROR: {0}", ex.Message);
                    return;
                }
            }
        }

        private static T Recieve(NamedPipeServerStream nps)
        {
            var bf = new BinaryFormatter();

            try
            {
                nps.WaitForConnection();

                var obj = bf.Deserialize(nps);

                if (obj is T)
                    return (T)obj;
            }
            // Catch the IOException that is raised if the pipe is
            // broken or disconnected.
            catch (IOException e)
            {
                Console.WriteLine("ERROR: {0}", e.Message);
            }
            return default(T);
        }

        #region Enums

        public enum NameTypes
        {
            PipeType1
        }

        #endregion
    }
}

程序.cs 请将 APP GUID 归功于 What is a good pattern for using a Global Mutex in C#?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Threading;

namespace SingleInstanceNP
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            // get application GUID as defined in AssemblyInfo.cs
            string appGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).GetValue(0)).Value.ToString();

            // unique id for global mutex - Global prefix means it is global to the machine
            string mutexId = string.Format("Global\\{{{0}}}", appGuid);

            using (var mutex = new Mutex(false, mutexId))
            {
                try
                {
                    if (!mutex.WaitOne(0, false))
                    {
                        //signal existing app via named pipes

                        NamedPipe<string>.Send(NamedPipe<string>.NameTypes.PipeType1, "test");

                        Environment.Exit(0);
                    }
                    else
                    {
                        // handle protocol with this instance   
                        Application.Run(new Form1());

                    }
                }
                finally
                {
                    mutex.ReleaseMutex();
                }
            }
        }
    }
}

Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace SingleInstanceNP
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            // start listening for named pipe connections
            var namedPipeString = new NamedPipe<string>(NamedPipe<string>.NameTypes.PipeType1);
            namedPipeString.OnRequest += new NamedPipe<string>.Request(namedPipeString_OnRequest);
            namedPipeString.Start();
        }

        void namedPipeString_OnRequest(string t)
        {
            MessageBox.Show(t);
        }
    }
}

关于c# - 在不重启应用程序的情况下处理 URL 协议(protocol),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9079947/

有关c# - 在不重启应用程序的情况下处理 URL 协议(protocol)的更多相关文章

  1. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  2. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  3. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  4. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  5. ruby-on-rails - rails 目前在重启后没有安装 - 2

    我有一个奇怪的问题:我在rvm上安装了ruby​​onrails。一切正常,我可以创建项目。但是在我输入“railsnew”时重新启动后,我有“程序'rails'当前未安装。”。SystemUbuntu12.04ruby-v"1.9.3p194"gemlistactionmailer(3.2.5)actionpack(3.2.5)activemodel(3.2.5)activerecord(3.2.5)activeresource(3.2.5)activesupport(3.2.5)arel(3.0.2)builder(3.0.0)bundler(1.1.4)coffee-rails(

  6. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  7. ruby - 默认情况下使选项为 false - 2

    这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb

  8. ruby-on-rails - Rails 应用程序中的 Rails : How are you using application_controller. rb 是新手吗? - 2

    刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr

  9. ruby-on-rails - rails : save file from URL and save it to Amazon S3 - 2

    从给定URL下载文件并立即将其上传到AmazonS3的更直接的方法是什么(+将有关文件的一些信息保存到数据库中,例如名称、大小等)?现在,我既不使用Paperclip,也不使用Carrierwave。谢谢 最佳答案 简单明了:require'open-uri'require's3'amazon=S3::Service.new(access_key_id:'KEY',secret_access_key:'KEY')bucket=amazon.buckets.find('image_storage')url='http://www.ex

  10. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

随机推荐