Enable AD Users with Out-GridView

Sometimes it requires just a couple of lines of code in PowerShell to produce highly useful helpdesk tools. Here is one that displays all currently disabled AD users. You can select one (or many by holding CTRL), and once you click OK, these users will be enabled:

#requires -Version 3.0 -Modules ActiveDirectory
Search-ADAccount -AccountDisabled |
  Out-GridView -Title 'Who should be enabled?' -OutputMode Multiple |
  # remove -WhatIf to actually enable accounts
  Enable-ADAccount -WhatIf

Twitter This Tip! ReTweet this Tip!

Turning AD User into a Hash Table

Sometimes it could be useful to load all attributes from a given AD user into a hash table. This way, you could edit them, and then use Set-ADUser with its -Add or -Replace parameters to apply them to another user account.

Here is how you read in all AD User attributes into a hash table:

#requires -Version 3.0 -Modules ActiveDirectory 

$blacklist = 'SID', 'LastLogonDate', 'SAMAccountName'

$user = Get-ADUser -Identity NAMEOFUSER -Properties *
$name = $user | Get-Member -MemberType *property | Select-Object -ExpandProperty Name

$hash = [Ordered]@{}
$name | 
  Sort-Object |
  Where-Object {
    $_ -notin $blacklist
  } |
  ForEach-Object {
  $hash[$_] = $user.$_ 
}

Note the use of $blacklist: this list can contain the names of any attributes you want to exclude.

Twitter This Tip! ReTweet this Tip!

Cloning Folder Structures (with NTFS Permissions) – Part 2

In the previous tip we illustrated how Get-FolderStructureWithPermission can document and create a list of all nested folders in a structure, along with their respective NTFS security settings. The result could be saved in a variable, or serialized to disk using Export-Csv

Today we show you the second part: once you have the information about a given folder structure, here is Set-FolderStructureWithPermission. It accepts a path to a folder in which you would like to clone the folder structure, plus the structure information itself that you got from Get-FolderStructureWithPermission:

#requires -RunAsAdministrator

function Set-FolderStructureWithPermission
{
  param
  (
    [String]
    [Parameter(Mandatory)]
    $Path,
    
    [Object[]]
    $folderInfo
  )

  $folderInfo | ForEach-Object {
    $relativePath = $_.Path
    $sddl = $_.SDDL
    
    $newPath = Join-Path -Path $Path -ChildPath $relativePath
    $exists = Test-Path -Path $newPath
    if ($exists -eq $false) 
    { 
      $null=New-Item -Path $newPath -ItemType Directory -Force 
    }
    $sd = Get-Acl -Path $newPath
    $sd.SetSecurityDescriptorSddlForm($sddl)
    Set-Acl -Path $newPath -AclObject $sd
  }
}

Because of how NTFS permissions are set, this function requires Administrator privileges to run.

Disclaimer: all code presented here is just for information purpose. While we do take great care to test it, there is no warranty whatsoever, and it is no production-ready code. It is your responsibility to test and determine whether this code runs flawlessly and fits your need.

A typical use case could be the cloning of an existing folder structure:

# clone user profile
$infos = Get-FolderStructureWithPermission -Path $home
Set-FolderStructureWithPermission -Path c:CloneHere -folderInfo $infos

Twitter This Tip! ReTweet this Tip!

Cloning Folder Structures (with NTFS Permissions) – Part 1

Sometimes you need to re-create a nested folder structure, and may also want to clone the NTFS permissions. Today we are tackling the first step: recording an existing folder structure along with NTFS permissions in SDDL form.

This task is accomplished by Get-FolderStructureWithPermission. It accepts a path to an existing folder, then returns all of its child folders along with their NTFS permissions in SDDL form:

function Get-FolderStructureWithPermission
{
  param
  (
    [String]
    [Parameter(Mandatory)]
    $Path
  )
  
  if ((Test-Path -Path $Path -PathType Container) -eq $false) 
  {
    throw "$Path does not exist or is no directory!"
  }

  Get-ChildItem -Path $Path -Recurse -Directory |
  ForEach-Object {
    $sd = Get-Acl -Path $_.FullName
    $sddl = $sd.GetSecurityDescriptorSddlForm('all')
  
  
    [PSCustomObject]@{
      Path = $_.FullName.Substring($Path.Length)
      SDDL = $sddl
    }
  
  }
}

