Custom Connector SDK (Named Pipe)

Overview

The Launcher installer ships an optional Connector SDK (a .NET DLL) that you can import to simplify communication over the named pipe.

SDK Contents

Typed Models

For all messages exchanged with the Launcher (ConnectionConfiguration, CustomConnectorEvent).

LauncherIpcClient Client Functionality

  • Pipe creation and connection

  • Serialization and deserialization

  • Message framing

  • Error handling

  • Automatic reading of ConnectionConfiguration

  • Automatic event construction (RemoteConnectionWindowCreated, RemoteConnectionWindowClosed, RemoteConnectionFailure, Custom)

Utility Methods

Method

Description

ConnectToLauncherAsync()

Creates an instance of LauncherIpcClient connected to the named pipe.

WaitForConnectionConfigurationAsync()

Blocks execution until a ConnectionConfiguration message is received from the Launcher

SendCustomEventAsync()

Sends a custom user-session event to the Launcher

SendRemoteConnectionWindowCreatedAsync()

Notifies the Launcher that the remote connection window was created successfully (optionally sends the process ID for tracking)

SendRemoteConnectionWindowClosedAsync()

Notifies the Launcher that the remote connection window was closed

SendRemoteConnectionFailureAsync()

Notifies the Launcher that the connection failed

Example Usage (C#)

The following example demonstrates how to use the Connector SDK to communicate with the Launcher over a named pipe.

using Connectors;
using LoginEnterprise.Launcher.Connectors.Custom.Ipc.Client;
...
// create an instance of launcher client AND connects to the pipe
await using var launcherClient = await LauncherIpcClient.ConnectToLauncherAsync();
try {
    // waits (blocks execution) until launcher sends the connection configurations
	var config = await launcherClient.WaitForConnectionConfigurationAsync();
	// send custom event
	await launcherClient.SendCustomEventAsync("starting new session");
	...
	// starts remote connection
	...
	// notifies the launcher the remote window is created
	await launcherClient.SendRemoteConnectionWindowCreatedAsync();
	...
	// after the window is closed
	...
    // notifies that the session is ended 
    await launcherClient.SendRemoteConnectionWindowClosedAsync();
}
catch (Exception e){
    // notifies that something went wrong during the connection
    await launcherClient.SendRemoteConnectionFailureAsync(
	    $"Connection failed: {e.Message}");
}

Using the Pipe Without the SDK

This section explains how to communicate with the Launcher over a named pipe without using the Connector SDK. It covers retrieving the pipe name, sending and receiving event messages, and implementing a minimal end-to-end flow.

1. Getting the Pipe Name

When the Launcher starts your connector, it exposes the pipe name through the VSI_IPC_PIPE_NAME environment variable. Your process should:

  1. Read this environment variable.

  2. Use the value to connect as a named pipe client.

Pseudo-code sample:

// get pipe name from env variables
pipeName = getenv("VSI_IPC_PIPE_NAME")
// use pipe name to connect to launcher
pipe = connect_to_named_pipe(pipeName)
// create write and read stream
reader = new TextReader(pipe, encoding=UTF8)
writer = new TextWriter(pipe, encoding=UTF8, autoFlush=true)

2. Event Messages (Newline-Delimited JSON)

Follow the format and structure of event messages exchanged between the Launcher and the Connector.

All messages over the pipe:

  • are UTF-8 encoded text,

  • contain a single JSON object per line, and

  • are terminated by a newline (\n).

Both the Launcher and the connector follow the same pattern:

  • To send a message: serialize the JSON object to a string, then write it, followed by a newline.

  • To receive a message: read a full line (until \n), then parse that line as JSON.

Pseudo-code sample:

// send message
jsonText = serialize_to_json(messageObject)
writer.write_line(jsonText) // appends '\n'
// receive message
line = reader.read_line() // reads until '\n'
messageObject = parse_json(line)

Important: Do not send multiple JSON objects on the same line, and do not rely on length prefixes. Newlines are the only framing mechanism.

3. Launcher > Connector: ConnectionConfiguration

Once your connector is connected to the pipe, the first message the Launcher sends is always a ConnectionConfiguration JSON object:

{
  "sessionId": "<GUID>",
  "host": "<string>",
  "username": "<string>",
  "password": "<string>",
  "domain": "<string>",
  "accountCustomFields": {
    "<string>": "<string>"
  },
  "accountSecureFields": {
    "<string>": "<string>"
  }
}

Use this information to start your remote connection.

4. Connector > Launcher: CustomConnectorEvent

While handling the connection, you can report status back to the Launcher using CustomConnectorEvent messages:

{
  "eventType": "<CustomConnectorEventType>",
  "message": "<string>",
  "processId": <int|null>
}

Where eventType is one of:

[
  "Custom",
  "RemoteConnectionWindowCreated",
  "RemoteConnectionFailure",
  "RemoteConnectionWindowClosed"
]