Monthly Archives: June 2011

PowerShell web cast by Don Jones

Combining Output from Multiple Sources

Webcast: Combining Output from Multiple Sources REGISTER NOW

July 6, 2011, 12pm CST

Presented by: Don Jones

Learn how easy-to-make custom objects not only let you combine output from multiple sources, but also allow you to create calculated properties and columns, customize output formatting, and easily send your output to CSV files, XML files, HTML, or pretty much anything you like.

Don Jones is the founder of and the lead scripting guru at SAPIEN Technologies. He’s the author or more than twenty books on information technology, including Managing Windows with VBScript and WMI, Advanced VBScript for Windows Administrators, and Windows PowerShell: TFM. Don has written and spoken extensively about scripting and automation for years, including columns in REDMOND Magazine,, Microsoft TechNet Magazine, and more, as well as a series of scripting-related Webinars for Microsoft TechNet. Don is a multiple recipient of Microsoft’s MVP Award, and one of the industry’s strongest advocates for Windows administrative automation.

Registration URL: _PSWC

Scripting Guy discusses PAM modules

My codeplex project publishing PowerShell Admin Modules (PAM) is discussed in this post

In particular the Get-OSInfo function from the PAMSysInfo module is heavily featured

UK PowerShell Group–June 2011 PowerShell and Office – slides and scripts

As promised on the Live Meeting the slides and scripts are now available at!/?cid=43cfa46a74cf3e96&sc=documents&uc=1&id=43CFA46A74CF3E96%212924!cid=43CFA46A74CF3E96&id=43CFA46A74CF3E96%212924

UK PowerShell Group–July meeting advance warning

The UK PowerShell group will be presenting a Live Meeting – Tuesday 26 July 2011 @ 7.30pm BST

Subject – PowerShell Remoting

More details to follow

IE history to CSV

Back in April last year I wrote a post about viewing IE history

I had a comment left asking how this could be put into a CSV file

We’ll start by turning the script into an advanced function that outputs an object

