1

I wrote this powershell script with the intent of creating a GUI where I can see my android screen casted to my computer.

The script creates a form, where a timer should update a picturebox with an image that it pulls from adb. The script also insures that adb is installed.

My problem is that the image in the picturebox is not updating, it is only loading the first image that is captured.

I believe this is a problem with the adb not overwriting the existing png file, but I am not sure, and it could quiet possibly be something else.

I'd appreciate any help!

Set-ExecutionPolicy Bypass -Scope Process -Force
function startTimer() { 
   $timer.start()
   Write-Host "Timer Started"
}
function stopTimer() {
    $timer.Enabled = $false
    Write-Host "Timer Stopped"
    $btnStart.Text = "Continue"
}
function TimerTick()
{
    adb shell rm -f /sdcard/sc.png
    adb shell screencap -p /sdcard/sc.png
    adb pull /sdcard/sc.png $BpathTo
    $image = [System.Drawing.Image]::Fromfile("$BpathTo\sc.png")
    $picb.Image = $image
    $lblLog.Text = (Get-Date).ToString()
    Write-Host "Refreshed at: "(Get-Date).ToString()
    Write-Host ""
}
if (!(Get-Command adb -ErrorAction SilentlyContinue)){
    if (!(Get-Command choco -ErrorAction SilentlyContinue)){
        Write-Host "Downloading Chocolatey Installer to setup ADB (required)"
        iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
    }
    Write-Host " Installing ADB..."
    choco install adb --force -y
}
Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName System.Windows.Forms
$timer = New-Object System.Windows.Forms.Timer
$timer.Interval = 1000
$timer.add_tick({TimerTick})

$BpathTo = (Get-Item -Path ".\").FullName
if ([System.IO.File]::Exists("$BpathTo\sc.png")){
    Remove-Item -Path "$BpathTo\sc.png"
}
adb shell screencap -p /sdcard/sc.png
adb pull /sdcard/sc.png $BpathTo
$image = [drawing.image]::FromFile("$BpathTo\sc.png")
$objForm = New-Object System.Windows.Forms.Form 
$objForm.Text = "ADB Screencast"
$objForm.Size = New-Object Drawing.Size @(($image.Width+20),($image.Height+85))
$objForm.StartPosition = "CenterScreen"
$objForm.Add_KeyDown({
    if ($_.KeyCode -eq "Escape") 
        {
            $objForm.Close()
        }
    })
$objForm.MinimizeBox=$false
$objForm.MaximizeBox=$false
$objForm.ShowIcon=$false
$objForm.ShowInTaskbar=$false
$halfH=(($image.Width)/2)
$btnStart = New-Object System.Windows.Forms.Button
$btnStart.Location = New-Object System.Drawing.Size(1,$image.Height)
$btnStart.Size = New-Object System.Drawing.Size($halfH,25)
$btnStart.Text = "Start"
$btnStart.Add_Click({StartTimer; })
$objForm.Controls.Add($btnStart)
$btnStop = New-Object System.Windows.Forms.Button
$btnStop.Location = New-Object System.Drawing.Size($halfH,$image.Height)
$btnStop.Size = New-Object System.Drawing.Size($halfH,25)
$btnStop.Text = "Stop"
$btnStop.Add_Click({StopTimer; })
$objForm.Controls.Add($btnStop)
$btnStop.Enabled  = $true
$lblLog = New-Object System.Windows.Forms.Label
$lblLog.Location = New-Object System.Drawing.Size(10,($image.Height+25)) 
$lblLog.Size = New-Object System.Drawing.Size($image.Width,20) 
$lblLog.Text = "Refresh Info:"
$objForm.Controls.Add($lblLog)
$picb = New-Object Windows.Forms.PictureBox
$picb.size = New-Object Drawing.Size @($image.Width,$image.Height)
$picb.Location = New-Object Drawing.Point 1,1
$picb.Image = $image
$objForm.Controls.Add($picb)
$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()
sh7411usa
  • 196
  • 1
  • 13
  • I think you should move your functions up a bit (just below the `Set-ExecutionPolicy` would be a good place), because now you are adding the `TimerTick` function before it is defined. Also, `[System.Reflection.Assembly]::LoadWithPartialName` is deprecated, use `Add-Type -AssemblyName System.Windows.Forms` and `Add-Type -AssemblyName System.Drawing` instead. Dispose of the objects when done: `$timer.Dispose()` and `$objForm.Dispose()`. – Theo Mar 03 '19 at 15:40
  • @theo ty for pointers, edited accordingly. though any idea why the picture is not updating? – sh7411usa Mar 03 '19 at 17:30
  • Just curious.. Did my answer work for you? – Theo Mar 07 '19 at 09:22
  • its still not updating, using a temp. solution of taking 100 screenshots, and then overwriting, but its very messy – sh7411usa Mar 12 '19 at 17:54

1 Answers1

0

I could not fully test this other than using a mockup with static images because I don't have android.
This seemed to work for me though:

I moved these lines to the top of the script:

Set-ExecutionPolicy Bypass -Scope Process -Force
Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName System.Windows.Forms

$timer = New-Object System.Windows.Forms.Timer
$timer.Interval = 1000

function startTimer() { 
   $timer.Start()
   Write-Host "Timer Started"
}
function stopTimer() {
    $timer.Enabled = $false
    Write-Host "Timer Stopped"
    $btnStart.Text = "Continue"
}
function TimerTick()
{
    adb shell rm -f /sdcard/sc.png
    adb shell screencap -p /sdcard/sc.png
    adb pull /sdcard/sc.png $BpathTo

    $image = [System.Drawing.Image]::Fromfile("$BpathTo\sc.png")
    $picb.Image = $image
    $lblLog.Text = (Get-Date).ToString()
    Write-Host "Refreshed at: "(Get-Date).ToString()
    Write-Host ""
}
$timer.Add_Tick({TimerTick})

and added these at the very end:

# clean up
$timer.Stop()
$timer.Dispose()
$objForm.Dispose()

For me in the mockup this worked, but I have also seen examples where the $timer is scoped to $global:timer...

Hope this helps

Theo
  • 57,719
  • 8
  • 24
  • 41