Tag Archives: PowerShell

Get LastReboot and Uptime value on Windows 10 and Windows Server via PS

In this lab, I have used PS to get LastReboot and Uptime value on Windows servers and clients. PS script will query “Get-WmiObject” to get the last boot time of the computers/servers.

Firstly, I will test with Windows Servers.

$OS1 = Get-WmiObject Win32_OperatingSystem -ComputerName DC1 -ErrorAction Stop
$LastReboot =($OS1.ConvertToDateTime($OS1.LastBootUpTime))
# Print LastReboot
$LastReboot
$Uptime = (Get-Date) -$OS1.ConvertToDateTime($OS1.LastBootUpTime)
$Uptime  = ([String]$Uptime.Days + " Days " + $Uptime.Hours + " Hours " + $Uptime.Minutes + " Minutes")
# Print uptime

Write a full PS script.

# This script is written by Tung on 2022-02-18
# This is used to get lastreboot and uptime on Windows servers.
# Get time when running the script
$filename = (Get-Date).tostring("dd-MM-yyyy-hh-mm")
# Change PowerShell working directory to C:\Shared
Set-Location C:\Shared
#$TestComputerName = get-content C:\Shared\tungmachine.txt
$servers = (Get-ADComputer -properties OperatingSystem -filter{(operatingsystem -like "*Windows Server*")}).name
Foreach ($server in $servers) {
        # Only check the machine if it is online
        $ping_result = Test-Connection -ComputerName $server -Count 1 -Quiet
        # If the machine is online
        if($ping_result){
        # Using "Get-WmiObject Win32_OperatingSystem" to get $OS object
        # Using "Get-WmiObject Win32_OperatingSystem -ComputerName $Testcomputer -ErrorAction Stop" to get $OS object on remote machines.
        $OS = Get-WmiObject Win32_OperatingSystem -ComputerName $server -ErrorAction Stop
        # Get LastReboot via $OS.LastBootUpTime variable
        $LastReboot =($OS.ConvertToDateTime($OS.LastBootUpTime)).tostring("dd-MM-yyyy")    
        # Get Uptime via $OS.LastBootUpTime variable
        $Uptime = (Get-Date) -$OS.ConvertToDateTime($OS.LastBootUpTime)
        # Create a hash table (dictionary type) with 3 columns: PSComputerName, LastReboot and Uptime
        $lastlogonproperties = @{
        # Add PSComputerName into column #1
        PSComputerName  = $server
        # Convert and only get dd-mm-yyyy on last reboot variable.
        # Add LastReboot into column #2
        # Only get dd-mm-yyy field on LastReboot record.
        LastReboot =($OS.ConvertToDateTime($OS.LastBootUpTime)).tostring("dd-MM-yyyy")
        # Add LastReboot into column #3
        Uptime  = ([String]$Uptime.Days + " Days " + $Uptime.Hours + " Hours " + $Uptime.Minutes + " Minutes")
        }

    # Create a new table object on PS to append the hash table values above   
    $forcecsv = New-Object psobject -Property $lastlogonproperties
    # change order of columns before appending to csv file. 
    # Convert it to csv file and save under LastReboot directory.
    $forcecsv | select-object PSComputerName, LastReboot, Uptime | export-csv -NoTypeInformation -append "C:\Shared\LastReboot\Server\$filename.csv"
    }
}

Run the script.

Then, do the same PS script to query Windows 10 machines.

Change “(operatingsystem -like “*Windows Server*”)” to (operatingsystem -like “*Windows 10*”)