function get-iehistory {            
param ()            
$shell = New-Object -ComObject Shell.Application            
$hist = $shell.NameSpace(34)            
$folder = $hist.Self            
$hist.Items() |             
foreach {            
 if ($_.IsFolder) {            
   $siteFolder = $_.GetFolder            
   $siteFolder.Items() |             
   foreach {            
     $site = $_            
     if ($site.IsFolder) {            
        $pageFolder  = $site.GetFolder            
        $pageFolder.Items() |             
        foreach {            
           $visit = New-Object -TypeName PSObject -Property @{            
               Site = $($site.Name)            
               URL = $($pageFolder.GetDetailsOf($_,0))            
               Date = $( $pageFolder.GetDetailsOf($_,2))            

The main changes are to stop writing strings to the output and to create an object to put the data into.

Run the function by dot sourcing the file you have the script in – its easier to do this in ISE Then try these commands

get-iehistory | export-csv iehistory.csv -TypeInformation
Import-Csv iehistory.csv

Setting Security permissions on an AD group

We saw how to create an AD security group here


This is how we can give a user full control of that group

function set-groupsecurity {            
param (            
$dom = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()            
$root = $dom.GetDirectoryEntry()            
$search = [System.DirectoryServices.DirectorySearcher]$root            
$search.Filter = "(&(objectclass=group)(Name=$name))"            
$search.SizeLimit = 3000            
$result = $search.FindOne()            
$object = $result.GetDirectoryEntry()            
$sec = $object.ObjectSecurity            
## set the rights and control type            
$act = [System.Security.AccessControl.AccessControlType]::Allow            
$adrights = [System.DirectoryServices.ActiveDirectoryRights]::GenericAll            
## who does this apply to            
$domname = ([ADSI]"").Name            
$who = New-Object -TypeName System.Security.Principal.NTAccount -ArgumentList "$domname", "jtest"            
# apply rule            
$newrule = New-Object -TypeName System.DirectoryServices.ActiveDirectoryAccessRule -ArgumentList $who, $adrights, $act            

We get a directory object for the group and then get the ObjectSecurity. Create a new rule to allow full control. Assign it to user jtest (could just as easily be a group) and apply the rule

UK PowerShell UG–30 June 2011

The rescheduled UG session (via Live Meeting) on using Office products with PowerShell is tomorrow. Details from

Network Connection Ids

Yesterday I was looking at changing a Network connection id (the name that shows in Network and Sharing Center when you look at the adapters). I kept getting an error – either COM or number of arguments depending if I was running locally or remotely.

I eventually realised that I must be using a connection id that already existed in the Registry.  I tracked them down to


This works for Windows 7 and Windows 2008 R2. Please check for other Windows versions.

This produces a bunch of subkeys of the form


Each of these has a subkey Connection with a value of Name that we are interested in

function get-Registryconnectionid{             
param (             
Write-Verbose "Reading registry keys for IDs"            
$HKLM = 2147483650            
$key = "SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}"            
$reg = [wmiclass]'\\.\root\default:StdRegprov'            
$subkeys = $reg.EnumKey($HKLM, $key)            
foreach ($name in $subkeys.snames){            
  if ($name -eq "Descriptions"){Continue}            
  $conkey = "SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}\$name\Connection"            
  Write-Debug $conkey            
  $cvalue = "Name"            
  $id = $reg.GetStringValue($HKLM, $conkey, $cvalue)  ## REG_SZ            
  $ivalue = "DefaultNameIndex"            
  $index = $reg.GetDwordValue($HKLM, $conkey, $ivalue)  ## REG_DWORD            
  $connection = New-Object -TypeName PSObject -Property @{            
       Index = $index.uValue            
       Connection = $id.sValue            
Retrieves network connection ids 

Retrieves network connection ids held in the registry.
This includes current and previous ids.

.PARAMETER  Computer
Computer name


get-Registryconnectionid -computer server02


This uses the standard WMI methods to read a local or remote registry

The corresponding current values are given by

Get-WmiObject -Class Win32_NetworkAdapter | select NetConnectionId, Index

The two index values are not related

Quick Tip: Discovering service start accounts

Do you know which accounts are used to start the services running on your machines? if you need this information try:

Get-WmiObject -Class Win32_Service | select Name, DisplayName, StartName

For a remote machine this becomes

Get-WmiObject -Class Win32_Service -ComputerName Win7 | select Name, DisplayName, StartName

And for testing which services are started by a specific account use:

Get-WmiObject -Class Win32_Service -ComputerName Win7 | where {$_.StartName -eq 'NT Authority\LocalService'} | select Name, DisplayName, StartName

I wanted to use a WMI filter instead of Where-Object but it didn’t want to work

Creating AD security groups

Continuing my AD excursion for a while. I saw a forum post about creating AD groups and came up with this function

function new-securitygroup {            
param (            
$rootdse = [ADSI]""            
$adpath = "$ou,$($rootdse.distinguishedName)"            
Write-Debug $adpath            
# set constants for group types            
$globalgroup = 0x00000002            
$domainlocalgroup = 0x00000004            
$security = 0x80000000            
$universalgroup = 0x00000008            
$targetou = [ADSI]"LDAP://$adpath"            
switch ($psCmdlet.ParameterSetName) {            
 "DL" {            
        $grouptype1 = $security -bor $universalgroup            
        $grouptype2 = $security -bor $domainlocalgroup}            
 "G"  {$grouptype = $security -bor $globalgroup }            
 "U"  {$grouptype = $security -bor $universalgroup }            
 default {Write-Host "Error!!! Should not be here" }            
$newgroup = $targetou.Create("Group", "cn=$name")            
if ($domainlocal) {            
  $newgroup.GroupType = $grouptype1            
  $newgroup.GroupType = $grouptype2            
else {            
  $newgroup.GroupType = $grouptype            
$newgroup.samAccountname = $name            


Parameter sets are used to keep the group types mutually exclusive

Note how we have to change the group type to universal before changing to domain local

Examples of use are as follows

new-securitygroup -name test-g -ou "ou=All Groups" -global

new-securitygroup -name test-u -ou "ou=All Groups" -universal

new-securitygroup -name test-dl -ou "ou=All Groups" –domainlocal


Trying to change the group type and/or the samaccountname as you create the group will generate an error