Power Automate Desktop フローがリモートPCでタイムアウト停止したときログが消える問題を、SharePointリストへの実行ログ記録で解決する
1. 概要(TL;DR)
- Power Automate Desktop(以下PAD)のフローをリモートPC(無人/Unattended)で実行していると、タイムアウトでフローが強制停止された際、管理センター(Power Automate 管理ポータル/クラウドフローの実行履歴)に詳細ログが残らないことがあります
- 原因を追おうにも「どのアクションまで進んでいたか」「どこで止まったか」が管理画面からは追跡できず、調査に時間がかかっていました
- そこで、PADの各アクション(または主要な区切りごと)の実行状況をSharePointリストに都度書き込むことで、タイムアウトで強制終了されても「最後に記録された時点までの進捗」が必ず残るようにしました
- 本記事では、この構成の作り方・ハマった点・最終的な実装をまとめます
この記事はこんな人向けです
- PAD(特に無人/リモートマシンでの実行)のフローが途中で止まり、原因調査に困っている方
- Power Automate 管理センターの実行履歴だけでは不十分だと感じている方
- クラウドフロー・デスクトップフロー間の連携でログ基盤を自作したい方
2. 前提・環境
- Power Automate クラウドフロー(トリガー:スケジュールまたは手動)から「PC上のフローを実行する(Run a flow built with Power Automate for desktop)」アクションでPADフローを呼び出す構成です
- PADフローの実行対象は**Machine group経由のリモートPC(無人モード)**です
- ログ記録先は SharePoint Online のリストです
- PAD側からSharePointへの書き込みは、**PADの「(Sharepointリスト)項目の作成」アクションを使い、PADフロー単体から書き込んでいます
- 使用コネクタ:
- SharePoint Online(
shared_sharepointonline/PostItem操作 = 項目の作成) - Power Automate for desktop(PADアクション本体)
- SharePoint Online(
- SharePoint接続は、Power Automate(クラウド)側で事前に作成済みの接続(サービスアカウント等)をPADフロー内で参照する形になっています
※ご自身の環境(認証方式・SharePointサイトURL・コネクタのバージョンなど)に合わせて適宜置き換えてください。
3. やりたかったこと
- PADフローがどのアクション/どのステップまで進んだかを、フロー実行中にリアルタイムでSharePointリストに記録したいと考えました
- 記録する項目の例:
- 実行ID(相関ID)
- PC名(実行対象マシン)
- ステップ名 / アクション名
- ステータス(開始 / 進行中 / 成功 / 失敗)
- タイムスタンプ(UTC)
- エラーメッセージ(あれば)
- タイムアウトで強制終了された場合でも、最後に書き込まれたレコードから「どこまで進んで、どこで止まったか」を追えるようにしたいと考えました
- 管理者が管理センターを開かなくても、SharePointリストを見るだけで実行状況・詰まり箇所が一目でわかる状態を目指しました
4. つまづいたポイント
4-1. タイムアウトで停止すると管理センターに情報が残らない
クラウドフロー側の「PC上のフローを実行する」アクションにはタイムアウト値を設定できますが、これを超過すると該当アクションは失敗扱いになり、実行履歴上は
アクションがタイムアウトしました
という程度の情報しか残らず、PAD側で実際に何が起きていたか(どのサブフロー・どのアクションで詰まっていたか)は一切わからない状態でした。
特にリモート無人実行の場合、RDPセッション切断やマシンのスリープ、ネットワーク瞬断などが絡むと、PAD側のローカルログ自体も生成・同期が完了しないケースがあり、後追い調査が非常に困難でした。
4-2. ログ用のサブフローを汎用化しようとすると、渡す値の形式で悩みました
各ステップから呼び出す共通の「ログ書き込み」サブフローを作るとき、呼び出し元ごとにパラメーターの数や意味が微妙に異なる(ステップ名だけの場合、詳細メッセージも渡したい場合など)ため、個別の引数を都度増やす設計だと呼び出し側の記述が煩雑になってしまいました。
4-3. タイムスタンプを「並び替え用」と「人が読む用」で両方持ちたい
SharePointリスト上でログを時系列にソートするには機械可読なUTC ISO 8601形式のタイムスタンプが欲しい一方、リストを目視で確認するときは日本時間の見慣れた表記([yyyy-MM-dd HH:mm:ss])の方が読みやすく、1つのフォーマットでは両立できませんでした。
4-4. SharePointの内部列名(field_2など)と、リスト画面上の表示名が一致せず混乱しました
PostItem呼び出しの @'item/field_2' のような内部列名は、SharePointリストの列を作成した際に自動採番された内部名であり、リストの画面に表示される列名(たとえば「FlowName」「StepName」)とは見た目上まったく違う文字列になります。コードだけを見て「field_2って何のことだろう」と分からなくなり、リストの列設定画面と何度も突き合わせる羽目になりました。実際の対応関係は6-2節にまとめています。
5. 試したこと(トライ&エラー)
-
ログの値を個別引数でサブフローに渡す設計は汎用性が低く断念しました
→ 呼び出し元ごとに渡したい項目数が変わるため、代わりに1行分のログ内容を格納したテーブルデータ(Datatable)を作り、その0番目の行にその都度データを詰めてからサブフローに渡す方式に変更しました。サブフロー側は常に「テーブルの0番目の行」を読むだけでよく、呼び出し側の書き方を統一できました -
タイムスタンプを1種類だけ用意して失敗しました
→ ソート用にUTC ISO 8601形式(yyyy-MM-ddTHH:mm:ss.ffffffZ)を1列、目視確認用に日本時間の[yyyy-MM-dd HH:mm:ss]形式の文字列をもう1列(詳細列に埋め込み)、と2種類の日時テキストを別々に生成する方式に変更しました。あとで SharePointリストのID列を表示してそれを基準にすればよかったと気づきました。
ですが UTC ISO 8601形式と、日本時間 yyyy-MM-dd 形式は、人によっては役に立つと考えたので残しておきます。 -
ネットワーク瞬断時、ログ書き込み自体が失敗してその場でフローが止まってしまいました
→ 特にリモート無人実行では通信が不安定になる場面があるため、エラー時の設定で指数バックオフ(Exponential Backoff)で2回まで自動リトライ**(最小間隔2秒・最大間隔360秒)する設定を追加しました。リトライしても失敗した場合はログ書き込み自体のエラーとして握りつぶし、本処理側のフローを止めないようにしています
6. 解決方法
6-1. 全体構成
PADフロー単体でSharePointリストへの書き込みまで完結させています。さらに、呼び出し元のクラウドフロー側からも同じSharePointリスト(FlowLog)に書き込むようにしており、クラウドフローの実行開始・完了と、PADフロー内の各ステップのログが同一リスト上で時系列につながる構成になっています。
[クラウドフロー] スケジュール/手動トリガー
├─ (開始ログをFlowLogリストに書き込み)
├─ Power Automate for desktop 実行アクション(タイムアウト値を設定)
│ └─ [PADフロー]
│ ├─ (本処理の各ステップ)
│ ├─ 節目ごとに [行をデータ テーブルに挿入する → サブフロー FlowLogger] を実行
│ │ ├─ ログ用テーブルデータ(LogDataTable)の0番目の行に値を詰める
│ │ ├─ 日時を2種類生成(UTC ISO8601 / 日本時間の表示用)
│ │ └─ クラウドコネクタ呼び出し(External.InvokeCloudConnector)で
│ │ SharePointの PostItem を実行(ON ERRORでリトライ)
│ └─ エラー発生時ブロックからも同じ FlowLogger を呼び出し
└─ (完了/失敗ログをFlowLogリストに書き込み)
こうしておくと、クラウドフロー側のタイムアウトでPADの実行アクションが強制終了した場合でも、FlowLogリストを見れば「クラウドフローは開始したが、完了ログが記録されないまま止まっている」「PAD側の最後のログがどのステップだったか」の両方を同じ画面上で確認できます。
6-2. SharePointリストの作成
あらかじめSharePoint Online上にログ用リスト FlowLog を作成しています。実際の画面は以下の通りです(TimestampViewという、Timestamp列の降順ビューです)。
画面に表示されている列名(表示名)と、PostItem呼び出し時に使う内部列名(field_2など)の対応は以下の通りです(4-5節で触れた「内部名と表示名がずれる」問題の実物です)。
| 表示名(リスト画面) | 内部列名 | 用途 |
|---|---|---|
Timestamp |
field_1 |
UTC ISO 8601形式のタイムスタンプです。このビューのソートキーになっています |
タイトル(Title) |
Title |
ログを書き込んだ時点のトップレベルのフロー名です(item/Title = 変数FlowName) |
FlowName |
field_2 |
フロー内の区分・サブフロー名です(Main、UploadLatestFiles、SendDraftEmailなど)。列名はFlowNameですが、実質は「今どの区画を実行中か」を表しています |
StepName |
field_3 |
対象プロジェクト/機種などの識別子です(project)。列名はStepNameですが、実際はプロジェクトコードが入る運用になっています |
Message |
field_4 |
ログメッセージ本体です(*** Desktopフロー終了 ***、ファイルアップロードなど) |
Details |
field_5 |
日本時間タイムスタンプ+ユーザーID(社員番号)+補足テキストを連結したものです(例:[2026-08-06 03:56:44]【E360325】) |
| (画面には非表示) | field_6 |
DesktopResult(成功/失敗などの結果値)です。NotSuccessという別ビューの絞り込み条件に使われています |
列名(
FlowName・StepName)と実際に入っている値の意味が一致していない点は、この構成を後から見返す人(未来の自分を含む)が混乱しやすいポイントです。運用に乗せる前に列名を実態に合わせて付け直しておく(あるいは列の説明文にメモを残しておく)ことをおすすめします。
また、このリストはクラウドフロー側のログ書き込みとも共通で使用しており、FlowName列にはPADのステップ名だけでなく、クラウドフロー側で記録したSendDraftEmailのような処理名も同じ列に混在して入っています。これにより、クラウドフローの実行〜PADフローの各ステップ〜クラウドフローの後処理までを、1つのリストの時系列(TimestampView)で追えるようになっています。
6-3. 呼び出し元:「行をデータ テーブルに挿入する」でログ1行分を組み立てます
各ステップの呼び出し元では、PAD標準の**「行をデータ テーブルに挿入する」**アクションを使い、LogDataTable の行インデックス0に、その時点でログとして残したい値を配列で詰めています。
- データ テーブル:
%LogDataTable% - 挿入場所:行インデックスの前
- 行インデックス:
0(常に0番目を上書きする形で使います) - 新しい値:
%[FlowName, '', 'Main', CCPA_RPA_Project['Project'] , '*** Desktopフロー終了 ***', '', DesktopResult]%
この行の後ろで、共通のサブフロー FlowLogger を実行します。
呼び出し元のPADコードとしては以下の形になります。
Variables.AddRowToDataTable.InsertItemToDataTable
DataTable: LogDataTable
RowIndex: 0
RowToAdd: [FlowName, '', 'Main', CCPA_RPA_Project['Project'] , '*** Desktopフロー終了 ***', '', DesktopResult]
サブフローの実行: FlowLogger
配列のインデックスと、FlowLoggerサブフロー内のPostItem呼び出し(6-4節)・SharePointリスト上の表示列(6-2節)との対応は以下の通りです。
| 配列インデックス | この例での値 |
PostItem側の内部列名 |
リスト表示名 |
|---|---|---|---|
[0] |
FlowName |
(未使用。item/Titleには別変数のFlowNameを渡しています) |
タイトル |
[1] |
''(未使用) |
- | - |
[2] |
'Main'(区分・サブフロー名) |
field_2 |
FlowName |
[3] |
project(プロジェクトコード) |
field_3 |
StepName |
[4] |
'*** Desktopフロー終了 ***'(ログメッセージ本体) |
field_4 |
Message |
[5] |
''(未使用、補足テキストを入れることもあります) |
field_5の一部として連結 |
Detailsの一部 |
[6] |
DesktopResult(処理結果) |
field_6 |
(非表示列) |
こうしておくことで、呼び出し元は「配列の中身を変えるだけ」でログ内容を自由に組み立てられ、FlowLoggerサブフロー側は「LogDataTable[0]の各列を読んでSharePointに書き込むだけ」というシンプルな責務分担になっています。エラー発生時ブロックから呼び出す場合も同様に、[4]の位置に'*** Desktopフロー異常終了 ***'のようなメッセージを、[6]にエラー内容を入れて同じFlowLoggerを呼び出せば、同じ列構成のままエラーログとして記録できます。
6-4. サブフローFlowLoggerの実装
まず、ソート用と表示用の2種類のタイムスタンプを作成します。
DateTime.GetCurrentDateTime.Windows
DateTimeFormat: DateTime.DateTimeFormat.DateAndTime
TimeZoneLocation: DateTime.TimeZoneLocation.UTC
CurrentDateTime=> LogUTCDateTime
Text.ConvertDateTimeToText.FromCustomDateTime
DateTime: LogUTCDateTime
CustomFormat: $'''yyyy-MM-ddTHH:mm:ss.ffffffZ '''
Result=> LogTimestamp
DateTime.GetCurrentDateTime.Windows
DateTimeFormat: DateTime.DateTimeFormat.DateAndTime
TimeZoneLocation: DateTime.TimeZoneLocation.TokyoStandardTime
CurrentDateTime=> LogCurrentDateTime
Text.ConvertDateTimeToText.FromCustomDateTime
DateTime: LogCurrentDateTime
CustomFormat: $'''[yyyy-MM-dd HH:mm:ss]'''
Result=> LogDetailsDateTime
-
LogDetailsDateTime:日本時間の[yyyy-MM-dd HH:mm:ss]形式です。目視確認用に詳細列へ埋め込みます
続けて、SharePointのPostItem操作を直接呼び出します。事前にPADのアクション追加ウィザードから「SharePoint Online」コネクタ→対象サイト(dataset)→対象リスト(table)→操作(PostItem)を選択すると、以下のようなアクションが自動生成されます(接続情報などはこのアクション定義に紐づいて保存されます)。難しいこと書いてますが実際やってることは「項目の作成」アクションです。
External.InvokeCloudConnector
Connection: 'b2800ddb-89be-4be5-bdfb-c691f2ecc79f'
ConnectorId: '/providers/Microsoft.PowerApps/apis/shared_sharepointonline'
OperationId: 'PostItem'
@dataset: $'''https://<tenant>.sharepoint.com/sites/<サイト名>'''
@table: $'''<リストのGUID>'''
@'item/Title': FlowName
@'item/field_1': LogTimestamp
@'item/field_2': LogDataTable[0][2]
@'item/field_3': LogDataTable[0][3]
@'item/field_4': LogDataTable[0][4]
@'item/field_5': $'''%LogDetailsDateTime% %UserID% %LogDataTable[0][5]%'''
@'item/field_6': LogDataTable[0][6]
ON ERROR
REPEAT 2 TIMES WAIT 2
RetryType: RetryType.Exponential
MinInterval: 2
MaxInterval: 360
ON ERROR
END
ポイントは以下の3つです。
-
@tableにリストのGUID、@datasetにサイトURLを指定するため、あらかじめ対象のSharePointサイト・リストを決めておく必要があります(ウィザードで選択すれば自動的に埋まります) -
field_2〜field_4はテーブルデータの該当列をそのまま渡すことで、呼び出し元がテーブルの中身を変えるだけでログ内容を自由に調整できます -
ON ERRORブロックで指数バックオフ・最大2回のリトライを設定しており、リモートPCでのネットワーク瞬断などでログ書き込み自体が失敗しても、自動的にリトライしてから諦める(=本処理側は止めない)挙動になっています
6-5. エラー発生時ブロックからの呼び出し
PADの「エラー発生時」ブロック(On block error)からも、6-3節と同じ流れ(「行をデータ テーブルに挿入する」→FlowLoggerの実行)で記録します。LogDataTable[0]の該当列に、ステータスに相当するメッセージ(例:'*** Desktopフロー異常終了 ***')とエラーメッセージ(%LastError.Message%)を詰めて呼び出す形です。これにより、フロー内で捕捉できるエラーは確実にSharePointリストへ残ります。
NotSuccessビュー: 実際のエラーを拾って出力しています。

6-6. タイムアウト(強制終了)への対処
エラー発生時ブロックで捕捉できるのは「PADが例外として認識できるエラー」までで、外部要因によるタイムアウト強制終了そのものは捕捉できません。そのため、各ステップの開始時点でも必ずログを書き込む運用にしています。こうしておくと、タイムアウトで強制終了された場合でも、SharePointリストに残っている最後の1件(=開始したが完了しなかったステップ)を見れば、どのステップの実行中に止まったかを特定できます。
7. まとめ・所感
- 今回のハマりポイントを一言でまとめると、**「タイムアウトによる強制終了はフロー側の正常なエラーハンドリングの対象外であり、記録は"外側"(=完了を待たずに都度書き込む形)に置くしかない」**という点でした
- 当初は中継用のクラウドフローが必要だと思い込んでいましたが、PADの「項目の追加」アクションを使えば、PADフロー単体からSharePointリストに直接書き込めるとわかったことで、構成をシンプルに保てました
- ログ1行分をテーブルデータの0番目の行に詰めてから共通サブフローに渡す設計にしたことで、呼び出し元ごとにログ項目数が変わっても共通部分を修正せずに済んでいます
- ネットワーク瞬断のような一時的な失敗に備えて、書き込み処理自体に指数バックオフのリトライを仕込んでおくと安心です
- 同様の構成は、以下のようなケースにも応用できそうです
- PADに限らず、長時間実行される任意の自動化処理の途中経過を外部から監視したい場合
- 複数の無人PCで並行実行しており、どのマシンのどのフローが今どの状態かをダッシュボード的に見たい場合(SharePointリストをPower BIやPower Appsで可視化)
- SharePoint以外の別のコネクタ(Dataverse、Teamsへの通知など)へも同じ
External.InvokeCloudConnectorの考え方を応用できる場合








