Skip to content
mnaoumov.dev
Go back

How to reach unreachable or copy files to RDP

Consider that usecase: I need to send a dll file to production environment to patch some bugs

I have a RDP access to production environment. All good? No! I do have RDP access to that environment but drive sharing and Internet is disabled on it. How can I transfer files in this case?!

I came up with an interesting solution… Use clipboard. But how to transfer binary file via clipboard?! Convert it to Base64! Gotcha!

This idea works as a charm.

The following script we are using locally

function ConvertTo-Base64Clipboard
{
    param
    (
        [string] $FilePath
    )

   [Convert]::ToBase64String((Get-Content -Path $FilePath -Encoding Byte)) | clip
}

This one - on production server

function Get-Clipboard
{
    PowerShell -NoProfile -Sta -Command `
    {
        Add-Type -AssemblyName PresentationCore
        [Windows.Clipboard]::GetText()
    }
}

function ConvertFrom-Base64Clipboard
{
    param
    (
        [string] $FilePath
    )

   [Convert]::FromBase64String((Get-Clipboard)) | Out-File -FilePath $FilePath -Encoding Byte
}

Voila!

This idea is not new, I found similar here and here

UPD: forgot to mention performance, conversion is taking time. So I reckon if you need to transfer multiple files, archive them into zip first and then transfer this archive file. Zip is natively supported by modern versions of Windows.

I am not sure about limitations of clipboard length. Some BCL API makes me think that it could be int.MaxValue. This gives us 2gb of base64, or 2gb * 3/4 = 1.5gb of binary data. So that should be more than enough.

There is also a way to rewrite Get-ClipboardText which doesn’t require running separate PowerShell process in STA mode

function Get-ClipboardText
{
    Add-Type -AssemblyName System.Windows.Forms
    $tb = New-Object System.Windows.Forms.TextBox
    $tb.Multiline = $true
    $tb.MaxLength = [int]::MaxValue
    $tb.Paste()
    $tb.Text
}

This works a bit faster

UPD2: Those scripts were written from memory, and later on I found couple of mistakes.

So I will provide final correct versions of the scripts

function ConvertTo-Base64Clipboard
{
    param
    (
        [string] $FilePath
    )

   [Convert]::ToBase64String((Get-Content -Path $FilePath -Encoding Byte)) | clip
}

and

function Get-Clipboard
{
    Add-Type -AssemblyName System.Windows.Forms
    $tb = New-Object System.Windows.Forms.TextBox
    $tb.Multiline = $true
    $tb.MaxLength = [int]::MaxValue
    $tb.Paste()
    $tb.Text
}

function ConvertFrom-Base64Clipboard
{
    param
    (
        [string] $FilePath
    )

   [Convert]::FromBase64String((Get-Clipboard)) | Set-Content -Path $FilePath -Encoding Byte
}

Part 2


Share this post on:

Previous Post
Git Extensions from console - UPD
Next Post
where.exe PowerShell alternative