[VBScript] クリップボードとの文字データのやり取りを実現する

どーもボキです。

2024/5/18更新
ボキが出入りする会社の話になりますが、Win11環境では従来ロジックではGetClipBoard(コピーした文字列を取得する関数)が動かなかったため、PowerShellを利用したものへ修正しました。

VBScriptでも、クリップボードからの文字列の取得、クリップボードへの文字列を反映、どちらもカンタンに実現できます。


サンプルプログラムのダウンロードと使い方

  • ダウンロード
  • 使い方は、実行する、だけ。
    SetClipBoard関数にてクリップボードへ、実行時間と実行ファイル名情報を送り、GetClipBoard関数にてクリップボードより文字データを取得し、ダイアログへ表示します(下図)。
    [VBScript] クリップボードとの文字データのやり取りを実現する_a0021757_10403130.png

SetClipboard関数、GetClipboard関数のソース

    クリップボードへのコピーは、以下の1行のコードでも実現できます。
    CreateObject("WScript.Shell").Exec("clip").StdIn.Write Str

    ただ上記の方法では、clipプロセスの終了待ちをしないため、クリップボードへの文字列反映が完了しないうちに次の処理へ移ってしまうことがあります。これが困るならWScript.Sleepなどを用いたタイミング調整が必要と、若干メンドウなことになります。そして、ボキ的重要ポイント、clipプロセスの実行時に一瞬ウィンドウが表示されてカッコ悪い!

    以下のコード(ダウンロード)なら、clipプロセスを非表示で実行し、処理完了まで待たせていますので、WScript.Sleepでの時間調整はいりません。当然、余計なウィンドウはでません。

    SetClipboard Now & vbLf & WScript.ScriptName

    Dim s
    s = GetClipboard
    MsgBox s

    ''-------------------------------------------------------------------------------
    '' クリップボードから文字列を取得する
    ''-------------------------------------------------------------------------------
    'Function GetClipboard
    ' GetClipboard = CreateObject("htmlfile").ParentWindow.ClipboardData.getData("text") & "" ' 「"」はリッチテキストの変換
    'End Function


    '-------------------------------------------------------------------------------
    ' クリップボードから文字列を取得する
    '-------------------------------------------------------------------------------
    Function GetClipboard
    On Error Resume Next

    Dim r: r = ""
    Dim objWS: Set objWS = CreateObject("WScript.Shell")
    Dim objFS: Set objFS = CreateObject("Scripting.FileSystemObject")
    Dim fpth
    fpth = objFS.GetSpecialFolder(2) & "\" & objFS.GetTempName
    ' クリップボードの内容を一時ファイルへ
    cmd = "cmd /c PowerShell Get-Clipboard -Format Text > " & fpth
    objWS.Run cmd, 0, True
    ' 一時ファイルの処理
    If objFS.FileExists(fpth) Then
    r = objFS.OpenTextFile(fpth, 1).ReadAll
    objFS.DeleteFile fpth, True
    End If
    GetClipboard = r
    On Error Goto 0
    End Function


    '-------------------------------------------------------------------------------
    ' クリップボードへ文字列をコピーする
    '-------------------------------------------------------------------------------
    Sub SetClipboard(iStr)
    On Error Resume Next
    ::::Do
    ' 一時ファイルへコピー文字を記載
    Dim objFS
    Set objFS = CreateObject("Scripting.FileSystemObject")
    Dim fpth
    fpth = DPath_temp & objFS.GetTempName
    Dim tmp
    Set tmp = objFS.CreateTextFile(fpth, True)
    tmp.Write iStr
    tmp.Close
    If Err Then MsgBox "環境依存文字が含まれるためコピーできません。", vbCritical, "SetClipboard": Exit Do
    ' 一時ファイルをクリップボードへ
    cmd = "cmd /c clip < " & fpth
    CreateObject("WScript.Shell").Run cmd, 0, True

    ::::Loop Until 1
    ' 一時ファイルを削除
    objFS.DeleteFile fpth, True
    On Error Goto 0
    End Sub


この記事での気付き

    VBScriptに限らず、必要となる処理をひとつの開発手段だけで実現するのではなく、複数の開発手段を組み合わせたハイブリットの開発手段を取れると、実現したいことに手早くたどり着けます。

    それに気付けるようになるためには、日頃から技術の幅を広げておくことが必要ですね。
    ファイル・フォルダ操作系ならば、bat、vbs、ps等、OSの基本機能とのハイブリット開発をオススメします。

    VBScriptに限らず、こういった処理系を使い分けるという考え方、重要ですし、チーム運営でもプログラム開発でも、餅は餅屋、得意を活かすことが重要ですよね。


にほんブログ村 IT技術ブログへ
にほんブログ村

Commented by くま at 2022-01-04 05:52
210501.vbs に
SetClipboard "aa""bbb""ccc""ddd""|"
と指定したら、「aa"bbb"ccc"ddd"| 」が
「慡戢扢挢捣搢摤簢」
と文字化けしてクリップボードに格納されていた。
何故ですか?
Commented by yozda at 2022-01-04 09:32
> くまさん
コメントありがとうございます。こちらでも発生しました。
おそらく、"aa bbb ccc ddd" の部分が、他の文字コードでの「慡戢扢挢捣搢摤簢」と同じバイトパターンになっていると思われます。

SetClipboard "aaa bbb ccc ddd" の場合は、文字化けしませんでした(aa → aaa)。
Commented by くま at 2022-01-04 22:23
どうもどうも。 
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 スキーマ」方式に変えました。お遊びとしては、なかなかイイです。
Commented by yozda at 2022-01-05 11:49
> くまさん
コメントありがとうござました。

「データ url スキーマ」方式、知りませんでした。こういうやり方もあるのですね。面白そうです。

SetClipboardの追加調査は、検討させていただきますね。
Commented by くま at 2022-01-05 20:42
ご参考
"a1 cde fgh" は、ㅡ挠敤映桧  の5文字に化けます。

少なくとも、英1文字(つまり、a-z, A-Z)キーボート1文字(但し~|{}以外)space英3文字space英3文字、のパータンは文字化け発生。

a1 cde fgh = &#x61;&#x31;&#x20;&#x63;&#x64;&#x65;&#x20;&#x66;&#x67;&#x68;
ㅡ挠敤映桧 = &#x3161;&#x6320;&#x6564;&#x6620;&#x6867;

つまり、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?。
Commented by yozda at 2022-01-05 22:41
> くまさん
詳細な解説ありがとうございます。バグがありそうですね。


これと同じ現象なのかは分かりませんが、似た経験はあります。

標準入出力を用いて全角文字を含むパスを渡すと、128B前後のパス文字にて文字化けが起き、パス情報をやり取りできない、という現象です。

今回の現象のように、全角文字を含むと必ず起きるわけではありませんでした。そのため、発生パターンが分からず、バス文字に異常がおきた(=パスが存在しない)場合は、別のコマンドプロンプトからファイル渡しでばすをもらバスを貰う、と言ったエラー処理を入れました。

今後の修正も入らないでしょうから、回避策があるなら、そちらで逃げておく、も良いかもしれませんね。
名前
URL
削除用パスワード

※このブログはコメント承認制を適用しています。ブログの持ち主が承認するまでコメントは表示されません。

by yozda | 2021-05-01 12:02 | ボキ、しごとのヒント集める | Comments(6)

ボキの興味、書き散らかします


by ボキ
カレンダー
S M T W T F S
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31