Return Array data from Invoke-Command -AsJob

Good day,

            I have been scratching my head on this problem for a couple days now and wanted to reach out for help. When I run the below code and go to receive my job, I get the error at the very bottom. "Cannot index into a null array". I've tried to create the array even before creating the 'PSCustomObject' to 'Force' it to be created as an array, within my invoke. Can anyone give me a hint as to whats going on and why my current code is not returning what I want? I am mainly worried about it returning '$table3' right now.

ForEach ($MBX in $($MBXServers).name){
    #$session=New-PSSession -ComputerName $MBX
        $table3=@()
    $argumentlist=@($mbx,$Global:MBXPassFail,$Global:MBXMastertable,$Global:MBXCCRI)
    Write-Host -ForegroundColor Green "Working on $mbx.name..."
    $Global:MBXPassFail.Add($MBX, "MBX  Pass")
    $Global:servercount++
    $Job="Service Job" + $Global:servercount
   Invoke-Command -ComputerName $MBX  -ScriptBlock {
   Get-PSSnapin -Registered  |Add-PSSnapin;
    $P=$null;$p=@();$J=$null;$J=@();$c=$null;$C=@();$F=$null;$f=@()
    $PublicFolders=Get-PublicFolderDatabase $argumentlist[0];
    $MailboxDbs=Get-MailboxDatabase -Server $argumentlist[0];
    $MailboxSrvr=Get-MailboxServer $argumentlist[0];
    $ExchCert=Get-ExchangeCertificate -Server $argumentlist[0] | select issuer -first 1;
    $executionPolicy=Get-ExecutionPolicy;
    $eventloglevel=Get-EventLogLevel -Server $argumentlist[0] | ? {$_.eventlevel -ne "lowest"};
    IF((($PublicFolders).MountAtStartup |select -Unique) -ne $false){$PFMount = "Fail"}Else{$PFMount = "Pass"};
    IF((($PublicFolders).RetainDeletedItemsUntilBackup | select -Unique) -ne $true){$PFretain = "Fail"}Else{$PFretain = "Pass"};
    IF((($PublicFolders).AllowFileRestore |select -Unique) -ne $false){$PFrestore="Fail"}Else{$PFrestore = "Pass"};
    IF((($MailboxDbs).prohibitsendreceivequota.isunlimited  |select -Unique) -ne $True){$MBXprohibit = "Fail"}Else{$mbxprohibit = "Pass"};
    IF((($MailboxDbs).mountatstartup  |select -Unique) -ne $true){$mbxmount = "Fail"}Else{$mbxmount = "Pass"};
    IF((($MailboxDbs).retaindeleteditemsuntilbackup | select -Unique) -ne $true){$mbxretain = "Fail"}Else{$mbxretain = "Pass"};
    IF((($MailboxDbs).allowfilerestore | select -Unique) -ne $false){$MBXrestore = "Fail"}Else{$MBXrestore = "Pass"};
    IF((($MailboxDbs).circularloggingenabled  |select -Unique) -ne $false){$MBXcirc = "Fail"}Else{$mbxcirc = "Pass"};
    IF((($MailboxSrvr).messagetrackinglogenabled | select -Unique) -ne $true){$mbxlog = "Fail"}Else{$mbxlog = "Pass"};
    IF(($executionPolicy.value) -notmatch "RemoteSigned"){$execpol = "Fail"}Else{$execpol = "Pass"};
    IF(($ExchCert.Issuer) -notmatch "CN=DOD CA-28, OU=PKI, OU=DoD, O=U.S. Government, C=US"){$Exchcer = "Fail"}Else{$exchcer = "Pass"};
    IF($Errorreporting -ne $false){$errreport = "Fail"}Else{$errreport = "Pass"};
    IF($Adminlogenabled -ne $true){$adminena = "Fail"}Else{$adminena = "Pass"};
    ForEach($D in (($MailboxDbs).prohibitsendquota.value |select -Unique)){$p += ($d).ToString() + ","};
    ForEach($D in (($MailboxDbs).prohibitsendreceivequota.isunlimited  |select -Unique)){$C += ($d).ToString() + ","};
    ForEach($D in (($MailboxDbs).issuewarningquota.value |select -Unique)){$J += ($d).ToString() + ","};
    ForEach($D in ($eventloglevel)){$F += ($d).tosring() + ","};
    IF($PublicFolders -eq $null){$PFMount = "Server does not host PFs"};
                                $table3=[pscustomobject]@{
                                                                    "Server" = $argumentlist[0]
                                                                    "EXCH-1-109 PF Mount at Startup" = $PFmount
                                                                    "EXCH-1-112 Retain Deleted Until Backup" = $PFretain
                                                                    "EXCH-1-115 Allow File Restore" = $PFRestore
                                                                    "EXCH-1-301 Prohibit Send/Receive Quota" = $($c) -replace ",",""
                                                                    "EXCH-1-303 Prohibit Send Quota" = $($p)
                                                                    "EXCH-1-306 Issue Warning Quota" = $($J) 
                                                                    "EXCH-1-309 Mount At Startup" = $mbxmount
                                                                    "EXCH-1-312 Retain Deleted Until Backup" = $mbxretain
                                                                    "EXCH-1-315 Allow File Restore" =$mbxrestore
                                                                    "EXCH-1-321 Email Forwarding" = $SMTPForward
                                                                    "EXCH-1-324 Auto Forward Enabled" = ($RemoteDomain | ? {($_.name -ne "Default") -and ($_.name -ne "com")}).autoforwardenabled | select -Unique
                                                                    "EXCH-1-802 Circular Logging Enabled" = $mbxcirc
                                                                    "EXCH-1-805 Message Tracking Log Subject Enabled" = ($MailboxSrvr).messagetrackinglogsubjectloggingenabled | select -Unique
                                                                    "EXCH-1-808 Message Tracking Log Enabled" = $mbxlog
                                                                    "EXCH-2-014 Cert Domains" = $ExchCer
                                                                    "EXCH-2-019 Execution Policy" = $execpol
                                                                    "EXCH-2-817 Event Log Level" = $($eventloglevel)
                                                                    "EXCH-2-820 Error Reporting Enabled" = $Errreport
                                                                    "EXCH-2-823 Administrator Audit Logging Enabled" = $Adminena
                                                                  };
                                <#$argumentlist[2] += $table3;
                                $site=(Get-ExchangeServer $argumentlist[0]).site.name;
                                $MBXTable=[pscustomobject][ordered]@{
                                                                   "Site" = $site
                                                                   "Server" = $argumentlist[0]
                                                                   "CCRI Status" = $argumentlist[1][$argumentlist[0]]
                                                                   "STIG" = "Mailbox"
                                                                   };
                                $MBXTable#>;
$LogHTMLDoc=$null
$target3 = "Mailbox" + '_CCRI' + '.html';
$log2 = $table3 | ConvertTo-Html;
$LogHTMLDoc = @"
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<title>CCRI Checker </title>
<head>
<style>BODY{background-color:white;}TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;background-color:LightGreen;}TH{border-width: 1px;padding: 5px;border-style: solid;border-color: black;background-color:Orange;}TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;white-space: nowrap;text-align: center;}</style>
</head><body>
<H2>
<b>
$($MBXTable.stig)
<b/>
<br>
</H2>
<P>
$Log2
</P>
</body></html>
"@;
$path="\\__________Left Blank________\Configuration_Messaging\test\$target3";
#Remove-Item -Path "\\__________Left Blank________\Configuration_Messaging\test\$target3"
$LogHTMLDoc | out-file $path -Append ;
Return $table3} -ArgumentList $argumentlist -AsJob -JobName $job 
                                                                    }



