PowerShell Workflow scoping issue - powershell

Recently we started exploring Workflows in PowerShell. It greatly enhances the execution speed, but it adds an extra level of complexity too.
The code below has a scoping issue. The variables in the Parallel clause ($Workflow:Ports and $Workflow:Drivers) ar apparently shared over the different $ComputerNames instead of being specific to one $ConputerName. When checking technet I can't seem to figure out how to make the variables $Ports and $Drivers specific to that computer ($C).
When using $Workflow:Ports they are shared between all computers, and this is not what we want. When using $Ports it's not available in the InlineScript clause.
The code:
Workflow Get-PrintersInstalledHC {
Param (
[String[]]$ComputerName
)
Foreach -Parallel ($S in $ComputerName) {
$Computer = InlineScript {
[PSCustomObject]#{
ComputerName = $Using:S
ComputerStatus = $null
Printers = $null
RetrievalDate = Get-Date
}
}
# $VerbosePreference = [System.Management.Automation.ActionPreference]$Using:VerbosePreference
Try {
$Printers = Get-Printer -ComputerName $S -Full -EA Stop
if ($Printers) {
Write-Verbose "$S Found $($Printers.Count) printers"
Parallel {
$Workflow:Ports = Get-PrinterPort -ComputerName $S
$Workflow:Drivers = Get-PrinterDriver -ComputerName $S
}
$CimConfig = InlineScript {
Try {
#region CmdLets that require admin permissions
$Params = #{
ComputerName = $Using:S
ClassName = 'Win32_PrinterConfiguration'
Property = '*'
ErrorAction = 'Stop'
Verbose = $false
}
$Config = Get-CimInstance #Params
Foreach ($P in $Using:Printers) {
Foreach($C in $Config) {
if ($P.Name -eq $C.Name) {
#{
PrinterName = $P.Name
CimStatus = 'Ok'
DriverVersionCim = $C.DriverVersion
Collate = $C.Collate
Color = $C.Color
Copies = $C.Copies
Duplex = $C.Duplex
PaperSize = $C.PaperSize
Orientation = $C.Orientation
PrintQuality = $C.PrintQuality
MediaType = $C.MediaType
DitherType = $C.DitherType
}
Break
}
}
}
#endregion
}
Catch {
Foreach ($P in $Using:Printers) {
#{
PrinterName = $P.Name
CimStatus = 'No admin permissions'
}
}
}
}
Foreach -parallel ($P in $Printers) {
$PrinterConfig = InlineScript {
$P = $Using:P
$Port = $Using:Ports | Where {$_.Name -eq $P.PortName}
$Driver = $Using:Drivers | Where {$_.Name -eq $P.DriverName}
Write-Verbose "$Using:S Printer '$($P.Name)'"
$DriverManufacturer = if ($Driver.Manufacturer) {$Driver.Manufacturer} else {
if ($Driver.Name -like '*Microsoft*') {'Microsoft'}
}
$DriverVersion = if ($Driver.DriverVersion -eq '0') {$null} else {
$Driver.DriverVersion
}
#{
Online_Hostname = if ($P.Name) {Test-Connection $P.Name -Quiet -EA Ignore} else {$null}
Online_PortHostAddress = if ($Port.PrinterHostAddress) {Test-Connection $Port.PrinterHostAddress -Quiet -EA Ignore} else {$null}
PortHostAddress = if ($Port.PrinterHostAddress) {$Port.PrinterHostAddress} else {$null}
PortDescription = if ($Port.Description) {$Port.Description} else {$null}
DriverType = $Driver.PrinterEnvironment -join ','
DriverManufacturer = ($DriverManufacturer | Select -Unique) -join ','
DriverVersion = ($DriverVersion | Select -Unique) -join ','
}
}
$Cim = $CimConfig | Where-Object -FilterScript {$P.Name -eq $_.PrinterName}
$P | Add-Member -NotePropertyMembers ($PrinterConfig + $Cim) -TypeName NoteProperty
}
InlineScript {
$Computer = $Using:Computer
$Computer.Printers = $Using:Printers
$Computer.ComputerStatus = 'Ok'
$Computer
}
}
else {
Write-Verbose "$S No printers found"
}
}
Catch {
InlineScript {
$Computer = $Using:Computer
if (Test-Connection $Using:S -Count 2 -Quiet) {
$Computer.ComputerStatus = $Using:_.Message
}
else {
$Computer.ComputerStatus = 'Offline'
}
$Computer
}
}
}
}

