Video Presentation with Experts Live TV available online on Channel9 and YouTube

Last week I met up with Bert Wolters for a video presentation/interview. Bert has been recording a series of sessions on the latest and greatest functionality in Windows 10 and in this episode I discuss some of the new functionalities in PowerShell 5.0 in combination with Windows 10. The video has been recorded in Dutch, so unfortunately it will a bit hard to follow for the English speaking community.

In the video I showcase the following features:

  • Better Multiline support for the PowerShell console
  • Colored console for cmdlets, parameters and arguments
  • PowerShell cmdlets for Windows Defender
  • PowerShell debugging in the ISE using <CTRL> + B
  • DuPSUG, Dutch PowerShell User Group

Alternatively the video is also available on Microsoft’s Channel9:

For more information or the direct link of the video in this article please refer to the links below. Feel free to leave a comment either here or in the YouTube comment section.

Links in the article
Channel9 – Experts Live TV – 10 weken Windows 10 – Aflevering 9 – Powershell 5
Channel9 – Windows 10 in 10 Minuten
YouTube – Experts Live TV – 10 weken Windows 10 – Aflevering 9 – Powershell 5
DuPSUG.com, Dutch PowerShell User Group
TwitterLinkedInFacebookGoogle+RedditWordPressEmailTumblrPinterestHacker NewsShare

Clear-RecycleBin New PowerShell 5.0 cmdlet, available in Windows 10

In PowerShell 5.0 a new cmdlet has been introduced that provides the ability to clear the Recycle Bin programmatically. It supports the following four parameters:

  1. DriveLetter
  2. Force
  3. WhatIf
  4. Confirm

Unfortunately there is no Get-RecycleBin cmdlet, for this purpose I have written a short function that enumerates the contents of Recycle Bin for the current user:

1
2
3
4
Function Get-RecycleBin {
    (New-Object -ComObject Shell.Application).NameSpace(0x0a).Items() |
	Select-Object Name,Size,Path
}

Get-RecycleBin

By verifying this output we can now determine if we would like to Clear the Recycle Bin or if some files that are stored there should be recovered before deleting all files. The following command will delete all files from the Recycle Bin for all drive letters:

1
Clear-RecycleBin

Clear-RecycleBin

The default mode of operation of this cmdlet is to ask for confirmation before deleting all files. This is similar behavior to right clicking the icon of Recycle Bin and clicking ‘Empty Recycle Bin’. To delete the files without confirmation the following code can be used:

1
Clear-RecycleBin -Force

Alternatively the Confirm parameter can also be explicitly set to $false:

1
Clear-RecycleBin -Confirm:$false

Unfortunately there is no online help available for this cmdlet, so for more information about this cmdlet please refer to the built-in help in PowerShell:

1
Get-Help Clear-RecycleBin -ShowWindow

New versions of Connect-Mstsc and Get-OrphanHomeFolder in TechNet Script Gallery

One of the things that keeps me busy is maintaining the library of scripts I have made available in the TechNet Script Library. I get a good number of questions and requests about my scripts there and I enjoy picking out some of the interesting or useful requests to implement them in my scripts. Recently I received some requests for new functionality in some of my scripts so I decided two of my scripts for the latest round of updates.

For Connect-Mstsc I have updated both the PowerShell 3.0 and up version as well as the version that is backwards compatible with PowerShell 2.0. A new parameter has been introduced, -Public, which corresponds with the /public switch of the mstsc.exe tool. It runs Remote Desktop in public mode, which was requested by MSFTW. Here is an example of this switch parameter in action:

.EXAMPLE   
Connect-Mstsc -ComputerName server01:3389 -User contoso\jaapbrasser -Password supersecretpw -Public

Description 
-----------     
A RDP session to server01 at port 3389 will be created using the credentials of contoso\jaapbrasser and the /public switch will be set for mstsc

Get-OrphanHomeFolder has been updated to support wildcards/regular expressions to be able to exclude folders. This came from a request of martin_i who has a lot of folders named .v2 which he would like to exclude instead of manually specifying each path. Here is an example:

