Search code examples
batch-filecmdclip

CMD : Clip command Issue


Working in a call center, i have pretty repetitive logs to write down for each calls, i am trying to build a simple HTA capable of copying the log templates (and emails) to the clipboard with a click.

Unfortunately, it isn't possible to copy a text file in .vbs (?).

So the HTA open the .bat on click with the text name argument (%1). From it's location on a server session (%~dp0) the .batch open the text file (%1) in the folder "Assets".

cls
@pushd %~dp0    
clip < %~dp0Assets\%1
@popd

I know, i have to work with what i have. But everything works smoothly !

Until i paste the content of the clipboard :

  • "d'avoir" becomes "dÆavoir"
  • "é" --> "Ú"
  • "à" --> "Ó"
  • etc ...

I tried Unicode, Ansi and UTF-8, same issue.

Anyone has an idea ?


Solution

  • The problem is that you're executing clip while the active codepage of the console doesn't match the encoding of the text you're copying to the clipboard. You should also make sure the text files containing your extended characters are saved in UTF8 format. In other words, the problem is in the copying, not in the pasting; and everything doesn't work as smoothly as you assert.

    Try this:

    @echo off & setlocal
    
    rem // capture current console codepage to a variable
    for /f "tokens=2 delims=:" %%I in ('chcp') do set /a cp=%%I
    
    rem // change console codepage to Unicode
    chcp 65001 >NUL
    
    rem // copy asset to clipboard
    clip < "%~dp0\Assets\%~1" && 2>&1 echo Successfully copied.
    
    rem // revert console to original codepage
    chcp %cp% >NUL
    

    I landed on another magic combination involving PowerShell and .NET methods for juggling the encoding and setting the clipboard contents. Try this .bat script:

    <# : batch portion
    @echo off & setlocal
    
    set "infile=%~dp0Assets\%~1"
    
    if not exist "%infile%" (
        2>&1 echo Usage: %~dp0 assetfile
        2>&1 echo ... where assetfile is a file in %~dp0Assets\
        goto :EOF
    )
    
    powershell -STA "iex (${%~f0} | out-string)"
    goto :EOF
    
    # end batch / begin PowerShell hybrid code #>
    
    add-type -As System.Windows.Forms
    $txt = gc $env:infile -encoding UTF8 | out-string
    
    [Windows.Forms.Clipboard]::SetText($txt)
    

    Another possible solution would be to store your text snippets within the script itself. Here's an example demonstrating heredocs within a batch + PowerShell hybrid script (saved with a .bat extension):

    <# : batch portion
    @echo off & setlocal
    
    set "str=%~1"
    powershell -STA "iex (${%~f0} | out-string)"
    goto :EOF
    
    # end batch / begin PowerShell #>
    
    $strings = @{
    foo = @"
    Until i paste the content of the clipboard :
    
        "d'avoir" becomes "dÆavoir"
    "@
    
    bar = @"
    "é" --> "Ú"
    "à" --> "Ó"
    etc ...
    "@
    } # end $strings collection of heredocs
    
    if (-not $strings[$env:str]) { "$env:str not defined."; exit 1 }
    
    add-type -As System.Windows.Forms
    [Windows.Forms.Clipboard]::Clear()
    [Windows.Forms.Clipboard]::SetText($strings[$env:str])
    

    You'll notice that the heredocs are enclosed with @" and "@. Usage: script.bat foo or script.bat bar