Powershell scripts you cant live without

Soldato
Joined
18 Oct 2002
Posts
8,116
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,116
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,116
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,116
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,116
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,116
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/
 
Associate
Joined
2 Aug 2005
Posts
588
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 protected]"
  $smtpTo = "[email protected]"
  $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 = “[email protected]”
# Email TO
$EmailTo = “[email protected]”
# 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 = "[email protected]"
$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
 
Soldato
OP
Joined
18 Oct 2002
Posts
8,116
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
Joined
12 Jan 2006
Posts
5,610
Location
UK
Would anyone know of a powershell script that I could run on a large number of shares/folders to check if that user has permissions on the folder?

P.S Got sorted in the end
 
Last edited:
Associate
Joined
28 Jan 2007
Posts
1,700
Location
Manchester
office365, when a team/manager asks you for a list of who has permissions to a shared mailbox. The script lists Full Mailbox Access, SendOnBehalfOf and SendAs. If anyone figures out how to list the UPN for SendOnBehalfOf please let me know :)

Code:
$mailboxupn = Read-Host -Prompt 'Enter mailbox upn'

write-host $mailboxupn "Mailbox Permissions" -ForegroundColor Yellow
write-host " "

#Full Mailbox Access
write-host "Full Mailbox Access" -ForegroundColor Yellow  
$tempdata1 = Get-MailboxPermission -Identity $mailboxupn | Where-Object {($_.IsInherited -eq $false) -and ($_.User -notlike "NT AUTHORITY\SELF")} | select User
#$tempdata1 -replace "User", "" -replace "@{=", "" -replace "}", ""
foreach ($tempitem1 in $tempdata1) {
    write-host $tempitem1.User
}

#SendAs
write-host " "
write-host "SendAs permissions" -ForegroundColor Yellow  
#Get-RecipientPermission -Identity $mailboxupn | Where-Object {($_.accessrights -like 'SendAs') -and -not ($_.trustee -like 'NT AUTHORITY\SELF')} | select Trustee
$tempdata2 = Get-RecipientPermission -Identity $mailboxupn | Where-Object {($_.trustee -notlike 'NT AUTHORITY\SELF')} | select Trustee
foreach ($tempitem2 in $tempdata2) {
    write-host $tempitem2.Trustee
}

#SendOnBehalfOf
write-host " "
write-host "SendOnBehalfOf permissions" -ForegroundColor Yellow  
$tempdata3 = Get-Mailbox -Identity $mailboxupn | select GrantSendOnBehalfTo
foreach ($tempitem3 in $tempdata3) {
    write-host $tempitem3.GrantSendOnBehalfTo
}
 
Associate
Joined
3 Oct 2007
Posts
795
Not a script, but the Quest ActiveRoles Management Shell deserves an honourable mention.

The functions are extremely similar to the standard AD powershell module, but I've found them far more intuitive and powerful.
When searching for powershell scripts I do occasionally find a script with the tell that every function is prefixed with a 'Q', Qaduser, Qadgroup, etc.

They were available for free from Quest before they got purchased by Dell, so 1.5.1 is the last free version available.
Not sure about linking to a download, so here's the SHA1 hash from my copy:
739d646f626a064200eb14d8ce1b8eb8634ee1d4
 
Associate
Joined
3 Oct 2007
Posts
795
In fact, here's a script using the QAD functions I frequently use that checks every domain controller for the true last login time - Rather than the 'within 7 days' you'll get when querying a single DC.

Couldn't say what site I got this from, but the author is credited

Code:
##==============================================================================
##==============================================================================
## SCRIPT.........: Get-AllUserLastLogon
## AUTHOR.........: Clint McGuire
## EMAIL..........:
## VERSION........: 1
## DATE...........: 2011_05_26
## COPYRIGHT......: 2011, Clint McGuire
## LICENSE........:
## REQUIREMENTS...: Powershell v2.0, Quest AD Cmdlets
## DESCRIPTION....: Gets all enabled users last logon times and exports to CSV file.
## NOTES..........:
## CUSTOMIZE......:
##==============================================================================
## REVISED BY.....:
## EMAIL..........:
## REVISION DATE..:
## REVISION NOTES.:
##
##==============================================================================
##==============================================================================

##==============================================================================
## START
##==============================================================================
$DCs = Get-QADComputer -ComputerRole DomainController
$LastLogon = @{}
ForEach ($DC in $DCs) {
$Users = Get-QADUser -Service $dc.dnshostname -SizeLimit 0
ForEach ($User in $Users)
{
If ($User.LastLogonTimestamp -ne $null)
{
$Time = $User.LastLogonTimestamp | Get-Date -Format u
}
Else
{
$Time = $User.LastLogonTimestamp
}
$UserName = $User.SamAccountName
If ($LastLogon.ContainsKey($UserName))
{
If ($LastLogon.Get_Item($UserName) -le $Time)
{
$LastLogon.Set_Item($UserName, $Time)
}
}
Else
{
$LastLogon.Add($UserName, $Time)
}
}
}
$LastLogon.GetEnumerator() | Sort-Object Name |Export-csv e:\powershell\AllADUserLastLogon.csv
##==============================================================================
## End
##==============================================================================
 
Associate
Joined
3 Oct 2007
Posts
795
For anything complicated with file and directory permissions I use SetACL.

When we migrated all of our home directories and file shares we used it to apply all the permissions we needed. I tested icacls, but it was far harder to get the granularity of permissions and inheritance we wanted.

I've just looked through the documentation as a refresher and it's pretty daunting. Bit worrying as I think another migration to 2012R2/2016 might be in my not too distant future.
 
Back
Top Bottom