1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Powershell scripts you cant live without

Discussion in 'Servers and Enterprise Solutions' started by LizardKing, May 19, 2017 at 2:39 PM.

  1. LizardKing

    Soldato

    Joined: Oct 18, 2002

    Posts: 7,217

    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: May 19, 2017 at 2:54 PM
  2. LizardKing

    Soldato

    Joined: Oct 18, 2002

    Posts: 7,217

    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
    
    
     
  3. LizardKing

    Soldato

    Joined: Oct 18, 2002

    Posts: 7,217

    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
     
  4. LizardKing

    Soldato

    Joined: Oct 18, 2002

    Posts: 7,217

    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 = "youremail@compname.com" 
    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<support@yourcomp.com>"
    
    # 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:support@yourcomp.com'>support@yourcomp.com</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)
    }
    }
    }
    
    
     
  5. LizardKing

    Soldato

    Joined: Oct 18, 2002

    Posts: 7,217

    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}
     
  6. traveyb

    Wise Guy

    Joined: Jul 25, 2012

    Posts: 1,223

    That password one is awesome, very nice thanks. Will dig out some of my scripts and post them up
     
  7. LizardKing

    Soldato

    Joined: Oct 18, 2002

    Posts: 7,217

    Location: The Land of Roundabouts

    Its such a simple idea yet has saved quite alot 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/
     
  8. Spammeh

    Hitman

    Joined: Aug 2, 2005

    Posts: 544

    These aren't all my own, and they are rather simple, but useful non-the-less

    User account disable script
    Code:
    
    Import-Module ActiveDirectory
     
    function Get-ADUsersLastLogon()
    {
     
      ################## Variables #####################
     
      # Number of days since user account object hasn't logged on to the domain
      $numberOfDays = (Get-Date).AddDays(-430)
     
      # Location of CSV output
      $logPath = "c:\DisabledUsers.csv"
    
      # OU that you wish to search for user accounts
      $searchbase = "DC=domain,DC=com"
    
      # OU that disabled accounts will be moved to
      $DisabledOU = "OU=Disabled Objects,DC=domain,DC=com"
     
      # Variables required to export to .csv
      $logDate = Get-Date -F dd-MM-yyyy
      $logArray = @()
    
      # Lookup to find domain controllers
      $dcs = Get-ADDomainController -Filter {Name -like "*"}
    
      # Search looking for user accounts older than $numberOfDays and accounts that are enabled
      $users = Get-ADUser -searchbase $SearchBase -Filter {((lastlogondate -le $numberOfDays) -AND (enabled -eq $True))}
     
      $time = 0
    
      # EMail variables
     
      $smtpServer = "SMTP"
      $smtpFrom = "email@company.com"
      $smtpTo = "user@company.com"
      $messageSubject = "$logDate - User Accounts Disabled"
      $messageBody = "Attached is a .csv containing the latest list of disabled user accounts, correct as of $logDate. Added this run: $logArray"
     
     
      ################# Script Body ####################
     
      foreach($user in $users)
      {
        #compares currentUser last logon time on each domain controller
        foreach($dc in $dcs)
        {
          $hostname = $dc.HostName
          $currentUser = Get-ADUser $user.SamAccountName | Get-ADObject -Server $hostname -Properties lastLogon
     
          if($currentUser.LastLogon -gt $time)
          {
            $time = $currentUser.LastLogon
          }
        }
        $time = 0
    
        # Disables user object
        Disable-ADAccount $currentUser
    
        # Adds description to user object description
        Set-ADUser $currentUser -Description "Account disabled on $logDate"
    
        # Moves user object to target OU
        Move-ADObject $currentUser -TargetPath $DisabledOU
     
        #Create array for logfile output
        $obj = $currentUser | Select Name,distinguishedname,@{n="status";e={'Disabled User'}},@{n="date disabled";e={$logdate}}
    
        #Output to Log
        $logArray += $obj
    
      }
        #Export contents of logArray to .csv
        $logArray | Export-Csv $logPath -NoTypeInformation -Append
    
        #Email Output
        Send-MailMessage -To $smtpTo -From $smtpFrom -Subject $messageSubject -Body $messageBody -Attachments $logPath -SmtpServer $smtpServer
    }
     
     # Run Function
     Get-ADUsersLastLogon
    Veeam Free Backup script
    Code:
    # VM names separated by commas
    $VMNames = “VM1”, “VM1”
    # vCenter name/IP
    $HostName = “10.30.10.140”
    # Directory that VM backups should go to
    $Directory = “\\10.30.10.85\Veeam”
    # Desired compression level, following compression level from Veeam (Optional)
    $CompressionLevel = “4”
    # Quiesce VM when taking snapshot (Optional; VMware Tools are required; Possible values: $True/$False)
    $EnableQuiescence = $True
    # Protect resulting backup with encryption key (Optional; $True/$False)
    $EnableEncryption = $False
    # Encryption Key (Optional; path to a secure string, C:\SecureString.txt”
    $EncryptionKey = “”
    # Retention settings (Optional; By default, VeeamZIP files are not removed and kept in the specified location for an indefinite period of time.
    # Possible values: Never , Tonight, TomorrowNight, In3days, In1Week, In2Weeks, In1Month)
    $Retention = “In3days”
    # Email Settings
    # Enable notification (Optional)
    $EnableNotification = $True
    # Email SMTP server
    $SMTPServer = “smtp.smtp.com”
    # Email FROM
    $EmailFrom = “sender@cnwr.com”
    # Email TO
    $EmailTo = “recipient@cnwr.com”
    # Email subject
    $EmailSubject = “Veeam Backup Job”
    # Email formatting
    $style = “<style>BODY{font-family: Arial; font-size: 10pt;}”
    $style = $style + “TABLE{border: 1px solid black; border-collapse: collapse;}”
    $style = $style + “TH{border: 1px solid black; background: #54b948; padding: 5px; }”
    $style = $style + “TD{border: 1px solid black; padding: 5px; }”
    $style = $style + “</style>”
    ##################################################################
    # End User Defined Variables
    ##################################################################
    #################### DO NOT MODIFY PAST THIS LINE ################
    Asnp VeeamPSSnapin
    $Server = Get-VBRServer -name $HostName
    $mbody = @()
    foreach ($VMName in $VMNames)
    {
    $VM = Find-VBRViEntity -Name $VMName -Server $Server
    $ZIPSession = Start-VBRZip -Entity $VM -Folder $Directory -Compression $CompressionLevel -DisableQuiesce:(!$EnableQuiescence) -AutoDelete $Retention
    If ($EnableNotification)
    {
    $TaskSessions = $ZIPSession.GetTaskSessions()
    $FailedSessions = $TaskSessions | where {$_.status -eq “EWarning” -or $_.Status -eq “EFailed”}
    if ($FailedSessions -ne $Null)
    {
    $mbody = $mbody + ($ZIPSession | Select-Object @{n=”Name”;e={($_.name).Substring(0, $_.name.LastIndexOf(“(“))}} ,@{n=”Start Time”;e={$_.CreationTime}},@{n=”End Time”;e={$_.EndTime}},Result,@{n=”Details”;e={$FailedSessions.Title}})
    }
    Else
    {
    $mbody = $mbody + ($ZIPSession | Select-Object @{n=”Name”;e={($_.name).Substring(0, $_.name.LastIndexOf(“(“))}} ,@{n=”Start Time”;e={$_.CreationTime}},@{n=”End Time”;e={$_.EndTime}},Result,@{n=”Details”;e={($TaskSessions | sort creationtime -Descending | select -first 1).Title}})
    }
    }
    }
    If ($EnableNotification)
    {
    $Message = New-Object System.Net.Mail.MailMessage $EmailFrom, $EmailTo
    $Message.Subject = $EmailSubject
    $Message.IsBodyHTML = $True
    $message.Body = $mbody | ConvertTo-Html -head $style | Out-String
    $SMTP = New-Object Net.Mail.SmtpClient($SMTPServer)
    $SMTP.Send($Message)
    }
    VMware Snapshot reminder:

    Code:
    # - SnapReminder V1.0 By Virtu-Al - http://virtu-al.net
    #
    # Please use the below variables to define your settings before use
    #
    $smtpServer = "mysmtpserver.mydomain.com"
    $MailFrom = "me@mydomain.com"
    $VISRV = "MYVISERVER"
     
    function Find-User ($username){
       if ($username -ne $null)
       {
          $usr = (($username.split("\"))[1])
          $root = [ADSI]""
          $filter = ("(&(objectCategory=user)(samAccountName=$Usr))")
          $ds = new-object system.DirectoryServices.DirectorySearcher($root,$filter)
          $ds.PageSize = 1000
          $ds.FindOne()
       }
    }
     
    function Get-SnapshotTree{
       param($tree, $target)
     
       $found = $null
       foreach($elem in $tree){
          if($elem.Snapshot.Value -eq $target.Value){
             $found = $elem
             continue
          }
       }
       if($found -eq $null -and $elem.ChildSnapshotList -ne $null){
          $found = Get-SnapshotTree $elem.ChildSnapshotList $target
       }
     
       return $found
    }
     
    function Get-SnapshotExtra ($snap){
       $guestName = $snap.VM   # The name of the guest
     
       $tasknumber = 999    # Windowsize of the Task collector
     
       $taskMgr = Get-View TaskManager
     
       # Create hash table. Each entry is a create snapshot task
       $report = @{}
     
       $filter = New-Object VMware.Vim.TaskFilterSpec
       $filter.Time = New-Object VMware.Vim.TaskFilterSpecByTime
       $filter.Time.beginTime = (($snap.Created).AddSeconds(-5))
       $filter.Time.timeType = "startedTime"
     
       $collectionImpl = Get-View ($taskMgr.CreateCollectorForTasks($filter))
     
       $dummy = $collectionImpl.RewindCollector
       $collection = $collectionImpl.ReadNextTasks($tasknumber)
       while($collection -ne $null){
          $collection | where {$_.DescriptionId -eq "VirtualMachine.createSnapshot" -and $_.State -eq "success" -and $_.EntityName -eq $guestName} | %{
             $row = New-Object PsObject
             $row | Add-Member -MemberType NoteProperty -Name User -Value $_.Reason.UserName
             $vm = Get-View $_.Entity
             $snapshot = Get-SnapshotTree $vm.Snapshot.RootSnapshotList $_.Result
             $key = $_.EntityName + "&" + ($snapshot.CreateTime.ToString())
             $report[$key] = $row
          }
          $collection = $collectionImpl.ReadNextTasks($tasknumber)
       }
       $collectionImpl.DestroyCollector()
     
       # Get the guest's snapshots and add the user
       $snapshotsExtra = $snap | % {
          $key = $_.vm.Name + "&" + ($_.Created.ToString())
          if($report.ContainsKey($key)){
             $_ | Add-Member -MemberType NoteProperty -Name Creator -Value $report[$key].User
          }
          $_
       }
       $snapshotsExtra
    }
     
    Function SnapMail ($Mailto, $snapshot)
    {
       $msg = new-object Net.Mail.MailMessage
       $smtp = new-object Net.Mail.SmtpClient($smtpServer)
       $msg.From = $MailFrom
       $msg.To.Add($Mailto)
     
       $msg.Subject = "Snapshot Reminder"
     
    $MailText = @"
    This is a reminder that you have a snapshot active on $($snapshot.VM) which was taken on $($snapshot.Created).
     
    Name: $($snapshot.Name)
     
    Description: $($snapshot.Description)
    "@
     
       $msg.Body = $MailText
       $smtp.Send($msg)
    }
     
    Connect-VIServer $VISRV
     
    foreach ($snap in (Get-VM | Get-Snapshot | Where {$_.Created -lt ((Get-Date).AddDays(-14))})){
       $SnapshotInfo = Get-SnapshotExtra $snap
       $mailto = ((Find-User $SnapshotInfo.Creator).Properties.mail)
       SnapMail $mailto $SnapshotInfo
    }
    AD User created since x date (used for auditors)

    Code:
    get-aduser -filter * -properties whencreated | where {$_.whencreated -ge [datetime]"1/5/2016"} | sort-object whencreated | select sAMAccountName,Name,WhenCreated,enabled | export-csv C:\Users\XXXXXXX\Documents\UsersSinceMay01.csv
    Domain OS versions:

    Code:
    #Functions
    function ImportADModule
    {
      Import-Module ActiveDirectory
      if (!($?))
      {
        #Only works for Windows Server OS with PS running as admin, download RSAT if using desktop OS
        Add-WindowsFeature RSAT-AD-PowerShell
        Import-Module ActiveDirectory
      }
    }
    
    function GetDN
    {
      param($domain)
      $names = $domain.Split(".")
      $bFirst = $true
      foreach ($name in $names)
      {
        if ($bFirst)
        {
          $dn += "DC=" + $name
          $bFirst = $false
        }
        else { $dn += ",DC=" + $name }
      }
      return $dn
    }
    
    function GetDNs
    {
      param($domains)
      $dns = @{}
      foreach ($domain in $domains)
      {
        $dns.Add($domain, (GetDN -domain $domain))
      }
      return $dns
    }
    
    function GetOSCountsPerDomain
    {
      param($dns, $enabled, $daysOld)
      $osCounts = @{}
      $cutOffDate = ((Get-Date).Adddays(-($daysOld))).ToFileTime()
      Write-Host "Getting Data" -NoNewline -ForegroundColor Yellow
    
      $filter = "(PwdLastSet -gt {0}) -and (Enabled -eq '{1}')" -f $cutOffDate, $enabled
      foreach ($domain in $dns.GetEnumerator())
      {
        $i = 0
        $domains = @{}
        Write-Host "." -NoNewline -ForegroundColor Yellow
        $computers = Get-ADComputer -Filter $filter -SearchBase $domain.Value -Server $domain.Key -Properties OperatingSystem, OperatingSystemVersion
        foreach ($computer in $computers)
        {
          if ($computer.OperatingSystem -eq $null) { $os = 'NULL'}
          else { $os = $computer.OperatingSystem }
          if ($computer.OperatingSystemVersion -eq $null) { $osver = 'NULL'}
          else { $osver = $computer.OperatingSystemVersion }
          try { $domains.Add(($os + " - " + $osver), 1) }
          catch { $domains.Set_Item(($os + " - " + $osver), ($domains.Get_Item($os + " - " + $osver))+1) }
        }
        $osCounts.Add($domain.Key, $domains)
      }
      Write-Host
      return $osCounts
    }
    
    function DisplayOutput
    {
      param($osCounts)
      Write-Host
      foreach ($osCount in $osCounts.GetEnumerator())
      {
        Write-Host $OSCount.Key -ForegroundColor Green
        $osCount.Value.GetEnumerator() | Sort-Object Value -Descending | Format-Table -AutoSize
      }
    }
    
    #Main
    
    #Import AD Module for PowerShell
    ImportADModule
    
    #Get list of domains from current forest
    $Domains = (Get-ADForest).domains
    
    #Get hash table of domains and distinguished names from current forest
    $DNs = GetDNs -domains $Domains
    
    #Get OS counts per domain (specify age here)
    $OSCounts = GetOSCountsPerDomain -dns $DNs -enabled $true -daysOld 30
    
    #Display Results
    DisplayOutput -osCounts $OSCounts
     
  9. Pigeon_Killer

    Caporegime

    Joined: Nov 21, 2005

    Posts: 28,497

    Going to use that password one as well thanks :)

    Cjwdev has a few tools that have replaced the majority of scripts I ran, highly recommend their AD Info tool.
     


Share This Page