From bb1282e066dd756911a16cbdea0f7f58d6458092 Mon Sep 17 00:00:00 2001 From: Manuel Kamper Date: Fri, 22 Mar 2019 23:12:32 +0100 Subject: [PATCH] Initial --- Mk0.Tools.SingleInstance.sln | 25 ++++ .../Mk0.Tools.SingleInstance.csproj | 43 ++++++ .../Properties/AssemblyInfo.cs | 36 +++++ Mk0.Tools.SingleInstance/SingleApplication.cs | 123 ++++++++++++++++++ README.md | 17 ++- 5 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 Mk0.Tools.SingleInstance.sln create mode 100644 Mk0.Tools.SingleInstance/Mk0.Tools.SingleInstance.csproj create mode 100644 Mk0.Tools.SingleInstance/Properties/AssemblyInfo.cs create mode 100644 Mk0.Tools.SingleInstance/SingleApplication.cs diff --git a/Mk0.Tools.SingleInstance.sln b/Mk0.Tools.SingleInstance.sln new file mode 100644 index 0000000..1f393ff --- /dev/null +++ b/Mk0.Tools.SingleInstance.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.438 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mk0.Tools.SingleInstance", "Mk0.Tools.SingleInstance\Mk0.Tools.SingleInstance.csproj", "{EE314A04-04C0-4FFB-999C-893F61EC59BD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EE314A04-04C0-4FFB-999C-893F61EC59BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EE314A04-04C0-4FFB-999C-893F61EC59BD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EE314A04-04C0-4FFB-999C-893F61EC59BD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EE314A04-04C0-4FFB-999C-893F61EC59BD}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {ACE43D6F-6DD1-4695-9A29-F0316CDFE039} + EndGlobalSection +EndGlobal diff --git a/Mk0.Tools.SingleInstance/Mk0.Tools.SingleInstance.csproj b/Mk0.Tools.SingleInstance/Mk0.Tools.SingleInstance.csproj new file mode 100644 index 0000000..b2fc616 --- /dev/null +++ b/Mk0.Tools.SingleInstance/Mk0.Tools.SingleInstance.csproj @@ -0,0 +1,43 @@ + + + + + Debug + AnyCPU + {EE314A04-04C0-4FFB-999C-893F61EC59BD} + Library + Properties + Mk0.Tools.SingleInstance + Mk0.Tools.SingleInstance + v4.6.1 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + \ No newline at end of file diff --git a/Mk0.Tools.SingleInstance/Properties/AssemblyInfo.cs b/Mk0.Tools.SingleInstance/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..64e14e7 --- /dev/null +++ b/Mk0.Tools.SingleInstance/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Allgemeine Informationen über eine Assembly werden über die folgenden +// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +// die einer Assembly zugeordnet sind. +[assembly: AssemblyTitle("Mk0.Tools.SingleInstance")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Mk0.Tools.SingleInstance")] +[assembly: AssemblyCopyright("Copyright © 2019 mk0.at")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly +// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von +// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen. +[assembly: ComVisible(false)] + +// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird +[assembly: Guid("ee314a04-04c0-4ffb-999c-893f61ec59bd")] + +// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +// +// Hauptversion +// Nebenversion +// Buildnummer +// Revision +// +// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, +// indem Sie "*" wie unten gezeigt eingeben: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Mk0.Tools.SingleInstance/SingleApplication.cs b/Mk0.Tools.SingleInstance/SingleApplication.cs new file mode 100644 index 0000000..b7de317 --- /dev/null +++ b/Mk0.Tools.SingleInstance/SingleApplication.cs @@ -0,0 +1,123 @@ +using System; +using System.Windows.Forms; +using System.Runtime.InteropServices; +using System.Diagnostics; +using System.Threading; +using System.Reflection; +using System.IO; + +namespace Mk0.Tools.SingleInstance +{ + /// + /// Summary description for SingleApp. + /// + public class SingleApplication + { + public SingleApplication() + { + } + + /// + /// Imports + /// + [DllImport("user32.dll")] + private static extern int ShowWindow(IntPtr hWnd, int nCmdShow); + + [DllImport("user32.dll")] + private static extern int SetForegroundWindow(IntPtr hWnd); + + [DllImport("user32.dll")] + private static extern int IsIconic(IntPtr hWnd); + + /// + /// GetCurrentInstanceWindowHandle + /// + /// + private static IntPtr GetCurrentInstanceWindowHandle() + { + IntPtr hWnd = IntPtr.Zero; + Process process = Process.GetCurrentProcess(); + Process[] processes = Process.GetProcessesByName(process.ProcessName); + foreach (Process _process in processes) + { + if (_process.Id != process.Id && + _process.MainModule.FileName == process.MainModule.FileName && + _process.MainWindowHandle != IntPtr.Zero) + { + hWnd = _process.MainWindowHandle; + break; + } + } + return hWnd; + } + /// + /// SwitchToCurrentInstance + /// + private static void SwitchToCurrentInstance() + { + IntPtr hWnd = GetCurrentInstanceWindowHandle(); + if (hWnd != IntPtr.Zero) + { + if (IsIconic(hWnd) != 0) + { + ShowWindow(hWnd, SW_RESTORE); + } + + SetForegroundWindow(hWnd); + } + } + + /// + /// Execute a form base application if another instance already running on + /// the system activate previous one + /// + /// main form + /// your app can set if single instance (true) or multi instance (false) + /// true if no previous instance is running + public static bool Run(Form frmMain, bool appSetting=true) + { + if (IsAlreadyRunning() && appSetting) + { + SwitchToCurrentInstance(); + return false; + } + Application.Run(frmMain); + return true; + } + + /// + /// for console base application + /// + /// + public static bool Run() + { + if (IsAlreadyRunning()) + { + return false; + } + return true; + } + + /// + /// check if given exe alread running or not + /// + /// returns true if already running + private static bool IsAlreadyRunning() + { + string strLoc = Assembly.GetExecutingAssembly().Location; + FileSystemInfo fileInfo = new FileInfo(strLoc); + string sExeName = fileInfo.Name; + + mutex = new Mutex(true, "Global\\" + sExeName, out bool bCreatedNew); + if (bCreatedNew) + { + mutex.ReleaseMutex(); + } + + return !bCreatedNew; + } + + static Mutex mutex; + const int SW_RESTORE = 9; + } +} diff --git a/README.md b/README.md index c0f0daf..3b3137b 100644 --- a/README.md +++ b/README.md @@ -1 +1,16 @@ -# Mk0.Tools.SingleInstance \ No newline at end of file +# Mk0.Tools.SingleInstance +(C) 2019 mk0.at + +With this code you are able to make your application a single instance. + +Usage example: + +static void Main(string[] args) +{ + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + SingleApplication.Run(new MainForm(), Demo.Properties.Settings.Default.singleInstance); +} + +MainForm is the form to show on start +singleInstance is an optional boolean value, where you can enable/disable SingleInstance within your application settings \ No newline at end of file