diff --git a/HelpersLib/HelpersLib.csproj b/HelpersLib/HelpersLib.csproj
index f158dc8e5..89e4d7ad4 100644
--- a/HelpersLib/HelpersLib.csproj
+++ b/HelpersLib/HelpersLib.csproj
@@ -293,8 +293,6 @@
-
-
UserControl
diff --git a/HelpersLib/SingleInstanceApplication/ApplicationInstanceManager.cs b/HelpersLib/SingleInstanceApplication/ApplicationInstanceManager.cs
deleted file mode 100644
index eb381f070..000000000
--- a/HelpersLib/SingleInstanceApplication/ApplicationInstanceManager.cs
+++ /dev/null
@@ -1,122 +0,0 @@
-#region License Information (GPL v3)
-
-/*
- ShareX - A program that allows you to take screenshots and share any file type
- Copyright (C) 2007-2014 ShareX Developers
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
- Optionally you can also view the license at .
-*/
-
-#endregion License Information (GPL v3)
-
-using System;
-using System.Diagnostics;
-using System.Runtime.Remoting;
-using System.Runtime.Remoting.Channels;
-using System.Runtime.Remoting.Channels.Ipc;
-using System.Threading;
-using System.Windows.Forms;
-
-namespace SingleInstanceApplication
-{
- public static class ApplicationInstanceManager
- {
- [DebuggerStepThrough]
- public static bool CreateSingleInstance(string name, EventHandler callback)
- {
- string eventName = string.Format("{0}-{1}", Environment.MachineName, name);
-
- InstanceProxy.IsFirstInstance = false;
- InstanceProxy.CommandLineArgs = Environment.GetCommandLineArgs();
-
- try
- {
- using (EventWaitHandle eventWaitHandle = EventWaitHandle.OpenExisting(eventName))
- {
- UpdateRemoteObject(name);
-
- if (eventWaitHandle != null) eventWaitHandle.Set();
- }
-
- Environment.Exit(0);
- }
- catch
- {
- InstanceProxy.IsFirstInstance = true;
-
- using (EventWaitHandle eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName))
- {
- ThreadPool.RegisterWaitForSingleObject(eventWaitHandle, WaitOrTimerCallback, callback, Timeout.Infinite, false);
- }
-
- RegisterRemoteType(name);
- }
-
- return InstanceProxy.IsFirstInstance;
- }
-
- public static bool CreateSingleInstance(EventHandler callback)
- {
- try
- {
- return CreateSingleInstance(Application.ProductName, callback);
- }
- catch
- {
- }
-
- return true;
- }
-
- private static void UpdateRemoteObject(string uri)
- {
- IpcClientChannel clientChannel = new IpcClientChannel();
- ChannelServices.RegisterChannel(clientChannel, true);
-
- InstanceProxy proxy = Activator.GetObject(typeof(InstanceProxy), string.Format("ipc://{0}{1}/{1}", Environment.MachineName, uri)) as InstanceProxy;
-
- if (proxy != null)
- {
- proxy.SetCommandLineArgs(InstanceProxy.IsFirstInstance, InstanceProxy.CommandLineArgs);
- }
-
- ChannelServices.UnregisterChannel(clientChannel);
- }
-
- private static void RegisterRemoteType(string uri)
- {
- IpcServerChannel serverChannel = new IpcServerChannel(Environment.MachineName + uri);
- ChannelServices.RegisterChannel(serverChannel, true);
-
- RemotingConfiguration.RegisterWellKnownServiceType(typeof(InstanceProxy), uri, WellKnownObjectMode.Singleton);
-
- Process process = Process.GetCurrentProcess();
- process.Exited += delegate
- {
- ChannelServices.UnregisterChannel(serverChannel);
- };
- }
-
- private static void WaitOrTimerCallback(object state, bool timedOut)
- {
- EventHandler callback = state as EventHandler;
- if (callback == null) return;
-
- callback(state, new InstanceCallbackEventArgs(InstanceProxy.IsFirstInstance, InstanceProxy.CommandLineArgs));
- }
- }
-}
\ No newline at end of file
diff --git a/HelpersLib/SingleInstanceApplication/InstanceProxy.cs b/HelpersLib/SingleInstanceApplication/InstanceProxy.cs
deleted file mode 100644
index 38b278787..000000000
--- a/HelpersLib/SingleInstanceApplication/InstanceProxy.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-#region License Information (GPL v3)
-
-/*
- ShareX - A program that allows you to take screenshots and share any file type
- Copyright (C) 2007-2014 ShareX Developers
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
- Optionally you can also view the license at .
-*/
-
-#endregion License Information (GPL v3)
-
-using System;
-using System.Security.Permissions;
-
-namespace SingleInstanceApplication
-{
- [Serializable]
- [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
- internal class InstanceProxy : MarshalByRefObject
- {
- public static bool IsFirstInstance { get; internal set; }
-
- public static string[] CommandLineArgs { get; internal set; }
-
- public void SetCommandLineArgs(bool isFirstInstance, string[] commandLineArgs)
- {
- IsFirstInstance = isFirstInstance;
- CommandLineArgs = commandLineArgs;
- }
- }
-
- public class InstanceCallbackEventArgs : EventArgs
- {
- internal InstanceCallbackEventArgs(bool isFirstInstance, string[] commandLineArgs)
- {
- IsFirstInstance = isFirstInstance;
- CommandLineArgs = commandLineArgs;
- }
-
- public bool IsFirstInstance { get; private set; }
-
- public string[] CommandLineArgs { get; private set; }
- }
-}
\ No newline at end of file
diff --git a/ShareX/Forms/MainForm.cs b/ShareX/Forms/MainForm.cs
index ac3814f79..e0617f0b3 100644
--- a/ShareX/Forms/MainForm.cs
+++ b/ShareX/Forms/MainForm.cs
@@ -41,7 +41,7 @@ namespace ShareX
{
public partial class MainForm : HotkeyForm
{
- public bool IsReady { get; private set; }
+ public ManualResetEvent ReadyWaitHandle { get; private set; }
private bool forceClose;
private UploadInfoManager uim;
@@ -49,6 +49,7 @@ public partial class MainForm : HotkeyForm
public MainForm()
{
+ ReadyWaitHandle = new ManualResetEvent(false);
InitControls();
HandleCreated += MainForm_HandleCreated;
}
@@ -62,7 +63,7 @@ private void MainForm_HandleCreated(object sender, EventArgs e)
AutoCheckUpdate();
#endif
- IsReady = true;
+ ReadyWaitHandle.Set();
DebugHelper.WriteLine("Startup time: {0} ms", Program.StartTimer.ElapsedMilliseconds);
@@ -675,7 +676,7 @@ private void MainForm_Resize(object sender, EventArgs e)
private void MainForm_LocationChanged(object sender, EventArgs e)
{
- if (IsReady && WindowState == FormWindowState.Normal)
+ if (ReadyWaitHandle.WaitOne(0) && WindowState == FormWindowState.Normal)
{
Program.Settings.MainFormPosition = Location;
}
@@ -683,7 +684,7 @@ private void MainForm_LocationChanged(object sender, EventArgs e)
private void MainForm_SizeChanged(object sender, EventArgs e)
{
- if (IsReady && WindowState == FormWindowState.Normal)
+ if (ReadyWaitHandle.WaitOne(0) && WindowState == FormWindowState.Normal)
{
Program.Settings.MainFormSize = Size;
}
diff --git a/ShareX/Program.cs b/ShareX/Program.cs
index bf6ef96bf..c8dd29f3b 100644
--- a/ShareX/Program.cs
+++ b/ShareX/Program.cs
@@ -24,7 +24,7 @@ You should have received a copy of the GNU General Public License
#endregion License Information (GPL v3)
using HelpersLib;
-using SingleInstanceApplication;
+using Microsoft.VisualBasic.ApplicationServices;
using System;
using System.Diagnostics;
using System.IO;
@@ -32,6 +32,7 @@ You should have received a copy of the GNU General Public License
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
+using System.Threading.Tasks;
using System.Windows.Forms;
using UploadersLib;
@@ -228,7 +229,6 @@ public static string Title
}
}
- public static bool IsMultiInstance { get; private set; }
public static bool IsPortable { get; private set; }
public static bool IsSilentRun { get; private set; }
public static bool IsSandbox { get; private set; }
@@ -247,6 +247,8 @@ public static string Title
public static HotkeyManager HotkeyManager { get; set; }
public static WatchFolderManager WatchFolderManager { get; set; }
+ private static ShareXApplicationBase _appBase;
+
[STAThread]
private static void Main(string[] args)
{
@@ -255,17 +257,18 @@ private static void Main(string[] args)
StartTimer = Stopwatch.StartNew();
- IsMultiInstance = CLIHelper.CheckArgs(args, "multi", "m");
-
- if (IsMultiInstance || ApplicationInstanceManager.CreateSingleInstance(SingleInstanceCallback))
- {
- Run(args);
- }
+ bool isMultiInstance = CLIHelper.CheckArgs(args, "multi", "m");
+ _appBase = new ShareXApplicationBase(!isMultiInstance);
+ _appBase.Startup += StartupHandler;
+ _appBase.StartupNextInstance += StartupNextInstanceHandler;
+ _appBase.Shutdown += ShutdownHandler;
+ _appBase.Run(args);
}
- private static void Run(string[] args)
+ private static void StartupHandler(object sender, StartupEventArgs e)
{
string appGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).GetValue(0)).Value.ToString();
+ string[] args = Environment.GetCommandLineArgs();
using (Mutex mutex = new Mutex(false, appGuid)) // Required for installer
{
@@ -291,9 +294,6 @@ private static void Run(string[] args)
}
}
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
-
DebugHelper.WriteLine("{0} started", Title);
DebugHelper.WriteLine("Operating system: " + Environment.OSVersion.VersionString);
DebugHelper.WriteLine("Command line: " + Environment.CommandLine);
@@ -312,24 +312,64 @@ private static void Run(string[] args)
DebugHelper.WriteLine("MainForm init started");
MainForm = new MainForm();
+ _appBase.MainForm = MainForm;
DebugHelper.WriteLine("MainForm init finished");
if (Settings == null)
{
SettingsResetEvent.WaitOne();
}
-
- Application.Run(MainForm);
-
- if (WatchFolderManager != null) WatchFolderManager.Dispose();
- SaveSettings();
- BackupSettings();
-
- DebugHelper.WriteLine("ShareX closing");
- DebugHelper.Logger.SaveLog(LogsFilePath);
}
}
+ private static void StartupNextInstanceHandler(object sender, StartupNextInstanceEventArgs e)
+ {
+ e.BringToForeground = false;
+ string[] args = new string[e.CommandLine.Count + 1];
+ args[0] = "";
+ e.CommandLine.CopyTo(args, 1);
+ if (MainForm.ReadyWaitHandle.WaitOne(0)) DoStartupNextInstance(args);
+ else Task.Factory.StartNew(WaitFormLoad, args);
+ }
+
+ private static void WaitFormLoad(object args)
+ {
+ try {
+ if (MainForm.ReadyWaitHandle.WaitOne(5000)) {
+ MainForm.Invoke(new Action(DoStartupNextInstance), args);
+ }
+ }
+ catch { }
+ }
+
+ private static void DoStartupNextInstance(string[] args)
+ {
+ if (args == null || args.Length <= 1) {
+ if (MainForm.niTray != null && MainForm.niTray.Visible) {
+ // Workaround for Windows startup tray icon bug
+ MainForm.niTray.Visible = false;
+ MainForm.niTray.Visible = true;
+ }
+
+ MainForm.ShowActivate();
+ }
+ else if (MainForm.Visible) {
+ MainForm.ShowActivate();
+ }
+
+ MainForm.UseCommandLineArgs(args);
+ }
+
+ private static void ShutdownHandler(object sender, EventArgs e)
+ {
+ if (WatchFolderManager != null) WatchFolderManager.Dispose();
+ SaveSettings();
+ BackupSettings();
+
+ DebugHelper.WriteLine("ShareX closing");
+ DebugHelper.Logger.SaveLog(LogsFilePath);
+ }
+
public static void LoadSettings()
{
LoadProgramSettings();
@@ -435,7 +475,7 @@ private static void Application_ThreadException(object sender, ThreadExceptionEv
OnError(e.Exception);
}
- private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
+ private static void CurrentDomain_UnhandledException(object sender, System.UnhandledExceptionEventArgs e)
{
OnError((Exception)e.ExceptionObject);
}
@@ -448,49 +488,6 @@ private static void OnError(Exception e)
}
}
- private static void SingleInstanceCallback(object sender, InstanceCallbackEventArgs args)
- {
- if (WaitFormLoad(5000))
- {
- Action d = () =>
- {
- if (args.CommandLineArgs == null || args.CommandLineArgs.Length <= 1)
- {
- if (MainForm.niTray != null && MainForm.niTray.Visible)
- {
- // Workaround for Windows startup tray icon bug
- MainForm.niTray.Visible = false;
- MainForm.niTray.Visible = true;
- }
-
- MainForm.ShowActivate();
- }
- else if (MainForm.Visible)
- {
- MainForm.ShowActivate();
- }
-
- MainForm.UseCommandLineArgs(args.CommandLineArgs);
- };
-
- MainForm.InvokeSafe(d);
- }
- }
-
- private static bool WaitFormLoad(int wait)
- {
- Stopwatch timer = Stopwatch.StartNew();
-
- while (timer.ElapsedMilliseconds < wait)
- {
- if (MainForm != null && MainForm.IsReady) return true;
-
- Thread.Sleep(10);
- }
-
- return false;
- }
-
public static void ConfigureUploadersConfigWatcher()
{
if (Program.Settings.DetectUploaderConfigFileChanges && uploaderConfigWatcher == null)
diff --git a/ShareX/ShareX.csproj b/ShareX/ShareX.csproj
index 10e2f20f7..11d654335 100644
--- a/ShareX/ShareX.csproj
+++ b/ShareX/ShareX.csproj
@@ -70,6 +70,7 @@
False
..\packages\MegaApiClient.1.0.4\lib\MegaApiClient.dll
+
False
..\packages\Newtonsoft.Json.6.0.3\lib\net40\Newtonsoft.Json.dll
@@ -227,6 +228,7 @@
True
Resources.resx
+
diff --git a/ShareX/ShareXApplicationBase.cs b/ShareX/ShareXApplicationBase.cs
new file mode 100644
index 000000000..802a1a51f
--- /dev/null
+++ b/ShareX/ShareXApplicationBase.cs
@@ -0,0 +1,24 @@
+using Microsoft.VisualBasic.ApplicationServices;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace ShareX
+{
+ class ShareXApplicationBase : WindowsFormsApplicationBase
+ {
+ public ShareXApplicationBase(bool isSingleInstance)
+ {
+ IsSingleInstance = isSingleInstance;
+ EnableVisualStyles = true;
+ }
+
+ public new Form MainForm
+ {
+ get { return base.MainForm; }
+ set { base.MainForm = value; }
+ }
+ }
+}