コルネの進捗や備忘録が記されたなにか

進捗や成果物や備忘録てきななにかを雑に更新していきます。


スポンサードリンク

【PowerShell Runbook】 入力パラメータの型検証


スポンサードリンク

はじめに

この記事は、PoweShell Runbook で、入力パラメータにて値を渡したときその値の型はどうなるのか?
を検証した記事になります。

誤っている箇所があればご指摘いただければと思います。

型検証を行おうと思ったきっかけはこちらの記事で、Power Automate からJSON 値を渡したはずがConvertFrom-Json でなぜか失敗してしまったことがきっかけです。
Microsoft 365 ユーザーアカウントの作成を自動化する

PowerShell Runbook での入力パラメータの構成方法

PowerShell Runbook で入力パラメータを構成するには、以下のように記述します。

Param
(
  [Parameter (Mandatory= $true/$false)]
  [Type] $Name1 = <Default value>,

  [Parameter (Mandatory= $true/$false)]
  [Type] $Name2 = <Default value>
)

詳しくは以下の公式doc をご確認ください。

docs.microsoft.com

検証

PowerShell Runbook の作成

今回作成したPowerShell Runbook には以下のような検証用シェルを作成しました。
PowerShell Runbook の詳しい作成方法は今回省きます。

Param
(
    $str_1,[string]$str_2,
    $num_1,[int]$num_2,
    $json_1,$json_2,$json_3
)

$str = "str"
$num = 1
$json = '{ "name": "korune" }'

echo ("str:" + $str)
echo (" - type:" + $str.GetType().FullName)

echo  "`r`n"

echo ("num:" + $num)
echo (" - type:" + $num.GetType().FullName)

echo  "`r`n"

echo ("json:" + $json)
echo (" - type:" + $json.GetType().FullName)

echo  "`r`n"

echo ("str_1:" + $str_1)
echo (" - type:" + $str_1.GetType().FullName)
echo ("str_2:" + $str_2)
echo (" - type:" + $str_2.GetType().FullName)

echo  "`r`n"

echo ("num_1:" + $num_1)
echo (" - type:" + $num_1.GetType().FullName)
echo ("num_2:" + $num_2)
echo (" - type:" + $num_2.GetType().FullName)

echo  "`r`n"

echo ("json_1:" + $json_1)
echo (" - type:" + $json_1.GetType().FullName)
echo ("json_2:" + $json_2)
echo (" - type:" + $json_2.GetType().FullName)
echo ("json_3:" + $json_3)
echo (" - type:" + $json_3.GetType().FullName)

echo  "`r`n"

echo ("`r`n---ConvertFrom-Json----`r`n")

$convert_json = ConvertFrom-Json $json
echo ("json:" + $convert_json)
echo (" - type:" + $convert_json.GetType().FullName)
echo  "`r`n"

$convert_json_1 = ConvertFrom-Json $json_1
echo ("json_1:" + $convert_json_1)
echo (" - type:" + $convert_json_1.GetType().FullName)
echo  "`r`n"

$convert_json_2 = ConvertFrom-Json $json_2
echo ("json_2:" + $convert_json_2)
echo (" - type:" + $convert_json_2.GetType().FullName)
echo  "`r`n"

$convert_json_3 = ConvertFrom-Json $json_3
echo ("json_3:" + $convert_json_3)
echo (" - type:" + $convert_json_3.GetType().FullName)
echo  "`r`n"

echo ("`r`n---ConvertFrom-Json(not in param)----`r`n")

echo ("json")
ConvertFrom-Json $json
echo  "`r`n"

echo ("json_1")
ConvertFrom-Json $json_1
echo  "`r`n"

echo ("json_2")
ConvertFrom-Json $json_2
echo  "`r`n"

echo ("json_3")
ConvertFrom-Json $json_3

ただ実際変数に設定されている値と、その型がわかり、またConvertFrom-Json で失敗するのはどういったケースなのか?
がわかればいいので、書き方は適当です。

テスト実行

それぞれ以下の画像のような変数を設定して実行してみました。

f:id:koruneko:20210217014859p:plain

その際の出力は以下のようになりました。

str:str
 - type:System.String

num:1
 - type:System.Int32

json:{ "name": "korune" }
 - type:System.String

str_1:a
 - type:System.String
str_2:b
 - type:System.String

num_1:1
 - type:System.String
num_2:2
 - type:System.Int32

json_1:{ "name": "korune" }
 - type:System.String
