Hey, I’m maybe trying to put together something unconventional and if there is better ways to do this i’m very keen to know.
So, I already got a working cmdlet that has some C# code to access a websocketsharp dll, with it i’m sending a command to a remote websocket server and it is returning the value to the output stream.
I want to incorporate this functionality intoa UD Dashboard that I just started tinkering with but I’m facing issues with Add-Type not working properly in the context of the dashboard.
function Send-Cmd
{
[CmdletBinding()]
Param (
[Parameter(Mandatory = $True)]
[string]$WSEndpointUrl,
[Parameter(Mandatory = $True)]
[string]$Command
)
try
{
Add-Type -Path ".\websocket-sharp.dll"
Add-Type -Path ".\Newtonsoft.Json.dll"
}
catch [System.Reflection.ReflectionTypeLoadException]
{
Write-Host "Message: $($_.Exception.Message)"
Write-Host "StackTrace: $($_.Exception.StackTrace)"
Write-Host "LoaderExceptions: $($_.Exception.LoaderExceptions)"
}
$CurrentlyLoadedAssemblies = [System.AppDomain]::CurrentDomain.GetAssemblies()
$AssembiesFullInfo = $CurrentlyLoadedAssemblies | Where-Object {
$_.GetName().Name -eq "Microsoft.CSharp" -or
$_.GetName().Name -eq "mscorlib" -or
$_.GetName().Name -eq "System" -or
$_.GetName().Name -eq "System.Collections" -or
$_.GetName().Name -eq "System.Core" -or
$_.GetName().Name -eq "System.IO" -or
$_.GetName().Name -eq "System.Linq" -or
$_.GetName().Name -eq "System.Runtime" -or
$_.GetName().Name -eq "System.Runtime.Extensions" -or
$_.GetName().Name -eq "System.Runtime.InteropServices" -or
$_.GetName().Name -eq "System.Threading" -or
$_.GetName().Name -eq "websocket-sharp" -or
$_.GetName().Name -eq "Newtonsoft.Json"
}
$AssembiesFullInfo = $AssembiesFullInfo | Where-Object {$_.IsDynamic -eq $False}
$ReferencedAssemblies = $AssembiesFullInfo.FullName | Sort-Object | Get-Unique
$usingStatementsAsString = @"
using Microsoft.CSharp;
using System.Collections.Generic;
using System.Collections;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime;
using System.Threading;
using System;
using WebSocketSharp;
using System.Net.WebSockets;
using Newtonsoft.Json;
"@
$TypeDefinition = @"
$usingStatementsAsString
namespace MyCore.Utils
{
public class WebSocketClient
{
public static string StartWSSession(string url, string cmd)
{
string reply = null;
using (var ws = new WebSocketSharp.WebSocket(url))
{
int received = 0;
// Set the WebSocket events.
ws.OnOpen += (sender, e) =>
{
Response jsonmsg = new Response();
jsonmsg.Identifier = 2000;
jsonmsg.Message = cmd;
jsonmsg.Name = "PowershellWS";
string output = JsonConvert.SerializeObject(jsonmsg);
ws.Send(output);
};
ws.OnMessage += (sender, e) => {
Response response = JsonConvert.DeserializeObject<Response>(e.Data);
if (response.Identifier == 2000) {
Console.WriteLine(response.Message);
reply = response.Message;
received ++;
ws.Close();
}
};
ws.OnError += (sender, e) =>
Console.WriteLine(e.Message);
ws.OnClose += (sender, e) =>
Console.WriteLine(e.Reason);
// Connect to the server.
ws.Connect();
while (received < 1){Thread.Sleep(1);}
}
return reply;
}
}
internal class Response
{
[JsonProperty(PropertyName = "Identifier")]
public int Identifier { get; set; }
[JsonProperty(PropertyName = "Message")]
public string Message { get; set; }
[JsonProperty(PropertyName = "Name")]
public string Name { get; set; }
}
}
"@
Add-Type -ReferencedAssemblies $ReferencedAssemblies -TypeDefinition $TypeDefinition
return [MyCore.Utils.WebsocketClient]::StartWSSession($WSEndpointUrl,$Command)
$WS.Assemblies.Add(".\Newtonsoft.Json.dll")
$WS.Assemblies.Add(".\websocket-sharp.dll")
$WS = New-UDEndpointInitialization -Function @("Send-Cmd")
$Dashboard = New-UDDashboard -Title "Testing" -Content {
New-UDCard -Title "Title" -Endpoint {Send-Cmd -WSEndpointUrl ws://websocket-server.com -Command hello}
} -EndpointInitialization $WS
Enable-UDLogging
Start-UDDashboard -Dashboard $Dashboard -Port 10001