how to capture variable value inside of invoke-command locally

Hi ,

I want to get cert details from remote computers and see a particular cert validity. The cert is valid for more than 30 days or not, this information I am trying to capture in to a excel or csv file. I have the below code which works fine, except that I am able to capture $valid value which is in invoke-command block. Inside the invoke-command block , I am able to see respective value for $valid variable. outside of the invoke-command block I could not capture this value. So the .csv file created is getting empty values for the column.

Please help to capture $valid variable value outside of invoke-command.




$FullPath = $MyInvocation.MyCommand.Path
$Scriptpath = Split-Path -Path $FullPath -Parent
cd $Scriptpath


#$outfile = '.\Output.csv'
$outfile = "C:\temp\result.csv"
$ServerList = '.\servers.txt'


[string[]$Computers = Get-Content "$ServerList"




      foreach($Computer in $Computers) {

"Checking on $Computer"
invoke-command -computername $Computer { if ($Envpath = Get-ChildItem Env:MQDIR )  # have to check for cert information only if MQDIR environment variable is presernt


{
   #<execute code to get cert details>

$Certificates | Format-Table -AutoSize



$IbmCertificate = $Certificates | Where-Object {$_.Name -eq "IBM"}

$IbmCertificate | ForEach-Object {
      "$($_.Name): " | Write-Host -ForegroundColor White -NoNewline
      If ($_.DaysRemaining -ge 30) {
             "valid for $($_.DaysRemaining) more days."
      $Valid = "Good"    

    $Valid
      } ElseIf ($_.DaysRemaining -gt 0) {
            $Valid = "valid for only $($_.DaysRemaining) more days."
      } Else {
            $Valid = "expired since $([math]::Abs($_.DaysRemaining)) days!"
      }
}

}

else

#no check is required if  Env:MQDIR variable is not there on a machine

{ $Valid = "Write-Host  Check is not required" }


}
"value of valid variable outside invoke-coomand = $Valid"

$OutputObj  = New-Object -Type PSObject
$OutputObj | Add-Member -MemberType NoteProperty -Name ComputerName -Value $Computer.ToUpper()
$OutputObj | Add-Member -MemberType NoteProperty -Name IsCertValid -Value "$Valid"

$UserOutput += @($OutputObj)
$UserOutput | Export-Csv $outfile -NoTypeInformation


}
#$UserOutput | Export-Csv $outfile -NoTypeInformation
Deepthi GosulaAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

oBdACommented:
First off: do yourself a favor and learn how to do indent properly, so that you can see easily how deeply nested you are.
Now, variables in a scriptblock are local to that scriptblock; you can't access them in the main script.
Everything you want to use in the main script that is generated in the scriptblock needs to be written to the pipeline inside the scriptblock - and only what you want to use.
So don't write purely informational objects into the pipeline inside the scriptblock, or you'll have to filter them out inside the main script.
Try it with the version below.
Make sure that you whatever you removed at "# <execute code to get cert details>" does not generate pipeline output when you reinsert it.
$FullPath = $MyInvocation.MyCommand.Path
$Scriptpath = Split-Path -Path $FullPath -Parent
Set-Location $Scriptpath

#$Outfile = '.\Output.csv'
$Outfile = "C:\temp\result.csv"
$ServerList = '.\servers.txt'

$Computers = Get-Content -Path $ServerList
$Computers | ForEach-Object {
	"Checking on $_" | Write-Host
	Invoke-Command -ComputerName $_ -ScriptBlock {
		If ($Envpath = Get-ChildItem Env:MQDIR) { # have to check for cert information only if MQDIR environment variable is present
			# <execute code to get cert details>
			$Certificates | Format-Table -AutoSize | Out-String | Write-Host
			$IbmCertificate = $Certificates | Where-Object {$_.Name -eq "IBM"}
			$IbmCertificate | ForEach-Object {
				"$($_.Name): " | Write-Host -NoNewline
				If ($_.DaysRemaining -ge 30) {
					$Valid = "good, for $($_.DaysRemaining) more days."
				} ElseIf ($_.DaysRemaining -gt 0) {
					$Valid = "valid for only $($_.DaysRemaining) more days." 
				} Else {
					$Valid = "expired since $([math]::Abs($_.DaysRemaining)) days!"
				}
				$Valid | Write-Host
			}
		} Else {	#no check is required if  Env:MQDIR variable is not there on a machine
			$Valid = "Check is not required"
		}
		New-Object -TypeName PSObject -Property @{
			'ComputerName' = $ENV:ComputerName
			'IsCertValid' = $Valid
		}
	}
} | Export-Csv -Path $Outfile -NoTypeInformation

Open in new window

0
Deepthi GosulaAuthor Commented:
Thank you for the explaining me about script block. Sorry I copied it from a notepad. I will make sure to do good. the code which run the command to get the cert information on remote computers has output piped.

it is like below.  please help me on  to get the output of this script exported to a .csv file. csv should have computer name and $valid variable value.
$FullPath = $MyInvocation.MyCommand.Path
$Scriptpath = Split-Path -Path $FullPath -Parent
cd $Scriptpath


#$outfile = '.\Output.csv'
$outfile = "D:\temp\result.csv"
$ServerList = '.\servers.txt'


[string[]]$Computers = Get-Content "$ServerList"
#[string[]]$ComputerName = Get-Content $TxtFqdnList




	foreach($Computer in $Computers) {

"Checking on $Computer"
invoke-command -computername $Computer { if ($Envpath = Get-ChildItem Env:MQSSL_DIR )


{

$MQPATH = Get-ChildItem Env:MQSSL_DIR | select-object -Property value
$SSLPATH = $MQPATH.value

$DTProvider = New-Object -TypeName System.Globalization.CultureInfo -ArgumentList 'en-US'
$Certificates = & runmqckm -cert -list -expiry 500 -db "$SSLPATH\*Key.kdb" -pw 'Password1' |
	Select-String -Pattern '\A\s+From:' -Context 1 |
	ForEach-Object {
		$_.Line -match '\s+From: \S+, (?<From>\S+ \d+, \d{4} \S+ \S\S).*To: \S+, (?<To>\S+ \d+, \d{4} \S+ \S\S)' | Out-Null
		New-Object -TypeName PSObject -Property ([ordered]@{
			'Name' = $_.Context.PreContext.Trim('" ');
			'From' = [DateTime]::ParseExact($Matches['From'], 'MMMM d, yyyy h:mm:ss tt', $DTProvider)
			'To' = [DateTime]::ParseExact($Matches['To'], 'MMMM d, yyyy h:mm:ss tt', $DTProvider)
			'DaysRemaining' = $Null
		})
	} | ForEach-Object {
		$_.DaysRemaining = [math]::Truncate(($_.To - (Get-Date)).TotalDays)
		$_
	}

$Certificates | Format-Table -AutoSize

$MQcertname = Get-ChildItem Env:MQCERTLABL
$MQcertname.Value

$IbmCertificate = $Certificates | Where-Object {$_.Name -eq $MQcertname.Value}

$IbmCertificate | ForEach-Object {
	"$($_.Name): " | Write-Host -ForegroundColor White -NoNewline
	If ($_.DaysRemaining -ge 30) {
		 "valid for $($_.DaysRemaining) more days." 
    $Valid = "Good"

    $Valid
	} ElseIf ($_.DaysRemaining -gt 0) {
		$Valid = "valid for only $($_.DaysRemaining) more days." 
	} Else {
		$Valid = "expired since $([math]::Abs($_.DaysRemaining)) days!"
	}
}

}

else 

{ $Valid = "Write-Host  Check is not required" }


}
}

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
oBdACommented:
Untested:
$FullPath = $MyInvocation.MyCommand.Path
$Scriptpath = Split-Path -Path $FullPath -Parent
Set-Location $Scriptpath

#$Outfile = '.\Output.csv'
$Outfile = "C:\temp\result.csv"
$ServerList = '.\servers.txt'

$Computers = Get-Content -Path $ServerList
$Computers | ForEach-Object {
	"Checking on $_" | Write-Host
	Invoke-Command -ComputerName $_ -ScriptBlock {
		If ($SslPath = $Env:MQSSL_DIR) { # have to check for cert information only if MQDIR environment variable is present
			$DTProvider = New-Object -TypeName System.Globalization.CultureInfo -ArgumentList 'en-US'
			$Certificates = & runmqckm -cert -list -expiry 500 -db "$($SslPath)\*Key.kdb" -pw 'Password1' |
				Select-String -Pattern '\A\s+From:' -Context 1 |
				ForEach-Object {
					$_.Line -match '\s+From: \S+, (?<From>\S+ \d+, \d{4} \S+ \S\S).*To: \S+, (?<To>\S+ \d+, \d{4} \S+ \S\S)' | Out-Null
					New-Object -TypeName PSObject -Property ([ordered]@{
						'Name' = $_.Context.PreContext.Trim('" ');
						'From' = [DateTime]::ParseExact($Matches['From'], 'MMMM d, yyyy h:mm:ss tt', $DTProvider)
						'To' = [DateTime]::ParseExact($Matches['To'], 'MMMM d, yyyy h:mm:ss tt', $DTProvider)
						'DaysRemaining' = $Null
					})
				} | ForEach-Object {
					$_.DaysRemaining = [math]::Truncate(($_.To - (Get-Date)).TotalDays)
					$_
				}
			$Certificates | Format-Table -AutoSize | Out-String | Write-Host
			$IbmCertificate = $Certificates | Where-Object {$_.Name -eq $Env:MQCERTLABL}
			$IbmCertificate | ForEach-Object {
				"$($_.Name): " | Write-Host -NoNewline
				If ($_.DaysRemaining -ge 30) {
					$Valid = "good, for $($_.DaysRemaining) more days."
				} ElseIf ($_.DaysRemaining -gt 0) {
					$Valid = "valid for only $($_.DaysRemaining) more days." 
				} Else {
					$Valid = "expired since $([math]::Abs($_.DaysRemaining)) days!"
				}
				$Valid | Write-Host
			}
		} Else {	#no check is required if  Env:MQDIR variable is not there on a machine
			$Valid = "Check is not required"
		}
		New-Object -TypeName PSObject -Property @{
			'ComputerName' = $ENV:ComputerName
			'IsCertValid' = $Valid
		}
	}
} | Export-Csv $Outfile -NoTypeInformation

Open in new window

0
Deepthi GosulaAuthor Commented:
this worked great. Output is as below.

"ComputerName","IsCertValid","PSComputerName","RunspaceId","PSShowComputerName"
"Server1","good, for 51 more days.","Server1.abc.com","abc-efg-ijk-lmnopq","True"
"Server2","good, for 51 more days.","Server2.abc.com","abc-efg-ijk-lmnopq","True"
"Server13","good, for 13 more days.","Server13.abc.com","abc-efg-ijk-lmnopq","True"
"Server14","good, for 13 more days.","Server14.abc.com","abc-efg-ijk-lmnopq","True"
"Server15","Check is not required","Server15.abc.com","abc-efg-ijk-lmnopq","True"
"Server16","Check is not required","Server16.abc.com","abc-efg-ijk-lmnopq","True"

In the last line I have used below code to remove the extra columns. Thank you very much this is great help. You solved my 2 days hassle in few minutes.
 select-object -property * -ExcludeProperty  PSComputerName,RunspaceId,PSShowComputerName |  Export-Csv $Outfile -NoTypeInformation
0
Deepthi GosulaAuthor Commented:
I have problem in exporting the contents in a script block to local. oBdA has given excellent guidance and solution to help to fix this issue. Thank you for all the great work you do oBdA.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Powershell

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.