Differences between revisions 33 and 85 (spanning 52 versions)
Revision 33 as of 2020-08-20 20:18:15
Size: 7687
Editor: scot
Comment:
Revision 85 as of 2022-09-04 18:18:19
Size: 22985
Editor: scot
Comment:
Deletions are marked like this. Additions are marked like this.
Line 15: Line 15:
= Windows and AD Scripts = = Windows =

== Basic filtering of services ==

{{{#!highlight powershell
Get-Service | ? { ($_.Status -eq "Running") -and ($_.StartType -eq "Manual") }
}}}
Line 40: Line 46:
}}}

== List of AD accounts and the last time they logged in ==

{{{#!highlight powershell
Get-ADUser -Filter * -SearchBase "dc=home,dc=scotnpatti,dc=com" -ResultPageSize 0 -Prop CN,samaccountname,lastLogonTimestamp |
     select CN, samaccountname,@{n="lastLogonDate";e={[datetime]::FromFileTime($_.LastLogonTimestamp)}}
}}}

== Delete AD User accounts that have not been used in X days ==

{{{#!highlight powershell
$DaysAgo = (Get-Date).AddDays(-180)
#Get-ADUser -Filter {Enabled -eq $True} -Properties LastLogonDate | ? {($_.LastLogonDate -le $DaysAgo) } | FT Name, SamAccountName, DistinguishedName, LastLogonDate
Get-ADUser -Filter {Enabled -eq $True} -Properties LastLogonDate | ? {($_.LastLogonDate -le $DaysAgo) } | Remove-ADUser -Confirm
}}}

== Delete AD Computer accounts that have not been used in X days ==
{{{#!highlight powershell
$YearAgo = (Get-Date).AddDays(-370)
Get-ADComputer -Filter * -Properties * | ? {$_.LastLogonDate -le $YearAgo } | Remove-ADObject -Recursive -Confirm
#Get-ADComputer -Filter * -Properties * | ? {$_.LastLogonDate -le $YearAgo } | FT Name, LastLogonDate -AutoSize

$udp = Get-NetUDPEndpoint
foreach ($u in $udp) {
    $procid = $u.OwningProcess
    $proc = Get-Process -PID $procid | SELECT ID,ProcessName
    Write-Host "||" $($u.LocalAddress) "||" $($u.LocalPort) "||" $($procid) "||" $proc.ProcessName "||"
}
Line 70: Line 62:
Line 75: Line 66:
}}}