You can pipe the output to Out-GridView, save it into a variable, or write it to disk using Export-Csv.

 
PS C:> Get-FolderStructureWithPermission -Path $home | Format-List 


Path : .dnx
SDDL : O:S-1-5-21-2012478179-265285931-690539891-1001G:S-1-5-21-2012478179-265285931-690539891-1001D:(A;OICIID;FA;;;SY)(A;OI
       CIID;FA;;;BA)(A;OICIID;FA;;;S-1-5-21-2012478179-265285931-690539891-1001)

Path : .plaster
SDDL : O:S-1-5-21-2012478179-265285931-690539891-1001G:S-1-5-21-2012478179-265285931-690539891-1001D:(A;OICIID;FA;;;SY)(A;OI
       CIID;FA;;;BA)(A;OICIID;FA;;;S-1-5-21-2012478179-265285931-690539891-1001)

Path : .vscode
SDDL : O:S-1-5-21-2012478179-265285931-690539891-1001G:S-1-5-21-2012478179-265285931-690539891-1001D:(A;OICIID;FA;;;SY)(A;OI
       CIID;FA;;;BA)(A;OICIID;FA;;;S-1-5-21-2012478179-265285931-690539891-1001)

Path : .vscode-insiders
SDDL : O:S-1-5-21-2012478179-265285931-690539891-1001G:S-1-5-21-2012478179-265285931-690539891-1001D:(A;OICIID;FA;;;SY)(A;OI
       CIID;FA;;;BA)(A;OICIID;FA;;;S-1-5-21-2012478179-265285931-690539891-1001)

Path : 3D Objects
SDDL : O:S-1-5-21-2012478179-265285931-690539891-1001G:S-1-5-21-2012478179-265285931-690539891-1001D:(A;OICIID;FA;;;SY)(A;OI
       CIID;FA;;;BA)(A;OICIID;FA;;;S-1-5-21-2012478179-265285931-690539891-1001)

...
 

Disclaimer: all code presented here is just for information purpose. While we do take great care to test it, there is no warranty whatsoever, and it is no production-ready code. It is your responsibility to test and determine whether this code runs flawlessly and fits your need.

Twitter This Tip! ReTweet this Tip!

Evaluating Exit Codes (aka Error Level – Part 3)

In part 3 of our mini-series about running console applications in PowerShell, here is a goodie: how can you run a console application separately from PowerShell, and still get notified when it is done, and retrieve its exit code?

Here is how: the code below runs ping.exe in a separate (hidden) window. PowerShell continues and is free to do whatever it wants. In the example, it outputs a number of “dot” characters while ping.exe is busy pinging a hostname.

Once the exe is done, the code retrieves the process ExitCode information:

$hostname = 'powershellmagazine.com'
# run the console-based application ASYNCHRONOUSLY in its own 
# window (PowerShell continues) and return the 
# process object (-PassThru)
# Hide the new window (you can also show it if you want)
$process = Start-Process -FilePath ping -ArgumentList "$hostname -n 4 -w 2000" -WindowStyle Hidden -PassThru

# wait for the process to complete, and meanwhile
# display some dots to indicate progress:
do
{
    Write-Host '.' -NoNewline
    Start-Sleep -Milliseconds 300
} until ($process.HasExited)
Write-Host

# the Error Level information is then found in ExitCode:
$IsOnline = $process.ExitCode -eq 0
$IsOnline

Twitter This Tip! ReTweet this Tip!

Evaluating Exit Codes (aka Error Level – Part 2)

When you directly launch a console-based application, PowerShell returns its exit code (aka Error Level) in the automatic variable $LASTEXITCODE. However, how do you get the exit code for a console-based application that you launch via Start-Process?

Here is how:

$hostname = 'powershellmagazine.com'
# run the console-based application synchronously in the PowerShell window, 
# and return the process object (-PassThru)
$process = Start-Process -FilePath ping -ArgumentList "$hostname -n 2 -w 2000" -Wait -NoNewWindow -PassThru

# the Error Level information is then found in ExitCode:
$IsOnline = $process.ExitCode -eq 0
$IsOnline

Twitter This Tip! ReTweet this Tip!