Related

powershell sort-object and keeps window open

I have following script to check the installed software on local and remote machines.
Usually it works fine but i have two problems. It only works when i open it in ISE. If i open it in a normal powershell, the script close immediately. Even a pause or read-host command won't work.
For example here is my script for a local machine. Hope you guys can help me.
Function Get-InstalledSoftware {
Param(
[Alias('Computer','ComputerName','HostName')]
[Parameter(
ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$true,
Position=1
)]
[string]$Name = $env:COMPUTERNAME
)
Begin{
$lmKeys = "Software\Microsoft\Windows\CurrentVersion\Uninstall","SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
$lmReg = [Microsoft.Win32.RegistryHive]::LocalMachine
$cuKeys = "Software\Microsoft\Windows\CurrentVersion\Uninstall"
$cuReg = [Microsoft.Win32.RegistryHive]::CurrentUser
}
Process{
if (!(Test-Connection -ComputerName $Name -count 1 -quiet)) {
Write-Error -Message "Unable to contact $Name. Please verify its network connectivity and try again." -Category ObjectNotFound -TargetObject $Computer
Break
}
$masterKeys = #()
$remoteCURegKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($cuReg,$computer)
$remoteLMRegKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($lmReg,$computer)
foreach ($key in $lmKeys) {
$regKey = $remoteLMRegKey.OpenSubkey($key)
foreach ($subName in $regKey.GetSubkeyNames()) {
foreach($sub in $regKey.OpenSubkey($subName)) {
$masterKeys += (New-Object PSObject -Property #{
"ComputerName" = $Name
"Name" = $sub.getvalue("displayname")
"SystemComponent" = $sub.getvalue("systemcomponent")
"ParentKeyName" = $sub.getvalue("parentkeyname")
"Version" = $sub.getvalue("DisplayVersion")
"UninstallCommand" = $sub.getvalue("UninstallString")
"InstallDate" = $sub.getvalue("InstallDate")
"RegPath" = $sub.ToString()
})
}
}
}
foreach ($key in $cuKeys) {
$regKey = $remoteCURegKey.OpenSubkey($key)
if ($regKey -ne $null) {
foreach ($subName in $regKey.getsubkeynames()) {
foreach ($sub in $regKey.opensubkey($subName)) {
$masterKeys += (New-Object PSObject -Property #{
"ComputerName" = $Name
"Name" = $sub.getvalue("displayname")
"SystemComponent" = $sub.getvalue("systemcomponent")
"ParentKeyName" = $sub.getvalue("parentkeyname")
"Version" = $sub.getvalue("DisplayVersion")
"UninstallCommand" = $sub.getvalue("UninstallString")
"InstallDate" = $sub.getvalue("InstallDate")
"RegPath" = $sub.ToString()
})
}
}
}
}
$woFilter = {$null -ne $_.name -AND $_.SystemComponent -ne "1" -AND $null -eq $_.ParentKeyName}
$props = 'Name','Version','ComputerName','Installdate','UninstallCommand','RegPath'
$masterKeys = ($masterKeys | Where-Object $woFilter | Select-Object $props | Sort-Object Name)
$masterKeys
}
End{}
}
Get-InstalledSoftware | select-object name | sort-object
Send your output somewhere, not just to the host window. I suspect the windows closes or your pause command is kicking in before its retrieved the results thus they aren't sent to the host window.
The following works fine for me run as a script:
Get-InstalledSoftware | Select-Object name | Sort-Object | Out-Gridview

Powershell - how to check logged users in specific Machines

