PowerShell W10 IoT Raspberry console viewer

Hi all,

Been a long time.

I recently got started with Windows 10 IoT on a Raspberry Pi 2, An fun but interesting journey to say the least, but a first tip if you also want to get started, check the Hardware Compatibility List first 😉

As W10 IoT is not that old yet, not much is supported yet – be especial careful with Cameras and Official 7″ Touch Displays (SPI) – let’s say that I have made some investments in the future ;), also finding a compatible USB Wi-Fi or BT adapter (Official WiPi is adapter not supported).

So I also had to start “Wired”, but I managed to find some compatible T-link Wi-Fi and CSR BT adapters here in .CH

One of the other things that are missing in W10 IoT is a console viewer, and as my <Sarcastic grin>  Cool 7″ Touch display is of no avail yet, in my case that means hooking it up to a 24″ display, making my Bot way less Mobile. </Sarcastic grin>

Meanwhile I can control them by Phone, but still while developing and testing a display attached can be nice while testing the App. Also not all ports can easy be reached,

WP_20160214_20_56_02_Pro_LI[1]

and if the Raspberry Pi is started without a Display it needs a reboot to enable the HDMI port (Should be a Configuration setting to make this Hot Pluggable but still..)

Hence still often it is to have quick console access shortly to check something, without a reboot and still keeping it mobile .

Then when  I was just a bit browsing around on the Raspberry Pi over a Remote PowerShell session (Yes of Course it has PowerShell !)  I stumbled upon some, actually a bit comical .EXE tools that gave me the inspiration to build this quick and Dirty PowerShell RPi IoT Console viewer in PowerShell , so I now easily do this :

PS C:\WINDOWS\system32> Show-RaspberryPIConsole MowBot03

Giving a very basic console viewer App (without needing anything on RPI side, as you can see it is running default app here):

SD1png

And not only that, even basic editing :), for example to logon quickly to a friends WiFi.(Although  you also can  accomplice this with PowerShell or the Web interface.)

SD2

Or quickly, although with a lot of Tabs ….. on the fly …calibrate some servo’s 😉

SD3ServoTOK_ServoTransplant

 

 

 

 

 

 

 

So how about the Code ?

First we connect to the Raspberry creating a remote PowerShell Session.

CodePart1

Note that I’m saving the credentials and the Session to the Raspberry Pi in Global  variables so that I only need to connect the first time I use the Console (Connecting to a RPI can take a while )

Now in the Next function is the first interesting Part:

CodePart2

When I was PowerShelling around on the Raspberry Pi I found the ScreenCapture.exe command line application, I tried it and as the name give away I could use it to make screen dumps, in the first part of this function I call this function remotely over the PowerShell session to the Raspberry Pi to create a screen dump and to retrieve the generated filename back.

Then, using the filename I retrieved back, I create an FTP request to retrieve the generated screen dump from the Raspberry Pi.

Next to the Web Interface and PowerShell Endpoint, Windows 10 IoT on the Raspberry Pi also has a FTP and SSH Daemon running by default.  

I directly save this stream into an Image object, that I return from the function and in the next part I quickly build a From to host it

Note that I skipped some lines of the code here, the implementation of the auto updating  and editing functionality of the console that is implemented in the Loop Function that I discuss next, the code till now just shows the image once.

$img = GetImage
CodePart3.png

Note I just scale the form around the Image, also note that I loaded the Windows.Forms library already in the initialization code in the first code fragment.

Coincidence does not exist, but the bits where aligned,  I was barely finished  with my viewer, quite happy with the performance of a couple of frames per Second 😉 … I Stumbled upon the next nifty .EXE ….. SENDKEYS.EXE .. and when I tested it… Yes PowerShell Bingo.. It did send the keystrokes not to my PowerShell  session, but as I kind of hoped … to the Active App

… Say no more … 😉 … here is the missing Code ….

CodePart4

In the loop function in the first part I handle to update loop, and text entered in the text box on top.

Note that the box above and send button can not really used anymore – As long as all keys are captured that is almost impossible to do, so if you like the first option more just disable or remove the part that captures the key  .

I decided as it is Quick and Dirty anyway, I like the second option more, just to capture all key presses.

Note that I’m using the KeyUp event, not KeyPress or even KeyDown , to also capture – for us the most important key [TAB] –  next to  Arrows, Space and Enter of course ! Also note the line :

$form.KeyPreview = $true

That option also need to be set to be able to capture all the Keys we need.

