[C#/VB] Simple instance merger class - BahNahNah - Nov 18, 2015
Download: GIST
Simple code that passes the commandline arguments to an existing version of the application (if it exists).
Gif:
![[Image: tO82nND.gif]](https://i.imgur.com/tO82nND.gif)
Example code:
Code public static void Main(string[] args)
{
SingleInstance.Create(OnNewInstance); //Setting up single instance of the current program
Console.WriteLine("First instance created");
Console.ReadLine();
}
private static void OnNewInstance(string path, string[] args)
{
Console.WriteLine("New instance created. Path: {0}", path);
for(int i =0; i < args.Length;i++)
Console.WriteLine("Arg {0}: {1}", i, args[i]);
}
VB:
Code Sub Main()
SingleInstance.Create(AddressOf OnNewInstance)
Console.WriteLine("First instance created")
Console.ReadLine()
End Sub
Private Sub OnNewInstance(ByVal path As String, ByVal args As String())
Console.WriteLine("New instance created. Path: {0}", path)
For i = 0 To args.Length - 1
Console.WriteLine("Args {0}: {1}", i, args(i))
Next
End Sub
Todo:
-Find a better way to store port.
* - DisguiserNET - Nov 18, 2015
thats a cool idea, but i can't think of a way for me to use it. mind telling me, what you made it for?
* - BahNahNah - Nov 18, 2015
(Nov 18, 2015 02:52 AM)DisguiserNET Wrote: thats a cool idea, but i can't think of a way for me to use it. mind telling me, what you made it for?
Associating a file type to your application (just passes the location of the associated file to the existing instance).
WebLaunched programs (like magnet links for torrents).
* - stratex - Nov 18, 2015
(Nov 18, 2015 02:52 AM)DisguiserNET Wrote: thats a cool idea, but i can't think of a way for me to use it. mind telling me, what you made it for?
This could probably be used for something like a web browser where instead of opening a new instance, it would open a new tab.
* - Only3 - Nov 18, 2015
this can easy done with process class and Environment.GetCommandLineArgs
* - Washi - Nov 18, 2015
Interesting concept, although why would you use sockets instead of pipes? Wouldn't that be easier as it takes away the need for a port?
https://msdn.microsoft.com/en-us/library/bb546102%28v=vs.110%29.aspx
* - BahNahNah - Nov 18, 2015
(Nov 18, 2015 09:41 AM)TheUnknownProgrammer Wrote: Interesting concept, although why would you use sockets instead of pipes? Wouldn't that be easier as it takes away the need for a port?
https://msdn.microsoft.com/en-us/library/bb546102%28v=vs.110%29.aspx
I thought pipelines where .net 4?
I try to make my programs .Net 2.0 when it is possible, so its more compatible with other peoples projects.
(Nov 18, 2015 08:37 AM)Only3 Wrote: this can easy done with process class and Environment.GetCommandLineArgs
Example?
* - Only3 - Nov 18, 2015
Code if (Args.Length < 2) {
Process.Start(new ProcessStartInfo(Application.ExecutablePath, "1"));
} else if (Args(1) == "1") {
// New Instance
}
* - BahNahNah - Nov 18, 2015
(Nov 18, 2015 04:08 PM)Only3 Wrote: Code if (Args.Length < 2) {
Process.Start(new ProcessStartInfo(Application.ExecutablePath, "1"));
} else if (Args(1) == "1") {
// New Instance
}
This would not work. Did you even try it?
* - Tedd - Nov 18, 2015
Ported to vb. I really like this, useful as fuck.
SingleInstance.vb:
Code 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
''' uid=2388291
'''
''' Ported to VB by Tedd
''' </summary>
Public Class SingleInstance
Public Delegate Sub MergeInstanceCallback(ByVal path As String, ByVal args As String())
Private applicationMutex As Mutex = Nothing
Private InstanceKey As String
Private PortSave As RegistryKey = Nothing
Private InstanceSocket As Socket = Nothing
Private SocketBuffer As Byte()
Private SenderEndpoint As EndPoint = New IPEndPoint(IPAddress.Loopback, 0)
Private MergeInstance As MergeInstanceCallback
Public Sub Create(ByVal callback As MergeInstanceCallback)
Create(callback, 1048576)
End Sub
Public 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 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 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 Function GetCurrentInstancePort() As Integer
Try
applicationMutex = Mutex.OpenExisting(InstanceKey)
If PortSave Is Nothing Then Return 0
Return DirectCast(PortSave.GetValue(InstanceKey, 0), Integer)
Catch ex As Exception
Return 0
End Try
End Function
Private 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
Module1.vb:
Code Module Module1
Dim SingleInst As SingleInstance
Sub Main()
SingleInst = New SingleInstance
SingleInst.Create(AddressOf OnNewInstance)
Console.WriteLine("First instance created")
Console.ReadLine()
End Sub
Private Sub OnNewInstance(ByVal path As String, ByVal args As String())
Console.WriteLine("New instance created. Path: {0}", path)
For i = 0 To args.Length - 1
Console.WriteLine("Args {0}: {1}", i, args(i))
Next
End Sub
End Module
* - BahNahNah - Nov 18, 2015
(Nov 18, 2015 08:11 PM)Tedd Wrote: Ported to vb. I really like this, useful as fuck.
SingleInstance.vb:
-code-
Module1.vb:
-code-
Thanks ;)
I modified it slightly to make it static and added it to the GIST.
* - Only3 - Nov 19, 2015
(Nov 18, 2015 04:17 PM)BahNahNah Wrote: This would not work. Did you even try it?
This work. Did you even try it?
* - BahNahNah - Nov 19, 2015
(Nov 19, 2015 03:56 AM)Only3 Wrote: This work. Did you even try it?
But it never checks if there is already another process running.
* - Only3 - Nov 19, 2015
bahna open ur brain its easy to do it
also this way u not creating new files all in memory
tip use the power of the args to pass the info
* - BahNahNah - Nov 19, 2015
(Nov 19, 2015 04:14 AM)Only3 Wrote: bahna open ur brain its easy to do it
also this way u not creating new files all in memory
tip use the power of the args to pass the info
I tried it.
![[Image: GDpED6R.gif]](https://i.imgur.com/GDpED6R.gif)
|