$computers = (Get-ADComputer -properties OperatingSystem -filter{(operatingsystem -like "*Windows 10*")}).name
# This script is written by Tung on 2022-02-18
# This is is used t get lastreboot and uptime on Windows 10 machines.
# Get time when running the script
$filename = (Get-Date).tostring("dd-MM-yyyy-hh-mm")
# Change PowerShell working directory to C:\Shared
Set-Location C:\Shared
#$TestComputerName = get-content C:\Shared\tungmachine.txt
$computers = (Get-ADComputer -properties OperatingSystem -filter{(operatingsystem -like "*Windows 10*")}).name
Foreach ($Computer in $computers) {
        # Only check the machine if it is online
        $ping_result = Test-Connection -ComputerName $Computer -Count 1 -Quiet
        # If the machine is online
        if($ping_result){
        # Using "Get-WmiObject Win32_OperatingSystem" to get $OS object
        # Using "Get-WmiObject Win32_OperatingSystem -ComputerName $Testcomputer -ErrorAction Stop" to get $OS object on remote machines.
        $OS = Get-WmiObject Win32_OperatingSystem -ComputerName $Computer -ErrorAction Stop
        # Get LastReboot via $OS.LastBootUpTime variable
        $LastReboot =($OS.ConvertToDateTime($OS.LastBootUpTime)).tostring("dd-MM-yyyy")    
        # Get Uptime via $OS.LastBootUpTime variable
        $Uptime = (Get-Date) -$OS.ConvertToDateTime($OS.LastBootUpTime)
        # Create a hash table (dictionary type) with 3 columns: PSComputerName, LastReboot and Uptime
        $lastlogonproperties = @{
        # Add PSComputerName into column #1
        PSComputerName  = $Computer
        # Convert and only get dd-mm-yyyy on last reboot variable.
        # Add LastReboot into column #2
        # Only get dd-mm-yyy field on LastReboot record.
        LastReboot =($OS.ConvertToDateTime($OS.LastBootUpTime)).tostring("dd-MM-yyyy")
        # Add LastReboot into column #3
        Uptime  = ([String]$Uptime.Days + " Days " + $Uptime.Hours + " Hours " + $Uptime.Minutes + " Minutes")
        }

    # Create a new table object on PS to append the hash table values above   
    $forcecsv = New-Object psobject -Property $lastlogonproperties
    # change order of columns before appending to csv file. 
    # Convert it to csv file and save under LastReboot directory.
    $forcecsv | select-object PSComputerName, LastReboot, Uptime | export-csv -NoTypeInformation -append "C:\Shared\LastReboot\Client\$filename.csv"
    }
}

Run the script.

Check Windows Defender status on a Windows computer

