PowerShell Script to Enable/Disable Sync Rule Provisoning

I had a need to run synchronization without having provisioning on periodically and accomplishing it as a manual process wasn’t going to work. I found a script script online that looked like it might be useful.
(https://social.technet.microsoft.com/Forums/en-US/8d9ae376-8d90-4b6e-8111-5ce9fa18e34e/using-powershell-to-enable-provisioning?forum=ilm2)

I simplified it and made it a function to add to our scheduled run profile script.

function Set-SRProvisoning()
    {
    Param
    (
    [Parameter(Mandatory=$false,Position=0)]$Server="localhost",
    [Parameter(Mandatory=$true,Position=1)]$Enable
    )
    
    set-variable -name URI -value "http://$($Server):5725/resourcemanagementservice' " -option constant
    
    if(@(get-pssnapin | where-object {$_.Name -eq "FIMAutomation"} ).count -eq 0) {add-pssnapin FIMAutomation}
    clear-host

    switch ($Enable)
        {
        $True {$ProvisioningStatus = "sync-rule"}
        $False {$ProvisioningStatus = "none"}
        Default {Write "Bad option"}
        }

    $exportObject = export-fimconfig -uri $URI `
                                        –onlyBaseResources `
                                        -customconfig ("/mv-data") `
                                        -ErrorVariable Err `
                                        -ErrorAction SilentlyContinue
     
    $provisioningState = ($exportObject.ResourceManagementObject.ResourceManagementAttributes | `
                            Where-Object {$_.AttributeName -eq "SyncConfig-provisioning-type"}).Value

    $importChange = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportChange
    $importChange.Operation = 1
    $importChange.AttributeName = "SyncConfig-provisioning-type"
    $importChange.AttributeValue = $ProvisioningStatus
    $importChange.FullyResolved = 1
    $importChange.Locale = "Invariant"
     
    $importObject = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportObject
    $importObject.ObjectType = $exportObject.ResourceManagementObject.ObjectType
    $importObject.TargetObjectIdentifier = $exportObject.ResourceManagementObject.ObjectIdentifier
    $importObject.SourceObjectIdentifier = $exportObject.ResourceManagementObject.ObjectIdentifier
    $importObject.State = 1 
    $importObject.Changes = (,$importChange)
    
    $importObject | Import-FIMConfig -uri $URI -ErrorVariable Err -ErrorAction SilentlyContinue

    switch ($Enable)
        {
        $True {write-host "`nProvisioning enabled successfully`n"}
        $False {write-host "`nProvisioning disabled successfully`n"}
        }
         
    } 

Move Hyper-V VM and Storage Files to New Location

The following script will move all of the VMs on a Hyper-V host to a new storage location. In this case we are moving the VMs from “C:\VM\VirtualMachines\” to “D:\VM\VirtualMachines\.” This script assumes that the VM disks are kept in the VM folder and not in a separate location.

$VMs=Get-VM
$Path="D:\VM\VirtualMachines\$($VM.Name)"

foreach ($VM in $VMs)
    {
    Move-VMStorage -VM $(Get-VM $VM.Name) -DestinationStoragePath $Path
    }

GPG Command Line Examples

Here are some GPG examples for creating symmetric and asymmetric encrypted messages. The code used below is written for PowerShell.

Download keys from a key server

gpg --keyserver pgp.mit.edu --search-keys streeter76@gmail.com
gpg --keyserver pgp.mit.edu --recv-keys 88488596

Import private key

gpg --import ./private.asc

Put the contents of a file into a variable to be encrypted

$a = gc /etc/passwd

Symmetric encryption of the variable contents

$a | gpg --symmetric --armor
# Decrypt the message
$a | gpg --decrypt

Symmetric encryption of the variable contents with the passphrase provided

$a | gpg --symmetric --armor --passphrase password
# Decrypt the message with the passphrase provided
$a | gpg --decrypt --passphrase password

Encrypt the variable contents for a recipient

$a | gpg -e -r joseph.streeter76@gmail.com --armor

Decrypt the message sent to recipient

$b | gpg -d

AD Forest DCDiag and RepAdmin Report

Two earlier posts, EASY TO READ DCDIAG REPORT and EASY TO READ REPADMIN RESULTS, included scripts for displaying the high level results of DCDiag and RepAdmin. I had since combined the two and made some tweaks, but it never really seemed right.

I’ve finally gotten around to making it presentable and more functional. It now displays all of the DCDiag tests and their results in two separate tables rather than just a few of the tests that I’d selected. It also accurately displays the server name for each set of tests. The previous versions would only create reports for a single domain, but now, since I work in a multi domain forest these days, it will grab the DCs in all domains in the forest.

The RepAdmin results are now broken up by domain controller and sorted by context. This makes it a little easier to read and track issues.

# http://www.anilerduran.com/index.php/2013/how-to-parse-dcdiag-output-with-powershell/

############
# Functions 
############
Function Get-ForestDomainControllers
    {
    $Results=@()
    foreach ($domain in (Get-ADForest).domains )
        {
        $Results+=(Get-ADdomain $domain).ReplicaDirectoryServers
        }
    Return $Results
    }

Function Get-DCDiagReport($DC)
    {
    "Testing $DC"
    $DCDIAG = dcdiag /s:$DC /v #/test:Intersite /test:topology
    $DCDiagResults = New-Object System.Object
    $DCDiagResults | Add-Member -name Server -Value $DC -Type NoteProperty -Force
    
    Foreach ($Entry in $DCDIAG) 
        {
        Switch -Regex ($Entry) 
            {
            "Starting" {$Testname = ($Entry -replace ".*Starting test: ").Trim()}
            "passed|failed" {If ($Entry -match "passed") {$TestStatus = "Passed"} Else {$TestStatus = "failed"}}
            }
            
        If ($TestName -ne $null -and $TestStatus -ne $null) 
            {
            $DCDiagResults | Add-Member -Type NoteProperty -name $($TestName.Trim()) -Value $TestStatus -Force
            }
        }
    Return $DCDiagResults
    }

Function Get-ReplReport 
    {
    "Starting Repadmin Tests"

    $Repl = repadmin /showrepl * /csv
    $ReplResults = $Repl | ConvertFrom-Csv 

    $ReplReport = @()

    Foreach ($result in $ReplResults) 
        {
        $ReplReport += New-object PSObject -Property @{
            "DestSite" = $Result.'Destination DSA Site'
            "Dest" = $Result.'Destination DSA'
            "NamingContext" = $Result.'Naming Context'
            "SourceSite" = $Result.'Source DSA Site'
            "Source" = $Result.'Source DSA'
            "Transport" = $Result.'Transport Type'
            "NumberFailures" = $Result.'Number of Failures'
            "LastFailureTime" = $Result.'Last Failure Time'
            "LastSuccessTime" = $Result.'Last Success Time'
            "LastFailureStatus" = $Result.'Last Failure Status'
            }
        }
    Return $ReplReport
    }

##############
# Gather Data 
##############

Clear-Host
Import-Module activedirectory

"Collecting Forest Domain Controllers"
$DCs=Get-ForestDomainControllers

"Starting DCDiag Tests"
$DCDiagRpt=@()
foreach ($DC in $DCs | sort)
    {
    $DCDiagRpt+=Get-DCDiagReport $DC.ToUpper()
    }

#################
# Display Results
#################

"Starting Repadmin Tests"
$ReplRrt=Get-ReplReport

"DCDiag Test Results (Page 1 of 2)"
$DCDiagRpt | ft Server,Connectivity,Advertising,DFSREvent,SysVolCheck,KccEvent,NCSecDesc,Replications,RidManager,Services,Intersite,LocatorCheck -AutoSize
"DCDiag Test Results (Page 2 of 2)"
$DCDiagRpt | ft Server,FrsEvent,KnowsOfRoleHolders,MachineAccount,NetLogons,ObjectsReplicated,SystemLog,VerifyReferences,CheckSDRefDom,CrossRefValidation -AutoSize

"Replication Test Results"
$Servers = $ReplRrt | select -ExpandProperty Source -Unique 

foreach ($Server in ($Servers | Sort))
    {
    "$Server"
    $ReplRrt | ? {$_.Source -eq $Server} | select "NamingContext","Dest","SourceSite","DestSite","NumberFailures","LastFailureTime","LastFailureStatus","LastSuccessTime","Transport" | sort NamingContext,Dest | ft -AutoSize
    }

SQL Cheat Sheet

A place to save the SQL queries that I constantly have to Google.

SELECT Statements

SELECT * 
  FROM [dbo].[table]
  WHERE (column = 'value1') AND (Column = 'value2')

SELECT DISTINCT [column] 
  FROM [dbo].[table]

SELECT column1, COUNT(column2) 
  FROM [dbo].[table]
  GROUP BY email
  HAVING ( COUNT(email) > 1 )

 DECLARE @Temp TABLE (NAME varchar(20))
  INSERT INTO @Temp (NAME)
  SELECT accountName --, COUNT(AccountName) AS Count
  FROM [StagingDirectory].[dbo].[Identities]
  GROUP BY accountName
  HAVING ( COUNT(accountName) > 1 )

  SELECT [accountName]
      ,[lastName]
      ,[firstName]
      ,[initials]
      ,[employeeID]
      ,[employeeStatus]
      ,[employeeType]
      ,[employeeNumber]
  FROM @Temp Temp
  JOIN Identities
  ON Temp.name=Identities.accountname
  ORDER BY accountName

UPDATE Statements

UPDATE [dbo].[table]
  SET column='value'
  WHERE column='value';

UPDATE [dbo].[table] 
  SET Column = REPLACE(Column,'xx','XX')

INSERT Statements

INSERT INTO [dbo].[table] (column1,column2,column3)
  VALUES ('value1','value2','value3');

DELETE Statements

DELETE FROM [dbo].[table] 
  WHERE column = 'value'

MERGE Statements

BEGIN TRAN;
MERGE Target AS T
USING Source AS S
ON (T.EmployeeID = S.EmployeeID) 
WHEN NOT MATCHED BY TARGET AND S.EmployeeName LIKE 'S%' 
    THEN INSERT(EmployeeID, EmployeeName) VALUES(S.EmployeeID, S.EmployeeName)
WHEN MATCHED 
    THEN UPDATE SET T.EmployeeName = S.EmployeeName
WHEN NOT MATCHED BY SOURCE AND T.EmployeeName LIKE 'S%'
    THEN DELETE 
OUTPUT $action, inserted.*, deleted.*;
ROLLBACK TRAN;
GO

PowerShell to Remove Password Not Required Flag in AD

We had a couple thousand users in our test AD that had the Password Not Required flag set without a password. This was causing an error when Microsoft Identity Management tried to set the password for these user objects.

We used the following script to remove the flag and set a password.

$Users = Get-ADUser -searchscope subtree -ldapfilter "(&(objectCategory=User)(userAccountControl:1.2.840.113556.1.4.803:=32))" 
$newPassword = (Read-Host -Prompt "Provide New Password" -AsSecureString)

foreach ($user in $Users)
    {
    Set-ADAccountPassword -Identity $User.samaccountname -NewPassword $newPassword -Reset
    Set-ADAccountControl $User.samaccountname -PasswordNotRequired $false
    }

Generate Unique Logon Name with PowerShell

This script takes the first name, last name, and middle initial to create a logon name so that it’s unique. It creates an array of available names for that user and then selects the first one that will work.

Param(
    $firstName = "Joseph",
    $LastName = "Streeter",
    $MI = "A"
    )

BEGIN 
    {
    Import-Module ActiveDirectory
    }

PROCESS 
    {
    Function Check-UserName($UserName)
        {
        if (Get-ADUser -f {samaccountname -eq $UserName} -ea 0) 
            {
            Return $False
            }
            Else
            {
            Return $True
            }
        }

    $UserNames = @()
    $UserNames += $firstName.substring(0,1) + $LastName
    $UserNames += $firstName.substring(0,1) + $MI + $LastName
  
    $i=1
    do
    {
    $UserNames += $firstName.substring(0,1) + $LastName + $i
    
    $i++    
    }
    while ($i -lt 99)
    
    foreach ($UserName in $UserNames)
        {
        if (Check-UserName $UserName -eq "True")
            {
            $UserName
            Break
            }
        }
    }

END 
    {
    Clear-Variable UserNames
    }

PowerShell Dump DHCP Reservations

A script to dump all of the reservations from a Windows DHCP server

$PropArray = @()
$scopes = Get-DhcpServerv4Scope -ComputerName dhcpprd01

foreach ($scope in $scopes)
    {    
    $Reservations = Get-DhcpServerv4Reservation -ComputerName dhcpprd01 -ScopeId $scope.ScopeId
    foreach ($Reservation in $Reservations)
        {
        $Prop = New-Object System.Object
        $Prop | Add-Member -type NoteProperty -name ScopeID -value $Reservation.ScopeID
        $Prop | Add-Member -type NoteProperty -name IpAddress -value $Reservation.IPAddress
        $Prop | Add-Member -type NoteProperty -name ClientID -value $Reservation.ClientID
        $Prop | Add-Member -type NoteProperty -name Name -value $Reservation.Name
        $Prop | Add-Member -type NoteProperty -name Type -value $Reservation.Type
        $PropArray += $Prop
       
        }
    }
$PropArray | ft -AutoSize

PowerShell Dump DHCP Leases

Dump all of the DHCP leases from a Windows DHCP server into an object using PowerShell

$PropArray = @()
$scopes = Get-DhcpServerv4Scope -ComputerName dhcpprd01

foreach ($scope in $scopes)
    {    
    $Leases = Get-DhcpServerv4Lease -ComputerName dhcpprd01 -ScopeId $scope.ScopeId
    foreach ($Lease in $Leases)
        {
        $Prop = New-Object System.Object
        $Prop | Add-Member -type NoteProperty -name ScopeID -value $Lease.ScopeID
        $Prop | Add-Member -type NoteProperty -name IpAddress -value $Lease.IPAddress
        $Prop | Add-Member -type NoteProperty -name ClientID -value $Lease.ClientID
        $Prop | Add-Member -type NoteProperty -name HostName -value $Lease.HostName
        $Prop | Add-Member -type NoteProperty -name AddressState -value $Lease.AddressState
        $PropArray += $Prop
        }
    }

$PropArray