Application.Restart () + Single Instance Konflikt in der Windows-Anwendung
Hallo Freunde,
Ich habe eine Windows-Anwendung, in der ich einzelne Instanz steuert.
Wenn diese Anwendung mit clickonce aktualisiert wird, wird die Anwendung nach dem Anwenden von Updates neu gestartet.
Die Anwendung wird neu gestartet, fährt jedoch nicht fort, da IsFirstInstance = false condition.
Die Application.Restart () -Dokumentation besagt jedoch, dass die laufende App heruntergefahren und eine neue Instanz erstellt wird.
Die Einzelinstanzklasse ist unten angegeben:
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));
}
}
}
Hier:
try { // Try opening existing wait handle eventWaitHandle = EventWaitHandle.OpenExisting(eventName); } catch(Exception ex) { // Got exception = handle wasn't created yet InstanceProxy.IsFirstInstance = true; }
Es wird keine Ausnahme geworfen. Wie Sie im Code sehen können, wird Environment.Exit (0) beendet.