I have a code to check on local machines logged sessions as below
Get-WmiObject win32_networkloginprofile | ? {$_.lastlogon -ne $null} | % {[PSCustomObject]#{User=$_.caption; LastLogon=[Management.ManagementDateTimeConverter]::ToDateTime($_.lastlogon)}}
Is it possible to check it for specific machines a logged sessions , even the one that have status "disconnected" ?
Obviously you need rights on the target computers:
Function Get-LoggedOnUser {
param(
[CmdletBinding()]
[Parameter(ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[string[]]$ComputerName = 'localhost'
)
begin {
$ErrorActionPreference = 'Stop'
}
process {
foreach ($Computer in $ComputerName) {
try {
quser /server:$Computer 2>&1 | Select-Object -Skip 1 | ForEach-Object {
$CurrentLine = $_.Trim() -Replace '\s+',' ' -Split '\s'
# If session is disconnected different fields will be selected
if ($CurrentLine[2] -eq 'Disc') {
[pscustomobject]#{
UserName = $CurrentLine[0];
ComputerName = $Computer;
SessionName = $null;
Id = $CurrentLine[1];
State = $CurrentLine[2];
IdleTime = $CurrentLine[3];
LogonTime = $CurrentLine[4..($CurrentLine.GetUpperBound(0))] -join ' '
}
# LogonTime = $CurrentLine[4..6] -join ' ';
}
else {
[pscustomobject]#{
UserName = $CurrentLine[0];
ComputerName = $Computer;
SessionName = $CurrentLine[1];
Id = $CurrentLine[2];
State = $CurrentLine[3];
IdleTime = $CurrentLine[4];
LogonTime = $CurrentLine[5..($CurrentLine.GetUpperBound(0))] -join ' '
}
}
}
}
catch {
New-Object -TypeName PSCustomObject -Property #{
ComputerName = $Computer
Error = $_.Exception.Message
} | Select-Object -Property UserName,ComputerName,SessionName,Id,State,IdleTime,LogonTime,Error
}
}
}
}

Why do I get different output in Powershell from start-job vs just running the code?

