SHIMSOFT-MS365info.psm1
function Get-MS365Info { <# .SYNOPSIS 「ライセンスのための製品名とサービス プラン 識別子」サイトの情報をもとに、 Microsoft 365 サービスの一覧情報を取得します。 https://learn.microsoft.com/ja-jp/entra/identity/users/licensing-service-plan-reference .DESCRIPTION 「ライセンスのための製品名とサービス プラン 識別子」サイトの情報をもとに、 Microsoft 365 サービスの一覧情報を取得します。 https://learn.microsoft.com/ja-jp/entra/identity/users/licensing-service-plan-reference サイトから取得した情報はキャッシュされ、基本的にはローカルにダウンロード済み情報から 応答を返します。明示的に ClearCache オプションを指定するか、キャッシュ情報が古いと判断された場合に 再ダウンロードされます。 .EXAMPLE Get-MS365info ---------- Microsoft 365 関連プランが網羅されます。 .EXAMPLE Get-MS365info -Language ko-kr -ClearCache ---------- 現在保持しているキャッシュをリフレッシュし、製品名を韓国語ローカライズします。 .EXAMPLE Get-MS365info -ClearCache -noLocalize ---------- 現在保持しているキャッシュをリフレッシュしますが、製品名のローカライズを行わずリフレッシュを行います。 .EXAMPLE Get-MS365info -Type Product ---------- Microsoft 365 関連プランのうち、スイート・単体プランのものが列挙されます。 .EXAMPLE Get-MS365info -Type ServicePlan ---------- Microsoft 365 関連プランのうち、Service Plan のものが列挙されます。 .EXAMPLE Get-MS365info -Type Suite ---------- Microsoft 365 関連プランのうち、複数の Service Plan を含むものをスイートとして列挙します。 .PARAMETER Language 既定値 $PSCulture 参照するサイトの言語を指定します。例 "ja-jp" や "en-us" .PARAMETER ClearCache キャッシュファイルをクリアし、サービス一覧をリフレッシュします。 .PARAMETER noLocalize キャッシュファイルをリフレッシュする再に指定言語でのローカライズをスキップし、時間短縮します。 ローカライズ説明として元データの CSV に含まれるものに合わせられます。 .PARAMETER Quiet キャッシュファイルを更新・再構築する際に進捗情報表示を最小限にします。 .PARAMETER Silent キャッシュファイルを更新・再構築する際に進捗情報表示を非表示にします。 .LINK .NOTES ja.exchange-rates.org の Web サイト利用は無許可利用です。 .INPUTS なし。パイプラインからの入力は受け付けません。 .OUTPUTS 換算結果は文字列です。 ListCurrencyID オプション指定時の結果は通貨オブジェクトの配列です。(Obj.Country / Unit / Code) #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingWriteHost", "", Justification="Progress information")] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSReviewUnusedParameter", "", Justification="Parameter used.")] Param( [Parameter(Mandatory=$false,Position=1)] [ValidateSet("af-za","am-et","ar-sa","as-in","az-latn-az","be-by","bg-bg","bn-in","bs-latn-ba","ca-es","ca-es-valencia","chr-cher-us","cs-cz","cy-gb","da-dk","de-de","el-gr","en-gb","en-us","es-es","es-mx","et-ee","eu-es","fa-ir","fi-fi","fil-ph","fr-ca","fr-fr","ga-ie","gd-gb","gl-es","gu-in","he-il","hi-in","hr-hr","hu-hu","hy-am","id-id","is-is","it-it","ja-jp","ka-ge","kk-kz","km-kh","kn-in","kok-in","ko-kr","lb-lu","lo-la","lt-lt","lv-lv","mi-nz","mk-mk","ml-in","mr-in","ms-my","mt-mt","nb-no","ne-np","nl-nl","nn-no","or-in","pa-in","pl-pl","pt-br","pt-pt","quz-pe","ro-ro","ru-ru","sk-sk","sl-si","sq-al","sr-cyrl-ba","sr-cyrl-rs","sr-latn-rs","sv-se","ta-in","te-in","th-th","tr-tr","tt-ru","ug-cn","uk-ua","ur-pk","uz-latn-uz","vi-vn","zh-cn","zh-tw")] [String]$Language=($PSCulture.toLower()), [Parameter(Mandatory=$false,Position=2)] [Switch]$noLocalize, [Parameter(Mandatory=$false,Position=3)] [ValidateSet("Product","ServicePlan","Suite","All")] [String]$Type="All", [Parameter(Mandatory=$false,Position=4)] [Switch]$ClearCache, [Parameter(Mandatory=$false,Position=5)] [Switch]$Quiet, [Parameter(Mandatory=$false,Position=6)] [Switch]$Silent ) $CSVURL = "https://download.microsoft.com/download/e/3/e/e3e9faf2-f28b-490a-9ada-c6089a1fc5b0/Product%20names%20and%20service%20plan%20identifiers%20for%20licensing.csv" $DescUrl_1 = "https://learn.microsoft.com/" $DescURL_2 = "/entra/identity/users/licensing-service-plan-reference" $DescURL = ("{0}{1}{2}" -f $DescURL_1,$Language,$DescURL_2) $CacheFile =("MS365info_{0}.csv" -f $Language) $CacheIsActive = $False if (Test-Path -Path "$PSScriptRoot\$CacheFile") { if ((Get-Date -Date (Get-ChildItem "$PSScriptRoot\$CacheFile").LastWriteTime -Format "yyyyMM") -eq (Get-Date -Format "yyyyMM")) { $PlanList = Import-Csv -Encoding Default -Path "$PSScriptRoot\$CacheFile" $CacheIsActive = $True } } if ($ClearCache) { $CacheIsActive = $False } if ($CacheIsActive -eq $False) { if ($False -eq $Silent) { Write-Host ("Refreshing cache file{0}." -f (" with no Localize"*[int][bool]::Parse($noLocalize))) } $wc = New-Object System.Net.WebClient $url = $CSVURL $st = $wc.OpenRead($url) $enc = [System.Text.Encoding]::GetEncoding("UTF-8") $sr = New-Object System.IO.StreamReader($st, $enc) $html = $sr.ReadToEnd() $sr.Close() # CSV file Get $SVCList = ConvertFrom-CSV $html $PlanList = @() if ($False -eq $noLocalize) { $url = $DescURL $st = $wc.OpenRead($url) $enc = [System.Text.Encoding]::GetEncoding("UTF-8") $sr = New-Object System.IO.StreamReader($st, $enc) $html = $sr.ReadToEnd() $sr.Close() $htmlLine = $html.Split("`n") #データ参照範囲削減 $Idx = $htmlLine.indexOf("<table>") $SubIdx = $htmlLine.indexOf("</table>") $htmlLine = $htmlLine[($idx)..($subIdx)] $ProductList = ($SVCList.String_ID | Sort-Object -Unique).Trim() $ServiceList = ($SVCList.Service_Plan_Name | Sort-Object -Unique | Where-Object {$_ -notin $ProductList }).Trim() $LocalizeName = @() $i = 1 $NumOf = $Productlist.count if ($False -eq $Silent) { Write-Host ("ProductList {0} Localizing..." -f $Language) } # ProductList 分の LocalaizeName を生成 foreach ($PSL in $ProductList) { $i++ if (($False -eq $Silent) -and ($False -eq $Quiet)) { if (($i % 100) -eq 0) { Write-Host ("{0} / {1} `t" -f $i,$NumOf) } } $Work1 = @($htmlLine | Where-Object {$_ -like ("*>{0}<*" -f ($PSL.Trim() -replace (" ",""))) }) $Idx = $htmlLine.indexOf($Work1[0]) if (-1 -ne $Idx) { $Work1 = $htmlLine[($idx-1)] -Replace ("<[/]*td>","") if ("" -eq $Work1) { $Work1 ="//not found//" } } else { $Work1 ="//not found//" } $LocalizeName += @{ ($PSL.Trim() -replace (" ","")) = ($Work1.Trim() -Replace ("&","&")) } } if (($False -eq $Silent) -and ($False -eq $Quiet)) { Write-Host ("{0} / {1} `t" -f ($i-1),$NumOf) } # ServiceList 分の LocalaizeName を生成 $i = 1 $NumOf = $Servicelist.count if ($False -eq $Silent) { Write-Host ("ServicetList {0} Localizing..." -f $Language) } foreach ($PSL in $ServiceList) { $i++ if (($False -eq $Silent) -and ($False -eq $Quiet)) { if (($i % 100) -eq 0) { Write-Host ("{0} / {1} `t" -f $i,$NumOf) } } $Work1 = @($htmlLine | Where-Object {$_ -like ("*>{0} (*" -f ($PSL.Trim() -replace (" ","")))}) $Idx = $htmlLine.indexOf($Work1[0]) if (-1 -ne $Idx) { $Work2 = @($Work1[0] -Split ("<br>")) $Work3 = $Work2 | Where-Object {$_ -like ("*{0} *" -f ($PSL.Trim() -replace (" ","")))} $SubIdx = $Work2.indexof($Work3) $Work1 = @($htmlLine[($idx+1)] -Split ("<br>")) if ("</tr>" -eq $Work1) { # Original Data Missing $Work1 = @($htmlLine[($idx-1)] -Split ("<br>")) } $Work2 = ($Work1[$subIdx] -replace ("\([a-f0-9]+-[a-f0-9]+-[a-f0-9]+-[a-f0-9]+-[a-f0-9]+\)","") ) -Replace ("<[/]*td>","") if ("" -eq $Work2) { $Work2 ="//not found//"} } else { $Work2 ="//not found//" } $LocalizeName += @{ ($PSL.Trim() -replace (" ","")) = ($Work2.Trim() -Replace ("&","&")) } } if (($False -eq $Silent) -and ($False -eq $Quiet)) { Write-Host ("{0} / {1} `t" -f ($i-1),$NumOf) } } # LocalaizeName を割り当て $i = 1 $NumOf = $SVClist.count if ($False -eq $Silent) { Write-Host "PlanList Refining..." } foreach ($SVC in $SVCList) { $i++ if (($False -eq $Silent) -and ($False -eq $Quiet)) { if (($i % 100) -eq 0) { Write-Host ("{0} / {1} `t" -f $i,$NumOf) } } $Mem = New-Object PSObject $Mem | Add-Member -MemberType NoteProperty -Name "Product_Display_Name" -Value $SVC.Product_Display_Name $Mem | Add-Member -MemberType NoteProperty -Name "String_ID" -Value ($SVC.String_ID.Trim() -Replace (" ","")) $Mem | Add-Member -MemberType NoteProperty -Name "GUID" -Value $SVC.GUID $Mem | Add-Member -MemberType NoteProperty -Name "Service_Plan_Name" -Value ($SVC.Service_Plan_Name.Trim() -Replace (" ","")) $Mem | Add-Member -MemberType NoteProperty -Name "Service_Plan_Id" -Value $SVC.Service_Plan_Id $Mem | Add-Member -MemberType NoteProperty -Name "Service_Plans_Included_Friendly_Names" -Value $SVC.Service_Plans_Included_Friendly_Names if ($False -eq $noLocalize) { if ($LocalizeName.($Mem.String_ID) -eq "//not found//") { $Mem | Add-Member -MemberType NoteProperty -Name "Product_Display_Name_Localize" -Value $SVC.Product_Display_Name $Mem | Add-Member -MemberType NoteProperty -Name "isLocalizeProduct" -Value $False } else { $Mem | Add-Member -MemberType NoteProperty -Name "Product_Display_Name_Localize" -Value $LocalizeName.($Mem.String_ID) $Mem | Add-Member -MemberType NoteProperty -Name "isLocalizeProduct" -Value $True } if ($LocalizeName.($Mem.Service_Plan_Name) -eq "//not found//") { $Mem | Add-Member -MemberType NoteProperty -Name "Service_Plans_Included_Friendly_Names_Localize" -Value $SVC.Service_Plans_Included_Friendly_Names $Mem | Add-Member -MemberType NoteProperty -Name "isLocalizeServicePlan" -Value $False } else { $Mem | Add-Member -MemberType NoteProperty -Name "Service_Plans_Included_Friendly_Names_Localize" -Value $LocalizeName.($Mem.Service_Plan_Name) $Mem | Add-Member -MemberType NoteProperty -Name "isLocalizeServicePlan" -Value $True } } else { $Mem | Add-Member -MemberType NoteProperty -Name "Product_Display_Name_Localize" -Value $SVC.Product_Display_Name $Mem | Add-Member -MemberType NoteProperty -Name "Service_Plans_Included_Friendly_Names_Localize" -Value $SVC.Service_Plans_Included_Friendly_Names $Mem | Add-Member -MemberType NoteProperty -Name "isLocalizeServicePlan" -Value $False $Mem | Add-Member -MemberType NoteProperty -Name "isLocalizeProduct" -Value $False } $PlanList += $Mem } # Saving Cache File if (($False -eq $Silent) -and ($False -eq $Quiet)) { Write-Host ("{0} / {1} `t" -f ($i-1),$NumOf) } if ($False -eq $Silent) { Write-Host ("Updated cache file.") } $PlanList | Export-Csv -Encoding Default -Path "$PSScriptRoot\$CacheFile" -NoTypeInformation } Switch ($Type) { "All" { $Result = $PlanList } "Product" { # Product 関連のみのリストにする。 $Result = $PlanList | Select-Object -Property Product_Display_Name, Product_Display_Name_Localize, String_ID, GUID, isLocalizeProduct | Sort-Object -Property String_ID -Unique | Sort-Object -Property Product_Display_Name_Localize } "ServicePlan" { # ServicePlan 関連のみのリストにする。 $Result = $PlanList | Select-Object -Property Service_Plans_Included_Friendly_Names, Service_Plans_Included_Friendly_Names_Localize, Service_Plan_Name, Service_Plan_ID, isLocalizeServicePlan | Sort-Object -Property Service_Plan_Name -Unique | Sort-Object -Property Service_PLans_Included_Friendly_Names_Localize } "Suite" { # Service_Plan_Name が2 個以上含まれる String_ID $SuiteList = $PlanList | Group-Object -Property String_ID | Where-Object {$_.Count -gt 1} $Result = $SuiteList | Select-Object -Property @{Name="String_ID";Expression={$_.Name}}, @{Name="DisplayName";Expression={$_.Group[0].Product_Display_Name}}, @{Name="DisplayNameLocalize";Expression={$_.Group[0].Product_Display_Name_Localize}}, @{Name="GUID";Expression={$_.Group[0].GUID}}, @{Name="isLocalizeProduct";Expression={$_.Group[0].isLocalizeProduct}}, @{Name="NumOfPlans";Expression={$_.Count}}, @{Name="Plans";Expression={$_.Group | Select-Object -Property @{Name="ServicePlan_DisplayName";Expression={ $_.Service_Plans_Included_Friendly_Names_Localize}}, Service_Plan_Name, Service_Plan_ID, isLocalizeServicePlan | Sort-Object -Property Service_PLans_Included_Friendly_Names_Localize}} } } Write-Output $Result } function Get-MS365IncludedPlans { <# .SYNOPSIS 指定した Microsoft 365 関連スイート製品に含まれるプランの一覧を表示します。 .DESCRIPTION 指定した Microsoft 365 関連スイート製品に含まれるプランの一覧を表示します。 内部的に Get-MS365Info -type All が呼び出されます。 .EXAMPLE Get-MS365IncludedPlans -String_ID "ENTERPRISEPREMIUM" ---------- ENTRPRISEPREMIUM = Office 365 E5 に含まれるプランの一覧が表示されます。 .EXAMPLE Get-MS365IncludedPlans -ServicePlanName "EXCHANGE_S_STANDARD" ---------- EXCHANGE_S_STANDARD = Exchange Online Plan 1 を含むプランの一覧が表示されます。 .EXAMPLE Get-MS365IncludedPlans -String_ID "ENTERPRISEPREMIUM" -Language ko-kr -ClearCache ---------- 現在保持しているキャッシュをリフレッシュし、製品名を韓国語ローカライズします。 .EXAMPLE Get-MS365IncludedPlans -String_ID "ENTERPRISEPREMIUM" -Language ko-kr -ClearCache -noLocalize ---------- 現在保持しているキャッシュをリフレッシュしますが、製品名のローカライズを行わずリフレッシュを行います。 .PARAMETER String_ID 参照するスイート製品の String_ID を指定します。例 "ENTERPRISEPREMIUM" や "SPE_E5" .PARAMETER ServicePlanName 参照するサービスプランの Service_Plan_Name を指定します。例 "ENTERPRISEPREMIUM" や "SPE_E5" .PARAMETER Language 既定値 $PSCulture 参照するサイトの言語を指定します。例 "ja-jp" や "en-us" .PARAMETER ClearCache キャッシュファイルをクリアし、サービス一覧をリフレッシュします。 .PARAMETER noLocalize キャッシュファイルをリフレッシュする再に指定言語でのローカライズをスキップし、時間短縮します。 ローカライズ説明として元データの CSV に含まれるものに合わせられます。 .PARAMETER Quiet キャッシュファイルを更新・再構築する際に進捗情報表示を最小限にします。 .PARAMETER Silent キャッシュファイルを更新・再構築する際に進捗情報表示を非表示にします。 .LINK .NOTES ja.exchange-rates.org の Web サイト利用は無許可利用です。 .INPUTS なし。パイプラインからの入力は受け付けません。 .OUTPUTS 換算結果は文字列です。 ListCurrencyID オプション指定時の結果は通貨オブジェクトの配列です。(Obj.Country / Unit / Code) #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingWriteHost", "", Justification="Progress information")] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSReviewUnusedParameter", "", Justification="Parameter used.")] Param( [Parameter(Mandatory=$false,Position=1)] [String]$String_ID="ENTERPRISEPREMIUM", [Parameter(Mandatory=$false,Position=1)] [String]$ServicePlanName, [Parameter(Mandatory=$false,Position=2)] [ValidateSet("af-za","am-et","ar-sa","as-in","az-latn-az","be-by","bg-bg","bn-in","bs-latn-ba","ca-es","ca-es-valencia","chr-cher-us","cs-cz","cy-gb","da-dk","de-de","el-gr","en-gb","en-us","es-es","es-mx","et-ee","eu-es","fa-ir","fi-fi","fil-ph","fr-ca","fr-fr","ga-ie","gd-gb","gl-es","gu-in","he-il","hi-in","hr-hr","hu-hu","hy-am","id-id","is-is","it-it","ja-jp","ka-ge","kk-kz","km-kh","kn-in","kok-in","ko-kr","lb-lu","lo-la","lt-lt","lv-lv","mi-nz","mk-mk","ml-in","mr-in","ms-my","mt-mt","nb-no","ne-np","nl-nl","nn-no","or-in","pa-in","pl-pl","pt-br","pt-pt","quz-pe","ro-ro","ru-ru","sk-sk","sl-si","sq-al","sr-cyrl-ba","sr-cyrl-rs","sr-latn-rs","sv-se","ta-in","te-in","th-th","tr-tr","tt-ru","ug-cn","uk-ua","ur-pk","uz-latn-uz","vi-vn","zh-cn","zh-tw")] [String]$Language=($PSCulture.toLower()), [Parameter(Mandatory=$false,Position=3)] [Switch]$noLocalize, [Parameter(Mandatory=$false,Position=4)] [Switch]$ClearCache, [Parameter(Mandatory=$false,Position=5)] [Switch]$Quiet, [Parameter(Mandatory=$false,Position=6)] [Switch]$Silent ) if ("" -eq $ServicePlanName) { $Product = Get-MS365info -Type Product -Language $Language -ClearCache:$ClearCache -noLocalize:$noLocalize -Quiet:$Quiet -Silent:$Silent if (-1 -eq $Product.String_ID.IndexOf($String_ID)) { $Result = -1 if ($False -eq $Silent) { Write-Error("指定された String_ID '{0}' は見つかりませんでした。" -f $String_ID) } } else { $PlanList = Get-MS365info -Type All -Language $Language -ClearCache:$ClearCache -noLocalize:$noLocalize -Quiet:$Quiet -Silent:$Silent | Where-Object {$_.String_ID -eq $String_ID} $Result = $PlanList | Select-Object -Property Service_Plans_Included_Friendly_Names, Service_PLans_Included_Friendly_Names_Localize, Service_Plan_Name, Service_Plan_ID, isLocalizeServicePlan | Sort-Object -Property Service_Plan_Name -Unique | Sort-Object -Property Service_PLans_Included_Friendly_Names_Localize } } else { $ServicePlans = Get-MS365info -Type ServicePlan -Language $Language -ClearCache:$ClearCache -noLocalize:$noLocalize -Quiet:$Quiet -Silent:$Silent if (-1 -eq $ServicePlans.Service_Plan_Name.IndexOf($ServicePlanName)) { $Result = -1 if ($False -eq $Silent) { Write-Error("指定された ServicePlanName '{0}' は見つかりませんでした。" -f $ServicePlanName) } } else { $PlanList = Get-MS365info -Type All -Language $Language -ClearCache:$ClearCache -noLocalize:$noLocalize -Quiet:$Quiet -Silent:$Silent | Where-Object {$_.Service_Plan_Name -eq $ServicePlanName} $Result = $PlanList | Select-Object -Property Product_Display_Name, Product_Display_Name_Localize, String_ID, GUID, isLocalizeProduct | Sort-Object -Property String_ID -Unique | Sort-Object -Property Product_Display_Name_Localize } } Write-Output $Result } function Compare-MS365SuitePlans { <# .SYNOPSIS 指定した Microsoft 365 関連スイート製品に含まれるプランを比較用に一覧を表示します。 .DESCRIPTION 指定した Microsoft 365 関連スイート製品に含まれるプランを比較用に一覧を表示します。 内部的に Get-MS365IncludedPlans -String_ID <<String_ID>> が呼び出されます。 .EXAMPLE Compare-MS365SuitePlans -Suites @("STANDARDPACK","ENTERPRISEPACK","ENTERPRISEPREMIUM") STANDARDPACK = Office 365 E1 ENTERPRISEPACK = Office 365 E3 ENTRPRISEPREMIUM = Office 365 E5 に含まれるプランの比較一覧が表示されます。 .EXAMPLE Compare-MS365SuitePlans -Suites @("STANDARDPACK","ENTERPRISEPACK","ENTERPRISEPREMIUM") -Language ko-kr -ClearCache ---------- 現在保持しているキャッシュをリフレッシュし、製品名を韓国語ローカライズします。 .EXAMPLE $Suites = @("STANDARDPACK","ENTERPRISEPACK","ENTERPRISEPREMIUM","SPE_E3","SPE_E5") $Matrix = Compare-MS365SuitePlans -Suites $Suites $Matrix | Where-Object {$_.DisplayName -ne "GUID"} | Select-Object -Property (@("DisplayNameLocalize")+$Suites) | FT ---------- 比較したいプランを配列変数にいれて比較し、表示します。 .EXAMPLE $Suites = (Get-MS365Info -Type Suite | Where-Object {$_.DisplayName -like "*Teams*"}).String_ID $Matrix = Compare-MS365SuitePlans -Suites $Suites $Matrix | Export-Csv -Path TeamsPlansMatrix.csv -Encoding Default -NoTypeinfo ---------- Get-MS365Info コマンド結果を名前でフィルターして Teams 関連プランを取得し、比較マトリックスを取得。 それを CSV で保存します。 .PARAMETER Suites 参照するスイート製品の String_ID 群を指定します。例 @("ENTERPRISEPREMIUM","SPE_E5") .PARAMETER Language 既定値 $PSCulture 参照するサイトの言語を指定します。例 "ja-jp" や "en-us" .PARAMETER Quiet キャッシュファイルを更新・再構築する際に進捗情報表示を最小限にします。 .PARAMETER Silent キャッシュファイルを更新・再構築する際に進捗情報表示を非表示にします。 .LINK .NOTES ja.exchange-rates.org の Web サイト利用は無許可利用です。 .INPUTS なし。パイプラインからの入力は受け付けません。 .OUTPUTS 換算結果は文字列です。 ListCurrencyID オプション指定時の結果は通貨オブジェクトの配列です。(Obj.Country / Unit / Code) #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingWriteHost", "", Justification="Progress information")] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSReviewUnusedParameter", "", Justification="Parameter used.")] Param( [Parameter(Mandatory=$true,Position=1)] [Array]$Suites, [Parameter(Mandatory=$false,Position=2)] [ValidateSet("af-za","am-et","ar-sa","as-in","az-latn-az","be-by","bg-bg","bn-in","bs-latn-ba","ca-es","ca-es-valencia","chr-cher-us","cs-cz","cy-gb","da-dk","de-de","el-gr","en-gb","en-us","es-es","es-mx","et-ee","eu-es","fa-ir","fi-fi","fil-ph","fr-ca","fr-fr","ga-ie","gd-gb","gl-es","gu-in","he-il","hi-in","hr-hr","hu-hu","hy-am","id-id","is-is","it-it","ja-jp","ka-ge","kk-kz","km-kh","kn-in","kok-in","ko-kr","lb-lu","lo-la","lt-lt","lv-lv","mi-nz","mk-mk","ml-in","mr-in","ms-my","mt-mt","nb-no","ne-np","nl-nl","nn-no","or-in","pa-in","pl-pl","pt-br","pt-pt","quz-pe","ro-ro","ru-ru","sk-sk","sl-si","sq-al","sr-cyrl-ba","sr-cyrl-rs","sr-latn-rs","sv-se","ta-in","te-in","th-th","tr-tr","tt-ru","ug-cn","uk-ua","ur-pk","uz-latn-uz","vi-vn","zh-cn","zh-tw")] [String]$Language=($PSCulture.toLower()), [Parameter(Mandatory=$false,Position=3)] [Switch]$Quiet, [Parameter(Mandatory=$false,Position=4)] [Switch]$Silent ) $AllPlanInfo = @() $PlanNames = @() foreach ($S in $Suites) { $ServicePlans = Get-MS365IncludedPlans -String_ID $S -Language $Language -Silent if (-1 -eq $ServicePlans) { if ($False -eq $Silent) { Write-Host ("String_ID: {0} is not found and skipping." -f $S) } } else { $AllPlanInfo += @{ $S = $ServicePlans.Service_Plan_Name } $PlanNames += $ServicePLans } } $PlanNames = $PlanNames | Sort-Object -Property Service_Plan_Name -Unique | Sort-Object -Property Service_Plans_Included_Friendly_Names_Localize $HeaderInfo = Get-MS365Info -Type Product -Language $Language | Where-Object {$_.String_ID -in $Suites} $Result = @() $Mem1 = New-Object PSObject $Mem1 | Add-Member -MemberType NoteProperty -Name "ServicePlanName" -Value "//" $Mem1 | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value "Suite Name" $Mem1 | Add-Member -MemberType NoteProperty -Name "DisplayNameLocalize" -Value "Suite Name" $Mem1 | Add-Member -MemberType NoteProperty -Name "ServicePlanID" -Value "Suite Name" $Mem2 = New-Object PSObject $Mem2 | Add-Member -MemberType NoteProperty -Name "ServicePlanName" -Value "//" $Mem2 | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value "Localize" $Mem2 | Add-Member -MemberType NoteProperty -Name "DisplayNameLocalize" -Value "Localize" $Mem2 | Add-Member -MemberType NoteProperty -Name "ServicePlanID" -Value "Localize" $Mem3 = New-Object PSObject $Mem3 | Add-Member -MemberType NoteProperty -Name "ServicePlanName" -Value "//" $Mem3 | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value "GUID" $Mem3 | Add-Member -MemberType NoteProperty -Name "DisplayNameLocalize" -Value "GUID" $Mem3 | Add-Member -MemberType NoteProperty -Name "ServicePlanID" -Value "GUID" foreach ($S in $Suites) { $Idx = $HeaderInfo.String_ID.IndexOf($S) if (-1 -ne $Idx) { $Mem1 | Add-Member -MemberType NoteProperty -Name $S -Value $HeaderInfo[$idx].Product_Display_Name $Mem2 | Add-Member -MemberType NoteProperty -Name $S -Value $HeaderInfo[$idx].Product_Display_Name_Localize $Mem3 | Add-Member -MemberType NoteProperty -Name $S -Value $HeaderInfo[$idx].GUID } } $Result += $Mem1 $Result += $Mem2 $Result += $Mem3 foreach ($P in $PlanNames) { $Mem1 = New-Object PSObject $Mem1 | Add-Member -MemberType NoteProperty -Name "ServicePlanName" -Value $P.Service_Plan_Name $Mem1 | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value $P.Service_Plans_Included_Friendly_Names $Mem1 | Add-Member -MemberType NoteProperty -Name "DisplayNameLocalize" -Value $P.Service_Plans_Included_Friendly_Names_Localize $Mem1 | Add-Member -MemberType NoteProperty -Name "ServicePlanID" -Value $P.Service_Plan_ID foreach ($S in $Suites) { $Idx = $HeaderInfo.String_ID.IndexOf($S) if (-1 -ne $Idx) { $Idx = $AllPlanInfo.($S).IndexOf($P.Service_Plan_Name) if (-1 -ne $Idx) { $Mem1 | Add-Member -MemberType NoteProperty -Name $S -Value "o" } else { $Mem1 | Add-Member -MemberType NoteProperty -Name $S -Value "" } } } $Result += $Mem1 } Write-Output $Result } Export-ModuleMember -Function Get-MS365Info, Get-MS365IncludedPlans, Compare-MS365SuitePlans |