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
}