【PowerShell】Get-Clipboardでコピーしたテキスト履歴をファイルに保存する方法
PowerShellのGet-Clipboardを使えば、監視中にコピーしたテキストの変化を検出し、日時付きの履歴としてファイルへ残せます。
この記事では元のスクリプトを基に、保存方法、起動から終了までの操作、各処理の意味、運用時の注意点までまとめます。
概要
Windowsでコピーした文字列をあとから確認したいときは、PowerShellのGet-Clipboardを定期的に実行し、前回取得した内容と違う場合だけファイルへ保存する方法が使えます。
専用のクリップボード管理ソフトを追加せず、コピー操作を続けながらテキストの記録を残せるのがこの方法の特徴です。
今回のスクリプトは、起動中だけクリップボードを監視する簡易的な履歴保存ツールです。
監視開始時に現在の内容を覚え、その後に新しいテキストへ変化したことを検出すると、日時と一緒にclipboard_history.txtへ記録します。
元の実行例ではWindows 11 Home 64Bitのversion 25H2を使用しています。
PowerShellでps1ファイルを実行でき、Get-Clipboardが利用できる環境を前提にしています。
保存対象はテキストです。
ファイルのコピーや画像など、クリップボードに入るすべての形式を履歴化する汎用ツールではなく、文章、URL、ファイル名、コマンドなどの文字列を後から振り返る用途に向いています。
標準設定では1秒ごとにクリップボードを確認します。
毎回無条件に書き込むのではなく、直前に取得した文字列と異なる場合だけ保存するため、同じ内容がクリップボードに残り続けているだけでは履歴は増えません。
履歴へ保存する文字列は最大1000文字に制限しています。
長い文章をコピーした場合は先頭1000文字までを残して省略表示を付けるため、意図せず巨大なテキストをコピーしたときに1件の記録が極端に大きくなるのを抑えられます。
PowerShellの画面に表示する内容は最大64文字です。
複数行の文字列は画面表示用に改行をスペースへ置き換えるので、監視中のコンソールが長いコピー内容で埋まりにくくなっています。
履歴ファイルはスクリプトと同じフォルダに作られます。
新しい履歴をファイルの先頭へ追加する方式なので、テキストエディターで開いたときは最新のコピー内容から確認できます。
Windows自体にもクリップボード関連の機能はありますが、このスクリプトの狙いは履歴を通常のテキストファイルとして残すことです。
ファイルとして保存されるため、終了後にメモ帳などで開いて確認しやすく、必要なら別の場所へコピーして保管できます。
一方で、監視していない時間のコピー内容を後から復元することはできません。
PowerShellを終了した時点で監視も止まるため、記録したい作業の前に起動し、作業が終わったらCtrl + Cで停止する使い方が基本です。
また、コピーした文字列にはパスワード、認証コード、個人情報、社内情報などが含まれる可能性があります。
このスクリプトは内容を選別せず、条件に合うテキストの変化を保存するので、履歴ファイルの保管場所と削除タイミングは利用者側で管理する必要があります。
仕組みは単純で、Get-Clipboardで取得、前回値と比較、必要なら整形、既存ファイルを読み込み、新しいエントリを先頭に結合してSet-Contentで書き戻す、という流れです。
処理を小さな段階に分けているため、PowerShellの学習用サンプルとしても追いやすい構成です。
この方法が便利なのは、コピーした内容を別のメモへ貼り付ける作業を毎回行わなくても、監視中なら変化を自動でテキスト化できる点です。
調査中に複数のURLやコマンドを行き来する場面では、直前に何をコピーしたかを後から探す補助になります。
ただし、履歴ファイルはバックアップではありません。
保存文字数の上限があり、監視停止中の内容は記録されず、同じ値の連続コピーも回数として残らないため、完全な操作記録が必要な用途とは分けて考える必要があります。
利用前には保存先を確認してください。
スクリプトと同じフォルダへ履歴が作られる設計なので、ps1をデスクトップへ置けば履歴もそこへ作られ、作業用フォルダへ置けばその中に作られます。
管理しやすい専用フォルダへまとめておくと整理が簡単です。
想定する利用場面は、短時間の調査、設定作業、文章編集、コマンド確認などです。
何度もコピーと貼り付けを繰り返す作業では、少し前に使った文字列を再確認したくなることがあります。
履歴を平文で残しておけば、作業終了後にも検索できます。
専用アプリの高度な検索、ピン留め、画像履歴、同期といった機能はありません。
その代わり、何をしているかがPowerShellコードとして見えるため、保存条件や文字数を自分で理解して調整したい場合には扱いやすい例です。
保存日時はコピー操作そのものが発生した瞬間をOSから受け取るものではなく、スクリプトが変化を検出してentryを作成した時点の日時です。
監視間隔があるため、時刻を厳密なイベント発生時刻として扱うのではなく、作業を振り返る目安として使います。
監視を始める前に、履歴へ残してよい情報の範囲を決めておくことも大切です。
個人利用のPCでも、認証情報や一時コードをコピーする場面があるなら、監視を一時停止する、履歴を作業後に確認して削除するなどの運用を考えてください。
スクリプトを共有PCで使う場合はさらに注意が必要です。
clipboard_history.txtは通常のテキストファイルなので、ファイルを読める人には内容も読めます。
便利だから常時起動するのではなく、保存する必要がある作業だけで使う方が管理しやすくなります。
PowerShellスクリプト
以下の内容をps1ファイルとして保存します。
元記事の例ではファイル名をWatch-Clipboard.ps1とし、UTF-8 BOM付きで保存しています。
設定値は冒頭の3項目にまとめています。
保存文字数、画面表示文字数、監視間隔を変えたい場合は、処理本体を触る前にこの部分だけ調整すると分かりやすくなります。
==========================================
設定項目
==========================================
履歴に残すテキストの最大文字数
$MaxTextLength=1000
コンソール表示用の最大文字数
$MaxDisplayLength=64
チェック間隔(秒)
$IntervalSeconds=1
==========================================
処理本体
==========================================
$ScriptDir=Split-Path-Parent$MyInvocation.MyCommand.Definition
$LogFilePath=Join-Path$ScriptDir”clipboard_history.txt”
Write-Host”クリップボードの監視を開始しました…”-ForegroundColorGreen
Write-Host”保存先:$LogFilePath”-ForegroundColorCyan
Write-Host”最大文字数:$MaxTextLength文字”-ForegroundColorCyan
Write-Host”終了するにはCtrl+Cを押してください。”-ForegroundColorYellow
Write-Host””
起動時点のクリップボード内容を初期値として保持
$script:lastText=Get-Clipboard-Raw-ErrorActionSilentlyContinue
try{
while($true){
$currentText=Get-Clipboard-Raw-ErrorActionSilentlyContinue
if($null-ne$currentText-and$currentText-ne””-and$currentText-ne$script:lastText){
$script:lastText=$currentText
#履歴ファイル用のテキスト処理(最大サイズ制限)
$savedText=$currentText
if($savedText.Length-gt$MaxTextLength){
$savedText=$savedText.Substring(0,$MaxTextLength)+”[…省略…]”
}
#エントリの作成
$timestamp=Get-Date-Format”yyyy-MM-ddHH:mm:ss”
$entry=”========================================”+[Environment]::NewLine+”[$timestamp]”+[Environment]::NewLine+$savedText+[Environment]::NewLine
#既存のファイル内容を読み込んで先頭に結合(降順)
$existingContent=””
if(Test-Path$LogFilePath){
$existingContent=Get-Content-Path$LogFilePath-Raw-EncodingUTF8-ErrorActionSilentlyContinue
}
$newContent=$entry+$existingContent
$newContent|Set-Content-Path$LogFilePath-EncodingUTF8
#コンソール表示用のテキスト整形
$displayText=$currentText-replace”rn|r|n”,””
if($displayText.Length-gt$MaxDisplayLength){
$displayText=$displayText.Substring(0,$MaxDisplayLength)+”…”
}
Write-Host”[$timestamp]保存:$displayText”-ForegroundColorGray
}
Start-Sleep-Seconds$IntervalSeconds
}
}
finally{
Write-Host””
Write-Host”監視を停止しました。”-ForegroundColorYellow
}
スクリプトは保存した場所を自分で取得し、そのフォルダにclipboard_history.txtを作成します。
そのため、実行するたびに別のカレントディレクトリへ移動しても、履歴ファイルの保存先はスクリプト自身の配置場所を基準に決まります。
初回起動時には、その時点でクリップボードに入っている内容をlastTextへ入れます。
これにより、監視開始前から残っていた文字列を新規コピーと誤認して、起動直後に履歴へ保存することを避けています。
ループ中はGet-Clipboard -Rawで内容を取得します。
Microsoft Learnの説明でも、-Rawを使うと複数行テキストを一つの複数行文字列として扱えるため、改行を含む文章を一つのコピー内容として比較しやすくなります。
ErrorActionにSilentlyContinueを指定しているため、取得時のエラー表示を抑えています。
ただし、エラーを画面に出さないことと、あらゆるクリップボード形式を正常に記録できることは同じではありません。
このスクリプトはテキスト履歴の保存用として扱うのが安全です。
新しい内容を検出すると、まずlastTextを更新します。
その後、保存用のsavedTextと画面表示用のdisplayTextを別々に作るため、ファイルに残す情報量とコンソールの見やすさを別の基準で調整できます。
ファイル保存ではGet-Content -Rawで既存履歴を一括取得し、新規エントリを前に結合してSet-Contentで全体を書き戻します。
この方式は最新履歴が上に来る利点がある反面、履歴ファイルが非常に大きくなると毎回全体を読み書きする量も増えます。
長期間常駐させて大量の履歴を蓄積する用途なら、追記方式やローテーションなど別の設計を検討する余地があります。
今回の例は、作業中のコピー内容を手軽に残し、あとからテキストファイルで確認するという小規模な利用に焦点を当てています。
コードを変更するときは、まず元のps1を別名で残してから試すと戻しやすくなります。
特に保存先や文字数制限を変更する場合は、短いテスト文字列を数回コピーし、想定した順序と内容で履歴が作られることを確認してから本番の作業へ使うと安心です。
コードを貼り付けて保存するときは、引用符やバッククォートを別の文字へ置き換えないようにします。
Webページからコピーしたあと、PowerShell用の記号が全角化していないか、行が途中で欠けていないかを確認すると、単純な転記ミスを見つけやすくなります。
保存後にいきなり長時間使うのではなく、テスト用のフォルダで起動し、「alpha」「beta」のような短い文字列を順にコピーして結果を見ると仕組みを確認しやすくなります。
想定外の内容が残る場合は、履歴を本格利用する前に設定やコードを見直せます。
履歴ファイル名を変えたい場合はJoin-Pathの第2引数にあるclipboard_history.txtを変更できます。
保存先そのものを別フォルダにしたい場合はコードの意味が変わるため、ScriptDirを基準にする現在の利点を理解したうえで変更してください。
IntervalSecondsを変更するときは、値を極端に小さくするより、実際のコピー頻度に合うかを確認します。
今回の1秒は元記事の設定例であり、用途によって最適値が固定されているわけではありません。
検出速度と処理回数のバランスを見て決めます。
MaxTextLengthを大きくすると長文を残せますが、1件あたりの保存量も増えます。
さらに現在の実装は履歴全体を書き戻すため、長文と多数の履歴が組み合わさるほどファイル操作の負担も増える方向になります。
MaxDisplayLengthは保存内容を削る設定ではありません。
ここを32へ下げても履歴側のMaxTextLengthが1000なら、保存用には最大1000文字が使われます。
画面の見やすさだけを変えたいときに独立して調整できる点がポイントです。
コード内の色指定はWrite-HostのForegroundColorで、開始、保存先、終了案内、保存通知などを見分けやすくするための表示上の設定です。
履歴ファイルへ色の情報が書き込まれるわけではありません。
スクリプトを別フォルダへ移動すると、次回実行時のLogFilePathも新しいスクリプト配置場所を基準に変わります。
以前のclipboard_history.txtが自動で移動するわけではないため、履歴を継続したいならファイルも一緒に管理します。
使用方法
監視の流れは、スクリプトを起動し、普段どおりテキストをコピーし、作業が終わったらCtrl + Cで止めるだけです。
ここでは開始、記録、終了の3段階に分けて確認します。
起動方法
Watch-Clipboard.ps1を保存したら、Windows PowerShellを起動し、スクリプトがあるフォルダから実行します。
たとえば現在位置にファイルがある場合は、ドットとバックスラッシュを付けて .\Watch-Clipboard.ps1 のように指定します。
正常に開始すると、監視開始のメッセージ、履歴ファイルの保存先、最大文字数、Ctrl + Cで終了できることがコンソールへ表示されます。
最初に保存先を確認しておくと、あとで履歴ファイルを探す手間を減らせます。
元記事では、ps1ファイルを右クリックしてPowerShellで実行する方法も例示されています。
どの起動方法でも重要なのは、スクリプトが実行状態のままになっていることです。
ウィンドウを閉じると監視も終了します。
環境によってps1の実行が許可されていない場合は、PowerShellの実行ポリシーに関するメッセージが出ることがあります。
その場合は表示された内容を確認し、組織管理のPCなら管理者のルールを優先してください。
この記事ではセキュリティ設定を一律に変更する手順までは扱いません。
起動直後のクリップボード内容は履歴へ追加されません。
スクリプトは開始時点の内容を基準値として記憶し、その後に別のテキストがコピーされたときから新しい履歴として保存します。
動作確認をするときは、短い単語を一つコピーしてコンソールに保存メッセージが出るか確認し、続けて別の単語をコピーします。
その後clipboard_history.txtを開き、新しい方が上に並んでいれば基本動作を確認できます。
PowerShellのプロンプトに現在のフォルダが表示されている場合は、Watch-Clipboard.ps1がその場所にあるか確認します。
別の場所にあるならSet-Locationなどで移動するか、スクリプトのパスを指定して実行します。
開始メッセージが出たあと、PowerShellは次の通常プロンプトへ戻らず監視を続けます。
これは停止しているのではなく、whileループが動作中だからです。
コピーを試して保存メッセージが増えることを確認してください。
初回テストでは、PowerShellの表示だけで成功と判断せず、実際にclipboard_history.txtが作られるところまで確認します。
保存先として表示されたパスと、エクスプローラーで見ているフォルダが一致しているか確認すると、別フォルダの同名ファイルを見てしまう混乱を防げます。
スクリプトを修正したあとに再テストするときは、実行中の古いプロセスを止めてから起動し直します。
ps1ファイルを書き換えても、すでに動いている実行内容が自動的に新しいコードへ差し替わるわけではありません。
複数のPowerShellウィンドウで同じスクリプトを同時に動かす使い方は避けた方が単純です。
同じclipboard_history.txtを複数プロセスが読み書きすると、どちらが最後に書き込むかによって期待しない結果になる可能性があります。
クリップボードへコピー
監視中の操作は普段のコピーと同じです。
ブラウザー、エディター、エクスプローラー上の名前、PowerShellの文字列など、必要なテキストを通常どおりCtrl + Cやアプリのコピー操作でクリップボードへ入れます。
内容が前回のテキストから変わると、次の監視タイミングで新規コピーとして扱われます。
標準のIntervalSecondsは1なので、コピー直後から最大でおおむね1回の待機間隔を経て検出される構成です。
コンソールには日時と保存内容の先頭部分が表示されます。
表示用文字列は改行をスペースへ変換し、64文字を超える場合は途中で省略するため、複数行の長文をコピーしても監視画面では一行として確認できます。
ファイル側には表示用の64文字制限ではなく、保存用の1000文字制限が適用されます。
画面で省略されて見えても、clipboard_history.txtにはより長い内容が残っている場合があります。
1000文字を超えるコピーは先頭1000文字まで保存され、その後ろに省略を示す文字列が付きます。
全文保存が必要な用途ではMaxTextLengthを増やせますが、長いデータを頻繁にコピーすると履歴ファイルのサイズも増える点を考慮してください。
同じ文字列を連続してコピーした場合、クリップボードのテキストがlastTextと同じなら新しい履歴としては保存されません。
コピー操作の回数を記録する仕組みではなく、取得したテキストの変化を記録する仕組みだからです。
いったん別の文字列をコピーしたあと、以前と同じ文字列へ戻った場合は、直前のlastTextとは異なるため再び保存対象になります。
履歴を見ると、同じ文字列が離れた位置に複数回現れることがあります。
保存される各エントリにはyyyy-MM-dd HH:mm:ss形式の日時が付きます。
厳密な操作ログや監査証跡を目的にした仕組みではありませんが、自分の作業中にどの順番でコピーしたかを振り返る目印として使えます。
機密情報をコピーした場合も、テキストとして取得され条件を満たせば履歴へ残り得ます。
パスワードマネージャーや業務システムから値をコピーする作業と併用するときは、clipboard_history.txtの取り扱いに注意し、不要になった履歴は適切に削除してください。
履歴ファイルを別のアプリで開いたまま編集していると、書き込みの競合など別の問題が起きる可能性があります。
監視中は基本的に閲覧だけにとどめ、編集や整理はスクリプトを停止してから行うと扱いやすくなります。
URLをコピーする用途では、一件ごとに日時が付くため、調査中に参照した候補をあとから見直す補助になります。
ただしURLの内容やページタイトルまでは取得せず、クリップボードに入った文字列だけを保存する点は区別してください。
コマンドをコピーする用途では、改行を含む複数行のコマンドもRaw文字列として扱われます。
コンソールのプレビューは一行化されますが、保存用データではMaxTextLengthの範囲内で元の改行を含む内容を記録できます。
コピー内容が短時間で頻繁に切り替わる作業では、ポーリング間隔との関係を意識する必要があります。
このスクリプトはコピーイベントを直接購読するのではなく、一定間隔で現在値を読むため、間隔より速い変化のすべてを捕まえる保証はありません。
保存結果を確認すると、各エントリの先頭に区切り線が入り、その次に日時、その下にコピー内容が並びます。
最新のentryをexistingContentの前へ結合するので、ファイルを開いてすぐ上の方を見るだけで直近の記録を確認できます。
コピーした文章に改行が含まれる場合、履歴ファイルではその改行を含んだままsavedTextとしてentryへ組み込みます。
コンソール表示だけは改行をスペースへ置換するため、画面表示とファイル表示が完全に同じ見た目になるわけではありません。
空文字は保存条件から除外されています。
クリップボードの取得結果が空なら新規エントリを作らず、次の監視へ進みます。
この判定により、内容のない状態を履歴として積み上げることを避けています。
監視中に履歴を検索したい場合は、書き込みが続いていることを前提に扱います。
確実に整理したいならCtrl + Cで止めてからファイルを開き、必要な情報を検索・編集・移動する方が手順を単純にできます。
コピー履歴を他人へ渡すときは、必要な行だけを抽出する方が安全です。
作業中のURLやコマンドに混じって、意図せず別の文字列が保存されている可能性があるため、clipboard_history.txtを丸ごと共有する前に内容を確認してください。
終了方法
監視を止めるときは、スクリプトを実行しているPowerShellウィンドウでCtrl + Cを押します。
元のスクリプトではfinallyブロックに停止メッセージを置いており、終了時に「監視を停止しました。
」と表示する構成です。
停止後もclipboard_history.txtはスクリプトと同じフォルダに残ります。
PowerShellを閉じても保存済みの履歴は消えないので、必要な内容を確認したり、別ファイルへ移したりできます。
次回もう一度Watch-Clipboard.ps1を起動すると、既存のclipboard_history.txtを読み込み、新しい履歴をその先頭へ加えます。
ファイルを削除しない限り、過去の記録と新しい記録が同じファイルに蓄積されます。
履歴をリセットしたい場合は、監視を停止してからclipboard_history.txtを別名で退避するか、不要であることを確認して削除します。
次回の保存時にファイルが存在しなければ、新しい履歴ファイルとして作られます。
ウィンドウ右上の閉じる操作でもプロセス自体は終わりますが、通常の利用ではCtrl + Cで明示的に停止し、停止メッセージを確認してからウィンドウを閉じる流れが分かりやすいです。
長時間の作業後は履歴ファイルの内容とサイズも確認してください。
今回の方式は新規保存のたびに既存内容を読み込んで全体を書き戻すため、記録が増え続ける運用より、必要な作業単位で停止・整理する使い方に向いています。
作業の区切りごとに履歴ファイルを別名保存する運用もできます。
たとえば調査テーマごとにファイルを退避してから次の監視を始めれば、一つの巨大な履歴へすべてを混在させずに済みます。
削除前には必要な情報が残っていないか確認します。
反対に、機密文字列が含まれている場合は、必要な情報だけ別の安全な場所へ移して履歴を残し続けない判断も重要です。
停止後に同じPowerShellウィンドウを使い続ける場合は、プロンプトへ戻ったことを確認します。
監視が終わっていれば新しいテキストをコピーしても履歴は増えません。
終了確認の簡単なテストとして利用できます。
次回起動時には、その時点でクリップボードにある文字列がlastTextへ入ります。
前回終了直前の値と同じかどうかに関係なく、起動時点の値自体は新規履歴として保存せず、その後の変化から監視を再開します。
履歴を保管する場合は、ファイル名に日付や作業名を付けて退避する方法も分かりやすいです。
スクリプトが参照する標準名はclipboard_history.txtなので、退避後は次回の新規保存で新しい標準名のファイルが作られます。
スクリプトの解説
冒頭のMaxTextLength、MaxDisplayLength、IntervalSecondsは、動作を調整するための設定値です。
MaxTextLengthはファイルへ残す1件あたりの最大文字数、MaxDisplayLengthはPowerShell画面へ出す最大文字数、IntervalSecondsはクリップボードを確認する間隔を表します。
ScriptDirは実行中のスクリプト自身のパスから親フォルダを取り出した値です。
LogFilePathはJoin-Pathでそのフォルダとclipboard_history.txtを結合して作るため、保存場所を固定のドライブ文字やユーザー名に依存させずに済みます。
lastTextは直前に確認したクリップボード文字列を保持するための変数です。
起動時にGet-Clipboard -Rawの結果を入れておき、ループ内でcurrentTextと比較することで、開始前の内容と新しい内容を区別します。
Get-ClipboardはMicrosoft.PowerShell.Managementのコマンドレットで、クリップボードの内容を取得します。
-Rawを付けると複数行テキストを一つの文字列として受け取れるため、このスクリプトでは改行を含む文章全体を一つの値として比較できます。
if文では、currentTextがnullではないこと、空文字ではないこと、lastTextと異なることをまとめて確認します。
この3条件を満たした場合だけ保存処理へ進むので、値がない状態や変化していない状態で履歴ファイルを書き換える回数を抑えます。
条件を通過するとlastTextをcurrentTextで更新します。
次のループではこの値が比較基準になるため、同じテキストがクリップボードに残っている間は保存処理へ入りません。
savedTextは履歴ファイル用の変数です。
LengthがMaxTextLengthを超える場合はSubstringで先頭部分を切り出し、省略を示す文字列を加えます。
ここでcurrentTextそのものを書き換えないため、後段の画面表示処理では元の取得値を使えます。
timestampはGet-Dateで現在日時を文字列化したものです。
区切り線、角括弧付きの日時、保存対象テキスト、改行を連結してentryを作ることで、履歴ファイルを人が開いたときに1件ごとの境界を見つけやすくしています。
Test-Pathはclipboard_history.txtがすでに存在するかを確認します。
存在するときだけGet-Content -Raw -Encoding UTF8で既存内容を読み込み、存在しない初回は空文字のまま次の処理へ進みます。
newContentはentryとexistingContentをこの順番で連結します。
新規エントリが前、既存履歴が後になるので、追記コマンドで末尾へ足す方式とは逆に、最新の記録が常にファイル先頭へ配置されます。
Set-ContentはnewContent全体をclipboard_history.txtへ書き込みます。
つまり1件追加するたびにファイル全体を更新する設計です。
履歴が少ない間は分かりやすい方法ですが、非常に大きな履歴を長期間ためる設計ではI/O量が増える点が弱点になります。
displayTextはコンソール確認専用です。
正規表現による-replaceでCRLF、CR、LFをスペースへ変換し、複数行のコピー内容を一行にまとめます。
さらにMaxDisplayLengthを超えた部分を切り詰めることで、監視画面の一行が長くなりすぎるのを防ぎます。
Write-HostはtimestampとdisplayTextを表示します。
この表示は履歴ファイルの内容そのものではなく、保存が発生したことをその場で確認するための短いプレビューです。
詳細を確認するときはclipboard_history.txtを開きます。
Start-Sleepはループの最後でIntervalSecondsだけ待機します。
待機を入れずにwhileを回し続けるより、一定間隔で確認する動作が明確になります。
間隔を短くすれば確認頻度は上がり、長くすれば検出までの待ち時間も長くなります。
tryとfinallyは監視ループの終了時処理をまとめるために使っています。
元記事の例ではCtrl + Cで終了したときにfinally側の停止メッセージを表示する構成で、利用者が監視終了を確認しやすくしています。
このスクリプトで特に理解しておきたいのは、Windowsのクリップボード履歴そのものを読み出しているわけではない点です。
Get-Clipboardでその時点の内容を繰り返し取得し、自前のlastTextと比較して独自のテキスト履歴を作っています。
そのため、監視間隔の間にクリップボードが複数回変化し、次のGet-Clipboard実行前にさらに別の値へ変わった場合、中間の内容を必ず捕捉できるとは限りません。
1秒間隔は扱いやすい設定例ですが、すべてのコピーイベントを保証するイベント駆動型の記録ではありません。
保存ファイルにはコピーしたテキストが平文で残ります。
便利さと同時に、コピーした機密情報まで残る可能性があることを理解し、共有フォルダや同期対象フォルダへ置くかどうかは慎重に決める必要があります。
設定を変更する場合は目的を一つずつ決めると安全です。
長文をより多く残したいならMaxTextLength、画面をさらに短くしたいならMaxDisplayLength、確認頻度を変えたいならIntervalSecondsというように、変更箇所と影響を対応させてテストします。
まずは元の設定で数件のテキストをコピーし、日時、並び順、省略、終了操作を確認するのがおすすめです。
仕組みを確認してから自分の作業に合わせて値を調整すれば、どの変更が動作へ影響したのかを追いやすくなります。
性能面で見ると、最も特徴的なのは最新順を実現するための全件読み込みと全件書き戻しです。
単純なAdd-Contentなら末尾への追記は容易ですが、最新を先頭に置く現在の表示順を維持するため、この例では既存内容との結合を選んでいます。
履歴の件数そのものには上限を設けていません。
MaxTextLengthは一件の文字数上限であり、ファイル全体のサイズ上限ではないため、長く使えばclipboard_history.txtは増え続けます。
定期的に退避や削除を行う運用が分かりやすいでしょう。
lastTextの比較は文字列全体に対して行われます。
末尾の空白や改行などが異なれば別の文字列として判定され得るため、人の目にはほぼ同じ文章でも保存される場合があります。
逆に完全に同じ文字列なら連続コピーしても追加されません。
SilentlyContinueは画面を静かに保つ目的では便利ですが、問題調査中には原因が見えにくくなることがあります。
動作しないときは、テスト環境でErrorAction指定を外してGet-Clipboard単体を実行し、取得結果やエラーを確認する切り分けが考えられます。
このコードは構成要素が独立しているため、学習するときは保存処理を一度に理解しようとせず、Get-Clipboard、比較、文字数制限、日時作成、ファイル読み込み、書き込み、画面表示の順に一つずつ追うと理解しやすくなります。
Get-Contentに-Rawを付けているのは、既存履歴を行の配列ではなく一つの文字列として取得し、そのままentryの後ろへ連結しやすくするためです。
クリップボード取得とファイル取得の両方でRawという考え方が登場しますが、対象はそれぞれ別です。
Encoding UTF8を明示して読み書きしているため、日本語を含む履歴を扱う前提がコード上でも分かります。
実際の文字コード挙動は利用するPowerShellのバージョンにも関係するため、別環境へ移す場合は日本語を含む短いテストで確認するのが確実です。
Environment.NewLineを使ってentryの改行を組み立てています。
文字列の中へ改行を直接大量に埋め込むより、区切り線、日時、本文の構造がコードから追いやすく、Windows環境の改行を意識した書き方になっています。
Substringは文字数上限を実装する中心です。
Lengthが上限を超えたときだけ実行するため、短い文字列に対して範囲外の切り出しを行いません。
上限以内ならsavedTextはcurrentTextと同じ内容のままです。
表示用の-replaceではWindowsで一般的なCRLFだけでなく、CR単体とLF単体も対象にしています。
複数種類の改行を一行表示へまとめることで、コピー元によって改行形式が異なる場合でもコンソールを一行に整えやすくしています。
監視ループはwhile ($true)なので、コード自身には通常終了の回数条件がありません。
利用者がCtrl + Cで止めることを前提とした対話的なツールです。
一定時間で自動終了したい場合は別の終了条件を設計する必要があります。
現在のコードはログの重複排除を「直前と同じか」だけで判断します。
過去の全履歴を検索して同じ文字列を二度と保存しない仕組みではありません。
これは直前のコピー変化を追うという目的には自然で、履歴全体のユニーク化とは異なる設計です。
最新順の保存は閲覧時には便利ですが、書き込み効率だけを考えるなら末尾追記の方が単純な場合があります。
どちらが適切かは、最新をすぐ見たいのか、長期間大量に蓄積したいのかで変わります。
今回のコードは前者を優先しています。
障害切り分けでは、まずGet-Clipboard -Rawを単独で実行し、期待した文字列が返るかを見る方法があります。
次にLogFilePathを画面へ表示して保存先を確認し、最後にファイル書き込み部分を見ると、取得、判定、保存のどこで問題が起きているかを分けやすくなります。
自分で機能追加するときも、元の役割分担を保つと見通しがよくなります。
たとえば保存件数制限を追加するならファイル管理の処理、特定文字列を除外するなら保存判定の処理というように、目的に近い場所へ条件を置くと後から読み返しやすくなります。
最後に、便利さを保ちながら安全に使うには、監視対象をテキストに限定した簡易ツールであること、履歴は平文で残ること、監視中だけ記録されること、最新順のため全体を書き戻すことの4点を覚えておくと判断しやすくなります。
用途がこの範囲に収まるなら、短いPowerShellスクリプトでコピー履歴を手元に残す方法として実用的です。