PowerShellでRemoteAppの作業用リソースを確実に更新する方法(COM APIとタスクスケジューラ)

RemoteApp とデスクトップ接続(作業用リソース)のフィードを PowerShell から更新したいのに、方法が分からない・rundll32 が動かない、と悩むことがあります。この記事では、COM API とタスク スケジューラを使って作業用リソースを確実に再取得する実装方法と、企業環境での注意点を詳しく解説します。

目次

RemoteApp とデスクトップ接続(作業用リソース)を PowerShell で更新したいシナリオ

RemoteApp とデスクトップ接続(英語 UI では RemoteApp and Desktop Connections / Work Resources)は、RDS や VDI、DaaS 環境で提供されるアプリケーション・デスクトップをクライアント側に「フィード」として配信する仕組みです。コントロール パネルや「設定」アプリから手動で更新できますが、次のような場面では スクリプトから自動更新したくなることが多いはずです。

  • 新しい RemoteApp を発行したため、ユーザー全員のフィードを自動更新したい
  • RDS / AVD のメンテナンス後にログオン スクリプトでフィード再取得をかけたい
  • ヘルプデスクから「更新ボタンを押してください」と案内するのではなく、ワンクリック スクリプトで対応したい
  • 多くの端末に対して、構成管理ツール(Intune / ConfigMgr など)からまとめて更新したい

ところが、PowerShell には「Update-WorkResources」のような専用コマンドレットが存在せず、検索すると古い情報として rundll32.exe tsworkspace,TaskUpdateWorkspaces といった呼び出し方法ばかりが見つかることがあります。ところが、この rundll32 方式は OS やビルドにより動作が不安定で、そもそも何も起きないケースもあります。

結論:専用コマンドレットはないため、COM かタスク スケジューラを呼び出す

先に結論を整理しておきます。

  • RemoteApp / 作業用リソースの更新専用 PowerShell コマンドレットは存在しない
  • COM API を使うか、タスク スケジューラの既定タスクを起動して更新するのが実用的な方法
  • rundll32.exe tsworkspace,... は内部的にタスクを呼ぶだけで、互換性が低いため非推奨

2 つのアプローチの特徴を、ざっくり比較すると次のようになります。

方式概要メリットデメリット / 注意点
方法A:COM APITSWorkspace の COM オブジェクトを PowerShell から直接呼び出すユーザー単位で制御しやすい フィード単位(1 つ)と全フィードの両方を扱える PowerShell スクリプトに組み込みやすいCOM コンポーネントが存在しない環境では使えない ユーザー セッション内で実行する必要がある
方法B:タスク スケジューラ既定登録されている WorkSpaceUpdateTask を起動するOS 標準機能のため互換性が高い schtasks や PowerShell の ScheduledTasks モジュールから容易に実行可能ユーザー別の制御はやや工夫が必要 タスクの存在を前提とするため、カスタマイズ環境では事前確認が必要

以降では、それぞれの方法を実際のコードとともに詳しく見ていきます。

方法A:COM API で RemoteApp 作業用リソースを更新する(推奨)

前提条件と実行コンテキスト

COM 方式を使う場合のポイントは次のとおりです。

  • 更新対象はユーザーごとの設定です。必ず「更新したいユーザー」のセッションで実行します。
  • 通常は管理者権限は不要です(ユーザーコンテキストでの実行が重要)。
  • COM オブジェクトが登録されていない環境ではエラーになるため、その場合は方法B(タスク)にフォールバックします。

単一フィードを更新する:TSWorkspace.Workspace

現在ログオンしているユーザーに紐づく「作業用リソース(フィード)」を 1 つ更新したい場合は、次のようなシンプルなスクリプトで実現できます。

# 管理者権限は通常不要。対象ユーザーで実行すること。
$ws = New-Object -ComObject 'TSWorkspace.Workspace'
$ws.Refresh()

ポイントは次のとおりです。

  • New-Object -ComObject 'TSWorkspace.Workspace' で、作業用リソースを操作する COM オブジェクトを生成
  • $ws.Refresh() は非同期的にフィードの再取得を開始します(コマンド自体はすぐに戻ることが多い)
  • 更新の可否は、リモート デスクトップ接続アイコンの変化や イベントログなどで確認できます

実運用では、ログオン スクリプトや手動メンテナンス用スクリプトに次のように組み込むと分かりやすいでしょう。

