Teams Phone設定漏れユーザーをPowerShellで一括特定

支払っているライセンス料、無駄になっていませんか?

Teams Phoneの運用で最も避けたいのが、「ライセンスは付与しているのに、設定が不完全でTeams Phoneが使われていない」という状態です。

特に、以下のような複雑なライセンス体系が混在している環境では、設定漏れが起きやすくなります。

  • Microsoft Teams Phone Standard(単体アドオン)
  • Microsoft 365 E5(Teams Phone機能が内包されている)
  • Shared Device(共有デバイス:会議室や受付用)

ライセンスを付けただけで安心してしまい、肝心のエンタープライズボイス(EnterpriseVoiceEnabled)の有効化や、電話番号の割り当てを忘れているケースが意外と多いです。

今回は、これらのライセンスはあるのに設定が止まっているユーザーを一括で抽出するコマンドをご紹介します。

課題:見落としがちな2つの「未設定」項目

Teams Phoneを外線として使うには、ライセンス付与に加えて以下の2点が必要です。

  1. EnterpriseVoiceEnabled が $true であること
  2. 電話番号が正しく割り当てられていること

これらが一つでも欠けていると、ユーザーの画面にはダイヤルパッドが出ず、会社は使われない機能に月額費用を払い続けることになります。

解決策:対象ライセンス保有者の中から「未設定」を抽出する

コマンドの実行

このコマンドでは、対象となる3種類のライセンス(TeamsPhoneStandard, Microsoft 365 E5, SharedDevice)のいずれかを持っているユーザーアカウントを全スキャンし、「EnterpriseVoiceEnabledが有効になっていない」または「電話番号が未設定」のユーザーを特定するための一覧を出力します。

以下のコマンドをPowerShellで実行すると、C:\temp\Teams_Full_Audit_Report.csvというファイルが生成され、全アカウントのライセンス付与状況を出力します。

※C:\temp フォルダが存在しない場合は自動でtempフォルダを作成します

# Teams、Microsoft Graphに接続
Connect-MicrosoftTeams
Connect-MgGraph -Scopes "User.Read.All","Organization.Read.All"

# 1. ライセンスのGUIDとライセンス名の対応表
$skuTable = @{
    "06ebc4ee-1bb5-47dd-8120-11324bc54e06" = "Microsoft 365 E5"
    "efcc7370-d88f-43b9-a681-424d858cfd79" = "Microsoft Teams Phone Standard"
 "295a8eb0-f78d-45c7-8b5b-1eed5ed02dff" = "Shared Device"
    # 必要に応じて、自環境で使っている ID をここに追加できます
}

# 2. 全ユーザー情報を取得
$allUsers = Get-CsOnlineUser

# 3. 結果を格納するリスト
$report = @()

foreach ($u in $allUsers) {
    $licenseNames = @()
    
    try {
        # Microsoft Graph からライセンス情報を取得
        $mgUser = Get-MgUser -UserId $u.UserPrincipalName -Property AssignedLicenses -ErrorAction Stop
        
        if ($mgUser.AssignedLicenses) {
            foreach ($lic in $mgUser.AssignedLicenses) {
               $id = $lic.SkuId.ToString()
               if ($skuTable.ContainsKey($id)) {
                   $licenseNames += $skuTable[$id]
               } else {
                   $licenseNames += "Unknown($id)"
               }
           }
       }
    } catch {
        # Microsoft Graphで見つからない(リソースアカウント)場合は"NotFound In Graph"と出力
        $licenseNames += "NotFound In Graph"
    }

    $obj = [PSCustomObject]@{
        DisplayName            = $u.DisplayName
        UserPrincipalName      = $u.UserPrincipalName
        EnterpriseVoiceEnabled = $u.EnterpriseVoiceEnabled
        LineURI                = if ($u.LineURI) { $u.LineURI } else { "未設定" }
        AssignedLicenses       = if ($licenseNames) { $licenseNames -join " / " } else { "ライセンスなし" }
    }
    $report += $obj
}

# 4. CSV出力処理 
$OutputPath = "C:\temp\Teams_Full_Audit_Report.csv"
if (!(Test-Path "C:\temp")) { New-Item -ItemType Directory -Path "C:\temp" -Force }
$report | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8

今回実行しているGet-MgUserコマンドで取得できる値はライセンスのGUID(SKU ID)です。

GUIDはシステムが使う内部IDであり、そのまま出力するとどのライセンスであるかわかりづらいため、コマンド内「1. ライセンスのGUIDとライセンス名の対応表」部分にて、ライセンスのGUIDをライセンス名に変換する処理を実施しています。

このため、利用するライセンスによってこの「1. ライセンスのGUIDとライセンス名の対応表」部分は適宜書き換えてください。

ライセンスとGUIDの対応表は以下を参照してください。
learn.microsoft.com

また、Get-MgUserコマンドではリソースアカウントに付与されたライセンスを取得できないため、リソースアカウントである場合は"NotFound In Graph"と出力する処理としています。

CSVの中身と見方

出力されたCSVは、以下のようなイメージになります。

項目名 出力例
DisplayName アカウントの表示名 -
UserPrincipalName アカウントのUPN user@example.com
EnterpriseVoiceEnabled EnterpriseVoiceが有効化されているかどうか TRUE(有効)またはFALSE(無効)
LineURI 割り当てられた電話番号 tel:+81XXXXXXXX
番号が割り当てられていない場合は"未設定"と表示
AssignedLicenses 割り当てられたライセンス 対応表で指定したライセンスが割り当てられている場合はそのライセンス名を表示
対応表で指定してないライセンスが割り当てられている場合は"Unknown(GUID)"と表示
ライセンスが割り当てられていない場合は"ライセンスなし"と表示
リソースアカウントの場合は"NotFound In Graph"と表示

この出力結果から、「AssignedLicenses」にライセンスが出力されているのに、「EnterpriseVoiceEnabled」がFALSEであったり、「LineURI」が"未設定"であったりするアカウントが棚卸の対象と判断できます。

おわりに

ライセンスの割り当ては人事異動などで頻繁に発生しますが、その後の電話設定は手動や別フローになることが多く、不整合はどうしても発生します。

「誰にライセンスをあげたか」ではなく、「誰がちゃんと外線を使える状態か」を可視化することが、無駄なコストを削り、ユーザー満足度を高める近道です。

皆様のテナントでも、一度この手順で棚卸を実行し、「幽霊ライセンス」が眠っていないか確認することをおすすめします。

執筆担当者プロフィール
Hiroko, Kimura

Hiroko, Kimura(日本ビジネスシステムズ株式会社)

Microsoft 365製品の提案~運用が担当領域、特にTeams/Teams Phone多めです。趣味は音楽とテレビと映画。趣味にしたいのは筋トレ(エンジニアには筋肉が必要)。

担当記事一覧