.EXAMPLE    
.\Get-OrphanHomeFolder.ps1 -HomeFolderPath \\Server02\Fileshare\Home -MoveFolderPath \\Server03\Fileshare\MovedHomeFolders -ExcludePath '\.v2$' -RegExExclude 
 
Description: 
Will list all the folders in the \\Server02\Fileshare\Home folder and will move orphaned folders using robocopy, excluding folders that end with .v2

For more information or the direct download links of these scripts please refer to the links below. Feel free to leave a comment either here or in the TechNet Script Library.

TechNet Script Gallery
My entries in TechNet Script Gallery
Script to get orphaned home folders and folder size
Connect-Mstsc – Open RDP Session with credentials
Connect-Mstsc – Open RDP Session with credentials (PowerShell 2.0)

Active Directory Friday: Use MSAD_ReplNeighbor WMI class to replicate Active Directory

This article will provide details of initiating replication of using WMI in PowerShell. There are a lot of possible methods of starting replication such as using the ‘Active Directory Sites and Services’ console, using the Active Directory PowerShell module and the Sync-ADObject cmdlet.

We will use the MSAD_ReplNeighbor WMI Class for this purpose and specifically the SyncNamingContext method to initiate replication. This class is available in the root\MicrosoftActiveDirectory path on your domain controllers. The commands in this article should be executed on a domain controller. I have made the choice the use the Get-WmiObject in this article as the SyncNamingContext method is not available when using the Get-CimInstance cmdlet, aside from that method all commands can be executed using the Get-CimInstance

In the first code example I will access the MSAD_ReplNeighbor class and retrieve all information. In this article I will use a technique called splatting to input the parameters into the cmdlet:

1
2
3
4
5
$WmiSplat = @{
    Class = 'MSAD_ReplNeighbor'
    Namespace = 'root\MicrosoftActiveDirectory'
}
Get-WmiObject @WmiSplat | Get-Member

The output from this command will display all the available properties and methods, including the SyncNamingContext method that we will use in this article. To view the available partitions for replication, we can use the Select-Object cmdlet to only select the Unique NamingContextDN properties of the returned objects:

1
2
3
4
5
$WmiSplat = @{
    Class = 'MSAD_ReplNeighbor'
    Namespace = 'root\MicrosoftActiveDirectory'
}
Get-WmiObject @WmiSplat | Select-Object -Property NamingContextDN -Unique

Replicate-UniqueNamingDN

Based on this output we determine that the ‘DC=jaapbrasser,DC=com’ partition is the partition we are interested in. In the following code we will filter out only that partion and display a number of selected properties:

1
2
3
4
5
6
$WmiSplat = @{
    Class = 'MSAD_ReplNeighbor'
    Namespace = 'root\MicrosoftActiveDirectory'
    Filter = "NamingContextDN = 'DC=jaapbrasser,DC=com'"
}
Get-WmiObject @WmiSplat | Select-Object -Property SourceDsaCN,SourceDsaSite,TimeOfLastSyncSuccess,Replicaflags

Replicate-ViewReplication

The first thing that you’ll notice is that the two properties Replicaflags and TimeOfLastSyncSuccess are hard to read, in the following two examples two different approaches are shown to properly convert the TimeOfLastSyncSuccess property to a more human readable output:

1
2
3
4
5
6
7
8
9
10
$WmiSplat = @{
    Class = 'MSAD_ReplNeighbor'
    Namespace = 'root\MicrosoftActiveDirectory'
    Filter = "NamingContextDN = 'DC=jaapbrasser,DC=com'"
}
$DateTimeOfLastSyncSuccess = @{
    Name = 'DateTimeOfLastSyncSuccess'
    Expression = {[Management.ManagementDateTimeConverter]::ToDateTime($_.TimeOfLastSyncSuccess)}
}
Get-WmiObject @WmiSplat | Select-Object -Property SourceDsaCN,SourceDsaSite,$DateTimeOfLastSyncSuccess,Replicaflags

Alternatively we can use the Get-CimInstance cmdlet which already provides the converted object:

1
2
3
4
5
6
$CimSplat = @{
    Class = 'MSAD_ReplNeighbor'
    Namespace = 'root\MicrosoftActiveDirectory'
    Filter = "NamingContextDN = 'DC=jaapbrasser,DC=com'"
}
Get-CimInstance @CimSplat | Select-Object -Property SourceDsaCN,SourceDsaSite,TimeOfLastSyncSuccess,Replicaflags

