File: Microsoft\VisualBasic\ApplicationServices\SingleInstanceHelpers.vb
Web Access
Project: src\src\Microsoft.VisualBasic.Forms\src\Microsoft.VisualBasic.Forms.vbproj (Microsoft.VisualBasic.Forms)
' Licensed to the .NET Foundation under one or more agreements.
' The .NET Foundation licenses this file to you under the MIT license.
 
Imports System.IO
Imports System.IO.Pipes
Imports System.Runtime.InteropServices
Imports System.Runtime.Serialization
Imports System.Threading
 
Namespace Microsoft.VisualBasic.ApplicationServices
 
    Friend Module SingleInstanceHelpers
        Private Const NamedPipeOptions As PipeOptions = PipeOptions.Asynchronous Or PipeOptions.CurrentUserOnly
 
        Private Async Function ReadArgsAsync(
            pipeServer As NamedPipeServerStream,
            cancellationToken As CancellationToken) As Task(Of String())
 
            Const bufferLength As Integer = 1024
 
            Using stream As New MemoryStream
                While True
                    Dim buffer As Byte() = New Byte(bufferLength - 1) {}
                    Dim bytesRead As Integer = Await pipeServer.ReadAsync(
                        buffer:=buffer.AsMemory(start:=0, length:=bufferLength),
                        cancellationToken) _
                            .ConfigureAwait(continueOnCapturedContext:=False)
                    If bytesRead = 0 Then
                        Exit While
                    End If
                    Await stream.WriteAsync(
                        buffer:=buffer.AsMemory(start:=0, length:=bytesRead),
                        cancellationToken) _
                            .ConfigureAwait(continueOnCapturedContext:=False)
                End While
                stream.Seek(0, SeekOrigin.Begin)
                Dim serializer As New DataContractSerializer(GetType(String()))
                Try
                    Return DirectCast(serializer.ReadObject(stream), String())
                Catch ex As Exception
                    Return Nothing
                End Try
            End Using
        End Function
 
        Private Async Function WriteArgsAsync(
            pipeClient As NamedPipeClientStream,
            args As String(),
            cancellationToken As CancellationToken) As Task
 
            Dim content As Byte()
            Using stream As New MemoryStream
                Dim serializer As New DataContractSerializer(GetType(String()))
                serializer.WriteObject(stream, args)
                content = stream.ToArray()
            End Using
            Await pipeClient.WriteAsync(
                buffer:=content.AsMemory(start:=0, length:=content.Length), cancellationToken) _
                    .ConfigureAwait(continueOnCapturedContext:=False)
        End Function
 
        Friend Async Function SendSecondInstanceArgsAsync(
            pipeName As String,
            args As String(),
            cancellationToken As CancellationToken) As Task
 
            Using pipeClient As New NamedPipeClientStream(
                serverName:=".",
                pipeName:=pipeName,
                direction:=PipeDirection.Out,
                options:=NamedPipeOptions)
 
                Await pipeClient.ConnectAsync(cancellationToken) _
                    .ConfigureAwait(continueOnCapturedContext:=False)
                Await WriteArgsAsync(pipeClient, args, cancellationToken) _
                    .ConfigureAwait(continueOnCapturedContext:=False)
            End Using
        End Function
 
        Friend Function TryCreatePipeServer(
            pipeName As String,
            <Out> ByRef pipeServer As NamedPipeServerStream) As Boolean
 
            Try
                pipeServer = New NamedPipeServerStream(
                    pipeName:=pipeName,
                    direction:=PipeDirection.In,
                    maxNumberOfServerInstances:=1,
                    transmissionMode:=PipeTransmissionMode.Byte,
                    options:=NamedPipeOptions)
                Return True
            Catch ex As Exception
                pipeServer = Nothing
                Return False
            End Try
        End Function
 
        Friend Async Function WaitForClientConnectionsAsync(
            pipeServer As NamedPipeServerStream,
            callback As Action(Of String()),
            cancellationToken As CancellationToken) As Task
 
            While True
                cancellationToken.ThrowIfCancellationRequested()
                Await pipeServer.WaitForConnectionAsync(cancellationToken) _
                    .ConfigureAwait(continueOnCapturedContext:=False)
                Try
                    Dim args() As String = Await ReadArgsAsync(pipeServer, cancellationToken) _
                        .ConfigureAwait(continueOnCapturedContext:=False)
                    If args IsNot Nothing Then
                        callback(args)
                    End If
                Finally
                    pipeServer.Disconnect()
                End Try
            End While
        End Function
 
    End Module
End Namespace