2

嗨朋友们,

我有一个 Windows 应用程序,我在其中控制单个实例。

当此应用程序使用 clickonce 更新时,应用程序将在应用更新后重新启动。

应用程序重新启动但无法继续,因为 IsFirstInstance = false 条件。

但是 Application.Restart() 文档说它会关闭正在运行的应用程序并创建新实例。

单实例类如下:

 using System;
using System.Diagnostics;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
using System.Threading;
using agent_common_plugin_sdk;

/// <summary>
/// Application Instance Manager
/// </summary>
public static class ApplicationInstanceManager
{
    /// <summary>
    /// Creates the single instance.
    /// </summary>
    /// <param name="name">The name.</param>
    /// <param name="callback">The callback.</param>
    /// <returns></returns>
    public static bool CreateSingleInstance(string name, EventHandler<InstanceCallbackEventArgs> callback)
    {
        EventWaitHandle eventWaitHandle = null;
        string eventName = string.Format("{0}-{1}", Environment.MachineName, name);

        InstanceProxy.IsFirstInstance = false;
        InstanceProxy.CommandLineArgs = Environment.GetCommandLineArgs();



        try
        {
            // Try opening existing wait handle
            eventWaitHandle = EventWaitHandle.OpenExisting(eventName);
        }
        catch(Exception ex)
        {
            // Got exception = handle wasn't created yet
            InstanceProxy.IsFirstInstance = true;
        }

        if (InstanceProxy.IsFirstInstance)
        {
            // init handle
            eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName);

            // register wait handle for this instance (process)
            ThreadPool.RegisterWaitForSingleObject(eventWaitHandle, WaitOrTimerCallback, callback, Timeout.Infinite, false);
            eventWaitHandle.Close();

            // register shared type (used to pass data between processes)
            RegisterRemoteType(name);
        }
        else
        {
            // pass console arguments to shared object
            UpdateRemoteObject(name);

            // invoke (signal) wait handle on other process
            if (eventWaitHandle != null) eventWaitHandle.Set();

            // kill current process
            Environment.Exit(0);

        }

        return InstanceProxy.IsFirstInstance;
    }

    /// <summary>
    /// Updates the remote object.
    /// </summary>
    /// <param name="uri">The remote URI.</param>
    private static void UpdateRemoteObject(string uri)
    {
        // register net-pipe channel
        IpcClientChannel clientChannel = new IpcClientChannel();
        ChannelServices.RegisterChannel(clientChannel, true);

        // get shared object from other process
        InstanceProxy proxy =
            Activator.GetObject(typeof(InstanceProxy),
            string.Format("ipc://{0}{1}/{1}", Environment.MachineName, uri)) as InstanceProxy;

        // pass current command line args to proxy
        if (proxy != null)
            proxy.SetCommandLineArgs(InstanceProxy.IsFirstInstance, InstanceProxy.CommandLineArgs);

        // close current client channel
        ChannelServices.UnregisterChannel(clientChannel);
    }

    /// <summary>
    /// Registers the remote type.
    /// </summary>
    /// <param name="uri">The URI.</param>
    private static void RegisterRemoteType(string uri)
    {
        // register remote channel (net-pipes)
        IpcServerChannel serverChannel = new IpcServerChannel(Environment.MachineName + uri);
        ChannelServices.RegisterChannel(serverChannel, true);

        // register shared type
        RemotingConfiguration.RegisterWellKnownServiceType(
            typeof(InstanceProxy), uri, WellKnownObjectMode.Singleton);

        // close channel, on process exit
        Process process = Process.GetCurrentProcess();
        process.Exited += delegate { ChannelServices.UnregisterChannel(serverChannel); };
    }

    /// <summary>
    /// Wait Or Timer Callback Handler
    /// </summary>
    /// <param name="state">The state.</param>
    /// <param name="timedOut">if set to <c>true</c> [timed out].</param>
    private static void WaitOrTimerCallback(object state, bool timedOut)
    {
        // cast to event handler
        EventHandler<InstanceCallbackEventArgs> callback = state as EventHandler<InstanceCallbackEventArgs>;
        if (callback == null) return;

        // invoke event handler on other process
        callback(state,
                 new InstanceCallbackEventArgs(InstanceProxy.IsFirstInstance,
                                               InstanceProxy.CommandLineArgs));
    }
}

}

这里:

try { // Try opening existing wait handle eventWaitHandle = EventWaitHandle.OpenExisting(eventName); } catch(Exception ex) { // Got exception = handle wasn't created yet InstanceProxy.IsFirstInstance = true; }

没有异常被抛出。因此,正如您在代码中看到的,它将从 Environment.Exit(0) 退出。

4

0 回答 0