Powershell scripts you cant live without

Soldato
Joined
18 Oct 2002
Posts
8,125
Location
The Land of Roundabouts
Thought i'd share some of the scripts that i've found pretty much invaluable over the years, feel free to add any you may use yourself and perhaps we can create a nice little repo :) (any code comments and an origonal source are a bonus!)

1st off, quite a simple one, if you have a hybrid environment and fed up of waiting for a natural sync.

Code:
$SyncServer = "YourFedServer"
$SyncServerSession = New-PSSession -ComputerName $SyncServer -SessionOption (New-PSSessionOption -ProxyAccessType NoProxyServer)
Invoke-Command -Session $SyncServerSession -ScriptBlock {Start-ADSyncSyncCycle -PolicyType Delta}
Get-PSSession | Where-Object {$PSItem.ComputerName -eq $SyncServer} | Remove-PSSession
 
Last edited:
Soldato
OP
Joined
18 Oct 2002
Posts
8,125
Location
The Land of Roundabouts
2nd one is actually from our provisioning process when installing from a USB stick, we run it as a 1st run command as part of installing Windows

Amend the 1st 2 lines to suit your environment, it will pop up a box asking for the computer name then your credentials and will join it to the domain in the ou you specify.

Code:
$ou = "OU=computers,DC=domain,DC=name"
$domain = "domain.name"