== Remote Session / Shell ==
{{{#!highlight powershell
Enter-PSSession -Computer [ComputerName]
Line 96: Line 92:
== Windows Backup Setup ==

Suppose that we have added a new disk for local backup purposes and that it is Disk 1.

{{{#!highlight powershell
Add-WindowsFeature -Name Windows-Server-Backup
$policy = New-WBPolicy #Note that this is the backup policy, its like a job, but you can only have one of these daily backups weird huh? Yeah, I'll show you a different way later!
Add-WBSystemState -Policy $policy
$volumes = Get-WBVolume -CriticalVolumes
Add-WBVolume -Policy $policy -Volume $volumes
$disks = GEt-WBDisk
$target = New-WBBackupTarget -Disk $disks[1]
Add-WBBackupTarget -Policy $policy -Target $target
Set-WBSchedule -Policy $policy -Schedule "01:30" #Daily at 1:30 AM
Set-WBPolicy -Policy $policy #save this as the default policy, and answer Y to the format backup storage disk.
}}}

== Getting Rid of Pesky Service Not Running Errors ==

Did you ever look at your server dashboard and see a big fat red mark next to services only to find out that it is a service that will just quit again if you run it. You look into it and, no you don't need it!!! Two such services are:

 * OneSyncSvc
 * WpnUserService

Here is how to turn them off:

{{{#!highlight powershell
Set-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\OneSyncSvc*" -Name "Start" -Value 4
Set-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WpnUserService*" -Name "Start" -Value 4
}}}

If you just want these to be "Manual" instead of "Disabled" use a value of 3 instead of 4.


= AD Scripts =

== Add RSAT tools to Windows 10 ==

{{{#!highlight powershell
Get-WindowsCapability -Name RSAT* -Online | Add-WindowsCapability -Online
}}}

OR Use Choco: https://chocolatey.org
{{{#!highlight powershell
c:\> choco install -y rsat
}}}

== Install App Compatibility on Server Core ==

 1. Download the ISO (or if you are using my VM infrastructure, its already available, just load it into your DVD drive)

{{{#!highlight powershell
Add-WindowsCapability -Online -Name ServerCore.AppCompatibility -Source D:\LanguagesAndOptionalFeatures -LimitAccess
}}}

OR If you are lucky, you can try this one:

{{{#!highlight powershell
Add-WindowsCapability -Online -Name ServerCore.AppCompatibility~~~~0.0.1.0
}}}

Don't forget to eject the DVD.

== List FSMO roles and Global Catalog servers ==

{{{#!hightlight powershell
Get-ADDomain | Select-Object InfrastructureMaster, RidMaster, PDCEmulator
Get-ADForest | Select-Object DomainNamingMaster, SchemaMaster
Get-ADDomainController -Filter {IsGlobalCatalog -eq $true} |FT $_.Hostname
}}}

== Add User to the Active Directory as a batch ==

My preference is to add a user by creating a spreadsheet using the following commands.

{{{#!highlight powershell
New-ADUser -Name "A a" -GivenName "A" -Surname "a" -SamAccountName "ab" -Path "OU=OU_Students,DC=cs,DC=southern,DC=edu" -AccountPassword (ConvertTo-SecureString "z36Hynyghg" -AsPlainText -Force) -Enabled $true
Add-ADGroupMember -Identity Students -Members ab
}}}

See: [[attachment:Sample Add students accounts for Powershell.xlsx|Excel Example]]

== List of AD accounts and the last time they logged in and created date ==

{{{#!highlight powershell
# This method looks like it should work, but LastLogon is stored at each domain controller, and the domain controller you are
# using, may not have ever been logged into by the user
#Get-ADUser -Filter * -SearchBase "dc=home,dc=scotnpatti,dc=com" -ResultPageSize 0 -Prop CN,samaccountname,lastLogonTimestamp |
# select CN, samaccountname,@{n="lastLogonDate";e={[datetime]::FromFileTime($_.LastLogonTimestamp)}}

# INSTEAD USE THIS METHOD
# NOTE: if run on a domain controller, it must be run as an elevated user. It appears to run fine from a client without elevated privileges
#To get the correct created dates, you must run this script from an elevated prompt or NOT ON A DOMAIN CONTROLLER
Import-Module ActiveDirectory
function Get-LastLogonEvents
{
    $UserList = New-Object System.Collections.ArrayList
    $dcs = Get-ADDomainController -Filter {Name -like "*"}
    $users = Get-ADUser -Filter *
    foreach($user in $users)
    {
        $time = 0
        $created = Get-Date -Date "8/10/2000 12:00:00 AM"
        foreach($dc in $dcs)
        {
            $hostname = $dc.HostName
            $aduser = Get-ADUser $user.SamAccountName -Properties whenCreated
            $currentUser = $aduser | Get-ADObject -Server $hostname -Properties lastLogon, lastLogonTimestamp
            if($currentUser.LastLogon -gt $time)
            {
                $time = $currentUser.LastLogon
            }
            if($currentUser.LastLogonTimeStamp -gt $time)
            {
                $time = $currentUser.LastLogonTimeStamp
            }
            if($aduser.whenCreated -gt $created)
            {
                $created = $aduser.whenCreated
            }
        }
        
        $dt = [DateTime]::FromFileTime($time)
        $temp = New-Object System.Object
        $temp | Add-Member -MemberType NoteProperty -Name "SamAccountName" -Value $user.SamAccountName
        $temp | Add-Member -MemberType NoteProperty -Name "LastLogon" -Value $dt
        $temp | Add-Member -MemberType NoteProperty -Name "Created" -Value $created
        $UserList.Add($temp) | Out-Null
        $time = 0
    }
    return $UserList
}
$myList = Get-LastLogonEvents | Sort-Object Created,LastLogon | Select SamAccountName, LastLogon, Created
#Write-Output $myList
$myList | Export-Csv -Path "C:\Users\scot\Desktop\Users12-14-2021.csv"
}}}

== Delete AD User accounts that have not been used in X days ==

{{{#!highlight powershell
$DaysAgo = (Get-Date).AddDays(-180)
#Get-ADUser -Filter {Enabled -eq $True} -Properties LastLogonDate | ? {($_.LastLogonDate -le $DaysAgo) } | FT Name, SamAccountName, DistinguishedName, LastLogonDate
Get-ADUser -Filter {Enabled -eq $True} -Properties LastLogonDate | ? {($_.LastLogonDate -le $DaysAgo) } | Remove-ADUser -Confirm
}}}

== Delete AD Computer accounts that have not been used in X days ==
{{{#!highlight powershell
$YearAgo = (Get-Date).AddDays(-370)
Get-ADComputer -Filter * -Properties * | ? {$_.LastLogonDate -le $YearAgo } | Remove-ADObject -Recursive -Confirm
#Get-ADComputer -Filter * -Properties * | ? {$_.LastLogonDate -le $YearAgo } | FT Name, LastLogonDate -AutoSize
}}}

== List AD Computer accounts and the last time they have been logged in ==
{{{#!highlight powershell
# This method looks like it should work, but LastLogon is stored at each domain controller, and the domain controller you are
# using, may not have ever been logged into by the user
#Get-ADUser -Filter * -SearchBase "dc=home,dc=scotnpatti,dc=com" -ResultPageSize 0 -Prop CN,samaccountname,lastLogonTimestamp |
# select CN, samaccountname,@{n="lastLogonDate";e={[datetime]::FromFileTime($_.LastLogonTimestamp)}}

# INSTEAD USE THIS METHOD
Import-Module ActiveDirectory
function Get-LastComputerLogonEvents
{
    $ComputerList = New-Object System.Collections.ArrayList
    $dcs = Get-ADDomainController -Filter {Name -like "*"}
    Write-Output $dcs
    $computers = Get-AdComputer -Filter *
    $time = 0
    foreach($computer in $computers)
    {
        foreach($dc in $dcs)
        {
            $hostname = $dc.HostName
            $currentComputer = Get-ADComputer $computer.SamAccountName | Get-ADObject -Server $hostname -Properties lastLogon
            if($currentComputer.LastLogon -gt $time)
            {
                $time = $currentComputer.LastLogon
            }
        }
        
        $dt = [DateTime]::FromFileTime($time)
        $temp = New-Object System.Object
        $temp | Add-Member -MemberType NoteProperty -Name "SamAccountName" -Value $computer.SamAccountName
        $temp | Add-Member -MemberType NoteProperty -Name "LastLogon" -Value $dt
        $ComputerList.Add($temp) | Out-Null
        $time = 0
    }
    return $ComputerList
}
$myList = Get-LastComputerLogonEvents | Sort-Object LastLogon | FT SamAccountName, LastLogon
Write-Output $myList
}}}

You can also try this one-liner

{{{#!highlight powershell
Get-ADUser -filter {enabled -eq $true} -SearchBase "ou=OU_Students,dc=cs,dc=southern,dc=edu" -Properties * |
  Select-Object SamAccountName,Name,@{N='LastLogon';E={[DateTime]::FromFileTime($_.LastLogon)}}|
  ? {$_.LastLogon -lt '2022-01-01'} |
  Sort-Object LastLogon -Descending
}}}
Line 104: Line 302:
== Setting up a Group Managed Service Account ==

An account that is automatically managed (e.g. password updates) by the domain. See get-help New-AdServiceAccount

{{{#!highlight powershell
# Adds the required root key to the key distribution service
Add-KdsRootKey -EffectiveTime ((get-date).AddHours(-10))
#Create an account:
New-ADServiceAccount Sql-Srv-Acct -DNSHostName Sql-Srv-Acct.home.scotpatti.com -PrincipalsAllowedToRetrieveManagedPassword "Domain Controllers"
#Install account on rita.home.scotnpatti.com
Install-ADServiceAccount -Identity 'Sql-Srv-Acct'
}}}

== Setting up a Storage Pool & Virtual Disk ==

{{{#!highlight powershell
$PhysicalDisk=(Get-PhysicalDisk -CanPool $True
New-StoragePool -FriendlyName Carribean -StorageSubSystemFriendlyName "Windows Storage*" -ResiliencySettingNameDefault Parity -ProvisioningTypeDefault Thin -PhysicalDisks $PhysicalDisks -Verbose
New-VirtualDisk -StoragePoolFriendlyName Carribean -FriendlyName StarFish -ResiliencySettingName Parity -Size 2GB
Get-VirtualDisk -FriendlyName StarFish | Initialize-Disk -PartitionStyle GPT -PassThru
#Get-Disk #will list the number of the StarFish disk if you don't see it from the command above
New-Partition -DiskNumber [X] -DriveLetter '[Y]' -UseMaximumSize
Format-Volume -DriveLetter '[Y]' -FileSystem NTFS
}}}

Line 132: Line 356:
}}}

== Add DHCP Reservations to Ruth ==

{{{#!highlight powershell
Add-DhcpServerv4Reservation -ScopeId 10.10.4.0 -IPAddress 10.10.4.10 -ClientId "00-1D-D8-C0-00-01" -ComputerName "ruth" -Description "00-1D-D8-C0-00-01"
}}}

== Get a list of IP address for SCVMM ==

{{{#!highlight powershell
Get-SCMACAddress -Assigned | Format-Table -Property `
@{label="MAC address"; expression={$_.Name}; width=18},
@{label="Name"; expression={$_.Description}; width=30},
@{label="IP address"; expression={$a = $_.Address -replace ":", "";
                                   $l = Get-DhcpServerv4Lease -ScopeId 10.10.4.0 -ComputerName "ruth" -ClientId $a;
                                   $l.IPAddress}; width=16}

#Get-DhcpServerv4Lease -ScopeId 216.249.119.0 -ComputerName 'csdc01' -ClientId '001DD8B71C28'
}}}

== List SCVMM VMs/Templates and their Ownership - Change Ownership ==
{{{#!highlight powershell
Get-SCVMTemplate | ? { $_.Owner -eq "DOMAIN\X" } | Set-SCVMTemplate -Owner "DOMAIN\Y"
Get-SCVirtualMachine | ? { $_.Owner -eq "DOMAIN\X" } | Set-SCVirtualMachine -Owner "X\Y"
}}}

== List SCVMM VMs/Templates LimitCPUForMigration and Set to allow migration ==

Note: Setting LimitCPUForMigration = $true means that we are limiting the CPU so that it can migrate to different versions of the same CPU.

{{{#!highlight powershell
Get-SCVMTemplate | ? { $_.LimitCPUForMigration -eq $false } | Set-SCVMTemplate -LimitCPUForMigration $true
Get-SCVirtualMachine | ? { $_.LimitCPUForMigration -eq $false } | Set-SCVirtualMachine -LimitCPUForMigration $true
}}}

== List SCVMM VMs that are not associated with the cloud and associate them ==

{{{#!highlight powershell
$Cloud = $Cloud = Get-SCCloud -VMMServer samuel | ? {$_.Name -eq "Nimbus"}
Get-SCVirtualMachine -VMMServer samuel | ? { $_.Cloud -ne $Cloud } | Set-SCVirtualMachine -Cloud $Cloud
Line 203: Line 468:

== Power Shell Script to List Network Adapters on a VM ==

Note: When looking at the !VirtualNetworkAdapterType value, "Emulated" means that it is "legacy" network adapter and "Synthetic" means its a non-legacy adapter.

{{{#!highlight powershell
Get-SCVirtualMachine | ? { $_.Name -like "*pfsense*" } | Get-SCVirtualNetworkAdapter
}}}

== List VLANs for all CPTR 427 Virtual Machines in System Center ==

{{{#!highlight powershell
Get-SCVirtualMachine |
    ? { $_.Name -like "*427*" } |
    SELECT Name,@{label="VlanID";expression={($_.VirtualNetworkAdapters).VlanID}} |
    Sort-Object Name | Export-Csv -Path .\VlanData.csv
}}}

== List All disconnected Adapters ==

{{{#!highlight powershell
$vms = Get-SCVirtualMachine
foreach ($vm in $vms) {
    $adapters = Get-SCVirtualNetworkAdapter -VM $vm
    foreach ($adapter in $adapters) {
        if ($adapter.VMNetwork -eq $null -or $adapter.VMNetwork -eq "" ) {
            Write-Host $vm.Name "missing connection on'" $adapter.MACAddress "'"
        }
    }
}
}}}

== Revoke all MAC addresses Back to the Pool ==

This came up as a maintenance issue when we lost some VMs, but not the configurations

{{{#!highlight powershell
$HostGroup = Get-SCVMHostGroup | where { $_.Path -eq "All Hosts\Server2016" }
$MACAddressPool = Get-SCMACAddressPool -VMHostGroup $HostGroup
$MACAddress = Get-SCMACAddress -MACAddressPool $MACAddressPool[0]
ForEach ($item in $MACAddress) {
    Revoke-SCMACAddress $item
}
}}}

== Change all VMs to use Dynamic Memory and reduce memory usage ==

{{{#!highlight powershell
$list = Get-SCVirtualMachine | ? { ($_.Name -like "*427*") -and ($_.DynamicMemoryEnabled -eq $False) }
foreach ($vm in $list) {
    if ($vm.Status -ne "PowerOff") {Stop-SCVirtualMachine -VM $vm}
    Set-SCVirtualMachine -VM $vm -DynamicMemoryEnabled $True -MemoryMB 1024 -DynamicMemoryMinimumMB 1024 -DynamicMemoryMaximumMB 6144
}
}}}

= Grading Scripts =

These are here for preparing various assignments in classes for grading, or actually grading them.

== General Prep for CPTR 446 handins of the !CompanyEmployees solutions ==

{{{#!highlight powershell
 param ($path)

function Change-ConnectionString
{
    param ( $filepath )
    $success = $false
    foreach ($f in $filepath)
    {
        if (-not(Test-Path -Path $f -PathType Leaf))
        {
            Write-Host " ERROR: settings file not found!"
            break
        }
        $c = Get-Content $f -Raw | ConvertFrom-Json
        if ($c.ConnectionStrings.sqlConnection)
        {
            $c.ConnectionStrings.sqlConnection = "Server=localhost;Database=CompanyEmployee;User Id=sa;Password=ConstraintDB123;"
            $c | ConvertTo-Json -Depth 32 | Set-Content $f
            $success = $true
        }
        else
        {
            Write-Host " ERROR: settings file does not contain a 'sqlConnection' property!!!"
            break
        }
    }
    if ($success)
    {
        Write-Host " Settings file successfully change."
    }
    else
    {
        Write-Host " Error: Unable to successsfully update any appsettings.json!!!"
    }
}

function Find-FirstFolder
{
    param ( $folder )
    $list = Get-ChildItem -Path $folder -Recurse -File -Filter "appsettings.json" | Resolve-Path | ? { -not ( ( $_.Path -match "ware" ) -or ( $_.Path -match "bin" ) ) }
    if ($list.Length -gt 1)
    {
        Write-Host " Warning: More than one appsettings.json file found!"
    }
    return $list
}

if (!$path)
{
    $path = "."
}
$ScriptPath = $pwd
$FullPath = Resolve-Path -Path $path
cd $FullPath
$files = Get-ChildItem -Filter "*.zip" | select Name
foreach ($f in $files)
{
    $parts = $f.Name.Split(".")
    $outDir = ".\" + $parts[0].Split("_")[0].replace(' ','')
    Write-Host $outDir
    New-Item -Path $outDir -ItemType Directory | Out-Null
    Expand-Archive $f.Name -DestinationPath $outDir
    $settings = Find-FirstFolder -folder $outDir
    Change-ConnectionString -filepath $settings
}
cd $ScriptPath.ProviderPath
}}}

Here is a list of Power Shell Scripts that are too cool to ignore

Contents

  1. Here is a list of Power Shell Scripts that are too cool to ignore
  2. Windows
    1. Basic filtering of services
    2. Expand all zip files into directories with zip name
    3. List of Listening Ports with their owning programs
    4. List Memory Installed
    5. List object from Registry - namely version of .NET installed
    6. Remote Session / Shell
    7. Remote commands
    8. Replace a string in a file using a regular expression
    9. Windows Backup Setup
    10. Getting Rid of Pesky Service Not Running Errors
  3. AD Scripts
    1. Add RSAT tools to Windows 10
    2. Install App Compatibility on Server Core
    3. List FSMO roles and Global Catalog servers
    4. Add User to the Active Directory as a batch
    5. List of AD accounts and the last time they logged in and created date
    6. Delete AD User accounts that have not been used in X days
    7. Delete AD Computer accounts that have not been used in X days
    8. List AD Computer accounts and the last time they have been logged in
    9. Adding DNS records to Windows DNS - For CPTR 446 class
    10. Setting up a Group Managed Service Account
    11. Setting up a Storage Pool & Virtual Disk
  4. SCVMM Powershell scripts
    1. Get a list of Virtual Machines that have a DVD attached
    2. List VMs at the end of the semester to be deleted
    3. Get a list of VM Mac Addresses for CPTR 427
    4. Add DHCP Reservations to Ruth
    5. Get a list of IP address for SCVMM
    6. List SCVMM VMs/Templates and their Ownership - Change Ownership
    7. List SCVMM VMs/Templates LimitCPUForMigration and Set to allow migration
    8. List SCVMM VMs that are not associated with the cloud and associate them
    9. Setting up a Windows 2019 Server for the first time
    10. Power shell to list of VM hard drives sizes
    11. List the amount of memory used by virtual machines
    12. Power Shell Scripts to create a NAT network (without DHCP) on Windows 10
    13. Power Shell Script to List Network Adapters on a VM
    14. List VLANs for all CPTR 427 Virtual Machines in System Center
    15. List All disconnected Adapters
    16. Revoke all MAC addresses Back to the Pool
    17. Change all VMs to use Dynamic Memory and reduce memory usage
  5. Grading Scripts
    1. General Prep for CPTR 446 handins of the !CompanyEmployees solutions

For the uninitiated:

Symbol

Meaning

%

shortcut for foreach object

$_

current object in the pipeline

Get-Member

Will list the fields of the object you send it

Sort-Object -Property [property name]

Will sort the objects you send in by the property name(s) which can be a comma separated list

Where-Object {$_.property -like '*string*'}

Will filter the objects. Also short cut notation: ? {$_.property -like '*string*'}

Get-Command -Module PSWindowsUpdate

Lists all the commands in the PSWindowsUpdate module

Windows

Basic filtering of services

   1 Get-Service | ? { ($_.Status -eq "Running") -and ($_.StartType -eq "Manual") }

Expand all zip files into directories with zip name

   1 $list = Get-ChildItem | ? { $_.Name -like "*.zip" } | select Name
   2 foreach ($line in $list) {
   3     $parts = $line.Name.Split(".")
   4     $outDir = ".\" + $parts[0]
   5     $inFile = $line.Name
   6     mkdir $outDir
   7     Expand-Archive $inFile -DestinationPath $outDir 
   8 }

List of Listening Ports with their owning programs

   1 $listening = (Get-NetTCPConnection | ? {($_.State -eq "Listen") -and ($_.RemoteAddress -eq "0.0.0.0")})
   2 foreach ($l in $listening) {
   3     $procid = $l.OwningProcess
   4     $proc = Get-Process -PID $procid | SELECT ID,ProcessName
   5     Write-Host $($l.LocalPort) "||" $($procid) "||" $proc.ProcessName
   6 }
   7 
   8 $udp = Get-NetUDPEndpoint
   9 foreach ($u in $udp) {
  10     $procid = $u.OwningProcess
  11     $proc = Get-Process -PID $procid | SELECT ID,ProcessName
  12     Write-Host "||" $($u.LocalAddress) "||" $($u.LocalPort) "||" $($procid) "||" $proc.ProcessName "||"
  13 }

List Memory Installed

   1 Get-WmiObject win32_physicalmemory | Format-Table Manufacturer,Banklabel,Configuredclockspeed,Devicelocator,Capacity,Serialnumber -autosize

List object from Registry - namely version of .NET installed

   1 gci 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' | sort pschildname -des | foreach-object {$_.name; $_.GetValue("Version");}

Remote Session / Shell

   1 Enter-PSSession -Computer [ComputerName]

Remote commands

   1 Invoke-Command -ComputerName eve -ScriptBlock { date }

Replace a string in a file using a regular expression

So I downloaded a bunch of files from "the way back machine" site and I needed to update the hard-coded links to be relative site links. The following little script did it for me.

   1 $files = ls Level*.html
   2 foreach ($item in $files) {
   3     (Get-Content -path $item) | % { $_ -Replace '(https://web.archive.org/nebula/level)([0123456789]{2})/', 'Level$2.html' } | Set-Content $item
   4 } 

Windows Backup Setup

Suppose that we have added a new disk for local backup purposes and that it is Disk 1.

   1 Add-WindowsFeature -Name Windows-Server-Backup
   2 $policy = New-WBPolicy #Note that this is the backup policy, its like a job, but you can only have one of these daily backups weird huh? Yeah, I'll show you a different way later!
   3 Add-WBSystemState -Policy $policy
   4 $volumes = Get-WBVolume -CriticalVolumes
   5 Add-WBVolume -Policy $policy -Volume $volumes
   6 $disks = GEt-WBDisk
   7 $target = New-WBBackupTarget -Disk $disks[1]
   8 Add-WBBackupTarget -Policy $policy -Target $target
   9 Set-WBSchedule -Policy $policy -Schedule "01:30" #Daily at 1:30 AM
  10 Set-WBPolicy -Policy $policy #save this as the default policy, and answer Y to the format backup storage disk.

Getting Rid of Pesky Service Not Running Errors

Did you ever look at your server dashboard and see a big fat red mark next to services only to find out that it is a service that will just quit again if you run it. You look into it and, no you don't need it!!! Two such services are:

Here is how to turn them off:

   1 Set-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\OneSyncSvc*" -Name "Start" -Value 4
   2 Set-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WpnUserService*" -Name "Start" -Value 4

If you just want these to be "Manual" instead of "Disabled" use a value of 3 instead of 4.

AD Scripts

Add RSAT tools to Windows 10

   1 Get-WindowsCapability -Name RSAT* -Online | Add-WindowsCapability -Online

OR Use Choco: https://chocolatey.org

   1 c:\> choco install -y rsat

Install App Compatibility on Server Core

  1. Download the ISO (or if you are using my VM infrastructure, its already available, just load it into your DVD drive)

   1 Add-WindowsCapability -Online -Name ServerCore.AppCompatibility -Source D:\LanguagesAndOptionalFeatures -LimitAccess

OR If you are lucky, you can try this one:

   1 Add-WindowsCapability -Online -Name ServerCore.AppCompatibility~~~~0.0.1.0

Don't forget to eject the DVD.

List FSMO roles and Global Catalog servers

Get-ADDomain | Select-Object InfrastructureMaster, RidMaster, PDCEmulator
Get-ADForest | Select-Object DomainNamingMaster, SchemaMaster
Get-ADDomainController -Filter {IsGlobalCatalog -eq $true} |FT $_.Hostname

Add User to the Active Directory as a batch

My preference is to add a user by creating a spreadsheet using the following commands.

   1 New-ADUser -Name "A a" -GivenName "A" -Surname "a" -SamAccountName "ab" -Path "OU=OU_Students,DC=cs,DC=southern,DC=edu" -AccountPassword (ConvertTo-SecureString "z36Hynyghg" -AsPlainText -Force) -Enabled $true
   2 Add-ADGroupMember -Identity Students -Members ab

See: Excel Example

List of AD accounts and the last time they logged in and created date

   1 # This method looks like it should work, but LastLogon is stored at each domain controller, and the domain controller you are 
   2 # using, may not have ever been logged into by the user
   3 #Get-ADUser -Filter * -SearchBase "dc=home,dc=scotnpatti,dc=com" -ResultPageSize 0 -Prop CN,samaccountname,lastLogonTimestamp | 
   4 #     select CN, samaccountname,@{n="lastLogonDate";e={[datetime]::FromFileTime($_.LastLogonTimestamp)}} 
   5 
   6 # INSTEAD USE THIS METHOD 
   7 # NOTE: if run on a domain controller, it must be run as an elevated user. It appears to run fine from a client without elevated privileges
   8 #To get the correct created dates, you must run this script from an elevated prompt or NOT ON A DOMAIN CONTROLLER
   9 Import-Module ActiveDirectory
  10 function Get-LastLogonEvents
  11 {
  12     $UserList = New-Object System.Collections.ArrayList
  13     $dcs = Get-ADDomainController -Filter {Name -like "*"}
  14     $users = Get-ADUser -Filter *
  15     foreach($user in $users)
  16     {
  17         $time = 0
  18         $created = Get-Date -Date "8/10/2000 12:00:00 AM"
  19         foreach($dc in $dcs)
  20         {
  21             $hostname = $dc.HostName
  22             $aduser = Get-ADUser $user.SamAccountName -Properties whenCreated
  23             $currentUser = $aduser | Get-ADObject -Server $hostname -Properties lastLogon, lastLogonTimestamp
  24             if($currentUser.LastLogon -gt $time)
  25             {
  26                 $time = $currentUser.LastLogon
  27             }
  28             if($currentUser.LastLogonTimeStamp -gt $time)
  29             {
  30                 $time = $currentUser.LastLogonTimeStamp
  31             }
  32             if($aduser.whenCreated -gt $created)
  33             {
  34                 $created = $aduser.whenCreated
  35             }
  36         }
  37         
  38         $dt = [DateTime]::FromFileTime($time)
  39         $temp = New-Object System.Object
  40         $temp | Add-Member -MemberType NoteProperty -Name "SamAccountName" -Value $user.SamAccountName
  41         $temp | Add-Member -MemberType NoteProperty -Name "LastLogon" -Value $dt
  42         $temp | Add-Member -MemberType NoteProperty -Name "Created" -Value $created
  43         $UserList.Add($temp) | Out-Null
  44         $time = 0
  45     }
  46     return $UserList
  47 }
  48 $myList = Get-LastLogonEvents | Sort-Object Created,LastLogon | Select SamAccountName, LastLogon, Created
  49 #Write-Output $myList 
  50 $myList | Export-Csv -Path "C:\Users\scot\Desktop\Users12-14-2021.csv"

Delete AD User accounts that have not been used in X days

   1 $DaysAgo = (Get-Date).AddDays(-180)
   2 #Get-ADUser -Filter {Enabled -eq $True} -Properties LastLogonDate | ? {($_.LastLogonDate -le $DaysAgo)  } | FT Name, SamAccountName, DistinguishedName, LastLogonDate
   3 Get-ADUser -Filter {Enabled -eq $True} -Properties LastLogonDate | ? {($_.LastLogonDate -le $DaysAgo)  } | Remove-ADUser -Confirm

Delete AD Computer accounts that have not been used in X days

   1 $YearAgo = (Get-Date).AddDays(-370)
   2 Get-ADComputer -Filter * -Properties * | ? {$_.LastLogonDate -le $YearAgo } | Remove-ADObject -Recursive -Confirm 
   3 #Get-ADComputer -Filter * -Properties * | ? {$_.LastLogonDate -le $YearAgo } | FT Name, LastLogonDate -AutoSize

List AD Computer accounts and the last time they have been logged in

   1 # This method looks like it should work, but LastLogon is stored at each domain controller, and the domain controller you are 
   2 # using, may not have ever been logged into by the user
   3 #Get-ADUser -Filter * -SearchBase "dc=home,dc=scotnpatti,dc=com" -ResultPageSize 0 -Prop CN,samaccountname,lastLogonTimestamp | 
   4 #     select CN, samaccountname,@{n="lastLogonDate";e={[datetime]::FromFileTime($_.LastLogonTimestamp)}} 
   5 
   6 # INSTEAD USE THIS METHOD
   7 Import-Module ActiveDirectory
   8 function Get-LastComputerLogonEvents
   9 {
  10     $ComputerList = New-Object System.Collections.ArrayList
  11     $dcs = Get-ADDomainController -Filter {Name -like "*"}
  12     Write-Output $dcs
  13     $computers = Get-AdComputer -Filter *
  14     $time = 0
  15     foreach($computer in $computers)
  16     {
  17         foreach($dc in $dcs)
  18         {
  19             $hostname = $dc.HostName
  20             $currentComputer = Get-ADComputer $computer.SamAccountName | Get-ADObject -Server $hostname -Properties lastLogon
  21             if($currentComputer.LastLogon -gt $time)
  22             {
  23                 $time = $currentComputer.LastLogon
  24             }
  25         }
  26         
  27         $dt = [DateTime]::FromFileTime($time)
  28         $temp = New-Object System.Object
  29         $temp | Add-Member -MemberType NoteProperty -Name "SamAccountName" -Value $computer.SamAccountName
  30         $temp | Add-Member -MemberType NoteProperty -Name "LastLogon" -Value $dt
  31         $ComputerList.Add($temp) | Out-Null
  32         $time = 0
  33     }
  34     return $ComputerList
  35 }
  36 $myList = Get-LastComputerLogonEvents | Sort-Object LastLogon | FT SamAccountName, LastLogon
  37 Write-Output $myList

You can also try this one-liner

   1 Get-ADUser -filter {enabled -eq $true} -SearchBase "ou=OU_Students,dc=cs,dc=southern,dc=edu" -Properties * | 
   2   Select-Object SamAccountName,Name,@{N='LastLogon';E={[DateTime]::FromFileTime($_.LastLogon)}}| 
   3   ? {$_.LastLogon -lt '2022-01-01'} | 
   4   Sort-Object LastLogon -Descending 

Adding DNS records to Windows DNS - For CPTR 446 class

   1 Import-Csv googleips.csv | ForEach-Object {
   2     Add-DnsServerResourceRecordA -Name $_.DNSName -ComputerName dc1.cs.southern.edu  -ZoneName cs.southern.edu $_.IP
   3 }

Setting up a Group Managed Service Account

An account that is automatically managed (e.g. password updates) by the domain. See get-help New-AdServiceAccount

   1 # Adds the required root key to the key distribution service
   2 Add-KdsRootKey -EffectiveTime ((get-date).AddHours(-10))
   3 #Create an account:
   4 New-ADServiceAccount Sql-Srv-Acct -DNSHostName Sql-Srv-Acct.home.scotpatti.com -PrincipalsAllowedToRetrieveManagedPassword "Domain Controllers"
   5 #Install account on rita.home.scotnpatti.com
   6 Install-ADServiceAccount -Identity 'Sql-Srv-Acct'

Setting up a Storage Pool & Virtual Disk

   1 $PhysicalDisk=(Get-PhysicalDisk -CanPool $True
   2 New-StoragePool -FriendlyName Carribean -StorageSubSystemFriendlyName "Windows Storage*" -ResiliencySettingNameDefault Parity -ProvisioningTypeDefault Thin -PhysicalDisks $PhysicalDisks -Verbose
   3 New-VirtualDisk -StoragePoolFriendlyName Carribean -FriendlyName StarFish -ResiliencySettingName Parity -Size 2GB
   4 Get-VirtualDisk -FriendlyName StarFish | Initialize-Disk -PartitionStyle GPT -PassThru
   5 #Get-Disk #will list the number of the StarFish disk if you don't see it from the command above
   6 New-Partition -DiskNumber [X] -DriveLetter '[Y]' -UseMaximumSize
   7 Format-Volume -DriveLetter '[Y]' -FileSystem NTFS

SCVMM Powershell scripts

I needed this once when I was trying to refresh the Library share. It failed on refresh with an error saying that a DVD was in use and wouldn't refresh until it was no longer in use. The following commands allowed me to identify the machines.

In general all of these need:

   1 Import-Module VirtualMachineManager

Get a list of Virtual Machines that have a DVD attached

   1 Get-SCVMMServer -ComputerName Samuel
   2 Get-SCVirtualMachine | Get-SCVirtualDVDDrive | Where-Object {$_.Connection -eq "ISOImage"} | Select Name, Connection, ISO

List VMs at the end of the semester to be deleted

   1 Get-SCVirtualMachine | Select Name, MarkedAsTemplate, Owner | Sort-Object -Property Owner, Name | Export-Csv -Path .\vms2019w.csv

Get a list of VM Mac Addresses for CPTR 427

   1 Get-SCVirtualMachine | Where-Object { $_.Name -like "*427*" } | select -ExpandProperty VirtualNetworkAdapters | select MacAddress

Add DHCP Reservations to Ruth

   1 Add-DhcpServerv4Reservation -ScopeId 10.10.4.0 -IPAddress 10.10.4.10 -ClientId "00-1D-D8-C0-00-01" -ComputerName "ruth" -Description "00-1D-D8-C0-00-01"

Get a list of IP address for SCVMM

   1 Get-SCMACAddress -Assigned | Format-Table -Property `
   2 @{label="MAC address"; expression={$_.Name};                  width=18},
   3 @{label="Name";        expression={$_.Description};           width=30},
   4 @{label="IP address";  expression={$a = $_.Address -replace ":", "";
   5                                    $l = Get-DhcpServerv4Lease -ScopeId 10.10.4.0 -ComputerName "ruth" -ClientId $a;
   6                                    $l.IPAddress};             width=16}
   7 
   8 #Get-DhcpServerv4Lease -ScopeId 216.249.119.0 -ComputerName 'csdc01' -ClientId '001DD8B71C28'

List SCVMM VMs/Templates and their Ownership - Change Ownership

   1 Get-SCVMTemplate | ? { $_.Owner -eq "DOMAIN\X" } | Set-SCVMTemplate -Owner "DOMAIN\Y"
   2 Get-SCVirtualMachine | ? { $_.Owner -eq "DOMAIN\X" } | Set-SCVirtualMachine -Owner "X\Y"

List SCVMM VMs/Templates LimitCPUForMigration and Set to allow migration

Note: Setting LimitCPUForMigration = $true means that we are limiting the CPU so that it can migrate to different versions of the same CPU.

   1 Get-SCVMTemplate | ? { $_.LimitCPUForMigration -eq $false } | Set-SCVMTemplate -LimitCPUForMigration $true
   2 Get-SCVirtualMachine | ? { $_.LimitCPUForMigration -eq $false } | Set-SCVirtualMachine -LimitCPUForMigration $true

List SCVMM VMs that are not associated with the cloud and associate them

   1 $Cloud = $Cloud = Get-SCCloud -VMMServer samuel | ? {$_.Name -eq "Nimbus"}
   2 Get-SCVirtualMachine -VMMServer samuel | ? {  $_.Cloud -ne $Cloud  } | Set-SCVirtualMachine -Cloud $Cloud

Setting up a Windows 2019 Server for the first time

  1. Install the server - follow prompts.
  2. Setup the AVMA key as shown below OR use sconfig in the next step.

   1 # Install the AVMA key.
   2 slmgr /ipk TNK62-RXVTB-4P47B-2D623-4GF74
   3 
   4  1. 
   5 
   6 #First run sconfig and setup the name, timezone and network, remote management and remote desktop. You can also setup windows update from here. 
   7 
   8 # Next we need to install Windows update and get it started.
   9 # This will install nuget package too.
  10 Install-Module PSWindowsUpdate
  11 
  12 # Now start the update process
  13 #   First we'll look at what updates are there
  14 Get-WUInstall 
  15 #   Now install them
  16 Install-WindowsUpdate

See the NAT setup near the bottom! That appears to have negated the need to change firewall rules. Also, I was not able to connect to the system via Server Manager right away. But a few minutes later, I could. No changes were made. But for posterity, they are here:

   1 # To turn on or off the firewall 
   2 Get-NetFirewallProfile
   3 # to set firewall on or off
   4 Set-NetFirewallProfile -Name Domain,Public,Private -Enabled True
   5 
   6 #Te get/set the firewall rule for private networks to allow any machine on a private network.
   7 Get-NetFirewallRule | ? {$_.DisplayGroup -like "Windows Remote Management*" -and $_.Profile -like "*Private*"} | Get-NetFirewallAddressFilter #Shows the address filter
   8 Get-NetFirewallRule | ? {$_.DisplayGroup -like "Windows Remote Management*" -and $_.Profile -like "*Private*"} | Set-NetFirewallRule -RemoteAddress 192.168.1.0/24

Using Server Manager, install AD DS

Power shell to list of VM hard drives sizes

   1 $vms = Get-SCVirtualDiskDrive -all
   2 foreach ($v in $vms)
   3 {
   4     $d = $v | select -ExpandProperty VirtualHardDisk
   5     Write-Output "$($v.Name), $($d.Size)"
   6 }

List the amount of memory used by virtual machines

   1 Get-SCVirtualMachine | ForEach-Object { $size += $_.Memory }

Resources:

Power Shell Scripts to create a NAT network (without DHCP) on Windows 10

   1 New-VMSwitch -SwitchName "CPTE230" -SwitchType Internal
   2 Get-VMSwitch #just for show
   3 Get-NetAdapter #get the ifIndex of your vEthernet adapter e.g. 67
   4 New-NetIPAddress -IPAddress 192.168.1.1 -PrefixLength 24 -InterfaceIndex 67 #Using the network ifIndex found above, e.g. 67
   5 New-NetNat -Name CPTE230NAT -InternalIPInterfaceAddressPrefix 192.168.1.0/24 #create the NAT 

Power Shell Script to List Network Adapters on a VM

Note: When looking at the VirtualNetworkAdapterType value, "Emulated" means that it is "legacy" network adapter and "Synthetic" means its a non-legacy adapter.

   1 Get-SCVirtualMachine | ? { $_.Name -like "*pfsense*" } | Get-SCVirtualNetworkAdapter

List VLANs for all CPTR 427 Virtual Machines in System Center

   1 Get-SCVirtualMachine | 
   2     ? { $_.Name -like "*427*" } | 
   3     SELECT Name,@{label="VlanID";expression={($_.VirtualNetworkAdapters).VlanID}} | 
   4     Sort-Object Name | Export-Csv -Path .\VlanData.csv

List All disconnected Adapters

   1 $vms = Get-SCVirtualMachine
   2 foreach ($vm in $vms) {
   3     $adapters = Get-SCVirtualNetworkAdapter -VM $vm
   4     foreach ($adapter in $adapters) {
   5         if ($adapter.VMNetwork -eq $null -or $adapter.VMNetwork -eq "" ) {
   6             Write-Host $vm.Name "missing connection on'" $adapter.MACAddress "'"
   7         }
   8     }
   9 }

Revoke all MAC addresses Back to the Pool

This came up as a maintenance issue when we lost some VMs, but not the configurations

   1 $HostGroup = Get-SCVMHostGroup | where { $_.Path -eq "All Hosts\Server2016" }
   2 $MACAddressPool = Get-SCMACAddressPool -VMHostGroup $HostGroup
   3 $MACAddress = Get-SCMACAddress -MACAddressPool $MACAddressPool[0] 
   4 ForEach ($item in $MACAddress) {
   5     Revoke-SCMACAddress $item 
   6 }

Change all VMs to use Dynamic Memory and reduce memory usage

   1 $list = Get-SCVirtualMachine | ? { ($_.Name -like "*427*") -and ($_.DynamicMemoryEnabled -eq $False) }
   2 foreach ($vm in $list) {
   3     if ($vm.Status -ne "PowerOff") {Stop-SCVirtualMachine -VM $vm}
   4     Set-SCVirtualMachine -VM $vm -DynamicMemoryEnabled $True -MemoryMB 1024 -DynamicMemoryMinimumMB 1024 -DynamicMemoryMaximumMB 6144
   5 }

Grading Scripts

These are here for preparing various assignments in classes for grading, or actually grading them.

General Prep for CPTR 446 handins of the !CompanyEmployees solutions

   1  param ($path)
   2 
   3 function Change-ConnectionString
   4 {
   5     param ( $filepath )
   6     $success = $false
   7     foreach ($f in $filepath)
   8     {
   9         if (-not(Test-Path -Path $f -PathType Leaf)) 
  10         {
  11             Write-Host "  ERROR: settings file not found!"
  12             break
  13         }
  14         $c = Get-Content $f -Raw | ConvertFrom-Json
  15         if ($c.ConnectionStrings.sqlConnection) 
  16         {
  17             $c.ConnectionStrings.sqlConnection = "Server=localhost;Database=CompanyEmployee;User Id=sa;Password=ConstraintDB123;"
  18             $c | ConvertTo-Json -Depth 32 | Set-Content $f
  19             $success = $true
  20         }
  21         else 
  22         {
  23             Write-Host "  ERROR: settings file does not contain a 'sqlConnection' property!!!"
  24             break
  25         }
  26     }
  27     if ($success) 
  28     {
  29         Write-Host "  Settings file successfully change."
  30     }
  31     else 
  32     {
  33         Write-Host "  Error: Unable to successsfully update any appsettings.json!!!"
  34     }
  35 }
  36 
  37 function Find-FirstFolder 
  38 {
  39     param ( $folder )
  40     $list = Get-ChildItem -Path $folder -Recurse -File -Filter "appsettings.json" | Resolve-Path | ? { -not ( ( $_.Path -match "ware" ) -or ( $_.Path -match "bin" ) ) }
  41     if ($list.Length -gt 1) 
  42     {
  43         Write-Host "  Warning: More than one appsettings.json file found!"
  44     }
  45     return $list
  46 }
  47 
  48 if (!$path) 
  49 {
  50     $path = "."
  51 }
  52 $ScriptPath = $pwd
  53 $FullPath = Resolve-Path -Path $path
  54 cd $FullPath
  55 $files = Get-ChildItem -Filter "*.zip" | select Name
  56 foreach ($f in $files)
  57 {
  58     $parts = $f.Name.Split(".")
  59     $outDir = ".\" + $parts[0].Split("_")[0].replace(' ','')
  60     Write-Host $outDir
  61     New-Item -Path $outDir -ItemType Directory | Out-Null
  62     Expand-Archive $f.Name -DestinationPath $outDir
  63     $settings = Find-FirstFolder -folder $outDir
  64     Change-ConnectionString -filepath $settings
  65 }
  66 cd $ScriptPath.ProviderPath

WindowsAdministration/PowerShellScripts (last edited 2024-08-30 00:21:07 by scot)