This is possible. You’ll need to install the SignalR client in your app. Here’s the connection logic. It just connects up to the hub. It uses a different hub if authentication is enabled.
var url = "eventhub";
if (clientConnection.AppToken != null || clientConnection.UseDefaultCredentials)
{
url = "autheventhub";
}
var connection = new HubConnectionBuilder()
.ConfigureLogging(logging =>
{
logging.AddSerilog();
logging.SetMinimumLevel(LogLevel.Debug);
})
.WithUrl($"{clientConnection.Url}/{url}?group={clientConnection.Hub}", options =>
{
if (clientConnection.AppToken != null)
{
options.AccessTokenProvider = () => Task.FromResult(clientConnection.AppToken)!;
}
if (handler != null)
options.HttpMessageHandlerFactory = _ => handler;
options.UseDefaultCredentials = clientConnection.UseDefaultCredentials;
options.Headers.Add("PSUComputerName", Environment.MachineName);
options.Headers.Add("PSUUserName", Environment.UserName);
options.Headers.Add("PSUDomainName", Environment.UserDomainName);
})
.WithAutomaticReconnect(new RetryPolicy())
.Build();
When it receives a “Module” message, it will invoke the command. This method will get the name of the command. The data is a PSSerialized string.
connection.On(clientConnection.Hub + "Module", (string command, string data, bool returnResult) => eventHubExecutor.ExecuteCommand(clientConnection.Hub, command , data, returnResult));
Here’s some psuedocode. PS expects the ExecuteCommand method to return immediately with an execution ID. If not, the hub will only let one command run at a time.
public string ExecuteCommand(string hub, string command, string data, bool returnResult)
{
Log.Information($"Received event on hub {hub}.");
var executionId = Guid.NewGuid().ToString();
_ = Task.Run(() =>
{
var item = PSSerializer.Deserialize(data);
// run command
_output[executionId] = output;
}
return executionId;
}
After executing the command, it will then attempt to get a result back for the command.
connection.On("GetResult", (string eventId) => eventHubExecutor.GetResult(eventId));
It will need to access the _output
collection and return the result.
public string GetResult(string executionId)
{
if (!_output.TryGetValue(executionId, out var result))
{
return "running";
}
_output.TryRemove(executionId, out _);
return result;
}
Hope that helps!