Write-Host "作業用リソースを更新しています..."
$ws = New-Object -ComObject 'TSWorkspace.Workspace'
$ws.Refresh()
Write-Host "更新要求を送信しました。数十秒後にリソース一覧を確認してください。"

複数フィードをまとめて更新する:Microsoft.ManagementConsole.Advanced.TSWorkspace

PC に複数の作業用リソース フィードが登録されている場合、全てを一括で更新したいことがあります。その場合は、次の COM ProgID が利用できます。

$feeds = New-Object -ComObject 'Microsoft.ManagementConsole.Advanced.TSWorkspace'
$feeds.RefreshWorkspaces()

このコードでは、登録済みの全フィードに対して更新処理を投げます。ただし、環境によっては この COM ProgID 自体が存在しないことがあります。その場合は、次のようなエラーが表示されます。

New-Object : COM クラス ファクトリを取得できませんでした。
(クラスが登録されていません (HRESULT からの例外: 0x80040154))

このエラーが出た場合は、OS のエディションやインストールされている機能により COM コンポーネントが提供されていない可能性があるため、方法B(タスク スケジューラ)に切り替えるのが現実的です。

COM 方式でよくあるエラーと対処の目安

症状想定原因対処の方向性
クラスが登録されていません エラーCOM コンポーネント未インストール / 機能が無効方法Bに切り替え、RDS クライアント関連機能の有無を確認
エラーは出ないが何も変化しないフィードに差分がない / 更新自体が失敗イベントログ(RemoteApp / RDS 関連)を確認し、フィード URL・認証をチェック
サーバー側には新しい RemoteApp があるのにクライアントに出てこないプロキシや証明書の問題でフィード取得に失敗ブラウザでフィード URL にアクセスし、証明書警告や 401 エラーが出ていないか確認

方法B:タスク スケジューラの既定タスクを直接起動する(高い互換性)

COM 方式が使えない・使いたくない場合は、Windows に最初から登録されているタスク スケジューラのタスクを直接起動する方法が安定しています。

WorkSpaceUpdateTask タスクの位置と役割

RemoteApp / 作業用リソースの更新には、次のような既定タスクが利用されます。

項目値
タスク名WorkSpaceUpdateTask
タスクパス\Microsoft\Windows\RemoteApp and Desktop Connections Update\
役割登録済みの RemoteApp / デスクトップのフィードを再取得する
呼び出し元の一例rundll32.exe tsworkspace.dll,TaskUpdateWorkspaces など

つまり、古い rundll32 方式も最終的にはこのタスクに委譲されているため、最初からタスク スケジューラ経由で起動した方が挙動が安定します。

コマンドライン(schtasks)から更新する

最も簡単なのは、schtasks.exe を使う方法です。コマンド プロンプトでも PowerShell でも同じように実行できます。

schtasks /run /tn "\Microsoft\Windows\RemoteApp and Desktop Connections Update\WorkSpaceUpdateTask"

主なポイントは次のとおりです。

  • /tn にはタスクの「フルパス」を指定します(パスを間違えると「指定されたタスクは存在しません」のようなエラーになります)。
  • スクリプト内で実行する場合は、| Out-Null で出力を捨てるとログがすっきりします。
  • /s オプションを使えば、リモート コンピューター上のタスクを起動することも可能です(適切な権限が必要)。

例:PowerShell スクリプトから静かに起動する場合は、次のように書けます。

schtasks /run /tn "\Microsoft\Windows\RemoteApp and Desktop Connections Update\WorkSpaceUpdateTask" | Out-Null

PowerShell の ScheduledTasks モジュールで起動する

Windows 8 / Windows Server 2012 以降であれば、PowerShell 標準の ScheduledTasks モジュールを使ってタスクを操作できます。より PowerShell らしく書きたい場合はこちらが便利です。

$path = "\Microsoft\Windows\RemoteApp and Desktop Connections Update\"
$name = "WorkSpaceUpdateTask"

Get-ScheduledTask -TaskPath $path -TaskName $name | Start-ScheduledTask

このコードは次のような動作になります。

  • Get-ScheduledTask で該当タスクを取得
  • パイプで Start-ScheduledTask に渡し、タスクを即時実行

環境によっては、タスク名・パスがカスタマイズされていたり、タスク自体が削除されていることもあります。その場合は、次のように「存在確認+エラー表示」を入れておくと親切です。