Replicate-CimInstance

In order to be able to convert the Replicaflags attribute the value in the property should be converted using the table found in MSAD_ReplNeighbor class article on MSDN. Here is a portion of the the table available on MSDN:

Value
DS_REPL_NBR_WRITEABLE
16 (0x10)
DS_REPL_NBR_SYNC_ON_STARTUP
32 (0x20)
DS_REPL_NBR_DO_SCHEDULED_SYNCS
64 (0x40)
DS_REPL_NBR_USE_ASYNC_INTERSITE_TRANSPORT
128 (0x80)
DS_REPL_NBR_TWO_WAY_SYNC
512 (0x200)
DS_REPL_NBR_RETURN_OBJECT_PARENTS
2048 (0x800)
DS_REPL_NBR_FULL_SYNC_IN_PROGRESS
65536 (0x10000)
DS_REPL_NBR_FULL_SYNC_NEXT_PACKET
131072 (0x20000)
DS_REPL_NBR_NEVER_SYNCED
2097152 (0x200000)
DS_REPL_NBR_PREEMPTED
16777216 (0x1000000)
DS_REPL_NBR_IGNORE_CHANGE_NOTIFICATIONS
67108864 (0x4000000)
DS_REPL_NBR_DISABLE_SCHEDULED_SYNC
134217728 (0x8000000)
DS_REPL_NBR_COMPRESS_CHANGES
268435456 (0x10000000)
DS_REPL_NBR_NO_CHANGE_NOTIFICATIONS
536870912 (0x20000000)
DS_REPL_NBR_PARTIAL_ATTRIBUTE_SET
1073741824 (0x40000000)

Using the information in this table in combination with the Switch statement the output can be converted in a more human readable format, listing all the flags in text instead of a single integer. In the next example I have also updated the Filter to automatically fill in the current domain name by using the [adsi] type accelerator to select the distinguishedname of the default naming context:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$WmiSplat = @{
    Class = 'MSAD_ReplNeighbor'
    Namespace = 'root\MicrosoftActiveDirectory'
    Filter = "NamingContextDN = '$(-join ([adsi]'').distinguishedname)'"
}
$DateTimeOfLastSyncSuccess = @{
    Name = 'DateTimeOfLastSyncSuccess'
    Expression = {[Management.ManagementDateTimeConverter]::ToDateTime($_.TimeOfLastSyncSuccess)}
}
$ReadableReplicaFlags = @{
    Name = 'ReadableReplicaFlags'
    Expression = {
        Switch ($_.ReplicaFlags) {
            {$_ -bor 0x10} {'DS_REPL_NBR_WRITEABLE'}
            {$_ -bor 0x20} {'DS_REPL_NBR_SYNC_ON_STARTUP'}
            {$_ -bor 0x40} {'DS_REPL_NBR_DO_SCHEDULED_SYNCS'}
            {$_ -bor 0x80} {'DS_REPL_NBR_USE_ASYNC_INTERSITE_TRANSPORT'}
            {$_ -bor 0x200} {'DS_REPL_NBR_TWO_WAY_SYNC'}
            {$_ -bor 0x800} {'DS_REPL_NBR_RETURN_OBJECT_PARENTS'}
            {$_ -bor 0x10000} {'DS_REPL_NBR_FULL_SYNC_IN_PROGRESS'}
            {$_ -bor 0x20000} {'DS_REPL_NBR_FULL_SYNC_NEXT_PACKET'}
            {$_ -bor 0x200000} {'DS_REPL_NBR_NEVER_SYNCED'}
            {$_ -bor 0x1000000} {'DS_REPL_NBR_PREEMPTED'}
            {$_ -bor 0x4000000} {'DS_REPL_NBR_IGNORE_CHANGE_NOTIFICATIONS'}
            {$_ -bor 0x8000000} {'DS_REPL_NBR_DISABLE_SCHEDULED_SYNC'}
            {$_ -bor 0x10000000} {'DS_REPL_NBR_COMPRESS_CHANGES'}
            {$_ -bor 0x20000000} {'DS_REPL_NBR_NO_CHANGE_NOTIFICATIONS'}
            {$_ -bor 0x40000000} {'DS_REPL_NBR_PARTIAL_ATTRIBUTE_SET'}
        }
    }
}
Get-WmiObject @WmiSplat | Select-Object -Property SourceDsaCN,SourceDsaSite,$DateTimeOfLastSyncSuccess,$ReadableReplicaFlags

