如何使用PowerShell V2使用Websocket客户端打开与URL的长期连接?

时间:2016-10-26 08:46:45

标签: json powershell asynchronous websocket slack-api

我正在尝试使用PowerShell V2(测试目的)来启动Slack的实时消息传递(rtm)实例。但是根据Slack的常见问题解答,要连接到他们的rtm API,我需要通过Websocket客户端使用wss://协议来传输相关的事件。我也试图使它成为异步连接(接收和连接)。

这不起作用:

$webSock = New-Object System.Net.WebSocket.ClientWebSocket
$client = New-Object System.Threading.CancellationToken

另一件事是我需要一个函数来从PowerShell V2中的JSON转换。

我尝试过使用它,但它也不起作用:

function ConvertFrom-Json20([object] $item){ 
    add-type -assembly system.web.extensions
    $ps_js=new-object system.web.script.serialization.javascriptSerializer

    #The comma operator is the array construction operator in PowerShell
    return ,$ps_js.DeserializeObject($item)
}

2 个答案:

答案 0 :(得分:4)

可以使用.NET的System.Net.WebSockets.ClientWebSocket类来执行此操作。您需要运行Windows 8或Server 2012或更高版本作为底层操作系统才能使用此类,因此我认为您至少拥有PowerShell v3(因此ConvertFrom-Json cmdlet)。您还需要使用System.ArraySegment .NET类。

我创建了一个简单的框架,演示了如何使用各种类与PowerShell脚本中的Slack RTM API进行交互。你可以在这里找到GitHub上的项目: https://github.com/markwragg/Powershell-SlackBot

我还在这里更详细地写了一篇博文:http://wragg.io/powershell-slack-bot-using-the-real-time-messaging-api/

答案 1 :(得分:3)

奇怪的是,我最近也有同样的需求。感谢Mark Wragg及其有用的链接,这里有一些快速的代码可以实现这一目标。您至少需要Windows 8和Server 2012才能使这些工作正常。

Try{  
    Do{
        $URL = 'ws://YOUR_URL_HERE/API/WebSocketHandler.ashx'
        $WS = New-Object System.Net.WebSockets.ClientWebSocket                                                
        $CT = New-Object System.Threading.CancellationToken
        $WS.Options.UseDefaultCredentials = $true

        #Get connected
        $Conn = $WS.ConnectAsync($URL, $CT)
        While (!$Conn.IsCompleted) { 
            Start-Sleep -Milliseconds 100 
        }
        Write-Host "Connected to $($URL)"
        $Size = 1024
        $Array = [byte[]] @(,0) * $Size

        #Send Starting Request
        $Command = [System.Text.Encoding]::UTF8.GetBytes("ACTION=Command")
        $Send = New-Object System.ArraySegment[byte] -ArgumentList @(,$Command)            
        $Conn = $WS.SendAsync($Send, [System.Net.WebSockets.WebSocketMessageType]::Text, $true, $CT)

        While (!$Conn.IsCompleted) { 
            #Write-Host "Sleeping for 100 ms"
            Start-Sleep -Milliseconds 100 
        }

        Write-Host "Finished Sending Request"

        #Start reading the received items
        While ($WS.State -eq 'Open') {                        

            $Recv = New-Object System.ArraySegment[byte] -ArgumentList @(,$Array)
            $Conn = $WS.ReceiveAsync($Recv, $CT)
            While (!$Conn.IsCompleted) { 
                    #Write-Host "Sleeping for 100 ms"
                    Start-Sleep -Milliseconds 100 
            }

            #Write-Host "Finished Receiving Request"

            Write-Host [System.Text.Encoding]::utf8.GetString($Recv.array)


        }   
    } Until ($WS.State -ne 'Open')

}Finally{

    If ($WS) { 
        Write-Host "Closing websocket"
        $WS.Dispose()
    }

}