The script runs correctly when outside of Start-Job but when in a scriptblock I get incorrect results. Where am I going wrong?
I need the Start-Job functionality since I have servers where the remote commands will hang (separate problem - WMI is borked) and I need to timeout and move to the next server.
I've tried every variation I can find in Google and still don't have the results I'm looking for.
I am really at my wits end with this as I don't understand what is happening... Help?
Thanks!
$timeoutSeconds = 90
ForEach($server in $servers) {
#$ErrorActionPreference = "inquire"
#$WarningPreference = "inquire"
$ErrorActionPreference = "silentlycontinue"
$WarningPreference = "silentlycontinue"
write-host $SERVER
$code = {
param($SERVER,$LOGto,$outputPath)
$ping = (Test-Connection -ComputerName $SERVER -Count 2 -Quiet )
if($ping -eq $true)
{
$pingVerbose = (Test-Connection -ComputerName $SERVER -Count 1)
$IP = $pingVerbose.IPV4Address.IPAddressToString
$osname2 = (Get-WMIObject -computerName $SERVER win32_operatingsystem).name
if($osname2 -match "|")
{
$osname,$osname1 = $osname2.Split('|')
} else {
$osname = $osname2
}
$lastinstalled = (Get-HotFix -computerName $SERVER | where -property InstalledOn -ne $null)
if($lastinstalled.InstalledOn)
{
$lastinstalledOn1 = ($lastinstalled.InstalledOn | Sort-Object -Property InstalledOn )[-1]
$lastinstalledOn = $lastinstalledOn1
}
$lastQFE = (get-wmiobject -class win32_quickfixengineering -computerName $SERVER | where -property InstalledOn -ne $null)
if($lastQFE.InstalledOn -ne $null)
{
$lastQFEon = ($lastQFE.InstalledOn | Sort-Object -Property InstalledOn)[-1]
$lastQFEon = $lastQFEon
}
if(($lastinstalledOn) -or ($lastQFEon))
{
if(($lastinstalledOn) -and ($lastinstalledOn -gt $lastQFEon))
{
$installedOn = $lastinstalledOn.tostring("MM/dd/yyyy")
$HotFixNumber = ($lastinstalled.HotFixID | Sort-Object -Property HotFixID)[-1]
} else {
$installedOn = $lastQFEon.tostring("MM/dd/yyyy")
$HotFixNumber = ($lastQFE.HotFixID | Sort-Object -Property HotFixID)[-1]
}
} else {
$installedOn = ''
$HotFixNumber = ''
}
}
#add entries to the log file
ac $outputPath\$LOGto "$Server,$ip,$installedOn,$HotFixNumber,$ping,$osname "
Write-Host "$Server,$ip,$installedOn,$HotFixNumber,$ping,$osname "
}
$runCode = Start-Job -ScriptBlock $code -ArgumentList $server,$LOGto,$outputPath
if(Wait-Job $runCode -Timeout $timeoutSeconds)
{
Receive-Job $runCode
} else {
Remove-Job -Force $runCode
ac $($outputPath + "\error.txt") "$Server"
}
}
When running in the scriptblock I receive the wrong date and KB.
SERVERNAME
SERVERNAME,10.1.XX.XX,03/13/2015,KB3022777,True,Microsoft Windows Server 2012 R2 Standard
vs.
SERVERNAME
SERVERNAME,10.1.XX.XX,05/15/2017,KB4012213,True,Microsoft Windows Server 2012 R2 Standard
For posterity more than anything else...
The error I was making was using sort-object against a string instead of a numerical value.
The code below will work correctly once you replace the domain name and file path information.
Thanks,
-Luke
#change this to a directory of your choice
$outputPath = "C:\Users\username\Desktop"
cd $outputPath
#create a default file name
$LOGto = "AllWinHotFixDateDC_$((Get-Date).ToString('yyyyMMdd')).csv"
#create the headers
sc .\$LOGto "Server,IPAddress,InstalledOn,HotFixNumber,Ping,OS_Name"
#get the server names from AD
Get-ADComputer -Filter {(Enabled -eq "True") -and (OperatingSystem -like "*Windows*") } -SearchBase "OU=Servers,DC=mydomain,DC=net" -server 'mydomain.net' -SearchScope Subtree | Select Name -ExpandProperty name | Sort-Object | Out-File .\servers.txt
$servers = get-content .\servers.txt
$timeoutSeconds = 90
ForEach($server in $servers) {
$ErrorActionPreference = "inquire"
$WarningPreference = "inquire"
#$ErrorActionPreference = "silentlycontinue"
#$WarningPreference = "silentlycontinue"
write-host $SERVER
$code = {
param($SERVER,$LOGto,$outputPath)
$ping = (Test-Connection -ComputerName $SERVER -Count 2 -Quiet )
if($ping -eq $true)
{
$pingVerbose = (Test-Connection -ComputerName $SERVER -Count 1)
$IP = $pingVerbose.IPV4Address.IPAddressToString
$osname2 = (Get-WMIObject -computerName $SERVER win32_operatingsystem).name
if($osname2 -match "|")
{
$osname,$osname1 = $osname2.Split('|')
} else {
$osname = $osname2
}
$getinstalled = (Get-HotFix -computerName $SERVER)
if($getinstalled)
{
if($getinstalled.HotFixID -ne $null)
{
$validinstalled = ($getinstalled.HotFixID -match "KB*")
$KB = (($validinstalled -replace 'KB','') | Sort-Object {[int]($_ -replace '(\d+).*', '$1')})[-1]
$lastinstalledOnHotFix = ("KB$KB")
}
if ($getinstalled.InstalledOn -ne $null)
{
$lastInstalled = ($getinstalled | Sort-Object -Property InstalledOn)[-1]
$lastInstalledlist = $lastInstalled.InstalledOn | Sort-Object {[int]($_ -replace '(\d+).*', '$1')}
$lastInstalledon = $lastInstalledlist.tostring("MM/dd/yyyy")
} else {
$lastinstalledOn = "0"
}
}
Write-Host $lastinstalledOn
Write-Host $lastinstalledOnHotFix
$getQFE = (get-wmiobject -class win32_quickfixengineering -computerName $SERVER )
if($getQFE)
{
if($getQFE.HotFixID -ne $null)
{
$validQFE = ($getQFE.HotFixID -match 'KB')
$KB = (($validQFE -replace 'KB','') | Sort-Object {[int]($_ -replace '(\d+).*', '$1')})[-1]
$lastQFEonHotFix = ("KB$KB")
}
if($getQFE.InstalledOn -ne $null)
{
$lastQFE = ($getQFE | Sort-Object -Property InstalledOn)[-1]
$lastQFElist = $lastQFE.InstalledOn | Sort-Object {[int]($_ -replace '(\d+).*', '$1')}
$lastQFEon = $lastQFElist.tostring("MM/dd/yyyy")
} else {
$lastQFEon = "0"
}
}
Write-Host $lastQFEon
Write-Host $lastQFEonHotFix
if(($lastinstalledOn -ne $null) -or ($lastQFEon -ne $null))
{
if(($lastInstalledlist -ne $null) -and ($lastInstalledlist -gt $lastQFElist))
{
$installedOn = $lastinstalledOn
$HotFixNumber = $lastinstalledOnHotFix
} elseif($lastQFEon -ne $null)
{
$installedOn = $lastQFEon
$HotFixNumber = $lastQFEonHotFix
}
} else {
$installedOn = '0'
$HotFixNumber = $lastQFEonHotFix
}
}
#add entries to the log file
ac $outputPath\$LOGto "$Server,$ip,$installedOn,$HotFixNumber,$ping,$osname "
Write-Host "$Server,$ip,$installedOn,$HotFixNumber,$ping,$osname "
}
$runCode = Start-Job -ScriptBlock $code -ArgumentList $server,$LOGto,$outputPath
if(Wait-Job $runCode -Timeout $timeoutSeconds)
{
Receive-Job $runCode
} else {
Remove-Job -Force $runCode
ac $($outputPath + "\error.txt") "$Server"
}
}

