我写了一个使用C#的dll的powershell cmdletWebSocketSharp和Newtonsoft JSON。
应该将JSON字符串发送到WebSocket服务器,然后将答复返回到外文件中,或在其他上下文中用作变量,即
$varWithReply = Send-Cmd("ws://websocket-server.com/","mycommand")
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 void StartWSSession(string url, string cmd)
{
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);
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);}
}
}
}
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)
}
我尝试了
$varWithReply = Send-Cmd("ws://websocket-server.com/","mycommand")
Send-Cmd("ws://websocket-server.com/","mycommand") | Out-File .output.txt
,但我根本没有输出。这是因为C#控制台线流是独立的吗?我将如何解决此问题?
所以...看起来我犯了一个菜单错误。谢谢 @H.G。Sandhagen用您的评论指向正确的方向。
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; }
}
}
我认为PS是理所当然的,现在使用我做出的变量回复的回报,因此它实际上返回一个值,并且功能本身不能无效,因为这意味着它根本没有返回任何内容,必须成为"字符串"