質問するログイン新規登録
.NET

.NETとは、主に.NET Frameworkと呼ばれるアプリケーションまたは開発環境を指します。CLR(共通言語ランタイム)を搭載し、入力された言語をCIL(共通中間言語)に変換・実行することが可能です。そのため、C#やPythonなど複数の言語を用いることができます。

WebSocket

WebSocketとは双方向・全二重コミュニケーションのためのAPIでありプロトコルのことを指します。WebSocketはHTML5に密接に結びついており、多くのウェブブラウザの最新版に導入されています。

PowerShell

Windows PowerShellはコマンドラインインターフェースであり、システム管理を含むWindowsタスク自動化のためのスクリプト言語です。

Q&A

解決済

1回答

595閲覧

型が自動的にキャストされてエラーになる!

Workshop_Lilla

総合スコア1

.NET

.NETとは、主に.NET Frameworkと呼ばれるアプリケーションまたは開発環境を指します。CLR(共通言語ランタイム)を搭載し、入力された言語をCIL(共通中間言語)に変換・実行することが可能です。そのため、C#やPythonなど複数の言語を用いることができます。

WebSocket

WebSocketとは双方向・全二重コミュニケーションのためのAPIでありプロトコルのことを指します。WebSocketはHTML5に密接に結びついており、多くのウェブブラウザの最新版に導入されています。

PowerShell

Windows PowerShellはコマンドラインインターフェースであり、システム管理を含むWindowsタスク自動化のためのスクリプト言語です。

0グッド

0クリップ

投稿2025/06/27 00:02

編集2025/06/27 00:26

0

0

実現したいこと

PowerShellでWebSocketのサーバを作っていますが、エラーが出ます。

詳細

.Net の System.Net を使って WebScoket のサーバを作っています。
下記のリファレンスの通り、次のようにコールしているんですが、後述のようなエラーが出てしまいます。

リファレンス

https://learn.microsoft.com/ja-jp/dotnet/api/system.net.httplistenercontext.acceptwebsocketasync?view=net-8.0

コール

$objContext.AcceptWebSocketAsync($null)

発生している問題・エラーメッセージ

"1" 個の引数を指定して "AcceptWebSocketAsync" を呼び出し中に例外が発生しました: "空の文字列は、有効な subprotocol 値ではありません。値を指定しない場合は、"null" を使用してください。

試したこと

調べた限りでは、この関数のオーバーロードのもととなる関数は引数が3つの関数のようでしたので、そのリファレンスに従ってコールしましたが、同じエラーが出ました。
おそらく、なぜか null が string にキャストされて string.empty になってるんだと思いますが、解決策がわかりません。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

$objContext.AcceptWebSocketAsync($null)での呼び出し部分は、$nullではなく[NullString]::Valueで指定すると成功します。

PowerShell

1 $wsContextTask = $context.AcceptWebSocketAsync([NullString]::Value)

以下の簡単なPowerShellスクリプトによるWebSocketサーバーのサンプルプログラムで実行例を示します。もとはAIのCopilotさん提案のコードを元に、更に簡単にしたものです。尚、クライアント側はWebブラウザー上からJavaScriptで実行する簡単なコードなので、割愛します。

PowerShell

1# t4c.ps1 2#Add-Type -AssemblyName System.Net.HttpListener 3#Add-Type -AssemblyName System.Net.WebSockets 4 5$listener = New-Object System.Net.HttpListener 6$listener.Prefixes.Add("http://localhost:8081/ws/") 7$listener.Start() 8Write-Host "Listening on ws://localhost:8081/ws/..." 9$context = $listener.GetContext() 10 11if ($context.Request.IsWebSocketRequest) { 12 # Accept the WebSocket connection 13 # $nullでは失敗する 14 $wsContextTask = $context.AcceptWebSocketAsync($null) 15 Write-Host "#pass1 : $wsContextTask" 16 17 # [NullString]::Valueで成功する 18 $wsContextTask = $context.AcceptWebSocketAsync([NullString]::Value) 19 20 # $wsContextTaskが返っていることを確認 21 Write-Host "#pass2 : $wsContextTask" 22 $wsContextTask.Wait() 23 24 $wsContext = $wsContextTask.Result 25 $websocket = $wsContext.WebSocket 26 27 Write-Host "WebSocket connection accepted!" 28 29 $websocket.Dispose() 30} else { 31 $context.Response.StatusCode = 400 32 $context.Response.Close() 33 Write-Host "Rejected non-WebSocket request." 34}