get local admin users with password age

I am working on once assignment where want to get a list of local Windows admin users with X password age. Got below function for local admin users and other one for age. Please help me integrate these.
I have below command can work with users list to fetch details from specific groups and hostnames.
Get-Content -Path "D:\Groups.txt" | ForEach-Object {
Get-GroupMember -ComputerName (Get-Content -Path "D:\servers.txt") -LocalGroup $_
} | Export-Csv -Path D:\Getgroupmembers_$(Get-Date -Format ddMMyyyy).csv -NoTypeInformation
List of users:
function Get-GroupMember {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[Alias('Group')]
[string]$LocalGroup,
[Alias('CN','Computer')]
[string[]]$ComputerName = '.'
)
foreach ($Computer in $ComputerName) {
Write-Verbose "Checking membership of localgroup: '$LocalGroup' on $Computer"
try {
([adsi]"WinNT://$Computer/$LocalGroup,group").psbase.Invoke('Members') | ForEach-Object {
New-Object -TypeName PSCustomObject -Property #{
ComputerName = $Computer
LocalGroup = $LocalGroup
Member = $_.GetType().InvokeMember('Name', 'GetProperty', $null, $_, $null)
}
}
Write-Verbose "Successfully checked membership of localgroup: '$LocalGroup' on $Computer"
} catch {
Write-Warning $_
}
}
}
TO check Password age we can use below code and we need to integrate these two using one command:
function Get-PwdAge {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$false,
Position=1,
ValueFromPipeline=$false,
ValueFromPipelineByPropertyName=$false)]
[String]$Usr,
[Switch]$All
)
$filter = "(&(objectCategory=person)(objectClass=user)(name=$Usr))"
if ($All) {
$filter = '(&(objectCategory=person)(objectClass=user))'
}
$root = New-Object System.DirectoryServices.DirectoryEntry("LDAP://RootDSE")
$searcher = New-Object System.DirectoryServices.DirectorySearcher $filter
$SearchRoot = $root.defaultNamingContext
$searcher.SearchRoot = "LDAP://CN=Users,$SearchRoot"
$searcher.SearchScope = 'SubTree'
$searcher.SizeLimit = 0
$searcher.PageSize = 1000
$searcher.FindAll() | ForEach-Object {
$account = $_.GetDirectoryEntry()
$pwdset = [DateTime]::FromFileTime($_.Properties.Item("pwdLastSet")[0])
$age = (New-TimeSpan $pwdset).Days
$info = 1 | Select-Object Name, Login, AgeInDays, LastSet
$info.Name = $account.DisplayName[0]
$info.Login = $account.SamAccountName[0]
$info.AgeInDays = $age
$info.LastSet = $pwdset
$info
}
}
Param
(
[Parameter(Position=0,Mandatory=$false)]
[ValidateNotNullorEmpty()]
[Alias('cn')][String[]]$ComputerName=$Env:COMPUTERNAME,
[Parameter(Position=1,Mandatory=$false)]
[Alias('un')][String[]]$AccountName,
[Parameter(Position=2,Mandatory=$false)]
[Alias('cred')][System.Management.Automation.PsCredential]$Credential
)
$Obj = #()
$now = Get-Date
Foreach($Computer in $ComputerName)
{
If($Credential)
{
$AllLocalAccounts = Get-WmiObject -Class Win32_UserAccount -Namespace "root\cimv2" `
-Filter "LocalAccount='$True'" -ComputerName $Computer -Credential $Credential -ErrorAction Stop
}
else
{
$AllLocalAccounts = Get-WmiObject -Class Win32_UserAccount -Namespace "root\cimv2" `
-Filter "LocalAccount='$True'" -ComputerName $Computer -ErrorAction Stop
}
$Obj = $AllLocalAccounts | ForEach-Object {
$user = ([adsi]"WinNT://$computer/$($_.Name),user")
$pwAge = $user.PasswordAge.Value
$maxPwAge = $user.MaxPasswordAge.Value
$pwLastSet = $now.AddSeconds(-$pwAge)
New-Object -TypeName PSObject -Property #{
'Account Name' = $_.Name
'Disabled' = $_.Disabled
'Password Expires' = $_.PasswordExpires
'Password Last Set' = $pwLastSet
'Password Expiry Date' = $now.AddSeconds($maxPwAge - $pwAge)
'Password Required' = $_.PasswordRequired
'Domain' = $_.Domain
'Password Age' = ($now - $pwLastSet).Days
}
}
If($AccountName)
{
Foreach($Account in $AccountName)
{
$Obj|Where-Object{$_.Name -like "$Account"}
}
}
else
{
$Obj
}
}

