Powershell cmdlet中的C#代码不输出值

时间:2019-07-28 14:48:35

标签: c# powershell

我已经编写了一个Powershell cmdlet,该cmdlet使用C#使用一些DLL。 WebsocketSharp 以及Newtonsoft JSON。

应该将json字符串发送到websocket服务器,然后将回复返回到Out-File,或者用作另一个上下文中的变量,即

$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#控制台行流是独立的吗?我将如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

所以...看起来我犯了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是理所当然的,现在对返回的变量使用返回值,因此它实际上返回一个值,并且函数本身不能为空,因为这意味着它根本不返回任何内容,因此必须成为“字符串”