Wednesday, September 24, 2014

Set users HomeDirectory attribute in Active Directory with PowerShell

Last night I received a request to move a share that holds all users -HomeDirectory's' from an old file server to a newly configured Server 2012 R2 machine and to reconfigure every ones -HomeDirectory's' to point to the new share.

Sweet, this should be pretty fun, first I started by creating the new folder at C:\Shared\UserProfiles on the Server 2012 R2 box. For this I used the New-Item cmdlet as shown below.

001
New-Item -ItemType Directory -Path C:\Shared\UserProfiles -Verbose

     After Creating the new directory its ready to be shared, I have to say I really utilize PowerShell_ISE.exe and tab completion every time I create a new SMB or Server Message Block share with PSv3.0+


001
002
003
004
005
006
007
New-SmbShare –Name UserProfiles `
             –Path C:\Shared\UserProfiles `
             –Description ‘User Profiles’ `
             –FullAccess Administrator `
             –ReadAccess Everyone `
             -EncryptData $true `
             -verbose

Here is some output: ( Note: the paths are not all aligned as I'm recreating the output from home.)



Next was to copy all of the data from the old server at location A to the new server at location B. For this I used robocopy by opening an administrative CMD prompt and running the below commands :

robocopy \\oldserver\shared \\newserver\shared


8 hours later I left work and the robocopy was still only about a 1/4th of the way through copying the data to the new share(100+ GBs). . Seeing how the data transfer didn't complete during my shift I ended up asking someone to keep an eye on it as the data transfers and then gave them the below script to run. I turned this script into a function weather that was a good idea or not... but I prefer functions so I went with one. :)  This function will go through all Active Directory users with Get-ADUser and filter them for only the accounts that have a P: drive set for their HomeDrive ( where {$_.HomeDrive -eq "P:"}). From there I used a foreach statement to set each user account and then ended it off with a Get-ADUser to display a formatted output to the screen.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
<#
.Synopsis
   Finds all users with a P: drive as their home drive and resets their homedirectory to equal the New Directory.
.DESCRIPTION
   Retrieves all users with A P: drive and then sets their Home Directory to whatever is specified.
.EXAMPLE
   Set-HomeDirectory
.NOTES
   **New HomeDirectory is hardcoded**
.FUNCTIONALITY
   PowerShell v3.0+
.EXAMPLE
   PS C:\> Set-HomeDirectory -HomeDrive P:
.CREATED BY
    Matthew A. Kerfoot on 8/12/2014
#>

                  [CmdletBinding()]
            param([Parameter( Mandatory = $False,
                              ValueFromPipelineByPropertyName = $true )]
                              $Share = "\\SERVERNAME\Shared",
                  [Parameter( Mandatory = $False,
                              ValueFromPipelineByPropertyName = $true )]
                              $HomeDrive = "P:",
                  [Parameter( Mandatory = $False,
                              ValueFromPipelineByPropertyName = $true )]
                              $VerbosePreference = "Continue"
                )

        Begin{    # Find all users with a P: Drive
                  Import-Module ActiveDirectory
                  $users = Get-ADUser -Filter * -Properties * |
                           where {$_.homedrive -eq "P:"|
                           select -ExpandProperty samaccountname
        }

    Process{    # changes each users home drive and homedirectory
                foreach ($U in $Users)
                {
                    Set-ADUser -Identity $U -HomeDrive $HomeDrive -HomeDirectory "$Share\$u" -Verbose

                }
    }

 End {   # gives a formated output of the changes
         Get-ADUser -Filter * -Properties * |
         where {$_.HomeDrive -eq "$HomeDrive"|
         Select-Object samaccountname, homedrive, homedirectory `
         #| Format-Table -AutoSize
 }

Output:


And I just realized the time on this machine is 2 hours behind...

Until next time...

Thursday, September 11, 2014

Pop up window with PowerShell

PowerShell popup with use of xaml for formatting the output. Enjoy! I know I did, I used this with a gpo login script to help remind users what to do...

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
## creates the runspace
$run = [RunspaceFactory]::CreateRunspace()
$run.ApartmentState = “STA”
$run.Open()
## opens PowerShell.exe
$ps = {Add-Type -AssemblyName PresentationCore}.GetPowerShell()
$ps.Runspace = $run
## specify xaml formatting
$ps.AddScript({
    [xml]$xaml = @"
    <Window
        xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
        xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
        x:Name='Window' WindowStartupLocation = 'CenterScreen' Width = '1000' Height = '500' ShowInTaskbar = 'True' WindowStyle = 'None' AllowsTransparency = 'true'>
        <Window.Background>
            <SolidColorBrush Opacity= '0' ></SolidColorBrush>
        </Window.Background>
        <Grid x:Name = 'Grid' ShowGridLines='false' >
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height = '*'/>
            </Grid.RowDefinitions>
            <Viewbox Stretch = 'Fill'>
                <Label x:Name='Content' FontWeight = 'Bold' Content = 'PowerShell Rules!' FontSize = '30' FontStyle = 'Normal' Foreground = 'Blue' />
            </Viewbox>
        </Grid>
    </Window>
"@

    ## read xaml code
    $reader=(New-Object System.Xml.XmlNodeReader $xaml)
    $Global:popup=[Windows.Markup.XamlReader]::Load( $reader )
    ## sets right click to "Close Window"
    $popup.Add_MouseRightButtonUp({$this.close()})
    ## sets left click to "Drag\move Window"
    $popup.Add_MouseLeftButtonDown({$This.DragMove()})
    ## Always on top of all other windows
    $popup.Topmost = $True
    $popup.ShowDialog()
}).BeginInvoke() | Out-Null


Cleanup WinSxS

Cleanup WinSxS with PowerShell, remove features on demand in Windows Server 2012.

001
Get-WindowsFeature | where-object{$_.Installed -eq 0 -and $_.InstallState -eq 'Available'}


001
Get-WindowsFeature | where-object{$_.Installed -eq 0 -and $_.InstallState -eq 'Available'| uninstall-windowsfeature -remove