windowsbatch-fileclipboard

Access clipboard in Windows batch file


Any idea how to access the Windows clipboard using a batch file?


Solution

  • To set the contents of the clipboard, as Chris Thornton, klaatu, and bunches of others have said, use %windir%\system32\clip.exe.


    Update 2:

    For a quick one-liner, you could do something like this:

    powershell -sta "add-type -as System.Windows.Forms; [windows.forms.clipboard]::GetText()"
    

    Capture and parse with a for /F loop if needed. This will not execute as quickly as the JScript solution below, but it does have the advantage of simplicity.


    Updated solution:

    Thanks Jonathan for pointing to the capabilities of the mysterious htmlfile COM object for retrieving the clipboard. It is possible to invoke a batch + JScript hybrid to retrieve the contents of the clipboard. In fact, it only takes one line of JScript, and a cscript line to trigger it, and is much faster than the PowerShell / .NET solution offered earlier.

    @if (@CodeSection == @Batch) @then
    
    @echo off
    setlocal
    
    set "getclip=cscript /nologo /e:JScript "%~f0""
    
    rem // If you want to process the contents of the clipboard line-by-line, use
    rem // something like this to preserve blank lines:
    for /f "delims=" %%I in ('%getclip% ^| findstr /n "^"') do (
        setlocal enabledelayedexpansion
        set "line=%%I" & set "line=!line:*:=!"
        echo(!line!
        endlocal
    )
    
    rem // If all you need is to output the clipboard text to the console without
    rem // any processing, then remove the "for /f" loop above and uncomment the
    rem // following line:
    :: %getclip%
    
    goto :EOF
    
    @end // begin JScript hybrid chimera
    WSH.Echo(WSH.CreateObject('htmlfile').parentWindow.clipboardData.getData('text'));
    

    Old solution:

    It is possible to retrieve clipboard text from the Windows console without any 3rd-party applications by using .NET. If you have powershell installed, you can retrieve the clipboard contents by creating an imaginary textbox and pasting into it. (Source)

    Add-Type -AssemblyName System.Windows.Forms
    $tb = New-Object System.Windows.Forms.TextBox
    $tb.Multiline = $true
    $tb.Paste()
    $tb.Text
    

    If you don't have powershell, you can still compile a simple .NET application to dump the clipboard text to the console. Here's a C# example. (Inspiration)

    using System;
    using System.Threading;
    using System.Windows.Forms;
    class dummy {
        [STAThread]
        public static void Main() {
            if (Clipboard.ContainsText()) Console.Write(Clipboard.GetText());
        }
    }
    

    Here's a batch script that combines both methods. If powershell exists within %PATH%, use it. Otherwise, find the C# compiler / linker and build a temporary .NET application. As you can see in the batch script comments, you can capture the clipboard contents using a for /f loop or simply dump them to the console.

    :: clipboard.bat
    :: retrieves contents of clipboard
    
    @echo off
    setlocal enabledelayedexpansion
    
    :: Does powershell.exe exist within %PATH%?
    for %%I in (powershell.exe) do if "%%~$PATH:I" neq "" (
        set getclip=powershell "Add-Type -AssemblyName System.Windows.Forms;$tb=New-Object System.Windows.Forms.TextBox;$tb.Multiline=$true;$tb.Paste();$tb.Text"
    ) else (
    rem :: If not, compose and link C# application to retrieve clipboard text
        set getclip=%temp%\getclip.exe
        >"%temp%\c.cs" echo using System;using System.Threading;using System.Windows.Forms;class dummy{[STAThread]
        >>"%temp%\c.cs" echo public static void Main^(^){if^(Clipboard.ContainsText^(^)^) Console.Write^(Clipboard.GetText^(^)^);}}
        for /f "delims=" %%I in ('dir /b /s "%windir%\microsoft.net\*csc.exe"') do (
            if not exist "!getclip!" "%%I" /nologo /out:"!getclip!" "%temp%\c.cs" 2>NUL
        )
        del "%temp%\c.cs"
        if not exist "!getclip!" (
            echo Error: Please install .NET 2.0 or newer, or install PowerShell.
            goto :EOF
        )
    )
    
    :: If you want to process the contents of the clipboard line-by-line, use
    :: something like this to preserve blank lines:
    for /f "delims=" %%I in ('%getclip% ^| findstr /n "^"') do (
        set "line=%%I" & set "line=!line:*:=!"
        echo(!line!
    )
    
    :: If all you need is to output the clipboard text to the console without
    :: any processing, then remove the above "for /f" loop and uncomment the
    :: following line:
    
    :: %getclip%
    
    :: Clean up the mess
    del "%temp%\getclip.exe" 2>NUL
    goto :EOF