ryanmaves
asked on
Help with PowerShell $PSBoundParameters
My script below works and that should satisfy it's purpose, however, I am trying to learn more about what is happening.
In doing so I have put Write-Verbose within an If/Then process so that if the computer name is passed as a parameter it should Write-Verbose that it is passed as a parameter. However, if passed as a script, it should Write-Verbose that it is passed through pipeline.
Why in every example does the computer name(s) pass through as parameter??
That should pass the computer names through the cmdlet as pipeline and the Write-Verbose "$_ is going through pipeline" should be printed, but no matter how I use the cmdlet it always passes through as parameter.
Why is it not using the pipeline Else{} script??
In doing so I have put Write-Verbose within an If/Then process so that if the computer name is passed as a parameter it should Write-Verbose that it is passed as a parameter. However, if passed as a script, it should Write-Verbose that it is passed through pipeline.
Why in every example does the computer name(s) pass through as parameter??
Get-Content .\list.txt | Start-ReportPSCompliant -Verbose
That should pass the computer names through the cmdlet as pipeline and the Write-Verbose "$_ is going through pipeline" should be printed, but no matter how I use the cmdlet it always passes through as parameter.
Why is it not using the pipeline Else{} script??
function Start-ReportPSCompliant {
<#
.Synopsis
This reports on computers as to whether or not they have policy ready for PSRemoting by invoking a command to return the environment computer name. If it doesn't return then PSRemoting is not enabled or the device is unavailable.
.DESCRIPTION
Enter in a single computer name or multiple computer names. Value from pipeline is also
acceptable.
.EXAMPLE
Start-ReportPSCompliant Server1
.EXAMPLE
Start-ReportPSCompliant -Computer 'computer1','computer2'
.EXAMPLE
Get-Content C:\Scripts\list.txt | Start-ReportPSCompliant
.EXAMPLE
Start-ReportPSCompliant (Get-Content C:\Scripts\list.txt)
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory=$true,ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
[String[]]$Computer = 'localhost'
)
Begin {
Write-Verbose 'Looking for existing reports and removing files if found'
$Pa = Test-Path C:\Scripts\temp\compliant.txt
if ($Pa) {Remove-Item C:\Scripts\temp\compliant.txt; Write-Verbose 'compliant.txt list was removed'}
else {Write-Verbose 'compliant.txt list does not exist'}
$Pa = Test-Path C:\Scripts\temp\noncompliant.txt
if ($Pa) {Remove-Item C:\Scripts\temp\noncompliant.txt; Write-Verbose 'noncompliant.txt list was removed'}
else {Write-Verbose 'noncompliant.txt list does not exist'}
}
Process {
if ($PSBoundParameters.ContainsKey('computer')) {
# we have parameter input
Write-Verbose "$Computer is going through as parameter input"
foreach ($c in $Computer) {
CompliantWorker $c
}
}else{
# we have pipeline input
Write-Verbose "$_ is going through pipeline"
CompliantWorker $_
}
}
End {
Write-Verbose 'The operation is complete'
$Pa = Test-Path C:\Scripts\temp\compliant.txt
if ($Pa) {notepad C:\Scripts\temp\compliant.txt}
else {Write-Warning 'No computers in list were compliant!'}
$Pa = Test-Path C:\Scripts\temp\noncompliant.txt
if ($Pa) {notepad C:\Scripts\temp\noncompliant.txt}
else {Write-Verbose 'All computers in list were compliant!'}
}
}
function CompliantWorker {
param (
$Computer
)
Write-Verbose "Attempting to send a remote command to $Computer"
Invoke-Command $Computer {$env:COMPUTERNAME} -ErrorAction SilentlyContinue -ErrorVariable err
if($err.count -gt 0) {
Write-Output $Computer | Out-File C:\Scripts\temp\noncompliant.txt -Append
}
else {
$Computer | Out-File C:\Scripts\temp\compliant.txt -Append
}
}
ASKER
Thanks for the response footech. You're right, it shouldn't matter, but I don't understand why I'm not seeing my Verbose message that says my input is going through pipeline as opposed to parameter when I do in fact use the line
Get-Content .\list.txt | Start-ReportPSCompliant -Verbose
Should I not expect to see the Verbose message from the Else{} block?
Get-Content .\list.txt | Start-ReportPSCompliant -Verbose
Should I not expect to see the Verbose message from the Else{} block?
if ($PSBoundParameters.ContainsKey('computer')) {
# we have parameter input
Write-Verbose "$Computer is going through as parameter input"
foreach ($c in $Computer) {
CompliantWorker $c
}
}else{
# we have pipeline input
Write-Verbose "$_ is going through pipeline"
CompliantWorker $_
}
Nope. As I mentioned, the parameter is being used either way. So whether you feed it values via the command line directly or the pipeline, $Computer is the receptacle.
ASKER
Okay, I see what you are saying. My question then would be, what about my script has caused the parameter to handle pipeline input as well?
FYI. I got this script trick of $PSBoundParameters from Don Jones at 3:19:00 time frame in this youtube video below:
https://www.youtube.com/watch?v=7fFEV8xawx0
I guess I am trying to understand, do I have unnecessary lines in my script. I can't wrap my head around why the correct Verbose message isn't being used here. Unless, that means it's unnecessary script that can be removed, but why did Don Jones use it?
Thanks for entertaining my curiosity.
FYI. I got this script trick of $PSBoundParameters from Don Jones at 3:19:00 time frame in this youtube video below:
https://www.youtube.com/watch?v=7fFEV8xawx0
I guess I am trying to understand, do I have unnecessary lines in my script. I can't wrap my head around why the correct Verbose message isn't being used here. Unless, that means it's unnecessary script that can be removed, but why did Don Jones use it?
Thanks for entertaining my curiosity.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks for being thorough footech. You are right, turns out I didn't even need the If/Then statement in my code. The process simply is a foreach and sends it to my worker process. Everything still works the same.
Thanks for the lesson.
Thanks for the lesson.
Process {
foreach ($c in $Computer) { CompliantWorker $c }
}
ASKER
Note, without the foreach statement having it send to my worker, there does rise a problem when calling computernames into the parameter such as it doesn't process them individually, but tries to do it all at once. This causes all the computernames to be added to my non-compliant list because they are all considered to have an ($err.count -gt 0).
Thanks again!
Thanks again!
Get-Content .\list.txt | Start-ReportPSCompliant -Verbose
but not something like
"server1","server2" | Start-ReportPSCompliant -Verbose
You've written your script to handle pipeline input. It shouldn't matter whether you're actually using the pipeline or not.