Last active
December 14, 2016 05:17
-
-
Save pigeonhands/387f6bae7dcbe62ba46c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using Microsoft.Win32; | |
| using System; | |
| using System.IO; | |
| using System.Net; | |
| using System.Net.Sockets; | |
| using System.Reflection; | |
| using System.Text; | |
| using System.Threading; | |
| /// <summary> | |
| /// Application instance merger | |
| /// Made by BahNahNah | |
| /// </summary> | |
| public static class SingleInstance | |
| { | |
| public delegate void MergeInstanceCallback(string path, string[] args); | |
| private static Mutex applicationMutex = null; | |
| private static string InstanceKey; | |
| private static RegistryKey PortSave = null; | |
| private static Socket InstanceSocket = null; | |
| private static byte[] SocketBuffer; | |
| private static EndPoint SenderEndpoint = new IPEndPoint(IPAddress.Loopback, 0); | |
| private static MergeInstanceCallback MergeInstance; | |
| public static void Create(MergeInstanceCallback callback) | |
| { | |
| Create(callback, 1048576); | |
| } | |
| public static void Create(MergeInstanceCallback callback, int bufferSize) | |
| { | |
| if (callback == null) | |
| return; | |
| MergeInstance = callback; | |
| InstanceKey = Assembly.GetEntryAssembly().GetType().GUID.ToString(); | |
| PortSave = Registry.CurrentUser.OpenSubKey(@"AppEvents\Instances", true); | |
| if (PortSave == null) | |
| PortSave = Registry.CurrentUser.CreateSubKey(@"AppEvents\Instances"); | |
| if (InstanceKey == string.Empty) | |
| throw new Exception("Invalid InstanceKey"); | |
| SocketBuffer = new byte[bufferSize]; | |
| int instancePort = GetCurrentInstancePort(); | |
| if (instancePort == 0) | |
| CreateNewInstance(); | |
| else | |
| MergeInstances(instancePort); | |
| } | |
| private static void CreateNewInstance() | |
| { | |
| if (applicationMutex != null) | |
| applicationMutex.ReleaseMutex(); | |
| applicationMutex = new Mutex(true, InstanceKey); | |
| InstanceSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); | |
| InstanceSocket.Bind(SenderEndpoint); | |
| PortSave.SetValue(InstanceKey, ((IPEndPoint)InstanceSocket.LocalEndPoint).Port); | |
| InstanceSocket.BeginReceiveFrom(SocketBuffer, 0, SocketBuffer.Length, SocketFlags.None, ref SenderEndpoint, DataReceived, null); | |
| } | |
| private static void MergeInstances(int port) | |
| { | |
| InstanceSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); | |
| string[] args = Environment.GetCommandLineArgs(); | |
| using (MemoryStream ms = new MemoryStream()) | |
| using (BinaryWriter bw = new BinaryWriter(ms)) | |
| { | |
| bw.Write(args.Length); | |
| for (int i = 0; i < args.Length; i++) | |
| bw.Write(args[i]); | |
| InstanceSocket.SendTo(ms.ToArray(), new IPEndPoint(IPAddress.Loopback, port)); | |
| } | |
| Environment.Exit(0); | |
| } | |
| private static int GetCurrentInstancePort() | |
| { | |
| try | |
| { | |
| applicationMutex = Mutex.OpenExisting(InstanceKey); | |
| if (PortSave == null) | |
| return 0; | |
| return (int)PortSave.GetValue(InstanceKey, 0); | |
| } | |
| catch | |
| { | |
| return 0; | |
| } | |
| } | |
| private static void DataReceived(IAsyncResult AR) | |
| { | |
| int bytesRead = InstanceSocket.EndReceive(AR); | |
| if (bytesRead == 0) | |
| { | |
| InstanceSocket.BeginReceiveFrom(SocketBuffer, 0, SocketBuffer.Length, SocketFlags.None, ref SenderEndpoint, DataReceived, null); | |
| return; | |
| } | |
| byte[] data = new byte[bytesRead]; | |
| Buffer.BlockCopy(SocketBuffer, 0, data, 0, data.Length); | |
| string path = string.Empty; | |
| string[] args = null; | |
| using (MemoryStream ms = new MemoryStream(data)) | |
| using (BinaryReader br = new BinaryReader(ms)) | |
| { | |
| args = new string[br.ReadInt32() - 1]; | |
| path = br.ReadString(); | |
| for (int i = 0; i < args.Length; i++) | |
| args[i] = br.ReadString(); | |
| } | |
| MergeInstance(path, args); | |
| InstanceSocket.BeginReceiveFrom(SocketBuffer, 0, SocketBuffer.Length, SocketFlags.None, ref SenderEndpoint, DataReceived, null); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Imports System.Threading | |
| Imports Microsoft.Win32 | |
| Imports System.Net.Sockets | |
| Imports System.Net | |
| Imports System.Reflection | |
| Imports System.IO | |
| ''' <summary> | |
| ''' Application instance merger | |
| ''' Made by BahNahNah | |
| ''' | |
| ''' Ported to VB by Tedd | |
| ''' </summary> | |
| Public Class SingleInstance | |
| Public Delegate Sub MergeInstanceCallback(ByVal path As String, ByVal args As String()) | |
| Private Shared applicationMutex As Mutex = Nothing | |
| Private Shared InstanceKey As String | |
| Private Shared PortSave As RegistryKey = Nothing | |
| Private Shared InstanceSocket As Socket = Nothing | |
| Private Shared SocketBuffer As Byte() | |
| Private Shared SenderEndpoint As EndPoint = New IPEndPoint(IPAddress.Loopback, 0) | |
| Private Shared MergeInstance As MergeInstanceCallback | |
| Public Shared Sub Create(ByVal callback As MergeInstanceCallback) | |
| Create(callback, 1048576) | |
| End Sub | |
| Public Shared Sub Create(ByVal callback As MergeInstanceCallback, ByVal bufferSize As Integer) | |
| If callback = Nothing Then Return | |
| MergeInstance = callback | |
| InstanceKey = Assembly.GetEntryAssembly().GetType().GUID.ToString() | |
| PortSave = Registry.CurrentUser.OpenSubKey("AppEvents\Instances", True) | |
| If PortSave Is Nothing Then PortSave = Registry.CurrentUser.CreateSubKey("AppEvents\Instances") | |
| If InstanceKey = Nothing Then Throw New Exception("Invalid InstanceKey") | |
| ReDim SocketBuffer(bufferSize) | |
| Dim instancePort As Integer = GetCurrentInstancePort() | |
| If instancePort = 0 Then | |
| CreateNewInstance() | |
| Else | |
| MergeInstances(instancePort) | |
| End If | |
| End Sub | |
| Private Shared Sub CreateNewInstance() | |
| If Not applicationMutex Is Nothing Then applicationMutex.ReleaseMutex() | |
| applicationMutex = New Mutex(True, InstanceKey) | |
| InstanceSocket = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) | |
| InstanceSocket.Bind(SenderEndpoint) | |
| PortSave.SetValue(InstanceKey, DirectCast(InstanceSocket.LocalEndPoint, IPEndPoint).Port) | |
| InstanceSocket.BeginReceiveFrom(SocketBuffer, 0, SocketBuffer.Length, SocketFlags.None, SenderEndpoint, AddressOf DataReceived, Nothing) | |
| End Sub | |
| Private Shared Sub MergeInstances(ByVal port As Integer) | |
| InstanceSocket = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) | |
| Dim args As String() = Environment.GetCommandLineArgs() | |
| Using ms As MemoryStream = New MemoryStream() | |
| Using bw As BinaryWriter = New BinaryWriter(ms) | |
| bw.Write(args.Length) | |
| For i = 0 To args.Length - 1 | |
| bw.Write(args(i)) | |
| Next | |
| InstanceSocket.SendTo(ms.ToArray, New IPEndPoint(IPAddress.Loopback, port)) | |
| End Using | |
| End Using | |
| Environment.Exit(0) | |
| End Sub | |
| Private Shared Function GetCurrentInstancePort() As Integer | |
| Try | |
| applicationMutex = Mutex.OpenExisting(InstanceKey) | |
| If PortSave Is Nothing Then Return 0 | |
| Return DirectCast(PortSave.GetValue(InstanceKey, 0), Integer) | |
| Catch | |
| Return 0 | |
| End Try | |
| End Function | |
| Private Shared Sub DataReceived(ByVal AR As IAsyncResult) | |
| Dim bytesRead As Integer = InstanceSocket.EndReceive(AR) | |
| If bytesRead = 0 Then | |
| InstanceSocket.BeginReceiveFrom(SocketBuffer, 0, SocketBuffer.Length, SocketFlags.None, SenderEndpoint, AddressOf DataReceived, Nothing) | |
| Return | |
| End If | |
| Dim data(bytesRead) As Byte | |
| Buffer.BlockCopy(SocketBuffer, 0, data, 0, data.Length) | |
| Dim path As String = Nothing | |
| Dim args() As String = Nothing | |
| Using ms As MemoryStream = New MemoryStream(data) | |
| Using br As BinaryReader = New BinaryReader(ms) | |
| ReDim args(br.ReadInt32() - 1) | |
| path = br.ReadString() | |
| For i = 0 To args.Length - 1 | |
| args(i) = br.ReadString | |
| Next | |
| End Using | |
| End Using | |
| MergeInstance(path, args) | |
| InstanceSocket.BeginReceiveFrom(SocketBuffer, 0, SocketBuffer.Length, SocketFlags.None, SenderEndpoint, AddressOf DataReceived, Nothing) | |
| End Sub | |
| End Class |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment