PowerShellでExcahnge Onlineに接続する際の「最大接続数 n を超過したため、実行空間の作成に失敗しました。」を回避する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357828/8bc32533-9f1b-127d-1930-f1edf55abc4d.png)

PowerShellを使ってExchange Onlineのモジュールを使う際のTIPSです。このTIPSはコマンドをコンソールで実行する場面では使いませんが、PowerShellのバッチスクリプトを開発・テストするときに知っておくと役に立ちます。

#まず、PowerShellでExchange Onlineに接続する

PowerShellでExchange Onlineに接続するには「Connect-ExchangeOnline」を実行します。
バッチスクリプトで接続コマンドを使う際には「Credential」オプションで認証情報を渡します。

```powershell
$user = "XXX"
$pass = "XXX" | ConvertTo-SecureString
$credential = New-Object System.Management.Automation.PSCredential $user,$pass

#ExchangeOnlineに接続
Connect-ExchangeOnline -Credential $credential
```

これを実行すると、V1とV2コマンドの違いに関する情報が表示され、接続が完了します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357828/7fd0dfe5-d7b5-ff63-a3d4-4caf0491f8f0.png)

#接続コマンドを複数回実行するとエラーになる
バッチスクリプトの開発・テストをしている場面で上記の接続コマンドを実行するとエラーが表示されることがあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357828/dee77daa-76e5-ba1e-5d2a-df2dee420cf9.png)
エラーメッセージをテキストに起こしたのが以下のものです。メッセージの通り、このエラーはサーバーに対して最大接続数を超えるセッションをはろうとしたことにより発生したエラーです。

ISE等で開発を行う際には、スクリプトの実行を停止してもセッションや変数は自動では解放されないためにこのようなことが起こり得ます。
<font color="Red">
New-ExoPSSession : リモート サーバー outlook.office365.com からのデータの処理に失敗し、次のエラー メッセージが返されました: [AuthZRequestId=d1175b9e-f07f-4a3e-a954-dd7dd4bce7c3][FailureCategory=AuthZ-Au
thorizationException] ポリシー パーティ MaxConcurrency に対して許可されている最大接続数 3 を超過したため、実行空間の作成に失敗しました。既存の実行空間を閉じて終了してからやり直してください。
</font>

#このエラーを回避する方法
結論から言うと、以下の通り分岐条件をいれればこのエラーは回避できます。

```powershell
$user = "XXX"
$pass = "XXX" | ConvertTo-SecureString
$credential = New-Object System.Management.Automation.PSCredential $user,$pass

$PSSession   = Get-PSSession | Select-Object -Property State,Name
$isConnected = ((@($PSSession) -like '@{State=Opened; Name=ExchangeOnlineInternalSession*').Count -gt 0)
If ($isConnected -eq $false) 
{
    #ExchangeOnlineに接続
    Connect-ExchangeOnline -Credential $credential
}
```
#この分岐条件は何をしているのか？

「Get-PSSession」コマンドを使って現在のセッション情報を見て、Exchange Onlineに対してオープンになっているセッションがあるかどうかを確認しています。オープンになっているセッションが無い場合は接続コマンドを実行します。

反対に、既にオープンになっているセッションがある場合は接続コマンドを実行しません。

```powershell
Get-PSSession

 Id Name            ComputerName    ComputerType    State         ConfigurationName     Availability
 -- ----            ------------    ------------    -----         -----------------     ------------
  1 ExchangeOnli... outlook.offi... RemoteMachine   Opened        Microsoft.Exchange       Available
  2 ExchangeOnli... jpn01b.ps.co... RemoteMachine   Opened        Microsoft.Exchange       
```

# おまけ：コンプライアンスセンターへの接続でも同じ方法を使う
この方法は、アイテム保持ポリシーをバッチスクリプトで操作する等のためにコンプライアンスセンターへ接続する場面でも使えます。

```powershell
$user = "XXX"
$pass = "XXX" | ConvertTo-SecureString
$credential = New-Object System.Management.Automation.PSCredential $user,$pass

$PSSession   = Get-PSSession | Select-Object -Property State,Name
$isConnected = ((@($PSSession) -like '@{State=Opened; Name=ExchangeOnlineInternalSession*').Count -gt 0)
If ($isConnected -eq $false) 
{
    #ExchangeOnlineに接続
    Connect-ExchangeOnline -Credential $credential

    #コンプライアンスセンターに接続
    Connect-IPPSSession -UserPrincipalName $user
}
```
以上です。