Search code examples
powershelljobs

Why does my Screenshot Function not work as a Job


I have a function inside a Job which takes a Screenshot. The Script itself gets executed by Taskscheduler as a domain admin. I also checked "Run with highest privileges".

The Job should do a Screenshot and then send an E-Mail, but both of those thing don't happen. I also don't see an error message (maybe because it's a background job?). Maybe the E-Mail doesn't get sent because it wants to attach the screenshot to the e-mail, but can't because the screenshot wasn't created.

Why does my function not Take the Screenshot? The domain admin has privileges to write to the destination. The screenshot gets created when I run the function outside the start-job. if i have the function inside start-job it doesn't get created, doesn't matter if the script is started via Taskscheduler or manually.

What am I missing?

The following Code starts the Job and takes the screenshot:

Start-Job -Name LogikWebserverWatch {

    function Take-Screenshot([string]$outfile) 
    {
    [int]$PrtScrnWidth = (gwmi Win32_VideoController).CurrentHorizontalResolution
    [int]$PrtScrnHeight = (gwmi Win32_VideoController).CurrentVerticalResolution
    $bounds = [Drawing.Rectangle]::FromLTRB(0, 0, $PrtScrnWidth, $PrtScrnHeight)
    $bmp = New-Object Drawing.Bitmap $bounds.width, $bounds.height
    $graphics = [Drawing.Graphics]::FromImage($bmp)
    $graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size)
    $bmp.Save($outfile)
    $graphics.Dispose()
    $bmp.Dispose()
    }

    while ((Get-Process LogikWebserver).Responding) {sleep -Milliseconds 50}

    if (!(Get-Process LogikWebserver).Responding) {
    Try{

        $utf8 = New-Object System.Text.utf8encoding
        $datetime = (get-date).ToString('yyyyMMdd-HHmmss')
        Take-Screenshot -outfile C:\Install\LogikWebserverErrorReporting\Screenshot-$datetime.png
        # some more code [...]
    } Catch {  some more code [...] }
}}

Solution

  • The documentations says that:

    A Windows PowerShell background job runs a command without interacting with the current session.

    So you may have to load the required assemblies inside your job before it will work.

    When I tried your code above, it only created a screenshot when run outside of a job (as you mentioned), however adding this line to the top of the Start-Job ScriptBlock caused it to work from inside the job as well:

    [Reflection.Assembly]::LoadWithPartialName("System.Drawing")
    

    Or, as the above is now depracated:

    [System.Reflection.Assembly]::LoadFrom("C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Drawing.dll")
    

    Or

    Add-Type "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Drawing.dll"
    

    Note that I have not tested this when running from a schedued task.