[VBScript] クリップボードとの文字データのやり取りを実現する
2021年 05月 01日
2024/5/18更新
ボキが出入りする会社の話になりますが、Win11環境では従来ロジックではGetClipBoard(コピーした文字列を取得する関数)が動かなかったため、PowerShellを利用したものへ修正しました。
VBScriptでも、クリップボードからの文字列の取得、クリップボードへの文字列を反映、どちらもカンタンに実現できます。
サンプルプログラムのダウンロードと使い方
- ダウンロード
- 使い方は、実行する、だけ。
SetClipBoard関数にてクリップボードへ、実行時間と実行ファイル名情報を送り、GetClipBoard関数にてクリップボードより文字データを取得し、ダイアログへ表示します(下図)。![[VBScript] クリップボードとの文字データのやり取りを実現する_a0021757_10403130.png](https://pds.exblog.jp/pds/1/202405/18/57/a0021757_10403130.png)
SetClipboard関数、GetClipboard関数のソース
- クリップボードへのコピーは、以下の1行のコードでも実現できます。
CreateObject("WScript.Shell").Exec("clip").StdIn.Write Str
SetClipboard Now & vbLf & WScript.ScriptNameDim ss = GetClipboardMsgBox s''-------------------------------------------------------------------------------'' クリップボードから文字列を取得する''-------------------------------------------------------------------------------'Function GetClipboard' GetClipboard = CreateObject("htmlfile").ParentWindow.ClipboardData.getData("text") & "" ' 「"」はリッチテキストの変換'End Function'-------------------------------------------------------------------------------' クリップボードから文字列を取得する'-------------------------------------------------------------------------------Function GetClipboardOn Error Resume NextDim r: r = ""Dim objWS: Set objWS = CreateObject("WScript.Shell")Dim objFS: Set objFS = CreateObject("Scripting.FileSystemObject")Dim fpthfpth = objFS.GetSpecialFolder(2) & "\" & objFS.GetTempName' クリップボードの内容を一時ファイルへcmd = "cmd /c PowerShell Get-Clipboard -Format Text > " & fpthobjWS.Run cmd, 0, True' 一時ファイルの処理If objFS.FileExists(fpth) Thenr = objFS.OpenTextFile(fpth, 1).ReadAllobjFS.DeleteFile fpth, TrueEnd IfGetClipboard = rOn Error Goto 0End Function'-------------------------------------------------------------------------------' クリップボードへ文字列をコピーする'-------------------------------------------------------------------------------Sub SetClipboard(iStr)On Error Resume Next::::Do' 一時ファイルへコピー文字を記載Dim objFSSet objFS = CreateObject("Scripting.FileSystemObject")Dim fpthfpth = DPath_temp & objFS.GetTempNameDim tmpSet tmp = objFS.CreateTextFile(fpth, True)tmp.Write iStrtmp.CloseIf Err Then MsgBox "環境依存文字が含まれるためコピーできません。", vbCritical, "SetClipboard": Exit Do' 一時ファイルをクリップボードへcmd = "cmd /c clip < " & fpthCreateObject("WScript.Shell").Run cmd, 0, True::::Loop Until 1' 一時ファイルを削除objFS.DeleteFile fpth, TrueOn Error Goto 0End Sub
この記事での気付き
- VBScriptに限らず、必要となる処理をひとつの開発手段だけで実現するのではなく、複数の開発手段を組み合わせたハイブリットの開発手段を取れると、実現したいことに手早くたどり着けます。
それに気付けるようになるためには、日頃から技術の幅を広げておくことが必要ですね。
SetClipboard "aa""bbb""ccc""ddd""|"
と指定したら、「aa"bbb"ccc"ddd"| 」が
「慡戢扢挢捣搢摤簢」
と文字化けしてクリップボードに格納されていた。
何故ですか?
コメントありがとうございます。こちらでも発生しました。
おそらく、"aa bbb ccc ddd" の部分が、他の文字コードでの「慡戢扢挢捣搢摤簢」と同じバイトパターンになっていると思われます。
SetClipboard "aaa bbb ccc ddd" の場合は、文字化けしませんでした(aa → aaa)。
SetClipboard "ab cde fgh" は、扡挠敤映桧 の5文字に化けました。
もっと短いパターンを探しています。
もっと徹底的に調べて、発表してください。
---
蛇足: AP → clipboard の vbs データ格納は、私は、inputbox を切ると同時に第三者の sendkeys 操作 job を起動し、inputbox の枠 data を ^c し、 OK ボタンを押す 操作を(伝言板コピー方式)してもらっていました。
最近は、 clipboard 格納の度に伝言板として、
WshShell.Run """C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"" --new-window ""data:;charset=utf-8,""" & str1 ,1,true
を起動し、その後自分で sendkeys の ^c, win close をする 「データ url スキーマ」方式に変えました。お遊びとしては、なかなかイイです。
コメントありがとうござました。
「データ url スキーマ」方式、知りませんでした。こういうやり方もあるのですね。面白そうです。
SetClipboardの追加調査は、検討させていただきますね。
"a1 cde fgh" は、ㅡ挠敤映桧 の5文字に化けます。
少なくとも、英1文字(つまり、a-z, A-Z)キーボート1文字(但し~|{}以外)space英3文字space英3文字、のパータンは文字化け発生。
a1 cde fgh = a1 cde fgh
ㅡ挠敤映桧 = ㅡ挠敤映桧
つまり、clip さんは、16進の 61 31 20 63 64 65 20 66 67 68 の1バイト10個を、2バイト5個とみなし、2バイト内の前後を入れ換えし、3161 6320 6564 6620 6867 として clipboard に入れた。
原因: dos の clip.exe のキマグレ bug ?。特殊パターンの文字列に対し unicode のバイト単位の前後並び換えをしています。
---
test は簡単、0test.txt と言う file を作り、文字列を入れておく(但し、改行ナシ、とすること)。dos prompt から、type 0test.txt | clip 、あるいは、clip < 0test.txt と叩く。clipboard 内容を ctrl+v で確認。 海外でも簡単に起こるはずなのに why?。
詳細な解説ありがとうございます。バグがありそうですね。
これと同じ現象なのかは分かりませんが、似た経験はあります。
標準入出力を用いて全角文字を含むパスを渡すと、128B前後のパス文字にて文字化けが起き、パス情報をやり取りできない、という現象です。
今回の現象のように、全角文字を含むと必ず起きるわけではありませんでした。そのため、発生パターンが分からず、バス文字に異常がおきた(=パスが存在しない)場合は、別のコマンドプロンプトからファイル渡しでばすをもらバスを貰う、と言ったエラー処理を入れました。
今後の修正も入らないでしょうから、回避策があるなら、そちらで逃げておく、も良いかもしれませんね。