クライアントからはws://localhost:8081/ws/で接続します。これを実行してみます。

PowerShell

1PS> # PowerShellのバージョン 2PS> $PSVersionTable 3 4Name Value 5---- ----- 6PSVersion 5.1.19041.5965 7PSEdition Desktop 8PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...} 9BuildVersion 10.0.19041.5965 10CLRVersion 4.0.30319.42000 11WSManStackVersion 3.0 12PSRemotingProtocolVersion 2.3 13SerializationVersion 1.1.0.1 14 15 16PS> PowerShell -ExecutionPolicy RemoteSigned .\t4c.ps1 17Listening on ws://localhost:8081/ws/... 18"1" 個の引数を指定して "AcceptWebSocketAsync" を呼び出し中に例外が発生しました: "空の文字列は、有効な subprotocol 値で 19はありません。値を指定しない場合は、"null" を使用してください。 20パラメーター名:subProtocol" 21発生場所 C:\_work\ClassLibrary1\t4c.ps1:14 文字:5 22+ $wsContextTask = $context.AcceptWebSocketAsync($null) 23+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 24 + CategoryInfo : NotSpecified: (:) [], MethodInvocationException 25 + FullyQualifiedErrorId : ArgumentException 26 27#pass1 : 28#pass2 : System.Threading.Tasks.Task`1[System.Net.WebSockets.HttpListenerWebSocketContext] 29WebSocket connection accepted! 30PS> 31

$nullを指定しての呼び出しではご質問と同様のエラーが発生し、[NullString]::Valueでは成功していることが分かると思います。

おそらく、なぜか null が string にキャストされて string.empty になってるんだと思いますが、

これはほぼご推測の通りで、.NETのメソッドについて$nullSystem.String型の引数に指定するとPowerShellによってnullではなく空文字列""に変換されてしまうようです。Microsoftが個人のブログを共有したかたちで記事を載せているので、公式の情報と言ってよいのでしょう。

$nullについて知りたいこと - Microsoft Learn

※上記は自動翻訳による日本語記事なので、ところどころ読みづらい部分があります。元の英語記事はこちら。
Everything you wanted to know about $null - Microsoft Learn

nullではない空文字列は$s = ""のように表現できるのに、$nullSystem.Stringな引数に渡したメソッド呼び出し時に変換されてしまうのは私個人的にもちょっと不便、と言うか余計なお世話にも感じますね。まぁ、スクリプトと.NETの相互運用性から便宜を図る意図があったのでしょう。


[NullString]::Value について追記:

[NullString]::ValueについてはPowerShellの$nullとC#のstringの扱いについての話題でたまに見かけるのですが、なかなか公式のリファレンスには辿り着きづらいようです。今回の回答にあたって気になっていたので、少し調べていました。

PowerShell SDKの以下の情報がそれにあたるようです。

NullString Class - Microsoft Learn

Definition
...
This type is introduced to provide a way to pass null into a .NET method that has a string parameter.

との説明なので、まさにその用途のクラスですね。

投稿2025/06/28 03:44

編集2025/06/29 17:47
dodox86

総合スコア9418

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2025/06/28 04:30

ちなみにAIを使う場合(私の場合は主にCopilotさん)ですが、.NETのメソッドのSystem.Stringの引数に渡すのに$nullを使うかんじの使えない代替の提案をしてくるのが主でした。[NullString]::Valueにはなかなかたどり着けないかもしれません。単にWEB検索しても、少なくとも現時点では[NullString]については情報が少ないですね。
Workshop_Lilla

2025/06/29 23:53

回答ありがとうございます。 試したところ問題が解決しました! ベストアンサーに選ばせていただきました。 これは自力では全然たどり着けませんでした、お見事です!ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問