Receive-Job error

Ask your PowerShell-related questions, including questions on cmdlet development!
Forum rules
Do not post any licensing information in this forum.

Any code longer than three lines should be added as code using the 'Select Code' dropdown menu or attached as a file.
This topic is 5 years and 1 month old and has exceeded the time allowed for comments. Please begin a new topic or use the search feature to find a similar but newer topic.
Locked
User avatar
SakJaTeda
Posts: 11
Last visit: Fri Jan 20, 2023 2:53 pm

Receive-Job error

Post by SakJaTeda »

Hi Guys,

We are receiving notifications of stale AD computer accounts, but those reports seem to be faulty and I got asked to create an application that would basically re-check the results. I am using jobs to check every computer, so that the process does not freeze the form. What I have is basically a Start button and a timer, as follows:

Code: Select all

$buttonStart_Click={
    if ($datagridview1.DataSource)
    {
        $global:Computers = $datagridview1.DataSource
        $timerJobs.Start()
        $buttonOpenExcel.Enabled = $false
        $buttonOpenExcelAndAppend.Enabled = $false
        $buttonClearTable.Enabled = $false
        $buttonStart.Text = 'Working ...'
        $buttonStart.Enabled = $false
        $datagridview1.Cursor = 'WaitCursor'
        foreach ($Computer in $global:Computers)
        {
            $checkJob = Start-Job { Get-ADComputer $Computer."Computer Name" -Properties PasswordLastSet, LastLogonDate }
            $Computer | Add-Member -NotePropertyName "CheckJob" -NotePropertyValue $checkJob -Force
        }
    }
}

$timerJobs_Tick={
    foreach ($Computer in $global:Computers)
    {
        if (($Computer.CheckJob.State -eq 'Completed') -and $Computer.CheckJob.HasMoreData)
        {
            $results = Receive-Job $Computer.CheckJob
            $Computer."Checked PW Last Set" = ((Get-Date) - $results.PasswordLastSet).Days
            $Computer."Checked Last Logon" = ((Get-Date) - $results.LastLogonDate).Days
            Remove-Job $Computer.CheckJob
        }
    }
    Update-DataGridView -DataGridView $datagridview1 -Item $global:Computers
    if ('N/A' -notin $global:Computers."Checked PW Last Set")
    {
        Get-Job | Remove-Job -Force
        $buttonOpenExcel.Enabled = $true
        $buttonOpenExcelAndAppend.Enabled = $true
        $buttonClearTable.Enabled = $true
        $buttonStart.Text = 'Start!'
        $buttonStart.Enabled = $true
        $datagridview1.Cursor = 'Default'
        $timerJobs.Stop()
    }
}
The data is imported from Excel and loaded into a DataTable, like so:

Code: Select all

$PCList = New-Object System.Data.DataTable
$PCList.Columns.Add("Computer Name")
$PCList.Columns.Add("OU Location")
$PCList.Columns.Add("Password Last Set")
$PCList.Columns.Add("Last Logon TimeStamp")
$PCList.Columns.Add("Checked PW Last Set")
$PCList.Columns.Add("Checked Last Logon")
foreach ($row in $ExcelFile)
{
	$PCList.Rows.Add($row."Computer Name", $row."OU Location", $row."Password Last Set", $row."Last Logon TimeStamp", 'N/A', 'N/A')
}
When debugging, it all seems to be working fine until the point where it is about to retrieve the job - it throws an error about Identity in Get-ADComputer being null:

Code: Select all

ERROR: Cannot validate argument on parameter 'Identity'. The argument is null. Provide a valid value for the argument, and then try running the command again.
ERROR:     + CategoryInfo          : InvalidData: (:) [Get-ADComputer], ParameterBindingValidationException
ERROR:     + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.GetADComputer
ERROR:     + PSComputerName        : localhost
Anyone have any advise on how to fix this, please?

Thanks!
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: Receive-Job error

Post by jvierra »

Your CSV has an empty row or a row has an empty "computer name'" field.
Why would you use separate jobs for such a simple query? Just run the query or query all computers in one job and retrieve the data on each timer tick. There is no need for separate jobs here since AD will return data as it is available and is usually very fast.
User avatar
SakJaTeda
Posts: 11
Last visit: Fri Jan 20, 2023 2:53 pm

Re: Receive-Job error

Post by SakJaTeda »

Thanks for you reply.

There are definitely no empty rows - I tested on a a file that only has 3 rows and all 3 definitely have all the required fields.

The reason for having separate jobs is that we routinely receive ~10 Excel files, all of which may or may not contain several computer accounts and I intended to have it check the accounts simultaneously to save time. Even though AD is fairly fast for single queries, 10s of them will take some time.
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: Receive-Job error

Post by jvierra »

Jobs for each computer will not be faster. It will be slower. The results of each call for the computer response is available whenever you do a receive-job. Just receive the cob and use the data until the job is complete.

Also, variables in PowerShell do not exist in a job. They must be passed.

help Start-Job -online
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: Receive-Job error

Post by jvierra »

If you want to get high performance with PowerShell use a workflow. It runs multi-threaded and can create much better performance than a 100 jobs.

Code: Select all

Workflow GetComputerInfo {
    Param($ComputerList)
    foreach -Parallel -throttlelimit 16 ($computer in $ComputerList){
        Get-ADComputer $computer -Properties PasswordLastSet, LastLogonDate
    }
}
$job = GetComputerInfo -ComputerList $global:computers -AsJob
This will run 16 tasks in parallel and create new tasks as needed. The workflow runs as a job and output from each task is available immediately so "Receive-Job" will get the results on each timer tick. You can do 100 computers in less than about 5 seconds. Jobs will slow down after about 20 are defined. Jobs require a whole PowerShell process to be created. Workflow tasks do not.
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: Receive-Job error

Post by jvierra »

The attached example shows how to return data from job and update a DGV at high speed. Run it to see how repsponsive it is. It produces a continuous stream of updates to the DGV with no glitches and without freezing the form.
Attachments
Demo-SimpleDGVJobTracker.psf
(22.73 KiB) Downloaded 116 times
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: Receive-Job error

Post by jvierra »

SakJaTeda wrote: Wed Feb 20, 2019 9:27 pm
The reason for having separate jobs is that we routinely receive ~10 Excel files, all of which may or may not contain several computer accounts and I intended to have it check the accounts simultaneously to save time. Even though AD is fairly fast for single queries, 10s of them will take some time.
I can query 50 computers in AD in about 3 seconds. You will also find that AD throttles you number of requests. It will allow about three and new requests will be delayed until earlier connections are closed. Stacking requests will not improve performance by any measurable amount. You could send requests to different DCs which might give a little improvement.

You can also build a filter that can query for many computers in one call. That would produce the fastest results.

-Filter "Name -eq '$comp1' -or Name -eq '$comp2' -or Name -eq '$comp3'"

This filter can be generated programmatically.
This topic is 5 years and 1 month old and has exceeded the time allowed for comments. Please begin a new topic or use the search feature to find a similar but newer topic.
Locked