I am successfully able to grab the result text I need from the plink.exe
command-line below to $response
. In order for the command to execute on the remote SSH device, I had to first precede it with emulated keystrokes Y {enter} Y {enter}
Code:
$Device = "SSHDeviceHostname"
$Command = "sho ver | include uptime is"
Add-Type -AssemblyName System.Windows.Forms
$wshell.SendKeys('y~y~'); $response = cmd /C "C:\Windows\plink.exe -ssh -l `"$($CredentialToken.GetNetworkCredential().username)`" -pw `"$($CredentialToken.GetNetworkCredential().password)`" $Device `"$Command`"" 2>$null
Results:
y
y
C:\Users\MKANET\Desktop> $response
SSHDeviceHostname uptime is 5 years, 25 weeks, 1 day, 3 minutes
C:\Users\MKANET\Desktop>
I would like to hide the fake keystrokes Y {enter} Y {enter} from being displayed; without adversely affecting the $response
value. I tried to invoke-command
'ing the whole scriptblock on the localhost without success. I probably could execute this code in a separate hidden PowerShell session. However, that would most likely slow things down way too much.
PS: I also tried using cmd (below) which unfortunately plink.exe completely ignores the second echo `y; aborting the connection immediately:
cmd /C "Echo Y && Echo Y | plink.exe -ssh -l `"$($Credential.GetNetworkCredential().username)`" -pw `"$($Credential.GetNetworkCredential().password)`" $DeviceName `"$Command`""
To answer your literal question, you can do the following in a batch file:
powershell -command "Write-Host -NoNewLine y ; sleep 2 ; Write-Host -NoNewLine y" | plink ...
Note that the code really works in batch file (in cmd
) only. It does not work in Windows PowerShell. The |
has a different semantics in Windows PowerShell than in cmd.
In Windows PowerShell, it would wait for powershell
to complete before starting the plink
, so the only effect of sleep
is that it will delay starting the plink
. While in cmd
, powershell
and plink
run in parallel, as you want.
As commented by @mklement0, this has been improved since PowerShell (Core) 6. So there you can do:
& { 'y'; sleep 2; 'y' } | plink ...
But you should not blindly accept the host key. You lose a protection against man-in-the-middle attacks. You should verify the host key using the -hostkey
switch.
See Prepend a command in Start-Process to provide "y" input to Plink
Similarly for the KEX verification. There's no switch for the KEX in Plink. But you can create an ad-hoc store session in registry with the diffie-hellman-group1-sha1
allowed. And invoke the stored session in Plink.
$hostname = "example.com"
$username = "username"
$password = "password"
$hostkey = "c4:26:18:cf:a0:15:9a:5f:f3:bf:96:d8:3b:19:ef:7b"
$session = "Dummy"
$key = "HKCU:\SOFTWARE\SimonTatham\PuTTY\Sessions\$session"
New-Item -Path $key -Force | Out-Null
New-ItemProperty -Path $key -Name HostName -Value $hostname | Out-Null
New-ItemProperty -Path $key -Name UserName -Value $username | Out-Null
New-ItemProperty -Path $key -Name KEX `
-Value "ecdh,dh-gex-sha1,dh-group14-sha1,rsa,dh-group1-sha1,WARN" | Out-Null
& plink $session -pw $password -hostkey $hostkey