$path = "\Microsoft\Windows\RemoteApp and Desktop Connections Update\"
$name = "WorkSpaceUpdateTask"

$task = Get-ScheduledTask -TaskPath $path -TaskName $name -ErrorAction SilentlyContinue
if ($null -eq $task) {
    Write-Warning "WorkSpaceUpdateTask が見つかりません。環境を確認してください。"
} else {
    $task | Start-ScheduledTask
    Write-Host "作業用リソース更新タスクを起動しました。"
}

rundll32 tsworkspace 方式が非推奨な理由

古い記事やブログには、しばしば次のようなコマンドが紹介されています。

rundll32.exe tsworkspace,TaskUpdateWorkspaces
# または
rundll32.exe tsworkspace,TaskUpdateWorkspaces2

しかし、この方式にはいくつか問題があります。

  • 内部実装に依存しているため、OS / ビルドによっては何も起こらないことがある
  • 将来のバージョンで動作保証がなく、ドキュメントも乏しい
  • 結局はタスク スケジューラのタスクに処理が委譲されるだけで、メリットが薄い

そのため、新規のスクリプトや運用では、最初から COM かタスク スケジューラを直接呼び出すのが安全です。

そのまま使えるフォールバック付き関数:Update-WorkResources

ここまでの内容を踏まえて、「まず COM で試し、ダメならタスクにフォールバックする」関数を作っておくと便利です。以下は、そのままコピーして使える PowerShell 関数の一例です。

function Update-WorkResources {
    param(
        [switch]$All # 複数フィードをまとめて更新したい場合に指定
    )
    try {
        if ($All) {
            $feeds = New-Object -ComObject 'Microsoft.ManagementConsole.Advanced.TSWorkspace'
            $feeds.RefreshWorkspaces()
        } else {
            $ws = New-Object -ComObject 'TSWorkspace.Workspace'
            $ws.Refresh()
        }
        Write-Host "作業用リソースの更新を開始しました(COM)"
    } catch {
        Write-Warning "COM が利用できないため、タスクで更新します。"
        schtasks /run /tn "\Microsoft\Windows\RemoteApp and Desktop Connections Update\WorkSpaceUpdateTask" | Out-Null
        Write-Host "作業用リソースの更新タスクを起動しました"
    }
}

関数の動きと設計ポイント

  • -All なし:TSWorkspace.Workspace を使い、単一フィードを更新
  • -All あり:Microsoft.ManagementConsole.Advanced.TSWorkspace を使い、全フィード更新を試行
  • いずれかの COM オブジェクト生成や更新で例外が発生した場合は、catch で受けて WorkSpaceUpdateTask を起動

このように COM → タスク の順でフォールバックすることで、COM を持たないクライアントでも同じ関数を使い回せるようになります。

関数の配置と読み込み例

日常的に使う場合は、次のいずれかの方法で関数を読み込んでおくと便利です。

  • プロファイルへ直接定義
    例:$PROFILE(Microsoft.PowerShell_profile.ps1)に関数定義を追記
  • 外部スクリプト化してドットソース
    例:C:\Scripts\Update-WorkResources.ps1 に保存し、. C:\Scripts\Update-WorkResources.ps1 で読み込み

読み込んだあとは、次のように実行するだけです。

# 現在のユーザーのフィードを更新
Update-WorkResources

# 登録済みの全フィードをまとめて更新
Update-WorkResources -All

企業環境での運用例とベストプラクティス

単に「コマンドが動く」だけでなく、企業環境で安定運用するにはいくつかの工夫が必要です。ここでは代表的なパターンを紹介します。

ログオン スクリプトからの自動更新

ユーザーが Windows にログオンするタイミングで自動的にフィードを更新したい場合、GPO のログオン スクリプトに次のような処理を組み込むことができます。

# Update-WorkResources 関数が定義されている前提
try {
    Update-WorkResources -All
} catch {
    # 何らかの理由で関数が使えない場合はタスクだけ起動
    schtasks /run /tn "\Microsoft\Windows\RemoteApp and Desktop Connections Update\WorkSpaceUpdateTask" | Out-Null
}

ポイントは「毎回必ず更新する」のではなく、「構成変更時だけ」や「週に一度」など頻度を絞ることです。フィードの更新は比較的軽い処理ですが、帯域やサーバー負荷を考慮して、実行タイミングを設計した方が安心です。

