リモートデスクトップで特定のPDFだけコピーできない — 原因はPDFの内部構造
症状
手元のパソコン(接続元)からリモートデスクトップで別のパソコン(接続先)に接続し、接続先のFileMaker Proを操作してPDFを作成した。
この作成したPDFを、接続先から接続元へコピー&ペーストしようとすると、コピーダイアログは表示されるが、進捗バーがまったく進まない。
長時間待ってからキャンセルを押しても「取り消しています」と表示されたまま、キャンセル自体が完了しない。
リモートデスクトップを切断すると「特定できないエラー」と表示され、ようやくダイアログを閉じることができる。
接続元・接続先ともにWindows 11 Pro。
テキストファイルやEXEファイルは問題なくコピーできる。
別の接続先に接続した場合は、PDFも正常にコピーできる。
接続元・接続先の再起動でも改善しない。
原因はPDFの内部構造にあるため(後述)、逆方向(接続元→接続先)のコピーでも同様の問題が発生する可能性がある。
調査の流れ
環境の切り分け
まず、接続先の環境を疑った。
ウイルス対策ソフト(ウイルスバスター)を一時的に無効化してみたが、改善しない。
rdpclip.exe(リモートデスクトップのクリップボードプロセス)を再起動してみたが、改善しない。
イベントビューアー(eventvwr.msc)でアプリケーションログとシステムログを確認したが、関連するエラーは記録されていない。
グループポリシー(gpedit.msc)でクリップボードリダイレクトの制限を確認したが、設定されていない。
rdpclip.exeの再起動手順
rdpclip.exeはリモートデスクトップのクリップボード転送を担当するプロセスで、タスクマネージャーから終了・再起動できる。
rdpclip.exeを終了してもリモートデスクトップ接続は切断されない(クリップボード機能のみ一時的に無効になる)。
再起動手順:
- タスクマネージャーを開く(Ctrl+Shift+Esc)
- 「詳細」タブで rdpclip.exe を探し、右クリック→「タスクの終了」
- 「ファイル」→「新しいタスクの実行」で
rdpclip.exeと入力して実行
ファイルの切り分け
環境の問題ではないとわかったため、ファイルそのものを調べた。
別のPDFファイルをコピーしてみると、正常にコピーできた。
問題のPDFだけがコピーできない。
ファイル名が原因の可能性を考え、問題のPDFを「1234.pdf」にリネームしてコピーを試みたが、失敗した。
ファイル名は関係ない。
問題のPDFをZIP圧縮してからコピーすると、成功した。
ZIPで包めばコピーできるということは、PDFとしての中身が問題を引き起こしている。
PDFの属性比較
コピーできるPDFとコピーできないPDFのプロパティを比較した。
| 項目 | コピーできるPDF | コピーできないPDF |
|---|---|---|
| ファイルサイズ | 824 KB | 156 KB |
| 作成アプリケーション | Illustrator | FileMaker |
| PDFバージョン | 1.6 | 1.4 |
| セキュリティ設定 | なし | なし |
| ページ数 | 2 | 1 |
| コンテンツのコピー許可 | 許可 | 許可 |
セキュリティやアクセス権限に差はなかった。
問題のPDFはFileMaker Pro 16.0.6で生成されたものだった。
PDFの再作成テスト
問題のPDFを別の方法で作り直し、コピーできるかを確認した。
| 再作成方法 | コピー結果 |
|---|---|
| 「Microsoft Print to PDF」で印刷して再作成 | 成功 |
| Adobe Acrobatで「名前を付けて保存」 | 成功 |
| 画像として再作成 | 成功 |
どの方法でもコピーできるようになった。
PDFの中身(表示される内容)は同じでも、内部構造が変わることでコピーできるようになる。
ファイルシステムの調査
ファイルにNTFS代替データストリーム(ADS)やゾーン情報が付いている可能性を確認した。
dir /r コマンドでADSを確認したが、メインストリーム(159,732バイト)のみだった。
ファイルのプロパティに「ブロックの解除」チェックボックスは表示されない(Zone.Identifierなし)。
attrib コマンドでファイル属性を確認したが、アーカイブ属性(A)のみで正常だった。
ファイルをCドライブ直下の別フォルダに移動してコピーを試みたが、失敗した。
copy /b でバイナリコピーした複製も失敗した。
ファイルの場所やメタデータの問題ではなく、ファイルのバイナリデータそのものが原因であることが確定した。
NTFS代替データストリーム(ADS)とは
NTFSファイルシステムでは、1つのファイルに複数のデータストリームを持たせることができる。
通常のファイル内容はメインストリームに格納されるが、追加の隠れたデータストリーム(代替データストリーム、ADS)を付加できる。
代表的なADSがZone.Identifierで、インターネットやメールからダウンロードしたファイルに自動的に付加される。
Zone.Identifierが付いたファイルを開くと「このファイルは別のコンピューターから取得したものです」という警告が表示される。
ファイルのプロパティで「ブロックの解除」にチェックを入れると、Zone.Identifierが削除される。
dir /r コマンドで代替データストリームの有無を確認できる。
複数ファイル同時コピーの発見
偶然の発見だが、問題のPDFと別のPDFを同時に選択してコピーすると、成功した。
| コピー方法 | 結果 |
|---|---|
| 問題のPDF単体 | 失敗 |
| 問題のPDF + 別のPDF | 成功 |
| 問題のPDF + テキストファイル | 失敗 |
単体ではコピーできないが、別のPDFと一緒であればコピーできる。
テキストファイルとの組み合わせでは失敗するため、PDF同士の組み合わせに限られる。
なぜ複数ファイルだとコピーできるのか
Windowsのクリップボード転送では、単一ファイルと複数ファイルで処理方式が異なる。
| 処理 | 単一ファイル | 複数ファイル |
|---|---|---|
| サムネイル生成 | 実行される | スキップされることが多い |
| プレビューハンドラーの呼び出し | 実行される | スキップされることが多い |
| 転送方式 | ファイル内容を解析 | ファイルパスのリストとして転送 |
単一ファイルの場合、Windowsはファイルの中身を解析しようとする。
このときPDFの内部構造に問題があると、解析処理がハングする。
複数ファイルの場合はこの解析がスキップされるため、問題を回避できる。
ただし、テキストファイルとPDFの組み合わせでは失敗する理由は、ファイル種別が異なる場合の転送処理の違いによるものと推測されるが、正確な原因は不明。
PDFの内部構造の解析
問題の核心に迫るため、PDFファイルの内部構造を直接調べた。
PowerShellで以下のコマンドを実行し、PDFの構造要素を検索した。
Select-String -Path "問題のファイル.pdf" -Pattern "JavaScript|OpenAction|AA|Launch|EmbeddedFile|XFA"
結果、/OpenAction が検出された。
問題のPDFのカタログオブジェクト(PDFの目次にあたる部分)は以下の構造になっていた。
21 0 obj
/Type /Catalog
/Pages 6 0 R
/OpenAction [ 5 0 R
/XYZ null null 1 ] /PageLayout /SinglePage
/PageMode /UseNone
endobj
正常な構造:
21 0 obj
/Type /Catalog
/Pages 6 0 R
/OpenAction [ 5 0 R /XYZ null null 1 ]
/PageLayout /SinglePage
/PageMode /UseNone
endobj
違いは /OpenAction 配列の書式にある。
問題のPDFでは、配列の閉じ括弧 ] の直後にタブ文字を挟んで /PageLayout が同じ行に続いている。
正常なPDFでは、/OpenAction の値が1行で完結し、/PageLayout は別の行に記述される。
この不正な書式が、Windowsのクリップボード転送時のPDF解析処理をハングさせていた。
OpenActionとは
/OpenAction はPDFのカタログオブジェクトに記述できるエントリで、PDFを開いたときに自動的に実行するアクションを指定する。
この問題のPDFでは /OpenAction [ 5 0 R /XYZ null null 1 ] と指定されており、「5番オブジェクト(1ページ目)を、座標null/null、ズーム倍率1で表示する」という意味になる。
表示位置を指定するだけの一般的な設定であり、JavaScript実行のような危険な処理は含まれていない。
原因
FileMaker Pro 16.0.6が生成したPDFの内部構造(カタログオブジェクトの /OpenAction 記述)に書式上の問題があった。
リモートデスクトップのクリップボード転送では、Windowsがファイルの中身を解析する処理が含まれる。
この解析処理がPDFの不正な書式を正しく処理できず、ハングする。
NAS(SMB/CIFS)経由のファイルコピーでは問題が発生しない。
これは、SMBがファイルをバイナリデータとしてそのまま転送し、内容の解析を行わないためである。
| 転送方式 | ファイル解析 | 問題のPDF |
|---|---|---|
| リモートデスクトップ(クリップボード) | PDFのメタデータを解析する | ハングする |
| NAS / 共有フォルダ(SMB) | バイナリデータとしてそのまま転送 | 正常にコピーできる |
なお、同じFileMaker Pro 16.0.6で新規に生成したPDFは正常にコピーできた。
すべてのPDFで問題が起きるわけではなく、特定の条件で生成されたPDFにのみ発生する。
FileMaker側での対策は行えないため、運用で回避する必要がある。
回避策
根本的な解決(WindowsのPDF解析処理を無効化する方法)は、現時点では存在しない。
以下の方法で回避できる。
| 回避策 | 手軽さ | 説明 |
|---|---|---|
| 別のPDFと一緒に選択してコピー | 簡単 | ダミーのPDFを1つ用意しておき、常に一緒に選択してからコピーする |
| Adobe Acrobat Readerで開いて上書き保存 | やや手間 | 再保存することでPDFの内部構造が正規化される(実際に採用した方法) |
| NAS・共有フォルダ経由で転送 | やや手間 | SMBはファイル内容を解析しないため影響を受けない |
| ZIP圧縮してからコピー | やや手間 | ZIPで包めばPDFとして認識されない |
| 「Microsoft Print to PDF」で再作成 | やや手間 | まったく新しいPDFとして生成される |
最も手軽なのは「別のPDFと一緒にコピーする」方法で、ダミーのPDFを作業フォルダに1つ置いておくだけで対処できる。
実際の運用では、問題のPDFをAdobe Acrobat Readerで開いて上書き保存する方法を採用した。
FileMakerでPDFを作成した直後にAcrobat Readerで開き直して保存する手順を作業に組み込むことで、以降のコピーで問題が発生しなくなる。
Ghostscriptによる一括再処理(未検証)
大量のPDFを処理する場合は、Ghostscriptで内部構造を再構築できる可能性がある。
gswin64c.exe -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=output.pdf input.pdf
Ghostscriptはフリーソフトウェアで、コマンドラインからPDFの変換・再構築が可能。
上記コマンドを実行すると、PDFの内部構造が再構築されるため、不正な書式も修正されると考えられる。
バッチ処理と組み合わせることで、フォルダ内のPDFを一括で再処理することもできる。
ただし、この方法はこの問題に対して実際に検証したものではない。
Acrobat Readerでの上書き保存で解決できる場合は、そちらのほうが確実である。
まとめ
リモートデスクトップで特定のPDFだけコピーできない場合、PDF自体の内部構造に問題がある可能性がある。
NASやZIPでは正常にコピーできるのに、リモートデスクトップのクリップボード経由だけ失敗するという症状が特徴的である。
この種の問題は、ファイルの中身が正常に表示・印刷できるために原因の特定が難しく、「怪奇現象」として原因不明のまま見過ごされやすい。
PDFの生成元アプリケーションが内部構造に不正な書式を出力していないか確認することで、原因を特定できる場合がある。