General.psm1
#region Classes add-type @' namespace CPolydorou.General { public class UpTime { public string Name; public int Days; public int Hours; public int Minutes; public int Seconds; public int Milliseconds; } } '@ add-type @' namespace CPolydorou.General { public class LoggedOnUser { public string Username; public int SessionID; public string SessionName; public string SessionState; public System.TimeSpan SessionIdleTime; public System.DateTime LogonTime; } } '@ #endregion #region Functions #region ForEach-Object-Parallel function ForEach-Object-Parallel { <# .SYNOPSIS This function allows the user to run multiple jobs in parallel. .EXAMPLE (0..50) |ForEach-Parallel -MaxThreads 4{ $_ sleep 3 } #> param( [Parameter(Mandatory=$true,position=0)] [System.Management.Automation.ScriptBlock] $ScriptBlock, [Parameter(Mandatory=$true,ValueFromPipeline=$true)] [PSObject]$InputObject, [Parameter(Mandatory=$false)] [int]$MaxThreads=5, [Parameter(Mandatory=$false)] [hashtable]$Parameters ) BEGIN { $iss = [system.management.automation.runspaces.initialsessionstate]::CreateDefault() $pool = [Runspacefactory]::CreateRunspacePool(1, $maxthreads, $iss, $host) $pool.open() $threads = @() $scriptBlockString = "param(`$_" if($Parameters -ne $null) { $Parameters.Keys | %{ $scriptBlockString += ",`$$_" } } $scriptBlockString += ")`r`n" $scriptBlockString += $Scriptblock.ToString() $ScriptBlock = $ExecutionContext.InvokeCommand.NewScriptBlock($scriptBlockString) } PROCESS { $powershell = [powershell]::Create().addscript($scriptblock).addargument($InputObject) if($Parameters -ne $null) { $Parameters.Keys | %{ $powershell = $powershell.AddArgument($Parameters[$_]) } } $powershell.runspacepool=$pool $threads+= @{ instance = $powershell handle = $powershell.begininvoke() } } END { $notdone = $true while ($notdone) { $notdone = $false for ($i=0; $i -lt $threads.count; $i++) { $thread = $threads[$i] if ($thread) { if ($thread.handle.iscompleted) { $thread.instance.endinvoke($thread.handle) $thread.instance.dispose() $threads[$i] = $null } else { $notdone = $true } } } } } } #endregion #region Get-ConsoleUser function Get-ConsoleUser { <# .SYNOPSIS This function gets the username of the user logged on on a computer. .EXAMPLE Get-ConsoleUser -computername host1 #> Param( [Parameter(ParameterSetName = "ComputerName", Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [string[]] $ComputerName, [system.management.automation.psCredential]$Credential ) Process { if( $ComputerName.Count -eq 0 ) { if($Credential) { Get-WMIObject -class Win32_ComputerSystem -Credential $Credential | Select-Object Username } else { Get-WMIObject -class Win32_ComputerSystem | Select-Object Username } } else { foreach( $c in $ComputerName) { if($Credential) { Get-WMIObject -ComputerName $c -class Win32_ComputerSystem -Credential $Credential | Select-Object Username } else { Get-WMIObject -ComputerName $c -class Win32_ComputerSystem | Select-Object Username } } } } } #endregion #region Test-IsAdmin Function Test-IsAdmin { <# .SYNOPSIS Function used to detect if current user is an Administrator. .DESCRIPTION Function used to detect if current user is an Administrator. .EXAMPLE Test-IsAdmin Description ----------- Command will check the current user to see if an Administrator. #> [cmdletbinding()] Param() # Write-Verbose "Checking to see if current user context is Administrator" If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { return $false } Else { return $true } } #endregion #region Out-Speech Function Out-Speech() { <# .SYNOPSIS Function used to read strings. .EXAMPLE Out-Speech -Text "Read me!". #> Param( [string[]] $Text ) $v = New-Object -ComObject SAPI.SPVoice foreach( $s in $Text ) { $v.Speak($s) } } #endregion #region Get-PrinterLegacy function Get-PrinterLegacy { <# .SYNOPSIS Displays the list of installed printers. .DESCRIPTION This function lists all locally installed printers on local computer or a remote one. It uses WMI and not the printer functions added after Windows 7 which makes it very usefull on older systems. .EXAMPLE Get-PrinterLegacy This command returns a list of all locally installed printers. .EXAMPLE Get-PrinterLegacy -ComputerName client01 This command returns a list of all locally installed printers on computer 'client01'. #> Param ( [string]$ComputerName = ".", [system.management.automation.psCredential]$Credential ) if($Credential) { Get-WMIObject -Class Win32_Printer -ComputerName $ComputerName -Credential $Credential | Select-Object -Property Name, SystemName | Format-Table } else { Get-WMIObject -Class Win32_Printer -ComputerName $ComputerName | Select-Object -Property Name, SystemName | Format-Table } } #endregion #region Get-PowerEvent function Get-PowerEvent { <# .SYNOPSIS Displays the list of power events. .DESCRIPTION This function lists all power events on local computer. Power events are "Restart" and "Power off". .EXAMPLE Get-PowerEvent This command returns a list of power events. .EXAMPLE Get-PowerEvent | Where-Object {$_.Action -eq "Reboot"} This command returns all reboot events. #> Param( [Parameter(ParameterSetName = "ComputerName", Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [string[]] $ComputerName, [system.management.automation.psCredential]$Credential ) Process { # Varible to hold the events $events = @() if( $ComputerName.Count -eq 0 ) { if($Credential) { $events = Get-WinEvent -FilterHashtable @{logname='System'; id=1074} -Credential $Credential } else { $events = Get-WinEvent -FilterHashtable @{logname='System'; id=1074} } } else { foreach( $c in $ComputerName) { if($Credential) { $events += Get-WinEvent -FilterHashtable @{logname='System'; id=1074} -ComputerName $c -Credential $Credential } else { $events += Get-WinEvent -FilterHashtable @{logname='System'; id=1074} -ComputerName $c } } } $events | ForEach-Object{ $rv = New-Object PSObject | Select-Object Date, User, Action, Process, Reason, ReasonCode, Comment $rv.Date = $_.TimeCreated $rv.User = $_.Properties[6].Value $rv.Process = $_.Properties[0].Value # $rv.Action = $_.Properties[4].Value $rv.Action = $_.Properties[4].Value.substring(0,1).toupper() + $_.Properties[4].Value.substring(1).tolower() $rv.Reason = $_.Properties[2].Value $rv.ReasonCode = $_.Properties[3].Value $rv.Comment = $_.Properties[5].Value $rv } | Sort-Object -Property Date -Descending | Select-Object Date, Action, Reason, User | Format-Table } } #endregion #region Get-StartupApplications Function Get-StartupApplications { <# .SYNOPSIS Displays the list of applications that run on startup. .DESCRIPTION This function lists all applications that run on startup. .EXAMPLE Get-StartupApplications This command returns the list of applications that start on computer start. .EXAMPLE Get-StartupApplications -ComputerName client1 This command returns all applications that run when computer client1 starts. #> Param( [Parameter(ParameterSetName = "ComputerName", Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [string[]] $ComputerName, [system.management.automation.psCredential]$Credential ) Process { # Varible to hold the applications $apps = @() if( $ComputerName.Count -eq 0 ) { if($Credential) { $apps = Get-WmiObject Win32_startupcommand -Credential $Credential } else { $apps = Get-WmiObject Win32_startupcommand } } else { foreach( $c in $ComputerName) { if($Credential) { $apps += Get-WmiObject Win32_startupcommand -ComputerName $c -Credential $Credential } else { $apps += Get-WmiObject Win32_startupcommand -ComputerName $c } } } $apps | Sort-Object -Property Caption -Descending | Select-Object Caption, User, Command | Format-Table } } #endregion #region Get-UpTime Function Get-UpTime { <# .SYNOPSIS Displays the uptime for a system. .DESCRIPTION This function displays the uptime of a system. .EXAMPLE Get-UpTime This command displays the uptime of the system. .EXAMPLE Get-UpTime -ComputerName server1, server2 This command displays the uptime of server1 and server2. #> Param( [Parameter(ParameterSetName = "ComputerName", Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [Alias("Server","Name")] [string[]] $ComputerName, [system.management.automation.psCredential]$Credential ) Process { # Varible to hold timestamps $time = @() if( $ComputerName.Count -eq 0 ) { $wmi = New-Object PSObject if($Credential) { $wmi = Get-WmiObject -Class Win32_OperatingSystem -Credential $Credential } else { $wmi = Get-WmiObject -Class Win32_OperatingSystem } $time = New-Object -TypeName CPolydorou.General.UpTime $time.Name = $env:COMPUTERNAME $tmp += $wmi.ConvertToDateTime($wmi.LocalDateTime) – $wmi.ConvertToDateTime($wmi.LastBootUpTime) $time = New-Object -TypeName CPolydorou.General.UpTime $time.Name = $env:COMPUTERNAME $time.Days = $tmp.Days $time.Hours =$tmp.Hours $time.Minutes = $tmp.Minutes $time.Seconds = $tmp.Seconds $time.Milliseconds = $tmp.Milliseconds } else { foreach( $c in $ComputerName) { $wmi = New-Object PSObject if($Credential) { $wmi = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $c -Credential $Credential } else { $wmi = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $c } $tmp = $wmi.ConvertToDateTime($wmi.LocalDateTime) – $wmi.ConvertToDateTime($wmi.LastBootUpTime) $t = New-Object -TypeName CPolydorou.General.UpTime $t.Name = $c $t.Days = $tmp.Days $t.Hours =$tmp.Hours $t.Minutes = $tmp.Minutes $t.Seconds = $tmp.Seconds $t.Milliseconds = $tmp.Milliseconds $time += $t } } $time | Sort-Object -Property Name } } #endregion #region Get-RAMStatistics function Get-RAMStatistics { <# .Synopsis Gets information about RAM. .Example Get-RAMStatistics This example gets statistics about RAM on local computer. .Example Get-RAMStatistics -ComputerName server1,server2 -Credential $cred This example get statistics about RAM on computers server1 and server2 using the credentials saved on variable $cred using Get-Credential. .Description The Get-RAMStatistics cmdlet is used to get statistics about RAM Memory using WMI. That is the Total Physical Memory, the Free Physical Memory, the Total Virtual Memory and the Free Virtual Memory. .Parameter ComputerName The name of the computer to query. .Parameter Credential The credentials for the connection (if needed). #> Param( [Parameter(ParameterSetName = "ComputerName", Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [string[]] $ComputerName, [system.management.automation.psCredential]$Credential ) BEGIN{} PROCESS { $statistics = @() if( $ComputerName.Count -eq 0 ) { $info if($Credential) { $info = Get-WmiObject -Class Win32_OperatingSystem -Credential $Credential } else { $info = Get-WmiObject -Class Win32_OperatingSystem } $obj = New-Object PSObject $obj | Add-Member -MemberType NoteProperty -Name "Computer" -Value $env:COMPUTERNAME $obj | Add-Member -MemberType NoteProperty -Name "Total Physical Memory" -Value ( "{0:n0}" -f ($info.totalvisiblememorysize / 1KB)) $obj | Add-Member -MemberType NoteProperty -Name "Free Physical Memory" -Value ( "{0:n0}" -f ($info.freephysicalmemory / 1KB)) $obj | Add-Member -MemberType NoteProperty -Name "Total Virtual Memory" -Value ( "{0:n0}" -f ($info.totalvirtualmemorysize / 1KB)) $obj | Add-Member -MemberType NoteProperty -Name "Free Virtual Memory" -Value ( "{0:n0}" -f ($info.freevirtualmemory /1KB)) $statistics += $obj } else { foreach( $c in $ComputerName) { $info = New-Object PSObject if($Credential) { $info = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $c -Credential $Credential } else { $info = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $c } $obj = New-Object PSObject $obj | Add-Member -MemberType NoteProperty -Name "Computer" -Value $c $obj | Add-Member -MemberType NoteProperty -Name "Total Physical Memory" -Value ( "{0:n0}" -f ($info.totalvisiblememorysize / 1KB)) $obj | Add-Member -MemberType NoteProperty -Name "Free Physical Memory" -Value ( "{0:n0}" -f ($info.freephysicalmemory / 1KB)) $obj | Add-Member -MemberType NoteProperty -Name "Total Virtual Memory" -Value ( "{0:n0}" -f ($info.totalvirtualmemorysize / 1KB)) $obj | Add-Member -MemberType NoteProperty -Name "Free Virtual Memory" -Value ( "{0:n0}" -f ($info.freevirtualmemory /1KB)) $statistics = $statistics + $obj } } $statistics | Sort-Object -Property Computer -Descending | Format-Table } END{} } #endregion #region Get-ComputerDetails function Get-ComputerDetails { <# .Synopsis Gets information about operating system and bios. .Example Get-ComputerDetails This example gets information about local computer. .Example Get-ComputerDetails -ComputerName server1,server2 -Credential $cred This example gets information about computers server1 and server2 using the credentials saved on variable $cred using Get-Credential. .Description The Get-ComputerDetails cmdlet is used to get information about operating system and BIOS using WMI. .Parameter Credential The credentials used for the connection (if needed). .Parameter ComputerName The name of the computer to query #> Param( [Parameter(ParameterSetName = "ComputerName", Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [string[]] $ComputerName, [system.management.automation.psCredential]$Credential ) BEGIN{} PROCESS { $statistics = @() if( $ComputerName.Count -eq 0 ) { $os = New-Object PSObject $bios = New-Object PSObject if($Credential) { $os = Get-WmiObject -Class Win32_OperatingSystem -Credential $Credential $bios = get-wmiobject win32_bios -Credential $Credential } else { $os = Get-WmiObject -Class Win32_OperatingSystem $bios = get-wmiobject win32_bios } # create a new object $obj = new-object psobject # add properties - note that our capitalization # of the property names will be retained $obj | add-member noteproperty Computer $env:COMPUTERNAME $obj | add-member noteproperty BuildNumber ($os.buildnumber) $obj | add-member noteproperty OS ($os.caption) $obj | add-member noteproperty SPVersion ($os.servicepackmajorversion) $obj | add-member noteproperty OSArchitecture ($os.osarchitecture) $obj | add-member noteproperty BIOSSerial ($bios.serialnumber) $statistics += $obj } else { foreach( $c in $ComputerName) { $os = New-Object PSObject $bios = New-Object PSObject if($Credential) { $os = Get-WmiObject -Class Win32_OperatingSystem -Credential $Credential -ComputerName $c $bios = get-wmiobject win32_bios -Credential $Credential -ComputerName $c } else { $os = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $c $bios = get-wmiobject win32_bios -ComputerName $c } # create a new object $obj = new-object psobject # add properties - note that our capitalization # of the property names will be retained $obj | add-member noteproperty Computer $c $obj | add-member noteproperty BuildNumber ($os.buildnumber) $obj | add-member noteproperty OS ($os.caption) $obj | add-member noteproperty SPVersion ($os.servicepackmajorversion) $obj | Add-Member NoteProperty OSArchitecture ($os.osarchitecture) $obj | add-member noteproperty BIOSSerial ($bios.serialnumber) $statistics += $obj } } $statistics | Sort-Object -Property Computer -Descending | Format-Table } END{} } #endregion #region Get-SpecialFolder function Get-SpecialFolder { <# .Synopsis Gets information about the path of the user's special folders. .Example Get-SpecialFolder This example gets information about all special folders. .Example Get-SpecialFolder -Name Desktop This example gets information about the user's desktop folder. .Description The Get-SpecialFolder cmdlet is used to get information about the path of special folders. It is very usefull in order to test folder redirection. .Parameter Name The name of the computer to query #> Param( [Parameter(Mandatory = $false)] [string]$Name ) $SpecialFolders = @() $names = [Environment+SpecialFolder]::GetNames([Environment+SpecialFolder]) foreach($n in $names) { if($path = [Environment]::GetFolderPath($n)){ $obj = New-Object PSObject $obj | Add-Member -MemberType NoteProperty -Name Name -Value $n $obj | Add-Member -MemberType NoteProperty -Name Path -Value $path $SpecialFolders += $obj } } if( $Name.Length -gt 0 ) { $found = 0 foreach($s in $SpecialFolders) { if( $s.Name -eq $Name ) { $s $found = 1 break; } } if( $found -eq 0 ) { Write-Error "Could not find a special folder named $Name." } } else { $SpecialFolders } } #endregion #region Watch-Command function Watch-Command { <# .SYNOPSIS Watch the output of a command. .DESCRIPTION Watch-Command function executes a command or expression waits for a number of seconds and then runs it again. .PARAMETER Seconds The number of seconds between the concecutive runs. The default value is 5. .PARAMETER Command The command to run .EXAMPLE Watch-Command -Command {Get-ChildItem C:\} This command will display the contents of the c:\ folder every 5 seconds. .EXAMPLE Watch-Command -Command {Get-Content C:\file.log} -Seconds 10 This command will display the contents of the c:\file.log file every 10 seconds. #> param ( [Parameter(Mandatory=$True,Position=1)] [string]$Command, [Parameter(Mandatory=$False,Position=2)] [int]$Seconds = 5 ) Clear-Host Invoke-Expression $Command while ($true) { Clear-Host Invoke-Expression $Command Start-Sleep -Seconds $Seconds } } #endregion #region New-MessageBox Function New-MessageBox { <# .SYNOPSIS Create a message box. .DESCRIPTION The New-MessageBox cmdlet will create a new message box. .PARAMETER Title The title of the message box. .PARAMETER Message The message of the message box. .PARAMETER Type The type of the message box. .PARAMETER Icon The icon of the message box. .PARAMETER SecondsToWait The number of seconds that the messagebox will be active. .NOTES Return values 1: User selected OK 2: User selected Cancel #> # https://msdn.microsoft.com/en-us/library/x83z1d9f(v=vs.84).aspx Param ( [string]$Title, [string]$Message, [ValidateSet("OK", "OK-Cancel")] [string]$Type = "OK", [ValidateSet("Stop", "Exclamation", "Information")] [string]$Icon = "Information", [int]$SecondsToWait = 0 ) # Set the default variables $TypeCode = 0x0 $IconTypeCode = "0x10" # Create the shell instance $wshell = New-Object -ComObject Wscript.Shell # Check the message box type if( $Type -eq "OK" ) { $TypeCode = 0x0 } if( $Type -eq "OK-Cancel" ) { $TypeCode = 0x1 } if( $Type -eq "Abort-Retry-Ignore" ) { $TypeCode = 0x2 } if( $Type -eq "Yes-No-Cancel" ) { $TypeCode = 0x3 } if( $Type -eq "Yes-No" ) { $TypeCode = 0x4 } if( $Type -eq "Retry-Cancel" ) { $TypeCode = 0x5 } if( $Type -eq "Cancel-TryAgain-Continue" ) { $TypeCode = 0x6 } # Check the message box icon if( $Icon -eq "Stop" ) { $IconTypeCode = 0x10 } if( $Icon -eq "Question" ) { $IconTypeCode = 0x20 } if( $Icon -eq "Exclamation" ) { $IconTypeCode = 0x30 } if( $Icon -eq "Information" ) { $IconTypeCode = 0x40 } # Display the message box $retval = $wshell.Popup($Message,0,$Title,$TypeCode) # $wshell.Popup($Message,$SecondsToWait,$Title,$TypeCode) return $retval } #endregion #region Set-UserDefinedVariables Function Set-UserDefinedVariables { <# .SYNOPSIS Set the current session variables as user defined. .DESCRIPTION The Set-UserDefinedVariables cmdlet will set the variables in the current session as user defined in order for Clear-UserDefinedVariables to not remove them. .NOTES This cmdlet uses the __UserDefinedVariables variable. #> try { $currentVariables = Get-Variable | % Name $currentVariables += "__UserDefinedVariables" New-Variable -Force -Name __UserDefinedVariables -Value $currentVariables -Scope Global -ErrorAction Stop } catch { Write-Error "Failed to set the variables!" } } #endregion #region Get-UseDefinedVariables Function Get-UserDefinedVariables { <# .SYNOPSIS Get the current user defined variables. .DESCRIPTION The Get-UserDefinedVariables cmdlet will return all the variables that have been set as user defined by Set-UserDefinedVariables. .NOTES This cmdlet uses the __UserDefinedVariables variable. #> try { Get-Variable -Name "__UserDefinedVariables" -Scope Global -ErrorAction Stop | Out-Null } catch { Write-Error "User Defined Variables have not been set." return } Get-Variable | Where-Object {$_.Name -notin $__UserDefinedVariables} } #endregion #region Remove-UserDefinedVariables Function Remove-UserDefinedVariables { <# .SYNOPSIS Remove variables that have not been set. .DESCRIPTION The Remove-UserDefinedVariables will remove all variables in current session that have not been set with Set-UserDefinedVariables. .NOTES This cmdlet uses the __UserDefinedVariables variable. #> [cmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='Medium')] Param() try { Get-Variable -Name "__UserDefinedVariables" -Scope Global -ErrorAction Stop | Out-Null } catch { Write-Error "User Defined Variables have not been set." return } if ($pscmdlet.ShouldProcess("Clear-UserDefinedVariables")) { Get-Variable -Scope Global | % { if($__UserDefinedVariables -notcontains $_.Name) { Write-Verbose ("Removing variable: " + $_.Name) Remove-Variable $_.Name -Scope Global -Force } } } } #endregion #region Clear-UserDefinedVariables Function Clear-UserDefinedVariables { <# .SYNOPSIS Clear variables that have not been set. .DESCRIPTION The Clear-UserDefinedVariables will clear all variables in current session that have not been set with Set-UserDefinedVariables. .NOTES This cmdlet uses the __UserDefinedVariables variable. #> [cmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='Medium')] Param() try { Get-Variable -Name "__UserDefinedVariables" -Scope Global -ErrorAction Stop | Out-Null } catch { Write-Error "User Defined Variables have not been set." return } if ($pscmdlet.ShouldProcess("Clear-UserDefinedVariables")) { Get-Variable -Scope Global | % { if($__UserDefinedVariables -notcontains $_.Name) { Write-Verbose ("Clearing variable: " + $_.Name) Clear-Variable $_.Name -Scope Global -Force } } } } #endregion #region Get-BootTime Function Get-BootTime { <# .SYNOPSIS Displays the last time a system booted. .DESCRIPTION This function displays the last time a system booted. .EXAMPLE Get-BootTime This command displays the time when the local system last booted. .EXAMPLE Get-UpTime -ComputerName server1, server2 This command displays last time that the systems server1 and server2 booted. #> Param ( [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position=0)] [string[]] $ComputerName = $env:COMPUTERNAME, [Parameter(Mandatory = $false, Position=1)] [system.management.automation.psCredential]$Credential ) Begin{} Process { foreach( $c in $ComputerName) { if($Credential) { Get-WmiObject win32_operatingsystem -Credential $Credential -ComputerName $c | Select-Object @{Name="ComputerName"; Expression={$_.csname}}, @{Name=’BootTime’; Expression={$_.ConverttoDateTime($_.lastbootuptime)}} } else { Get-WmiObject win32_operatingsystem -ComputerName $c | Select-Object @{Name="ComputerName"; Expression={$_.csname}}, @{Name=’BootTime’; Expression={$_.ConverttoDateTime($_.lastbootuptime)}} } } } End{} } #endregion #region Get-ActivationStatus function Get-ActivationStatus { <# .SYNOPSIS Get the activation status for a computer. .DESCRIPTION The Get-ActivationStatus function will get the windows activation status for a computer. .PARAMETER ComputerName The name of the computer. If not specified, the name of the local computer is used. .EXAMPLE Get-ActivationStatus This command will get the activation status of the local computer .EXAMPLE Get-ActivationStatus -ComputerName Server1 This command will get the activation status of Server1 computer .INPUTS ComputerName: String Name: String #> [CmdletBinding()] param ( [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [string[]]$ComputerName = $Env:COMPUTERNAME ) Begin {} Process { foreach($c in $ComputerName) { try { $wpa = Get-WmiObject SoftwareLicensingProduct -ComputerName $c -Filter "ApplicationID = '55c92734-d682-4d71-983e-d6ec3f16059f'" -Property LicenseStatus -ErrorAction Stop } catch { $status = New-Object ComponentModel.Win32Exception ($_.Exception.ErrorCode) $wpa = $null } $out = New-Object psobject -Property @{ ComputerName = $c; Status = [string]::Empty; } if($wpa) { :outer foreach($item in $wpa) { switch ($item.LicenseStatus) { 0 {$out.Status = "Unlicensed"} 1 {$out.Status = "Licensed"; break outer} 2 {$out.Status = "Out-Of-Box Grace Period"; break outer} 3 {$out.Status = "Out-Of-Tolerance Grace Period"; break outer} 4 {$out.Status = "Non-Genuine Grace Period"; break outer} 5 {$out.Status = "Notification"; break outer} 6 {$out.Status = "Extended Grace"; break outer} default {$out.Status = "Unknown value"} } } Write-Output $out } else { $out.Status = $status.Message Write-Error $out } } } } #endregion #region Pause-Execution Function Pause-Execution { <# .SYNOPSIS Pause the execution until a key is pressed. .DESCRIPTION The Pause-Execution function will suspend the execution of a script until a key is pressed. .PARAMETER Message The message to display. .EXAMPLE Pause-Execution .EXAMPLE Pause-Execution -Message "Press any key to resume execution..." .NOTES Since the [Console]::Readkey is not implemented in Powershell ISE, when this function is called under ISE it will create a message box instead. #> Param ( [string]$Message = "Press any key to continue... " ) If ($psISE) { # The "ReadKey" functionality is not supported in Windows PowerShell ISE. $Shell = New-Object -ComObject "WScript.Shell" $Button = $Shell.Popup($Message, 0, "Execution Paused", 0) Return } Write-Host -NoNewline $Message $Ignore = 16, # Shift (left or right) 17, # Ctrl (left or right) 18, # Alt (left or right) 20, # Caps lock 91, # Windows key (left) 92, # Windows key (right) 93, # Menu key 144, # Num lock 145, # Scroll lock 166, # Back 167, # Forward 168, # Refresh 169, # Stop 170, # Search 171, # Favorites 172, # Start/Home 173, # Mute 174, # Volume Down 175, # Volume Up 176, # Next Track 177, # Previous Track 178, # Stop Media 179, # Play 180, # Mail 181, # Select Media 182, # Application 1 183 # Application 2 While ($KeyInfo.VirtualKeyCode -Eq $Null -Or $Ignore -Contains $KeyInfo.VirtualKeyCode) { $KeyInfo = $Host.UI.RawUI.ReadKey("NoEcho, IncludeKeyDown") } Write-Host } #endregion #region Get-LoggedOnUser Function Get-LoggedOnUser { <# .SYNOPSIS Get the user sessions on a computer .DESCRIPTION The Get-LoggedOnUser will get all the user sessions from a computer including RDP sessions and disconnected sessions. .PARAMETER ComputerName The name of the computer to query. .EXAMPLE Get-LoggedOnUser -ComputerName server1 This command will get the users connected to server named server1 #> [cmdletBinding()] Param ( [Parameter(Mandatory=$false, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [Alias("Name")] [string[]]$ComputerName = $env:COMPUTERNAME ) foreach($c in $ComputerName) { # query the computer for the sessions Write-Verbose "Getting sessions from computer $c..." $sessioninfo = query user /server:$c # parse sessions for($i=1; $i -lt $sessioninfo.Count; $i++) { # Split the output $columns = $sessioninfo[$i].Split(" ") # Remove empty lines $columns = $columns | Where-Object { $_.Trim().Length -gt 0} $tmp = 0 if($columns.count -eq 8) # there is no session name { $tmp = 1 } # Create the custom object and populate the values $session = New-Object CPolydorou.General.LoggedOnUser $session.Username = $columns[0] $session.SessionID = $columns[$tmp + 1] if($columns.Count -eq 8) { $session.SessionName = $columns[1] } $session.SessionState = $columns[$tmp + 2] if($columns[$tmp + 3] -eq ".") { $session.SessionIdleTime = New-Object -TypeName System.TimeSpan -ArgumentList ("0","0","0") } else { $days = 0 $hours = 0 $minutes = 0 if($columns[$tmp + 3] -like "*+*") { $days = $columns[$tmp + 3].Split("+")[0] $tmpvar = $columns[$tmp + 3].Split("+")[1] $hours = $tmpvar.Split(":")[0] $minutes = $tmpvar.Split(":")[1] } else { $hours = $columns[$tmp + 3].Split(":")[0] $minutes = $columns[$tmp + 3].Split(":")[1] } $session.SessionIdleTime = New-Object -TypeName System.TimeSpan -ArgumentList ($days, $hours, $minutes, 0) } $session.LogonTime = [DateTime]($columns[$tmp + 4] + " " + $columns[$tmp + 5] + " " + $columns[$tmp + 6]) $session } } } #endregion #region Disconnect-LoggedOnUser Function Disconnect-LoggedOnUser { <# .SYNOPSIS Disconnect a user sessions from a computer .DESCRIPTION The Disconnect-LoggedOnUser will get disconnect user session from a computer. .PARAMETER ComputerName The name of the computer to query. .PARAMETER SessionID The ID of the session to disconnect. .EXAMPLE Disconnect-LoggedOnUser -ComputerName server1 -SessionID 1 This command will get the users connected to server named server1 .EXAMPLE Get-LoggedOnUser | Where-Object {$_.Username -eq "admin"} | Disconnect-LoggedOnUser This command will disconnect the session of the user admin on server server1 #> [cmdletBinding()] Param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] $SessionID, [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] $ComputerName ) # Get the session from the remote computer Write-Verbose "Getting sessions on computer $ComputerName..." $session = Get-LoggedOnUser -ComputerName $ComputerName | Where-Object {$_.SessionID -eq $SessionID} if($session) { Write-Verbose "Signing out session $SessionID on computer $ComputerName..." rwinsta $SessionID /server:$ComputerName } else { Write-Error "Could not find a session with identity $SessionID on computer $ComputerName." } } #endregion #region Send-Email Function Send-Email { <# .SYNOPSIS Send an email message. .DESCRIPTION The Send-Email message function will send an email message. .PARAMETER From The "From" address. .PARAMETER To The "To" addresses. .PARAMETER Subject The subject of the message. .PARAMETER Body The body of the message. .PARAMETER From The "From" address. .PARAMETER BodyFormat The format of the body. .PARAMETER Attachment The path to the files to be attached. .PARAMETER CC The "CC" addresses. .PARAMETER BCC The "BCC" addresses. .PARAMETER SMTPServer The SMTP server to use. .PARAMETER Port The port of the SMTP server. .PARAMETER UseSSL Enable SSL when connecting to the server. .EXAMPLE Send-Email -From "someone@somedomain.com" -To "someone@anotherdomain.com" -Subject "Test Message" -Body "This is a test message." -SMTPServer myserver.domain.com -Port 25 #> [cmdletBinding()] Param ( [Parameter( Mandatory = $true )] [string]$From, [Parameter( Mandatory = $true )] [string[]]$To, [Parameter( Mandatory = $false )] [string]$Subject, [Parameter( Mandatory = $false )] [string]$Body, [Parameter( Mandatory = $false )] [ValidateSet('HTML', 'PlainText')] [string]$BodyFormat, [Parameter( Mandatory = $false )] [string[]]$Attachement, [Parameter( Mandatory = $false )] [string[]]$CC, [Parameter( Mandatory = $false )] [string[]]$BCC, [Parameter( Mandatory = $false )] [string]$SMTPServer = $env:COMPUTERNAME, [Parameter( Mandatory = $false )] [string]$Port = 25, [Parameter( Mandatory = $false )] [switch]$UseSSL, [Parameter( Mandatory = $false )] [System.Management.Automation.PSCredential]$Credential ) # Create the message Write-Verbose "Creating message object..." $message = new-object Net.Mail.MailMessage # Set the from address Write-Verbose "Setting the from field..." $message.From = $From # Add the "To" recipients foreach($t in $To) { Write-Verbose "Adding recipient $t..." $message.To.Add($t) } # Set the subject Write-Verbose "Setting the message subject..." $message.Subject = $Subject # Set the body if( $BodyFormat -eq "HTML") { Write-Verbose "Setting body format to HTML..." $message.IsBodyHtml = $true } # Set the body Write-Verbose "Setting the message body..." $message.Body = $Body # Add the attachements $attachmentObjects = @() foreach($a in $Attachement) { if( (Test-Path $a) -ne $true ) { Write-Error "Could not locate attachement $a" return } else { $p = Resolve-Path $a $attachmentObjects += New-Object Net.Mail.Attachment($p); } } foreach($a in $attachmentObjects) { Write-Verbose ("Adding attachment " + $a.Name) $message.Attachments.Add($a); } # Create the smpt client Write-Verbose "Creating SMTP Client..." $smtpClient = new-object Net.Mail.SmtpClient($SMTPServer, $Port); # Set the SSL settings if($UseSSL) { Write-Verbose "Enabling SSL..." $smtpClient.EnableSSL = $true } if($Credential) { Write-Verbose "Using credentials..." $smtpClient.Credentials = New-Object System.Net.NetworkCredential($Credential.GetNetworkCredential().Username, $Credential.GetNetworkCredential().Password); } try { $smtpClient.send($message); Write-Verbose "Message sent." } catch { Write-Verbose "Failed to send message." Write-Error $Error[0].Exception } # Dispose the attachements foreach($a in $attachmentObjects) { Write-Verbose ("Disposing attachement " + $a.name) $a.Dispose(); } } #endregion #region Invoke-Script Function Invoke-Script { <# .SYNOPSIS Execute a local script on a remote computer. .DESCRIPTION This function will execute a script saved on the local computer to a remote computer. .PARAMETER computername Here, the dotted keyword is followed by a single parameter name. Don't precede that with a hyphen. The following lines describe the purpose of the parameter: .PARAMETER Computername The name of the remote computer. .EXAMPLE Invoke-Script -Computername Server1 -Path .\Test.ps1 This command will execute the script Test.ps1 from the currently working directory on the server Server1 .EXAMPLE $Servers = @("Server1","Server2") $firstScriptParameter = @("10.0.0.1","10.0.0.2") $secondScriptParameter = "192.168.0.1" $parameters = @($firstScriptParameter, $secondScriptParameter) Invoke-Script -Computername $Servers -Path .\Test.ps1 -Parameters $parameters This command will execute the script Test.ps1 from the currently working directory on the servers Server1 and Server2. Two parameters were passed to the script. The first one is an array of strings and the second one a single string. This is how you can adopt the parameters on the script to the parameters needed on your script. #> [cmdletBinding()] Param ( [Parameter(Position=0, Mandatory=$false, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [Alias("Server")] [string[]]$Computername, [Parameter(Position=1, Mandatory=$false)] [string]$Path, [Parameter(Position=2, Mandatory=$false)] [array]$Parameters ) Begin { # Test path if( (Test-Path $Path) -ne $true) { Throw "Could not open the script file." } } Process { # Create a script block using the contents of the file Write-Verbose "Reading script file." $script = Get-Content $Path -Raw $sb = [Scriptblock]::Create($script) # Process each server in the Computername array Foreach($s in $Computername) { # Invoke the command on the remote server Write-Verbose ("Invoking script on computer " + $s) Invoke-Command -ComputerName $s -ScriptBlock $sb -ArgumentList ($Parameters) } } End {} } #endregion #region Get-NETFrameworkVersion function Get-NETFrameworkVersion { <# .Synopsis List the installed .NET Framework versions. .DESCRIPTION List the installed .NET Framework versions. .NOTES https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed #> [CmdletBinding()] Param ( # The name of the computer to check [Parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true, Position=0)] $ComputerName ) Begin { #region Define the version table $Versions = @{ 378389 = ".NET Framework 4.5" 378675 = ".NET Framework 4.5.1 installed with Windows 8.1" 378758 = ".NET Framework 4.5.1 installed on Windows 8, Windows 7 SP1, or Windows Vista SP2" 379893 = ".NET Framework 4.5.2" 393295 = ".NET Framework 4.6 installed with Windows 10" 393297 = ".NET Framework 4.6 installed on all other Windows OS versions other than 10" 394254 = ".NET Framework 4.6.1 installed on Windows 10" 394271 = ".NET Framework 4.6.1 installed on all other Windows OS versions other than 10" 394802 = ".NET Framework 4.6.2 installed on Windows 10 Anniversary Update" 394806 = ".NET Framework 4.6.2 installed on all other Windows OS versions other than 10 Anniversary Update" 460798 = ".NET Framework 4.7 installed on Windows 10 Creators Update" 460805 = ".NET Framework 4.7 installed on all other Windows OS versions other than 10 Creators Update" 461308 = ".NET Framework 4.7.1 installed on Windows 10 Creators Update" 461310 = ".NET Framework 4.7.1 installed on all other Windows OS versions other than 10 Creators Update" 461808 = ".NET Framework 4.7.2 installed on Windows 10 April 2018 Update" 461814 = ".NET Framework 4.7.2 installed on all other Windows OS versions other than Windows 10 April 2018 Update" } #endregion } Process { if($ComputerName) { # Use remote registry and connect to the remote computers foreach($c in $ComputerName) { #region Open Remote Registry try { $Registry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $c) } catch { Throw $_ } $RootKey = $Registry.OpenSubKey("SOFTWARE\\Microsoft\\Net Framework Setup\\NDP") #endregion #region Process the keys $keys = $RootKey.GetSubKeyNames() | Where-Object {$_ -like "v*"} # Loop through the keys foreach($k in $keys) { # Check for the "Version" property of older .Net versions (prior to 4) $versionKey = $RootKey.OpenSubKey($k) if($k -like "v4*") { # Handle v4 setup foreach($tk in $versionKey.GetSubKeyNames()) { $typeSubKey = $versionKey.OpenSubKey($tk) $version = $typeSubKey.GetValue("Version") $release = $typeSubKey.GetValue("Release") $type = $tk if($release -ne $null) { $descriptionKey = $Versions.Keys | Where-Object {$_ -eq $release} $description = $Versions.$descriptionKey } else { $release = "N/A" $description = "N/A" } $props = [ordered]@{ Version = $version Release = $release Type = $type Description = $description } New-Object -TypeName PSObject -Property $props } } else { # Handle older .Net versioning try { $version = $versionKey.GetValue("Version") $release = "N/A" $type = "N/A" $description = "N/A" $props = [ordered]@{ Version = $version Release = $release Type = $type Description = $description } New-Object -TypeName PSObject -Property $props } catch { } } } } } else { # Use the local PowerShell registry provider $keys = Get-ChildItem -Path 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' | Where-Object {$_.PSChildName -like "v*"} # Loop through the keys foreach($k in $keys) { # Examine the subkeys if($k.PSChildName -like "v4*") { $subKeys = Get-ChildItem -Path $k.PSPath foreach($sk in $subKeys) { $type = $sk.PSChildName try { $version = (Get-ItemProperty -Path $sk.PSPath -Name Version -ErrorAction Stop).Version } catch { $version = "N/A" } try { $release = (Get-ItemProperty -Path $sk.PSPath -Name Release -ErrorAction Stop).Release $description = $Versions.$release } catch { $release = "N/A" $description = "N/A" } $props = [ordered]@{ Version = $version Release = $release Type = $type Description = $description } New-Object -TypeName PSObject -Property $props } } else { try { $version = (Get-ItemProperty -Path $k.PSPath -Name Version -ErrorAction Stop).Version } catch {} try { $release = (Get-ItemProperty -Path $k.PSPath -Name Release -ErrorAction Stop).Release } catch { $release = "N/A" $description = "N/A" } $props = [ordered]@{ Version = $version Release = $release Type = "N/A" Description = $description } New-Object -TypeName PSObject -Property $props } } } } End {} } #endregion #endregion #region Remove-Duplicate function Remove-Duplicate { <# .Synopsis Remove duplicate objects from collections .DESCRIPTION Remove duplicate objects from collections by comparing the values of all or a subset of their properties .EXAMPLE Remove the duplicate objects in the "data" variable by comparing all their properties. PS C:\> $data Property1 Property2 Property3 --------- --------- --------- a a b 1 2 3 1 1 1 1 1 1 1 a b PS C:\> $data | Remove-Duplicate Property1 Property2 Property3 --------- --------- --------- a a b 1 2 3 1 1 1 1 a b .EXAMPLE Remove the duplicate objects in the "data" variable by comparing the "Property1" property. PS C:\> $data Property1 Property2 Property3 --------- --------- --------- a a b 1 2 3 1 1 1 1 1 1 1 a b PS C:\> $data | Remove-Duplicate -Property Property1 Property1 Property2 Property3 --------- --------- --------- a a b 1 2 3 .EXAMPLE Remove the duplicate objects in the "data" variable by comparing the "Property2" and "Property3" properties. PS C:\> $data Property1 Property2 Property3 --------- --------- --------- a a b 1 2 3 1 1 1 1 1 1 1 a b PS C:\> $data | Remove-Duplicate -Property Property2,Property3 Property1 Property2 Property3 --------- --------- --------- a a b 1 2 3 1 1 1 .EXAMPLE Remove the duplicate objects in the "data" variable without using the pipeline. PS C:\> $data Property1 Property2 Property3 --------- --------- --------- a a b 1 2 3 1 1 1 1 1 1 1 a b PS C:\> Remove-Duplicate -InputObject $data Property1 Property2 Property3 --------- --------- --------- a a b 1 2 3 1 1 1 1 a b #> [CmdletBinding(PositionalBinding=$false)] Param ( # The input objects [Parameter(Mandatory=$false, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Position=0)] $InputObject, # The properties to compare [Parameter(Mandatory=$false, Position=1)] [string[]] $Property ) #region Begin Begin { # Create the array to hold the objects already # sent to the output stream $output = New-Object -TypeName System.Collections.ArrayList } #endregion #region Process Process { #region Process the input foreach($i in $InputObject) { $alreadySent = 0 #region Properties have been specified if($Property) { #region Create the filter script $sb = "" foreach($p in $Property) { if($sb.Length -ne 0) { $sb += " -and " } $sb += '$_.' + "'" + $p + "'" + ' -eq ' + '$i.' + $p } $filterScript = [scriptblock]::Create($sb) #endregion #region Apply the filter to get objects already sent to output $result = @($output | Where-Object -FilterScript $filterScript ) if($result.Count -gt 0) { $alreadySent++ } #endregion } #endregion #region Comparing all properties else { #region Check if the object has been sent to the output stream already # Compare the object with all the objects in the collection foreach($o in $output) { if(Compare-ObjectByProperty -ReferenceObject $i -DifferenceObject $o) { $alreadySent++ break } } #endregion } #endregion #region If the object has not been sent, save it and send it if($alreadySent -eq 0) { $output.Add($i) | Out-Null $i } #endregion } #endregion } #endregion #region End End { } #endregion } #endregion #region Compare-ObjectByProperty function Compare-ObjectByProperty { <# .Synopsis Compare two objects using their properties. .DESCRIPTION Test if two objects are identical using the values of their properties. .EXAMPLE PS C:\> $data The objects 2 and 3 of the below array are identical, yet the -eq operator returns $false. The Compare-ObjectByProperty function will compare the values of the properties of the objects instead of comparing the entire objects. Property1 Property2 Property3 --------- --------- --------- a a b 1 2 3 1 1 1 1 1 1 1 a b PS C:\> $data[2] -eq $data[3] False PS C:\> Compare-ObjectByProperty -ReferenceObject $data[2] -DifferenceObject $data[3] True #> [cmdletBinding()] param( [Parameter(Mandatory=$true)] [PSCustomObject] $ReferenceObject, [Parameter(Mandatory=$true)] [PSCustomObject] $DifferenceObject ) -not (Compare-Object $ReferenceObject.PSObject.Properties $DifferenceObject.PSObject.Properties) } #endregion #region Get-PendingReboot Function Get-PendingReboot { #region Parameters [CmdletBinding()] Param( [Parameter(Mandatory = $false, Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true )] [Alias("Server", "Name")] [string[]] $ComputerName = $env:COMPUTERNAME ) #endregion #region Begin Begin {} #endregion #region Process Process { Foreach ($c in $ComputerName) { Write-Verbose "Processing computer $c..." #region Initialize variables $PendingComputerRename = $false # There is a pending computer rename $PendingFileRename = $false # There are pending file rename operations $PendingFileRenameOperations = $null # The pending file rename operations $PendingWindowsUpdate = $false # There are pending Windows Update operations $PendingSCCM = $false # System Center Configuration Manager client is installed $PendingCBS = $false # Check if there is a pending reboot from Component Based Servicing #endregion #region Connect to the registry provider Write-Verbose "Connecting to the registry WMI provider..." try { $WMIRegistry = [WMIClass] "\\$c\root\default:StdRegProv" $HKLM = [UInt32] "0x80000002" } catch { Write-Error "Could not connect to the registry WMI provider of $c." return } #endregion #region Check for pending computer rename operation Write-Verbose "Checking for pending computer rename..." try { # Get the active computer name $ActiveComputerName = $WMIRegistry.GetStringValue($HKLM,"SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName\","ComputerName").sValue # Get the computer name $ComputerName = $WMIRegistry.GetStringValue($HKLM,"SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName\","ComputerName").sValue # Check if a rename is pending if($ActiveComputerName -ne $ComputerName) { $PendingComputerRename = $true } } catch { Write-Error "Could not connect to the registy of $c. $_" return } #endregion #region Windows Update Write-Verbose "Checking for pending Windows Update reboot..." try { # Get the registry key $WURegistryKey = $WMIRegistry.EnumKey($HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\") # Check if windows update requires restart $PendingWindowsUpdate = $WURegistryKey.sNames -contains "RebootRequired" } catch { Write-Error "Could not connect to the registry of $c. $_" return } #endregion #region Check Pending File Rename Write-Verbose "Checking for pending file rename operations..." try { # Get the registry key $PendingFileRenameKey = $WMIRegistry.GetMultiStringValue($HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\","PendingFileRenameOperations") # Check if operations are pending if($PendingFileRenameKey.sValue) { $PendingFileRename = $true $PendingFileRenameOperations = $PendingFileRenameKey.sValue | Where-Object {$_.Length -gt 0} | Select-Object -Unique } } catch { Write-Error "Could not connect to the registry of $c. $_" return } #endregion #region Check for Component Based Servicing Write-Verbose "Checking for Component Based Servicing reboot..." try { # Get the OS version $WMI_OS = Get-WmiObject -Class Win32_OperatingSystem -Property BuildNumber, CSName -ComputerName $c -ErrorAction Stop if ([Int32]$WMI_OS.BuildNumber -ge 6001) { $CBSKey = $WMIRegistry.EnumKey($HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\") $PendingCBS = $CBSKey.sNames -contains "RebootPending" } } catch { Write-Error "Could not connect to the registry of $c. $_" return } #endregion #region Check for SCCM Write-Verbose "Checking for SCCM client reboot..." try { # Connect to the WMI namespace $SCCMSDK = [wmiclass]"\\$c\root\ccm\ClientSDK:CCM_ClientUtilities" $PendingSCCM = ($reboot.DetermineIfRebootPending()).RebootPending } catch { # Check if the service exists try { $WMIService = Get-WmiObject win32_service -Property Name, State -ComputerName $c -ErrorAction Stop | Where-Object {$_.Name -eq "CcmExec"} if($WMIService) { # The service exists, check its state if($WMIService.State -ne "Running") { Write-Warning "The SCCM service is not running." } } } catch { # The service does not exist, do nothing } } #endregion #region Create a custom object $properties = [ordered]@{ ComputerName = $c PendingReboot = ($PendingComputerRename -or $PendingFileRename -or $PendingWindowsUpdate -or $PendingSCCM -or $PendingCBS) PendingComputerRename = $PendingComputerRename PendingWindowsUpdate = $PendingWindowsUpdate PendingSCCM = $PendingSCCM PendingCBS = $PendingCBS PendingFileRename = $PendingFileRename PendingFileRenameOperations = $PendingFileRenameOperations } New-Object -TypeName PSObject -Property $properties #endregion } } #endregion #region End End {} #endregion } #endregion #region Display-DirectoryTree function Display-DirectoryTree { #region Parameters [cmdletBinding()] Param ( [Parameter( Mandatory = $false )] [string] $Path = (Get-Location).Path, [Parameter( Mandatory = $false )] [switch] $IncludeType, [Parameter( Mandatory = $false )] [string] $Indentation = "`t", [Parameter( Mandatory = $false )] [int] $MaxDepth = [int]::MaxValue ) #endregion #region Begin Begin { #region Recursive function Function _RecursiveDisplayTree { Param ( $RecursivePath, $Depth, $IncludeItemType, $IndentationString, $MaximumDepth ) # Check the current depth if($Depth -ge $MaximumDepth) { Write-Verbose "Maximum depth $MaximumDepth was reached." return } # Get the files Get-ChildItem -Path $RecursivePath -File -Force | %{ if($IncludeItemType -eq $true) { ($IndentationString * $Depth) + "[F] " + $_.Name } else { ($IndentationString * $Depth) + $_.Name } } # Process directories Get-ChildItem -Path $RecursivePath -Directory -Force | %{ if($IncludeItemType -eq $true) { ($IndentationString * $Depth) + "[D] " + $_.Name } else { ($IndentationString * $Depth) + $_.Name } _RecursiveDisplayTree -RecursivePath $_.FullName ` -Depth ($Depth + 1) ` -IncludeItemType $IncludeItemType ` -IndentationString $IndentationString ` -MaximumDepth $MaximumDepth } } #endregion } #endregion #region Process Process { if( (Test-Path -Path $Path) -ne $true) { Write-Error "Could not find folder $Path" } else { $fullPath = Resolve-Path -Path $Path _RecursiveDisplayTree -RecursivePath $fullPath.Path ` -Depth 0 ` -IncludeItemType ($MyInvocation.BoundParameters["IncludeType"].IsPresent -eq $true) ` -IndentationString $Indentation ` -MaximumDepth $MaxDepth } } #endregion #region End End {} #endregion } #endregion #region Send-SyslogMessage function Send-SyslogMessage { #region Parameters [CmdletBinding(PositionalBinding=$false, ConfirmImpact='Medium')] [Alias()] [OutputType([String])] Param ( # The message to send [Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, ValueFromRemainingArguments=$false)] [ValidateNotNullOrEmpty()] [String[]] $Message, # The syslog server hostname/IP [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $Server, # The severity of the event [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [ValidateSet("Emergency", "Alert", "Critical", "Error", "Warning", "Notice", "Information", "Debug")] [String] $Severity, # The facility of the event [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [ValidateSet("Kern", "User", "Mail", "Daemon", "Auth", "Syslog", "LPR", "News", "UUCP", "Cron", "AuthPriv", "FTP", "NTP", "Security", "Console", "Solaris-Chron", "Local0", "Local1", "Local2", "Local3", "Local4", "Local5", "Local6", "Local7")] [String] $Facility, # The host name [Parameter(Mandatory=$false)] [String] $Hostname = $env:COMPUTERNAME, # The application name [Parameter(Mandatory=$false)] [String] $Application = "PowerShell", # The protocol to use [Parameter(Mandatory=$false)] [ValidateSet("UDP", "TCP")] [string] $Protocol = "UDP", # The syslog server port [Parameter(Mandatory=$false)] [ValidateNotNullOrEmpty()] [int] $Port = 514 ) #endregion #region Begin Begin { } #endregion #region Process Process { # Process the facility [int]$FacilityInt = -1 switch ($Facility) { 'Kern' {$FacilityInt = 0} 'User' {$FacilityInt = 1} 'Mail' {$FacilityInt = 2} 'Daemon' {$FacilityInt = 3} 'Auth' {$FacilityInt = 4} 'Syslog' {$FacilityInt = 5} 'LPR' {$FacilityInt = 6} 'News' {$FacilityInt = 7} 'UUCP' {$FacilityInt = 8} 'Cron' {$FacilityInt = 9} 'AuthPriv' {$FacilityInt = 10} 'FTP' {$FacilityInt = 11} 'NTP' {$FacilityInt = 12} 'Security' {$FacilityInt = 13} 'Console' {$FacilityInt = 14} 'Solaris-Chron' {$FacilityInt = 15} 'Local0' {$FacilityInt = 16} 'Local1' {$FacilityInt = 17} 'Local2' {$FacilityInt = 18} 'Local3' {$FacilityInt = 19} 'Local4' {$FacilityInt = 20} 'Local5' {$FacilityInt = 21} 'Local6' {$FacilityInt = 22} 'Local7' {$FacilityInt = 23} Default {} } # Process the severity [int]$SeverityInt = -1 switch ($Severity) { 'Emergency' {$SeverityInt = 0} 'Alert' {$SeverityInt = 1} 'Critical' {$SeverityInt = 2} 'Error' {$SeverityInt = 3} 'Warning' {$SeverityInt = 4} 'Notice' {$SeverityInt = 5} 'Information' {$SeverityInt = 6} 'Debug' {$SeverityInt = 7} Default {} } # Calculate the priority of the message $Priority = ($FacilityInt * 8) + [int]$SeverityInt # Get the timestamp in a syslog format # Create a locale object $LocaleEN = New-Object System.Globalization.CultureInfo("en-US") #$Timestamp = Get-Date -Format "MMM dd HH:mm:ss" # $Timestamp = (Get-Culture).TextInfo.ToTitleCase([DateTime]::Now.ToString('MMM dd HH:mm:ss', $LocaleEN)) # $Timestamp = (Get-Culture).TextInfo.ToTitleCase([DateTime]::Now.ToString('o', $LocaleEN)) $Timestamp = (Get-Date).ToUniversalTime().ToString("o") foreach($m in $Message) { # Format the syslog message $syslogMessage = "<{0}>{1} {2} {3} {4}" -f $Priority, $Timestamp, $Hostname, $Application, $m Write-Verbose ("Sending message: " + $syslogMessage) # Create an encoding object to encode to ASCII $Encoder = [System.Text.Encoding]::ASCII # Convert the message to byte array try { Write-Verbose "Encoding the message." $syslogMessageBytes= $Encoder.GetBytes($syslogMessage) } catch { Write-Error "Failed to encode the message to ASCII." continue } # Send the Message if($Protocol -eq "UDP") { Write-Verbose "Sending using UDP." # Create the UDP Client object $UDPCLient = New-Object System.Net.Sockets.UdpClient $UDPCLient.Connect($Server, $Port) # Send the message try { $UDPCLient.Send($syslogMessageBytes, $syslogMessageBytes.Length) | Out-Null Write-Verbose "Message sent." } catch { Write-Error ("Failed to send the message. " + $_.Exception.Message) continue } } else { Write-Verbose "Sending using TCP." # Send the message via TCP try { # Create a TCP socket object $socket = New-Object System.Net.Sockets.TcpClient($Server, $Port) # Write the message in the stream $stream = $socket.GetStream() $stream.Write($syslogMessageBytes, 0, $syslogMessageBytes.Length) # Flush and close the stream $stream.Flush() $stream.Close() Write-Verbose "Message sent." } catch { Write-Error ("Failed to send the message. " + $_.Exception.Message) continue } } } } #endregion #region End End { } #endregion } #endregion #endregion #region Exports Export-ModuleMember -Function ForEach-Object-Parallel Export-ModuleMember -Function Get-ConsoleUser Export-ModuleMember -Function Test-IsAdmin Export-ModuleMember -Function Download-WinSCP Export-ModuleMember -Function Get-PrinterLegacy Export-ModuleMember -Function Get-PowerEvent Export-ModuleMember -Function Get-StartupApplications Export-ModuleMember -Function Get-UpTime Export-ModuleMember -Function Get-PendingReboot Export-ModuleMember -Function Get-RAMStatistics Export-ModuleMember -Function Get-ComputerDetails Export-ModuleMember -Function Get-SpecialFolder Export-ModuleMember -Function Watch-Command Export-ModuleMember -Function New-MessageBox Export-ModuleMember -Function Set-UserDefinedVariables Export-ModuleMember -Function Clear-UserDefinedVariables Export-ModuleMember -Function Remove-UserDefinedVariables Export-ModuleMember -Function Get-UserDefinedVariables Export-ModuleMember -Function Get-BootTime Export-ModuleMember -Function Get-ActivationStatus Export-ModuleMember -Function Pause-Execution Export-ModuleMember -Function Get-LoggedOnUser Export-ModuleMember -Function Disconnect-LoggedOnUser Export-ModuleMember -Function Send-Email Export-ModuleMember -Function Invoke-Script Export-ModuleMember -Function Get-NETFrameworkVersion Export-ModuleMember -Function Compare-ObjectByProperty Export-ModuleMember -Function Remove-Duplicate Export-ModuleMember -Function Display-DirectoryTree Export-ModuleMember -Function Send-SyslogMessage #endregion |