edps_122018_learningModules.psm1
FUNCTION Get-PipeByPart { <# .SYNOPSIS The intention of this script is merely to show the breakdown of a piped command as PowerShell processes it. .DESCRIPTION A piped command can be passed to the function, as a string, parsed into separate commands, and each segment then showing its results before being passed on to the next command. .EXAMPLE Get-PipeByPart -PipedCommand "Get-WMIObject Win32_BIOS -ComputerName 127.0.0.1, 192.168.2.60 -Property SMBIOSBIOSVersion, Manufacturer, Version | SELECT-Object SMBIOSBIOSVersion, Manufacturer | SORT SMBIOSBIOSVersion -Descending" The above command will first gather BIOS info from two computers. Next, it will SELECT-Objectonly 2 attributes or properties, the SN and Manufacturer. Finally, it will sort the results by SN. Notice, the piped commands need to be within overall quotes in order to be passed to Get-PipeByPart as a single parameter. .EXAMPLE Get-PipeByPart -PipedCommand "Get-Disk -Number '1' | FL" If you need to use quotes within the piped commands you're passing, you can use single quotes to include them inside your overall quotes. .EXAMPLE Get-PipeByPart -PipedCommand "Get-Disk -Number `"1`" | FL" If you need to use quotes within the piped commands you're passing, you can use tickmark double quotes (`") to include them inside your overall quotes. .EXAMPLE $myResult = Get-PipeByPart -PipedCommand "Get-Disk -Number `"1`" | FL" -returnResults Finally, if you need to save the individual results of the piping process, you can have them returned as show above, using the -returnResults switch. .PARAMETER PipedCommand PipedCommand is looking for the... piped command... you're looking to examine. Use the examples to see how to deal with quotes you want to include in your commands as outer-double-quotes will need to wrap this parameter. .PARAMETER returnResults returnResults will, instead of presenting the breakdown on the screen, return an array with columns for each command ($myResult.Command) and then the result ($myResult.Result). .LINK http://blog.everydaypowershell.com/2018/11/get-pipedparts-understanding-order-of.html .NOTES Mark Smith everydayPowerShell.com Twitter: @edPowerShell Blog For This Function: http://blog.everydaypowershell.com/2018/11/get-pipedparts-understanding-order-of.html #> #region Param + Checks [cmdletbinding(SupportsShouldProcess=$True)] param( [string]$PipedCommand, [switch]$returnResults ) $failure=$currentState=$null IF(!($PipedCommand)){ $failure = "No piped command was provided. Please use `"Get-Help Get-PipeByPart -Examples`" for examples of how to use this function." Write-Error $failure return } ELSEIF($PipedCommand -notlike "*`|*"){ $failure = "You've included no actual piped (`"`|`") commands. Please use `"Get-Help Get-PipeByPart -Examples`" for examples of how to use this function." Write-Error $failure return } #endregion #region Parse And Prep [Array]$PipedCommand = ($PipedCommand).Split("|") $PipedCommand = $PipedCommand.Trim() $commandCount = $PipedCommand.Count $pipedCommandResults = @() Clear-Host Start-Sleep -Seconds 1 $nowCount = 0 #endregion #region Present Commands ForEach($currentCommand in $PipedCommand){ $nowCount++ $newRow = "" | SELECT-Object Command,Result $newRow.Command = [string]$currentCommand $newRow.Result = $null IF($nowCount -eq 1){ $currentState = [PSObject](Invoke-Command -ScriptBlock ([scriptblock]::Create($currentCommand))) $newRow.Result = $currentState } ELSEIF($nowCount -eq $commandCount){ $currentState = $currentState | Invoke-Command -ScriptBlock ([scriptblock]::Create($currentCommand)) $newRow.Result = $currentState } ELSE{ $currentState = $currentState | Invoke-Command -ScriptBlock ([scriptblock]::Create($currentCommand)) $newRow.Result = $currentState } $pipedCommandResults += $newRow } #endregion IF($returnResults){ return $pipedCommandResults } ELSE{ $PipedCommandResults | ForEach-Object { Write-Verbose $_.Command -Verbose Write-Output $_.Result } } } Export-ModuleMember -Function Get-PipeByPart FUNCTION Confirm-TargetSystem { <# .SYNOPSIS Attempt to verify that a system is the intended target system and, optionally, is intended logged on user. .DESCRIPTION Attempt to verify that a system is the intended target system and, optionally, is intended logged on user. Will use Get-WMIObject to reach out to target system and attempt to match the computer name or IP address and, if provided, the username as well. .EXAMPLE Confirm-TargetSystem -sysID PSCenter Expected results of a confirmed system: sysID : PSCenter sysName : PSCENTER sysIP : 192.168.2.60 usrID : NA usrLoggedOn : NA isIntendedSystem : True isIntendedUser : False failureNotes : NA .EXAMPLE Confirm-TargetSystem -sysID PSCenters Expected results of a failed confirmation where the system could not be viably reached. sysID : PSCenters sysName : sysIP : usrID : NA usrLoggedOn : NA isIntendedSystem : isIntendedUser : failureNotes : The system is unavailable to communicate with the system PSCenters. Error: The RPC server is unavailable. (Exception from HRESULT: 0x800706BA) .EXAMPLE Confirm-TargetSystem -sysID PSCenter -usrID PSAdmin If all results confirmed, feedback would appear as: sysID : PSCenter sysName : PSCENTER sysIP : 192.168.2.60 usrID : PSAdmin usrLoggedOn : PSCENTER\PSAdmin isIntendedSystem : True isIntendedUser : True failureNotes : NA .EXAMPLE Confirm-TargetSystem -sysID 192.168.1.21 -tCred BettyBoop Expected results if your credentials are invalid on the remote system. sysID : 192.168.1.21 sysName : sysIP : usrID : NA usrLoggedOn : NA isIntendedSystem : isIntendedUser : failureNotes : You do not have access to this system with your current credentials. Perhaps try other credentials using the -tCred option if you haven't already? Error: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) .EXAMPLE IF(Confirm-TargetSystem -sysID PSCenter -usrID PSAdmin | SELECT -ExpandProperty isIntendedSystem){Write-Host "Hello"} To use in another script to confirm whether or not to proceed with an intended action/configuration, above will return true and act if confirmation of the system is clear. .PARAMETER sysID sysID is looking for either a computer name or IP address. Whatever normal way you communicate with computers in your environment and can ping systems, that can be plugged in here. .PARAMETER usrID usrID is looking to match the user's login ID. For example, if I login with PSCenter\PSAdmin, using -usrID PSAdmin will count as a match if PSCenter\PSAdmin is what's returned when checking the remote system. .PARAMETER tCred tCred is aiming to collect alternate creds if you need to connect with the remote system with another account. If I'm in my computer as MSmith but need to reach out with my tech cred PSAdmin, I would include -tCred PSAdmin. When I do, I'll be prompted for my current password and then PSAdmin will be the account to reach out to the remote system. .LINK http://blog.everydaypowershell.com/2018/12/is-that-really-my-target-system.html .NOTES Mark Smith everydayPowerShell.com Twitter: @edPowerShell Blog For This Function: http://blog.everydaypowershell.com/2018/12/is-that-really-my-target-system.html #> [cmdletbinding()] param ( $sysID, $usrID, [switch]$silent, [PSCredential]$tCred ) IF(!($silent)){ Clear-Host Start-Sleep -Seconds 1 } #region Param Check & Variable Prep IF(!($sysID)){ $closingMsg = "You have not entered identifying information for a system that needs to be confirmed. Confirm-TargetSystem cannot run without this information. " $closingMsg += "Please use `"Get-Help Confirm-TargetSystem -Examples`" for examples of how to use this function. " $closingMsg += "Thank you. Confirm-TargetSystem will now stop." Write-Error -Message $closingMsg -ErrorAction Stop } IF(!($usrID)){ $warningMsg = "You have not entered identifying information for a user on the target system. Confirm-TargetSystem will only attempt to verify the system, not the user at this time." IF(!($silent)){ Write-Warning -Message $warningMsg -WarningAction Continue } } IF(!($tCred)){ $infoMsg = "You have not entered specific creds to be used with this function. PowerShell will use $($env:USERDOMAIN)\$($env:USERNAME) as the authority to reach out to the remote system." IF(!($silent)){ Write-Information -MessageData $infoMsg -InformationAction Continue } } ELSE{ $infoMsg = "You have chosen to use alternative creds for Confirm-TargetSystem. PowerShell will use $($tCred.UserName) as the authority to reach out to the remote system." IF(!($silent)){ Write-Verbose -Message $infoMsg -Verbose } } $result = "" | Select-Object sysID, sysName, sysIP, usrID, usrLoggedOn, isIntendedSystem, isIntendedUser, failureNotes $result.sysID = $sysID IF($usrID){ $result.usrID = $usrID } ELSE{ $result.usrID = "NA" $result.usrLoggedon = "NA" } #endregion #region Verify System IF(!($silent)){ Write-Verbose -Message "Attempting To Verify System $sysID now." -Verbose } TRY{ IF($tCred){ Write-Verbose "Attempting verification using $($tCred.UserName)." $result.sysName = Get-CimInstance -ClassName CIM_ComputerSystem -CimSession (New-CimSession -Credential $tCred -ComputerName $sysID -SkipTestConnection) -ErrorAction Stop -WarningAction Stop | Select-Object -ExpandProperty Name #$result.sysName = Get-WmiObject -Class Win32_ComputerSystem -Credential $tCred -ComputerName $sysID -ErrorAction Stop -WarningAction Stop | Select-Object -ExpandProperty Name } ELSE{ Write-Verbose "Attempting verification with $($env:USERDOMAIN)\$($env:USERNAME)." $result.sysName = Get-CimInstance -ClassName CIM_ComputerSystem -ComputerName $sysID -ErrorAction Stop -WarningAction Stop | Select-Object -ExpandProperty Name } $result.sysIP = (Test-Connection $sysID -Count 1 -ErrorAction Stop -WarningAction Stop | Select-Object -ExpandProperty IPV4Address).IPAddressToString } CATCH [Microsoft.Management.Infrastructure.CimException] { IF(($_.Exception.Message) -like "*WinRM cannot complete the operation*"){ $result.failureNotes = "The system is unavailable to communicate with the system $sysID.`nError:`n$($_.Exception.Message)" return $result } ELSEIF(($_.Exception.Message) -like "*Access is denied*"){ $closingMsg = "You do not have access to this system with your current credentials. " $closingMsg += "Perhaps try other credentials using the -tCred option if you haven't already?`n" $closingMsg += "Error:`n$($_.Exception.Message)" $result.failureNotes = $closingMsg return $result } ELSE{ [string]$closingMsg = "$($_.Exception.GetType().FullName)`n" $closingMsg += "$($_.Exception.Message)" $result.failureNotes = $closingMsg return $result } } CATCH{ [string]$closingMsg = "$($_.Exception.GetType().FullName)`n" $closingMsg += "$($_.Exception.Message)" $result.failureNotes = $closingMsg return $result } #endregion #region Verify User IF($usrID){ IF(!($silent)){ Write-Verbose -Message "Attempting To Verify User $usrID Is On $sysID now." -Verbose } TRY{ IF($tCred){ Write-Verbose "Attempting verification using $($tCred.UserName)." $result.usrLoggedOn = Get-CimInstance -ClassName CIM_ComputerSystem -CimSession (New-CimSession -Credential $tCred -ComputerName $sysID -SkipTestConnection) -ErrorAction Stop -WarningAction Stop | Select-Object -ExpandProperty UserName } ELSE{ Write-Verbose "Attempting verification with $($env:USERDOMAIN)\$($env:USERNAME)." $result.usrLoggedOn = Get-CimInstance -ClassName CIM_ComputerSystem -ErrorAction Stop -WarningAction Stop | Select-Object -ExpandProperty UserName } } CATCH{ [string]$closingMsg = "$($_.Exception.GetType().FullName)`n" $closingMsg += "$($_.Exception.Message)" $result.failureNotes = $closingMsg return $result } } #endregion #region Closure IF($sysID -eq ($result.sysName)){ $result.isIntendedSystem = "True" } ELSEIF($sysID -eq ($result.sysIP)){ $result.isIntendedSystem = "Unverified" } ELSEIF($sysID -ne ($result.sysName) -and $sysID -ne ($result.sysIP)){ $result.isIntendedSystem = "False" } IF($usrID -eq ($result.usrLoggedon) -or ($result.usrLoggedOn) -like "*\$usrID"){ $result.isIntendedUser = "True" } ELSE{ $result.isIntendedUser = "False" } $result.failureNotes = "NA" return $result #endregion } Export-ModuleMember -Function Confirm-TargetSystem |