json_2:'{ "name": "korune" }'
 - type:System.String
json_3:[{ "name": "korune" }]
 - type:System.String


---ConvertFrom-Json----
json:@{name=korune}
 - type:System.Management.Automation.PSCustomObject

json_1:@{name=korune}
 - type:System.Management.Automation.PSCustomObject

json_2:{ "name": "korune" }
 - type:System.String

json_3:
 - type:System.Object[]


---ConvertFrom-Json(not in param)----
json

name  
----  
korune

json_1

name  
----  
korune

json_2
{ "name": "korune" }

json_3

Length         : 1
LongLength     : 1
Rank           : 1
SyncRoot       : {@{name=korune}}
IsReadOnly     : False
IsFixedSize    : True
IsSynchronized : False
Count          : 1

番号(_X)が変数の末についていないものは、変数の値をシェル内で定義しています。
変数の末が_1のものは、Param() にて型宣言を行わずに変数を定義しています。
変数の末が_2のものは、Param() にて型宣言を行って変数を定義しています。
* JSON 除く

JSON の型宣言を行っていないのはJSON 型というものが存在しないためです。

ちなみにPowerShell で利用可能な型は以下になります。

Type Name
[array] [System.Array]
[bool] [System.Boolean]
[byte] [System.Byte]
[char] [System.Char]
[datetime] [System.DateTime]
[decimal] [System.Decimal]
[double] [System.Double]
[guid] [System.Guid]
[hashtable] [System.Collections.Hashtable]
[int16] [System.Int16]
[int32][int] [System.Int32]
[int64][long] [System.Int64]
[nullable] [System.Nullable]
[psobject] [System.Management.Automation.PSObject]
[regex] [System.Text.RegularExpressions.Regex]
[sbyte] [System.SByte]
[scriptblock] [System.Management.Automation.ScriptBlock]
[single][float] [System.Single]
[string] [System.String]
[switch] [System.Management.Automation.SwitchParameter]
[timespan] [System.TimeSpan]
[type] [System.Type]
[uint16] [System.UInt16]
[uint32] [System.UInt32]
[uint64] [System.UInt64]
[xml] [System.Xml.XmlDocument]

出力結果を纏めると以下のようになります。

設定値と型の関係

変数名 備考 設定値
str シェル内定義 str System.String
str_1 型宣言なし a System.String
str_2 型宣言あり[string] b System.String
num シェル内定義 1 System.Int32
num_1 型宣言なし 1 System.String
num_2 型宣言あり[int] 2 System.Int32
json シェル内定義 { "name": "korune" } System.String
json_1 型宣言なし { "name": "korune" } System.String
json_2 型宣言なし '{ "name": "korune" }' System.String
json_3 型宣言なし [{ "name": "korune" }] System.String

ConvertFrom-Json の結果

変数名 設定値 出力
json { "name": "korune" } name
----
korune
System.Management.Automation.PSCustomObject
json_1 { "name": "korune" } name
----
korune
System.Management.Automation.PSCustomObject
json_2 '{ "name": "korune" }' { "name": "korune" } System.String
json_3 [{ "name": "korune" }] Length : 1
LongLength : 1
Rank : 1
SyncRoot : {@{name=korune}}
IsReadOnly : False
IsFixedSize : True
IsSynchronized : False
Count : 1
System.Object[]

ConvertFrom-Json の結果はドキュメントを確認すると、 System.Management.Automation.PSCustomObject となっている。
ConvertFrom-Json

json_2json_3 の結果は System.Management.Automation.PSCustomObject ではないが、何故エラーになっていない?
私の知識が足りないので、ここはもう少し調査を行う必要がある。。。

Power Automate からPowerShell Runbook に値を渡してみる

Power Automate からPowerShell Runbook に値を渡すようフローを作成します。
渡す値は先ほどと同じ値を渡したいと思います。

その結果が以下になります。

f:id:koruneko:20210222014457p:plain

json_2 にて "有効な JSON を入力してください。" とでているのはPowerShell 内で ConvertFrom-Json を利用しているのでその解析結果によるものかと思いますが、 str_1 で同様のエラーがでているのは何故??
Object 型から string 型への変換に失敗してこのエラーがでている?? こちらの公式ドキュメントのRunbook の入力パラメーターを構成する - Runbook に JSON オブジェクトを渡すをみてみると、

JSON データを受け入れるには、Runbook は、入力パラメーターとしてオブジェクトを受け取る必要があります

