「クリップボードのテキストをGnuPGで復号化」の代替品の代替品

id:eel3:20120521:1337527087 にて、Windows上でクリップボードにコピーされているGnuPGの暗号化テキストを復号化してテキストビューアで表示するツールを作成した。

あのツールはバッチファイルで実装していて、GnuPG(gpg.exe)とttPageとクリップボード上のテキストを取り出す自作ツール(C言語 + Windows API)を使用していた。普通のWindows XP上で使用することを念頭に置いていた為だ。

あれから暫くたち、メインPCのOSがWindows 7になったこともあり、PowerShellで書き直してみることにした。ただ復号化にGnuPGは必要だし、復号化したテキストのエンコード判定が面倒なのは変わらないのでエディタかビューア(ここではttPage)に任せてしまうので、実質的には「クリップボードからの読み込みに独自ツールが要らなくなった」という効果しかないのだけど。

# You must execute this script in STA mode
# $ powershell -Sta -File <this script>

Set-StrictMode -version Latest

function Get-ClipBoard
{
    Add-Type -assemblyName System.Windows.Forms

    $data = [System.Windows.Forms.Clipboard]::GetDataObject()
    if ($data.GetDataPresent([System.Windows.Forms.DataFormats]::Text)) {
        $data.GetData([System.Windows.Forms.DataFormats]::Text)
    }
}

trap {
    Set-StrictMode -off
    @($encrypt_file, $decrypt_file) | ?{$_ -ne $Null} | Remove-Item
    break
}

$encrypt_file = [System.IO.Path]::GetTempFileName()
$decrypt_file = [System.IO.Path]::GetTempFileName()

Get-ClipBoard | Out-File $encrypt_file -encoding Default
gpg.exe -d $encrypt_file | Out-File $decrypt_file -encoding Default
if ($? -eq $True) {
    ttpage.exe $decrypt_file | Out-Null
}

Remove-Item $encrypt_file, $decrypt_file

たったこれだけのコードなのに、幾つも注意すべき点がある。

  • Windows.Forms.TextBoxではクリップボードのテキストを完全に取得しきることができないケースがあった為、Windows.Forms.Clipboardを使用している。
  • 同様の理由で、Get-ClipBoardとgpg.exeをパイプで繋ぐのではなく、一時ファイルを経由するようにしている。
  • Windows.Forms.Clipboardを使用している影響で、このスクリプトはSTAで実行しなくてはならない。
  • 一時ファイルの多用は、文字コード絡みの問題を避ける為でもある。
  • 問題発生時に一時ファイルが残らないようにtrapを仕掛けている。この時、存在しない変数にアクセスしても大丈夫なようにstrictモードを無効にしている。
  • gpg.exeのオプション-oで出力先一時ファイルを指定すると、一時ファイルが既に存在するのでファイル上書きの確認入力が発生する。それを避ける為にOut-Fileで出力している。
  • 復号化したテキストの文字コード判定及び変換はttpage.exeに一任している。

スクリプト呼び出し用のバッチファイルはこんな感じ。

@echo off
powershell -ExecutionPolicy RemoteSigned -Sta -File %~dp0decrypt_clipboard.ps1