Replicate-Formatted

By creating both the $DateTimeOfLastSyncSuccess and $ReadableReplicaFlags hashtables, the content can now be displayed in a human readable format, which should make it easier to determine how replication is progressing or where it would be interesting to attempt to initiate replication.

The following example will start replication of the domain partition with all site links of the current server. The ClassName and Filter parameter have been replaced by the Query parameter to illustrate a different approach of querying for this information.

1
2
3
4
5
6
7
8
$WmiSplat = @{
    Namespace = 'root\MicrosoftActiveDirectory'
    Query = "Select * From MSAD_ReplNeighbor Where NamingContextDN = '$(-join ([adsi]'').distinguishedname)'"
}
Get-WmiObject @WmiSplat | ForEach-Object {
    Write-Output "Replicate domain partition: $($_.Domain) from DC: $($_.SourceDsaCN) in the $($_.SourceDsaSite) site"
    $_.SyncNamingContext()
}

Replicate-Replication

This will replicate the domain partition with the defined site links. The Write-Output cmdlet will show which DC and which site replication has been started with. The SyncNamingContext method does accept a single argument as well, an integer that contains the parameters for this method.

For a complete overview of the available parameters please refer to this table:

Parameter Value
DS_REPSYNC_ASYNCHRONOUS_OPERATION 0x1
DS_REPSYNC_WRITEABLE 0x2
DS_REPSYNC_PERIODIC 0x4
DS_REPSYNC_INTERSITE_MESSAGING 0x8
DS_REPSYNC_ALL_SOURCES 0x10
DS_REPSYNC_FULL 0x20
DS_REPSYNC_URGENT 0x40
DS_REPSYNC_NO_DISCARD 0x80
DS_REPSYNC_FORCE 0x100
DS_REPSYNC_ADD_REFERENCE 0x200

Using the examples in this article you can now verify when replication last occurred and replicate a Active Directory partition between two or multiple sites. If you have any questions or feedback on this article feel free to use the comments section and for more information on this MSAD_ReplNeighbor WMI class have a look at the following resources:

MSAD_ReplNeighbor WMI class
MSAD_ReplNeighbor class
SyncNamingContext method of the MSAD_ReplNeighbor class

Windows 10: Using the Get-WindowsUpdateLog cmdlet

This post is part of the Windows 10 blog series in which I will look at a number of new functionalities in Windows 10 as well as new functionality in PowerShell 5.0. In every article I will highlight a specific cmdlet or technology and provide additional information about the cmdlet

The recently introduced Get-WindowsUpdateLog cmdlet merges the Windows Update logs that are stored in ETL files together into a single plain text log file. The following command can be used to convert these log to a log file:

1
Get-WindowsUpdateLog -LogPath $env:temp\UpdateLog.log

Get-WindowsUpdateLog

Unfortunately the output from this cmdlet is send directly to the host, so it is not possible to store this information in a variable or to interact with it in a meaningful way. I hope this will be corrected before release as it makes it a bit cumbersome to interact with this cmdlet.

The cmdlet works by a three steps process:

  1. Read Information from the .etl files
  2. Convert to intermediate format, either CSV or XML
  3. Convert the intermediate to text and output to the specified logpath

To view the information stored in the intermediate file, which is in a nice structured format the following code can be used:

1
Import-Csv -Path C:\Users\JAAPBR~1\...\wuetl.CSV.tmp.00000

The converted log is available in the specified path, to open the log file in the default text editor, usually notepad, the Invoke-Item can be used:

1
Invoke-Item -Path $env:temp\UpdateLog.log

NotepadWindowsUpdateLog

Get-WindowsUpdateLog
Get-WindowsUpdateLog