According to Microsoft, (https://www.microsoft.com/security/blog/2021/05/11/gartner-names-microsoft-a-leader-in-the-2021-endpoint-protection-platforms-magic-quadrant/), Microsoft Windows Defender becomes a Leader in the 2021 Endpoint Protection Platforms Magic Quadrant.

Checking Windows Defender status on a Windows computer.

Get-MpComputerStatus | Select-Object -Property Antivirusenabled,AMServiceEnabled,AntispywareEnabled,BehaviorMonitorEnabled,IoavProtectionEnabled,NISEnabled,OnAccessProtectionEnabled,RealTimeProtectionEnabled,AntivirusSignatureLastUpdate
PS script to check Windows Defender service on Windows domain-joined machine.
[CmdletBinding()]
 
Param
(
    [Parameter(Mandatory=$false,
                ValueFromPipelineByPropertyName=$true,
                ValueFromPipeline=$true
                )]
    [string[]]$ComputerName = $env:COMPUTERNAME
)

$result=@()
$ErrorActionPreference="SilentlyContinue"

$filename = (Get-Date).tostring("dd-MM-yyyy-hh-mm")
# Query Windows 10 domain-joined on Active Directory
$computername = (Get-ADComputer -filter {OperatingSystem -Like '*Windows 10*'}).name
foreach($computer in $computername){
    $ping_result = Test-Connection -ComputerName $computer -Count 1 -Quiet
        if($ping_result){
        $result=Invoke-Command -ComputerName $computer {Get-MpComputerStatus | Select-Object -Property Antivirusenabled,AMServiceEnabled,AntispywareEnabled,BehaviorMonitorEnabled, `
        IoavProtectionEnabled,NISEnabled,OnAccessProtectionEnabled,RealTimeProtectionEnabled,AntivirusSignatureLastUpdated}
        }
        If ($result) {
                     $result+=New-Object -TypeName PSObject -Property ([ordered]@{
                    'Computer'=$result.PSComputername
                    'AntiVirusStatus'=$result.AntivirusEnabled
                    'AV Update'=$result.AntivirusSignatureLastUpdated
                    'Anti-Malware'=$result.AMServiceEnabled
                    'Anti-Spyware'=$result.AntispywareEnabled
                    'Behavior Monitor'=$result.BehaviorMonitorEnabled
                    'Office-Anti-Virus'=$result.IoavProtectionEnabled
                    'NIS'=$result.NISEnabled
                    'AccessProtection'=$result.OnAccessProtectionEnabled
                    'RelatimeProtection'=$result.RealTimeProtectionEnabled
                    })
                    }
}
Write-Output $result_WD

Run the PS script.

PowerShell commands and notes

PowerShell commands and notes:

#Recursive file search using PowerShell
Get-ChildItem -Path C:\ -Filter *Graylog* -Recurse -ErrorAction SilentlyContinue -Force
#checkdate in the last 24 hours
$checkdate = (Get-Date).AddHours(-24)
#check all files have been modified in the last 24 hours and output file name, size and the time was last modified
Get-ChildItem -Path C:\Shared -file -Recurse | Where-Object {$_.LastWriteTime -ge $checkdate} | Select-Object -Property Fullname,Length,LastWriteTime
#checkdate in the last 90days
$checkdate = (Get-Date).AddDays(-90)
#check files on the  C:\users\Administrator\Downloads directory and at least 100MB in size and LastWriteTime is less than $checkdate. Then output the result to csv file.
$files = Get-ChildItem -Path C:\users\Administrator\Downloads -file -Recurse |
Where-Object {$_.length -ge 100MB -AND $_.LastWriteTime -le $checkdate} |
Select Fullname,Length,CreationTime,LastWriteTime |
Export-CSV -Path myfiles-90days_100MB.csv

Check WinRM service is running on a remote host.

Test-NetConnection -ComputerName WIN10NEW11 -Port 5985 -WarningAction SilentlyContinue
#shows the last computer name started, running.
get-CimInstance -ClassName win32_operatingsystem -ComputerName $env:computername | Select-Object -property PSComputerName, LastBootUpTime, {(Get-Date) - $_.lastbootuptime}

Get Antivirus Product is installed and its status with PowerShell.

Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntivirusProduct

List the user accounts in the local administrator group in a Windows machine.

Get-CimInstance win32_group -filter "name = 'administrators' AND LocalAccount = 'true'" | Get-CimAssociatedInstance -ResultClassName win32_useraccount

List all installed software that has a name defined in a Windows machine.

Get-CimInstance win32_product -filter "name like '%'" | Select-Object -property Name,Vendor,Version,Description,InstallDate

Check if Wordpad is running, kills the Wordpad process, and then creates a sample text file that includes the current date that kills the process.

(Get-Process wordpad -ea silentlycontinue) -and (stop-process -name wordpad) -and ("$(Get-Date) killed wordpad") | Out-file C:\Shared\wordpadlog.txt

Search any files that have file extension is .srt on D:\Shared folder, then remove them.

Check before removing.
PS D:\Get-Childitem -path "D:\Shared" -Filter *.srt -Recurse -ErrorAction SilentlyContinue -Force | Remove-Item -Force -Whatif


PS D:\Get-Childitem -path "D:\Shared" -Filter *.srt -Recurse -ErrorAction SilentlyContinue -Force | Remove-Item -Force

Install IIS Web server via PS.

Add-WindowsFeature Web-Server, Web-WebServer, Web-Common-Http, Web-Default-Doc, Web-Dir-Browsing, Web-Http-Errors, Web-Static-Content, Web-Health, Web-Http-Logging, Web-Log-Libraries, Web-Request-Monitor, Web-Performance, Web-Stat-Compression, Web-Security, Web-Filtering, Web-Windows-Auth, Web-App-Dev, Web-Net-Ext45, Web-Asp-Net45, Web-ISAPI-Ext, Web-ISAPI-Filter, Web-Mgmt-Tools, Web-Mgmt-Console, Web-Mgmt-Compat, Web-Metabase, NET-Framework-45-Features, NET-Framework-45-Core, NET-Framework-45-ASPNET, NET-WCF-Services45, NET-WCF-HTTP-Activation45, NET-WCF-TCP-PortSharing45, WAS, WAS-Process-Model, WAS-Config-APIs -restart

Install Active Directory module via PS.

Import-Module ServerManager
Add-WindowsFeature -Name "RSAT-AD-PowerShell" –IncludeAllSubFeature

# Check the installation status of a module
Get-WindowsFeature RSAT-AD-PowerShell

Shut down and Restart Windows machine.

# Stop-Computer -Force -WhatIf
Stop-Computer -Force
# Restart-Computer -Force -WhatIf
Restart-Computer -Force
# Delay restart on 5 seconds
Start-Sleep -Seconds 5 ; Restart-Computer -Force
# Restart machine remotely
Restart-Computer -ComputerName PC1 -Force
# Restart-Computer (Multiple Windows 10 domain joined clients)

(Get-ADComputer -Filter 'operatingsystem -notlike "*server*"').Name | Restart-Computer -Force -ErrorAction silentlycontinue

Get, stop and start Windows services.

Get-Service
# search Windows updates service.
Get-Service | where-object {$_.name -like "*wuauserv*"}
# Start Windows updates service.
Start-Service wuauserv -PassThru
# Stop Windows updates service.
Stop-Service wuauserv -PassThru
# Get Windows updates status
Get-Service -name wuauserv
# Change statustype 
Set-Service -name wuauserv -StartupType Disabled -Status Stopped

Get Current Windows OS build version

This is a PS code to get the current Windows OS build version. It is based on (“https://smsagent.blog/2017/05/18/find-the-full-windows-build-number-with-powershell/”)


Function Get-WindowsVersion{

[CmdletBinding()]

Param
(
    [Parameter(Mandatory=$false,
                ValueFromPipelineByPropertyName=$true,
                ValueFromPipeline=$true
                )]
    [string[]]$ComputerName = $env:COMPUTERNAME
)

Begin
{
    $Table = New-Object System.Data.DataTable
    $Table.Columns.AddRange(@("ComputerName","Windows Edition","Version","OS Build"))
}
Process
{
    Foreach ($Computer in $ComputerName)
    {
        $Code = {
            $ProductName = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' –Name ProductName).ProductName
            Try
            {
                $Version = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' –Name ReleaseID –ErrorAction Stop).ReleaseID
            }
            Catch
            {
                $Version = "N/A"
            }
            $CurrentBuild = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' –Name CurrentBuild).CurrentBuild
            $UBR = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' –Name UBR).UBR
            $OSVersion = $CurrentBuild + "." + $UBR


           # Get-CimInstance Win32_OperatingSystem to list Build number in the machine
            $getOS = gcim Win32_OperatingSystem 
            # Assign the initial value for this variable
            $currentOSVersion = "Unknown OS"
            # Check Build number is corresponding with Windows 10 and Windows Server OS edition.
            # https://docs.microsoft.com/en-us/windows/release-health/release-information 
            # https://docs.microsoft.com/en-us/windows-server/get-started/windows-server-release-info

             Switch -WildCard ($getOS.BuildNumber){
            # if BuildNumber is 19043, Windows version is Windows 10 21H1 and so on.
            '*19043*'{$currentOSVersion = "21H1"}
            '*19042*'{$currentOSVersion = "20H2"}
            '*19041*'{$currentOSVersion = "2004"}
            '*18363*'{$currentOSVersion = "1909"}
            '*18362*'{$currentOSVersion = "1903"}
            '*17763*'{$currentOSVersion = "1809"}

            # if BuildNumber is 14393, Windows version is Windows Server 2016 version 1067 and so on.
            '*14393*'{$currentOSVersion = "1607"}
            '*17763.107*'{$currentOSVersion = "1809"}
            '*18363.418*'{$currentOSVersion = "1909"}
            '*19041.264*'{$currentOSVersion = "2004"}
            '*19042.508*'{$currentOSVersion = "20H2"}
            '*20348.169*'{$currentOSVersion = "2022"}
            }

            $TempTable = New-Object System.Data.DataTable
            $TempTable.Columns.AddRange(@("ComputerName","Windows Edition","Version","OS Build"))
            [void]$TempTable.Rows.Add($env:COMPUTERNAME,$ProductName,$currentOSVersion,$OSVersion)
        
            Return $TempTable
        }

        If ($Computer -eq $env:COMPUTERNAME)
        {
            $Result = Invoke-Command –ScriptBlock $Code
            [void]$Table.Rows.Add($Result.Computername,$Result.'Windows Edition',$Result.Version,$Result.'OS Build')
        }
        Else
        {
            Try
            {
                $Result = Invoke-Command –ComputerName $Computer –ScriptBlock $Code –ErrorAction Stop
                [void]$Table.Rows.Add($Result.Computername,$Result.'Windows Edition',$Result.Version,$Result.'OS Build')
            }
            Catch
            {
                $_
            }
        }

    }

}
End

{
    Return $Table
}
}

Run the command.

PS C:\shared\ Get-MyWindowsVersion

Query all Windows 10 domain-joined on Active Directory.

(Get-ADComputer -filter {OperatingSystem -Like '*Windows 10*'})

Query all Windows Server 2016 domain-joined on Active Directory.

Get-ADComputer -filter {OperatingSystem -Like '*Windows Server*'}

A script to detect Windows 10 OS’s current patch version if the machine is online.

$filename = (Get-Date).tostring("dd-MM-yyyy-hh-mm")
# Query Windows 10 domain-joined on Active Directory
$computername = (Get-ADComputer -filter {OperatingSystem -Like '*Windows 10*'}).name
foreach($computer in $computername){
    $ping_result = Test-Connection -ComputerName $computer -Count 1 -Quiet
        if($ping_result){
        get-windowsversion -computer $computer
#        | Select-Object -Property ComputerName,  'Windows Edition', Version, 'OS build' |
#        Sort-Object 'OS build' | export-csv -NoTypeInformation -Append "$filename.csv"
        }
        else{
            Write-Host "Host ICMP: failure"
        }
    }
Save the output to csv file

# Get date when running the script
$filename = (Get-Date).tostring("dd-MM-yyyy-hh-mm")
# Query Windows 10 domain-joined on Active Directory
$computername = (Get-ADComputer -filter {OperatingSystem -Like '*Windows 10*'}).name
foreach($computer in $computername){
        # the machine is offline if the script is not ablt to get any echo reply from sending 3 echo requests
        $ping_result = Test-Connection -ComputerName $computer -Count 3 -Quiet
        # if the machine is online
        if($ping_result){
        # get Windows 10 current patch information and append the result yo csv file
            get-windowsversion -computer $computer | 
            Select-Object -Property ComputerName,  'Windows Edition', Version, 'OS build' |
            Sort-Object 'OS build' | export-csv -NoTypeInformation -Append "$filename.csv"
        }
#        else{
#            Write-Host "Host ICMP: failure"
#        }
}

Force installing Windows updates via PowerShell PSWindowUpdates

F_PSWindowsUpdates.PS1 is shared on \\DC1\Shared

# This is PowerShell script to force on installing Windows Updates via PSWindowsUpdate on Windows machines
# https://www.powershellgallery.com/packages/PSWindowsUpdate/2.2.0.2
# It is created on 2021-10-21
# Allow PowerShell to be run on Windows machines with PSWindowsUpdate module
Set-ExecutionPolicy RemoteSigned
# Installs everything (newest version) along with required modules.
Install-Module PSWindowsUpdate
# Import Module PSWindowsUpdate before running the script
Import-Module -Name PSWindowsUpdate
# Force Windows updates are completely downloaded, installed and then restarted. Will check if we have a WSUS server
Install-WindowsUpdate -AcceptAll -AutoReboot
# Send an email after running PSWindowsUpdate command
# Will send email if the last previous command is successful.
if ($? -eq $True){
        # Use this command for TLS requirement
        [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
        # Get machine name
        $machinename = get-content env:computername
        # Get current date and time
        $currentdate = get-date
        # Get current date and time
        $currentdate = get-date
        # SMTP server of Xyz.com</p>
        $SMTP = "smtp-mail.xyz.com"
        # Mail from<
        $From = "youremail@xyz.com"
        # Rcpt to
        $To = "youremail@xyz.com"# Subject line
        $Subject = "Windows updates on $cname"
        # Email body
        $Body = "Finising running Windows updates on $machinename on $currentdate"
        #Create a connection to SMTP Outlook via the port 587</p>
        $Email = New-Object Net.Mail.SmtpClient($SMTP, 587)
        # Enable SSL for the connection
        Email.EnableSsl = $true
        #Log in to xyz mail server with your credential
        $Email.Credentials = New-Object System.Net.NetworkCredential("youremail@xyz.com", "yourpassword");
        # Send email syntax
        $Email.Send($From, $To, $Subject, $Body)
}

Assign this script on Task Scheduler.