[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
$computer = [Microsoft.VisualBasic.Interaction]::InputBox("Enter the computer name", "Computer", "$env:computername")
Add-Computer -domainname $domain -OUpath $ou -credential (get-credential) -NewName $computer
 
Soldato
OP
Joined
18 Oct 2002
Posts
8,125
Location
The Land of Roundabouts
A simple little one liner to show locked out users
Code:
Search-ADAccount -Locked | Select Name, LockedOut, LastLogonDate
Then if you want to unlock all the accounts
Code:
Search-ADAccount -Locked | Select Name, LockedOut, LastLogonDate | Unlock-ADaccount

If i get time i'll sanitize a few of my bigger ones later on today
 
Soldato
OP
Joined
18 Oct 2002
Posts
8,125
Location
The Land of Roundabouts
Heres our password reminder emails, we have a few users that are email only users so quite handy for them to get a reminder when there passwords are due to expire
I cant remember where i got the original from unfortunately. this has been updated slightly from the original to make it a bit nicer
The first 3 lines need editing to suit. if you want to test it without firing off emails to everyone thats meets the criteria change the following line
Code:
$smtpTo = "$useremail"
to something like
Code:
 $smtpTo = "[email protected]"

Code:
$ADResults = Get-ADUser -SearchBase "DC=domain,DC=name" -Filter {(Enabled -eq $True) -and (EmailAddress -like "*")} -Properties EmailAddress, PasswordExpired, PasswordNeverExpires, PasswordLastSet
$smtpServer = "YourSMTPserver"
$smtpFrom = "Support<[email protected]>"

# LOOP THROUGH USERS IN ACTIVE DIRECTORY
foreach ($user in $ADResults){
  $name = $user.Name
  $passwordlastset = $user.PasswordLastSet
  $passwordexpired = $user.PasswordExpired
  $passwordneverexpires = $user.PasswordNeverExpires
  $useremail = $user.EmailAddress

    # CALCULATE TIME BEFORE PASSWORD EXPIRATION
    #if your password has not expired and your password is not set to never expire and your password is not new
    if (($passwordexpired -ne $True) -and ($passwordneverexpires -ne $True) -and ($passwordlastset -ne $null)){
        $user_enddate = $passwordlastset + ((Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge.TotalDays)
        $DaysLeft = (New-TimeSpan -Start (Get-Date) -End $user_enddate).Days
    # NOTIFY USER IF PASSWORD IS EXPIRING WITHIN 2 WEEKS
        if ($DaysLeft -le "9"){

#### Header details to make the email nicer
$Header = "<style>"
$Header = $Header + "BODY{background-color:white;}"
$Header = $Header + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
$Header = $Header + "TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:#CB5DB3}"
$Header = $Header + "TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:lightgrey}"
$Header = $Header + "</style>"
#### Body
$b = "
<font face='calibri' size='3'>
Dear $name <br>
Your password is due to expire in $DaysLeft day(s)!<br>
If you do not change your password before it expires, you will be unable to access your email and/or computer.<br><br>
<strong>Ways you can change your password.</strong><br>
On your work desktop/laptop -&nbsp; press ctrl/alt del (if you're a remote worker ensure the vpn is connected first) <br>
The webmail portal.&nbsp;<a title='Webmail Portal' href='https://portal.office.com/account/'>Link</a> - Follow the link to Security &amp; Privacy and there will be a link there to change it. <em>(Note - The Safari browser does not support this)</em><br><br>
<strong>Dont forget to also update any devices (mobiles etc) that you use to access your emails.</strong><br><br>
If you need futher assistance you can contact IT support via<br>
01234 123456<br>
Email - <a href='mailto:[email protected]'>[email protected]</a><br><br>
Thank you<br>
Support<br><br>
</font>
<em>This e-mail was automatically generated</em>
"

$body = ConvertTo-HTML -head $a -body $b



$smtpTo = "$useremail"

$messageSubject = "Your password is due to expire in $DaysLeft days"
$message = New-Object System.Net.Mail.MailMessage $smtpfrom, $smtpto
$message.Subject = $messageSubject 
$message.Body = $body
If ($DaysLeft -lt 3) {
$message.Priority = "High"
}
$message.IsBodyHTML = $true
$smtp = New-Object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($message)
}
}
}
 
Soldato
OP
Joined
18 Oct 2002
Posts
8,125
Location
The Land of Roundabouts
Another little one liner,

This will search your o365 tennent for any disabled users with a license. (you will need to be connected to your tenant first)
Code:
get-aduser -filter {enabled -eq 'false' -and userprincipalname -ne "*"} -SearchBase "$TargetOU" | get-msoluser | where {$_.isLicensed -eq $true}
 
Soldato
OP
Joined
18 Oct 2002
Posts
8,125
Location
The Land of Roundabouts
That password one is awesome, very nice thanks. Will dig out some of my scripts and post them up

Its such a simple idea yet has saved quite a lot of the helpdesks time. Unfortunately you still get people who don't read and end up getting locked out.

Another invaluable powershell script that cleans our your wsus server fair better than its built in application.
http://www.adamj.org/clean-wsus.html

And courtesy of a Reddit/powershell poster a very easy to use GUI builder
https://poshgui.com/
 
Soldato
OP
Joined
18 Oct 2002
Posts
8,125
Location
The Land of Roundabouts
Veeam Free Backup script

Very handy, i noticed they had enabled scripting a few weeks back and was going to look into automating it, just saved me the hassle :)

I was asked by a client to setup a poormans regular clone of a server, the built in scheduler annoyingly doesn't allow for deleting of target VM's so had to be scripted.
Luckily i found this little gem so didnt need to write something myself :D

If this is set up as a daily task on a server with PowerCli installed then it will create a clone of a VM on another host which will then get deleted and re-cloned when run again.
Original
http://luckyblogshere.blogspot.co.uk/2012/08/delete-vm-then-clone-vm-powershell.html

I only moved most of the params to the top and specified a resource pool for the clone to be created in.
Code:
$date = Get-Date
$vcServer = "Vcenter server"
$fromVMname = "VMtoClone"
$newVMName = "Clone_OfServer"
$tgtEsxName = "Target_ESXI_Host"
$tgtDatastoreName = "datastore001"
$userName = "root"
$passWord = "Password"
$notes = ("Clone of: " + $fromVMname + " for backup. Created on: " + $date)
$ResPool = "Backup"
$emailto = "[email protected]"
$emailFrom = "[email protected]"
$smtpServer = smtpserver.domain.name
# Connect to the vCenter Server
Add-PSSnapin –Name VM*
Connect-VIServer -Server $vcServer -User $username -Password $passWord




#
# Test to see if $newVMname already exists in vCenter Server and
# set $vmExist to a value other than $null if it does
$vmExist = Get-VM -Name $newVMname -ErrorAction SilentlyContinue



# Delete the VM $newVMname if $vmExist returns a value other than $null
if ($vmExist -ne $null)
{
 Remove-VM -deletefromdisk -VM $newVMName -confirm:$false
}
#
# Create a clone of $fromVMname to $newVMName, email if there is an error
$cloneTask = New-VM -Name $newVMName -VM (Get-VM $fromVMname) -VMHost (Get-VMHost $tgtEsxName) -Datastore (Get-Datastore $tgtDatastoreName) -ResourcePool $ResPool -RunAsync
Wait-Task -Task $cloneTask -ErrorAction SilentlyContinue
Get-Task | where {$_.Id -eq $cloneTask.Id} | %{
     if($_.State -eq "Error"){
          $event = Get-VIEvent -Start $_.FinishTime | where {$_.DestName -eq $newVMName} | select -First 1
          $subject = "Clone of " + $newVMName + " failed"
          $body = $event.FullFormattedMessage

          $smtp = new-object Net.Mail.SmtpClient($smtpServer)
          $smtp.Send($emailFrom, $emailTo, $subject, $body)
     }
}
#
# Set the notes field of the VM $notes
Set-VM -VM $newVMName -Notes $notes -confirm:$false
#
#Disconnect from the vCenter Server
Disconnect-VIServer -Server $vcServer -Confirm:$false
 
Soldato
OP
Joined
18 Oct 2002
Posts
8,125
Location
The Land of Roundabouts
joke of the day email anyone? i was learning on interacting with websites and came up with this as a quick concept. Zero error handling so if the site ever changes it will likely break - Just edit the first few lines to suit.

Code:
##### Joke of the Day email
$smtpTo = "[email protected]"
$cc = @("[email protected]","[email protected]")
$smtpServer = "YourSMTPserver"
$smtpFrom = "Joke<[email protected]>"
$messageSubject = "▅ ▆ ▇ Joke Of The Day ▇ ▆ ▅"



$URI = “http://www.laughfactory.com/jokes/joke-of-the-day “
$HTML = Invoke-WebRequest -Uri $URI
$joke = ($HTML.ParsedHtml.getElementsByTagName(‘div’) | Where{ $_.className -eq 'joke-text’ } ).innerText -replace "Today's Joke", "" | select -first 1

$message = New-Object System.Net.Mail.MailMessage $smtpfrom, $smtpto
  if($cc -ne $null) {
    foreach($person in $cc) {
    $message.CC.Add($person)
    }
  }

$message.Subject = $messageSubject    
$message.Body = $joke
$message.IsBodyHTML = $true   
$smtp = New-Object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($message)
 
Back
Top Bottom