And yes, it is as “Dirty”as it gets        (B.T.W it is best to first click the stop button, before trying to close the form, else it might to be busy to obey 😉  )         but I think a very handy tool while playing with Windows 10 IoT on the Raspberry Pi to accidently be able to reach the console remotely .

And if you 10 -15 years ago worked on a HP server  with an ILO board,  this is actually not THAT bad at all , and of course it has some performance impact, but looks like the raspberry can handle it 😉 (note also memory management)  ;

perf

Below you can find the complete Function in Clear text format.

Enjoy,

Greetings /\/\o\/\/

________________________________________________________________________________

$rpi = “mowbot03”
# Raspberry Pi Windows 10 IoT Q&D Console viewer
# MOW 2016
# http://thePowerShellGuy.comfunction Show-RaspberryPIConsole ([string]$rpi) {
[void][reflection.assembly]::LoadWithPartialName(“System.Windows.Forms”)
if (-not $IoTcred) {
$global:IoTcred = get-credential -user localhost\administrator -Message “Enter credentials for IoT Admin of $rpi”
}
if (-not $RpiSession) {
$global:RpiSession = New-PSSession -ComputerName $rpi -Credential $global:IoTcred
}
function GetImage(){
$RemotePath = invoke-command -session $RpiSession {
$filename = (get-date).ToString(“yyyyMMdd_hhmmss_ff”) + “.jpg”
(ScreenCapture.exe ($env:temp + “\$filename”)) | out-Null
if ($last) {del $last} ;
$last = ($env:temp + “\$filename”)
$last
}
  $FtpPath = $RemotePath.replace(“C:”,”ftp://$rpi”).replace(“\”,”/”)
$filename = $FtpPath.split(“/”)[-1]
  $FTPRequest = [System.Net.FtpWebRequest]::Create($FtpPath)
$FTPRequest.Method = [System.Net.WebRequestMethods+Ftp]::DownloadFile
$FTPResponse = $FTPRequest.GetResponse()
$ResponseStream = $FTPResponse.GetResponseStream()
  $img = [System.Drawing.Image]::FromStream($ResponseStream )
$img
}
$i = 0;
$textToSend = “”
$script:doLoop = $true;
function loop{
while ($script:doLoop) {
$i ++
[System.Windows.Forms.Application]::DoEvents()
if ($textToSend.Length -gt 0) {
$s = [scriptblock]::Create(“sendkeys “”$textToSend”””)
invoke-command -session $RpiSession $s
$textToSend = “”
}
$img = GetImage
$pictureBox.Image = $img;
$pictureBox.Update()
$form.Text = “MOW Raspberry PI Console Viewer (Screendump $i)”
}
}
$img = GetImage
$form = new-object Windows.Forms.Form
$form.KeyPreview = $true
$form.Add_KeyUp({
if ($_.KeyValue -gt 0x2F -and $_.KeyValue -lt 0x70) {
$txtInput.text += $_.KeyCode
$global:keyarg = $_
$s = [scriptblock]::Create(“sendkeys “”$($_.KeyCode)”””)
invoke-command -session $RpiSession $s
} else {
$txtInput.text += $_.KeyCode
$global:keyarg = $_
$s = [scriptblock]::Create(“sendkeys -v 0x{0:x2}” -f $_.KeyValue)
invoke-command -session $RpiSession $s}
})
$form.Text = “MOW Raspberry PI Console Viewer”
$form.Width = $img.Size.Width;
$form.Height =  $img.Size.Height;
$buttonStart = new-object Windows.Forms.Button
$buttonStart.Text = “Start”
$buttonStart.add_click({$script:doLoop = $true;loop})
$buttonStop = new-object Windows.Forms.Button
$buttonStop.Text = “Stop”
$buttonStop.add_click({$script:doLoop = $false})
$buttonStop.Left = 100
$txtInput = new-object Windows.Forms.textBox
$txtInput.Left = 200
$txtInput.Width = 200$buttonSend = new-object Windows.Forms.Button
$buttonSend.Text = “Send”
$buttonSend.Left = 400
$buttonSend.add_click({$textToSend = $txtInput.Text;loop})
$pictureBox = new-object Windows.Forms.PictureBox
$pictureBox.Top = 40
$pictureBox.Width =  $img.Size.Width;
$pictureBox.Height =  $img.Size.Height + 40 ;
$pictureBox.Image = $img;
$form.controls.add($pictureBox)
$form.controls.add($buttonStart)
$form.controls.add($buttonStop)
$form.controls.add($buttonSend)
$form.controls.add($txtInput)
$form.Add_Shown( { $form.Activate() ;loop } )
$form.ShowDialog()
}
Show-RaspberryPIConsole $rpi

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s