Split-Pipeline parallel jobs script won't finish the last job

So I've been using Split-Pipeline module for some time now, and what bothers me about it, rarely does it really finish. I always get stuck with the last job in the queue hanging and have to either stop the script or kill ISE:
VERBOSE: Split-Pipeline: Jobs = 1; Load = End; Queue = 0
example: 300 servers, running a scan for hotfixes on them using split-pipeline. I'm using pretty standard parameters:
$servers | Split-Pipeline -Verbose -Count 10 { process {#some code for scanning#}}
So 10 jobs each loaded with 30 servers, first lets say 250 servers are scanned really fast, then it slows down a little and when the last job remains only, it never finishes...
Anyone experienced something similar? I've tested the same on several machines and it's always the same so I don't think it's related to the machine running the script.
EDIT: heres the code
$servers = (Get-Clipboard).trim() #server1..100
$KB = (Get-Clipboard).trim() -split ', ' #KB4022714, KB4022717, KB4022718, KB4022722, KB4022727, KB4022883, KB4022884, KB4022887, KB4024402, KB4025339, KB4025342, KB4021903, KB4021923, KB4022008, KB4022010, KB4022013, KB3217845
$servers | Split-Pipeline -Verbose -Variable KB -Count 10 { process {
$hash = [ordered]#{}
try
{
$hash.Hostname = $_
$os = gwmi win32_operatingsystem -ComputerName $_ -ErrorAction Stop
$hash.OS = $os.Caption
$hash.Architecture = $os.OSArchitecture
$today = [Management.ManagementDateTimeConverter]::ToDateTime($os.LocalDateTime)
$hash.LastReboot = [Management.ManagementDateTimeConverter]::ToDateTime($os.LastBootUpTime)
$hash.DaysSinceReboot = ($today - $hash.LastReboot).Days
}
catch
{
$hash.OS = $Error[0]
$hash.Architecture = 'N/A'
$hash.LastReboot = 'N/A'
$hash.DaysSinceReboot = 'N/A'
}
try
{
$hash.PendingReboot = icm -cn $_ {
if (Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending" -EA SilentlyContinue) { return $true }
if (Get-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired" -EA SilentlyContinue) { return $true }
if (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" -Name PendingFileRenameOperations -Ea SilentlyContinue) { return $true }
try
{
$util = [wmiclass]"\\.\root\ccm\clientsdk:CCM_ClientUtilities"
$status = $util.DetermineIfRebootPending()
if(($status -ne $null) -and $status.RebootPending)
{
return $true
}
}
catch{}
return $false
}
}
catch
{
$hash.PendingReboot = 'N/A'
}
try
{
$hotfix = Get-HotFix -ComputerName $_ -Id $KB -ErrorAction Stop
if ($hotfix)
{
$hash.Hotfix = $hotfix.HotFixID -join ','
}
else
{
$hash.Hotfix = "No Hotfix from the list applied"
}
}
catch
{
$hash.Hotfix = $Error[0]
}
$obj = New-Object -TypeName PSObject -Property $hash
$obj | Export-Csv c:\temp\hotfixes.csv -NoTypeInformation -Append -Force
}
}