Application.Restart() + Single Instance conflict in windows application

匆匆过客 提交于 2019-12-06 12:27:13

问题


Hi Friends,

I have a windows application where i controls single instance.

When this application updates using clickonce, application will restart after applying updates.

The application restarts but fails to continue as, IsFirstInstance = false condition.

But Application.Restart() documentation says it shutdowns running app and creates new instance.

Single instance class is given below:

 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));
    }
}

}

here:

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

no exception is being thrown. Hence as you can see in the code, it will exit from Environment.Exit(0).

来源:https://stackoverflow.com/questions/14498633/application-restart-single-instance-conflict-in-windows-application

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!