と記載されています。

これは私の推測なので詳細はわかりませんが、この"ジョブの作成"コネクタのエラーハンドリングが適切ではないのでは??と推測しました。
ここは中のソースを確認するなりサポートに確認するなりしないとわからないですね。

必須項目にはしていないので、該当項目を空白にして保存を行ったところ以下エラーが出力されました。

f:id:koruneko:20210222015746p:plain

フローの保存がコード 'OpenApiOperationParameterValidationFailed' およびメッセージ '入力パラメーター 'body' の検証がワークフロー操作 'ジョブの作成' で失敗しました: 種類/形式 'Integer' のパス 'body/properties/parameters/num_1' にある値 '1' のパラメーターは、種類/形式 'Object' に変換できません。' で失敗しました。

先ほどRunbook のテストを行うときにパラメータ入力のスクショを貼り付けましたが、その際、型の宣言を行わなかった変数の型は 'Object' と表示されていたかと思います。

f:id:koruneko:20210222020308p:plain

このことから型のデフォルト設定値は Object だということがわかりますが、公式ドキュメントみるとそもそもPowerShell Runbook の入力パラメーターの Type は必須になっていて、デフォルト値がなにか記載とかないんですよね...
Runbook の入力パラメーターを構成する - PowerShell Runbook の入力パラメーターを構成する

まぁ、ちゃんと型宣言しろよ。ってことかもしれませんが、これPowerShell Runbook 側でエラーとかださなくていいんですかね?もしくはドキュメントの記載を変えるか。
PowerShell の構文としては問題ないので、ドキュメントの記載方法変えたほうがいいような...と思いますが、私がなにか勘違いしているのでしょうかね。

とりあえずこのことからも、型の宣言はきちんと行っておくべきだということがわかりますね。

対象項目を空白にしましたが、問題はまだあります。

f:id:koruneko:20210222021114p:plain

フローの保存がコード 'OpenApiOperationParameterValidationFailed' およびメッセージ '入力パラメーター 'body' の検証がワークフロー操作 'ジョブの作成' で失敗しました: API 操作 'CreateJob' では、プロパティ 'body/properties/parameters/json_3' の種類を 'Object' にする必要がありますが、種類が 'Array' です。' で失敗しました。

指摘の通り、 [{ "name": "korune" }] は配列なのでエラーがでています。
一旦上の3つの項目、

  • str_2
  • num_2
  • json_1

だけを設定して実行してみます。

その結果が以下になります。

str:str
 - type:System.String

num:1
 - type:System.Int32

json:{ "name": "korune" }
 - type:System.String

str_1:
str_2:b
 - type:System.String

num_1:
num_2:1
 - type:System.Int32

json_1:@{name=korune}
 - type:System.Management.Automation.PSCustomObject
json_2:
json_3:

---ConvertFrom-Json----
json:@{name=korune}
 - type:System.Management.Automation.PSCustomObject

json_1:

json_2:

json_3:

---ConvertFrom-Json(not in param)----
json

name  
----  
korune


json_1

json_2

json_3

ConvertTo-Json できてないじゃん...

入力値を確認してみます。

f:id:koruneko:20210222022040p:plain

入力値としては想定通りの値が渡ってきています。

ログをみてみます。

f:id:koruneko:20210222022306p:plain

f:id:koruneko:20210222022330p:plain

Invalid JSON primitive: .

つまりJSON じゃないといわれていますね。

出力結果をみてみると、 json_1 は以下のように出力されています。

json_1:@{name=korune}
 - type:System.Management.Automation.PSCustomObject

このことから、どうやらPower Automate からPowerShell Runbook へJSON を渡したときは ConvertTo-Json が行われた結果が変数に設定されるようです。

これは、shibatea さんがMicrosoft 365 ユーザーアカウントの作成を自動化するのコメントでも記載してくれている通り、Power Automate の"ジョブの作成"のRunbook のパラメーターの型は dynamic (動的) なので、渡したパラメーターを自動的に型解決してくれているのだと思います。

Azure Automation - Connectors | Microsoft Docs

このことから考えてもちゃんと型宣言しておくべきですね。

おわりに

以上、PowerShell Runbook の入力パラメータの型検証結果でした。

私の推測より記載している部分が多々ありますので、あくまでも参考程度にしていただければと思います。
また、誤っている情報がありましたら、指摘していただけると助かります。


スポンサードリンク