############### Error ###############

Cannot index into a null array.
    + CategoryInfo          : InvalidOperation: (0:Int32) [], RuntimeException
    + FullyQualifiedErrorId : NullArray
    + PSComputerName        : # Left Blank #
 

September 14th, 2015 2:28pm

Why would you leave out the most important part of the error.  Post the complete error message.

Free Windows Admin Tool Kit Click here and download it now
September 14th, 2015 2:39pm

#2 - Why use remoting when you have the CmdLets installed locally?

September 14th, 2015 2:41pm

That is the error, only I see it 8 times....

Your second question, what do you mean? I realize some of this info is environmental, but not all of it. and I want a break down per server of their status. So, I want to run it across all 65 of our mailbox servers as quickly as I can.

Free Windows Admin Tool Kit Click here and download it now
September 14th, 2015 2:44pm

I still have to run this same ForEach for all CAS and Transport servers. Those have more server specific checks, but this was my first 'test'. Once I can get my return data that way I want, I can move onto the next two Loops.
September 14th, 2015 2:45pm

My mistake, must have slipped seeing this one; this points me to my invoke-command but I still am unsure where to look.


You cannot call a method on a null-valued expression.
    + CategoryInfo          : InvalidOperation: (tosring:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull
    + PSComputerName        : # Left Blank #

Free Windows Admin Tool Kit Click here and download it now
September 14th, 2015 2:49pm

Each error has a line number and a code template with it.  Somehow you have lost or deleted this information.

You do not want to remote a remote.  Either run the CmdLets locally or use Exchange remoting With the correct remoting setup.

Create a simple code block or function that gets some of your info from one server and returns an object.  Next create a loop that creates one job per server.

After that you wait on the jobs and collect and format the report

Start small and build in layers until you understand how this works.  Your method is convoluted and will make the whole task harder.

September 14th, 2015 2:52pm

I tried making my Array a 'Global' array so it could become available outside my invoke to no avail :-(
Free Windows Admin Tool Kit Click here and download it now
September 14th, 2015 2:55pm

My Foreach loop ran perfectly (very slow though), until I dished it out as a job. It populates the data into my variables from the remote machine but will not fill the array. I understand how a foreach and invoke-command works, I am trying to use them together and return an array of information (as you can see). What do you mean by 'You do not want to remote a remote'? I have definitely started small with this and I am at its 'final' stages now. I began just as you said, starting small with tiny bits of information. It led me to building the array and getting exactly what I wanted, with a caveat; that info wouldn't be available for 25+ hours.
September 14th, 2015 3:01pm

You cannot run things the way you are and you need to simplify to sort out al of your issues.

Always separate the script block so it satys indepp-endent. This is a reminder to you that it is NOT part of the current seeison.

Example:

ForEach ($MBX in $($MBXServers).name) {
	
	$argumentlist = @($mbx, $Global:MBXPassFail, $Global:MBXMastertable, $Global:MBXCCRI)
	Write-Host -ForegroundColor Green "Working on $mbx.name..."
	Invoke-Command -ComputerName $MBX -ScriptBlock $sb -ArgumentList $argumentlist -AsJob -JobName $mbx
}

Define the $SB outside of the loop and test it stand aloneuntilit works.

To execute a script block use $sb.Invoke($argumentlist)

If you are not using Exchaneg remoting then sstart simple with this SB:

$sb={
    Add-PSSnapin
    Get-PublicFolderDatabase $args[0]
}

Just run that much and make it work.  Once you can run that then build your job loop and test that.

After all of the control pieces are tested then add a couple of lines at a time to your script block and test.

Free Windows Admin Tool Kit Click here and download it now
September 14th, 2015 3:04pm

Do not format your output in the jobs. Return the objects and build report externally.  It is easier to debug and control.  Your approach is fighting every advantage that objects systems offer.

September 14th, 2015 3:07pm

Actually your loop should look like this:

ForEach ($server in $MBXServers) {
	Write-Host -ForegroundColor Green "Working on $mbx.name..."
	Invoke-Command -ComputerName $server.Name -ScriptBlock $sb -ArgumentList $mbx -AsJob -JobName $server.Name
}

You cannot pass globals to Invoke.  You can pass the value but you cannot change it in an Invoke or a job.

Remember that the script block must be independent except for the arguments and can only return data to Receive-Job.

Free Windows Admin Tool Kit Click here and download it now
September 14th, 2015 3:10pm