Intune / 構成管理ツールと組み合わせる

Microsoft Intune や Configuration Manager などの構成管理ツールで配布する場合は、次の点に注意します。

  • 必ずユーザーコンテキストで実行する(システム権限だけではユーザー設定が更新されない)
  • 複数ユーザーが利用する共有端末では、それぞれのユーザーに対して更新処理が走るように設計する
  • 実行ログをカスタム ログファイルやイベントログに残し、トラブルシューティングしやすくする

例えば、Intune の「スクリプト」機能で配布する場合、スクリプト中に次のような簡易ログを入れておくと、後から確認しやすくなります。

$logPath = "$env:ProgramData\RemoteAppFeed\Update.log"
"[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] Updating work resources for $env:USERNAME" | Out-File -FilePath $logPath -Append -Encoding UTF8

Update-WorkResources -All

ユーザーコンテキストを確実にするためのヒント

「管理者がリモートから一括実行したい」という要件もよくありますが、RemoteApp のフィード更新はユーザーごとの設定であるため、基本的には次のいずれかの方法をとる必要があります。

  • ユーザーにログオンしてもらった状態で、リモート PowerShell セッション(Enter-PSSession)から呼び出す
  • ユーザーごとのログオン スクリプトやタスク スケジューラにスクリプトを登録しておく
  • VDI / AVD などではゴールデン イメージ更新時に「初回ログオン時に実行されるスクリプト」として組み込む

管理者コンソールから SYSTEM 権限で一括実行しても、期待したユーザー プロファイルに反映されないケースが多いので注意が必要です。

トラブルシューティング:更新しても反映されないときの確認ポイント

スクリプト自体は正常終了しているのに、「RemoteApp のアイコンが増えない」「削除したアプリが残ったまま」といった相談はよくあります。その場合は、次の項目を順番に確認すると原因を切り分けやすくなります。

症状確認するポイント備考
新しい RemoteApp がクライアントに出てこないサーバー側で RemoteApp が正しく発行されているか ユーザーが該当 RemoteApp に割り当てられているか クライアントからフィード URL にブラウザでアクセスし、XML が取得できるかXML 取得に失敗している場合、プロキシ・認証・証明書が疑わしい
削除した RemoteApp がクライアント側に残るフィードのキャッシュが更新されているか クライアント側で別のフィードが同名アイコンを提供していないか複数フィードを利用している環境では、どのフィードのアイコンか整理して確認
スクリプト実行時にエラーは出ないが、イベントログに警告が出る「アプリケーションとサービス ログ」配下の RemoteApp / RDS 関連ログ 証明書の有効期限・信頼チェーン証明書の失効や名前不一致は、サイレントな失敗の原因としてありがち
特定ユーザーだけ更新に失敗するそのユーザーのプロファイルに破損がないか フィード URL の資格情報が壊れていないか(資格情報マネージャー)一度フィード削除 → 再登録で解消するケースも多い

まとめ:PowerShell で RemoteApp の作業用リソースを安定して更新するために

最後に、本記事のポイントを整理します。

  • RemoteApp とデスクトップ接続(作業用リソース)には、専用の PowerShell コマンドレットは存在しない
  • 代わりに、次の 2 つの方法で更新をスクリプト化できる
    • 方法A:COM API(TSWorkspace.Workspace / Microsoft.ManagementConsole.Advanced.TSWorkspace)を PowerShell から呼び出す
    • 方法B:タスク スケジューラの WorkSpaceUpdateTask を起動する
  • rundll32.exe tsworkspace,... は内部実装に依存し、OS によって動作が不安定なため非推奨
  • 実運用では、COM → タスク とフォールバックする Update-WorkResources 関数のようなラッパーを用意すると管理しやすい
  • フィード更新はあくまで「再取得」であり、サーバー側に差分がなければ見た目が変わらないことも多い点に注意
  • 企業環境では、ネットワーク・プロキシ・証明書・ユーザーコンテキストなど周辺要素も含めたトラブルシューティングが重要

RemoteApp / 作業用リソースの更新を PowerShell から自動化しておくと、新しいアプリ配信や構成変更のたびにユーザーに操作を依頼する必要がなくなり、ヘルプデスクの負荷軽減にもつながります。ここで紹介した COM とタスク スケジューラの組み合わせをベースに、自社環境に合ったスクリプトや運用ルールを整備してみてください。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次