PowerShell for Windows Admins


December 23, 2013  10:06 AM

LastLogoff timestamp



Posted by: Richard Siddaway
Security

I was recently asked if there was any way to fill in the LastLogoff timestamp

The short answer is no.  The values in the attributes related to logons are maintained by Active Directory during the logon process.

I wouldn’t want them to be programmable as that as would create a potential loop hole in my logging process.

As far as I can tell LastLogoff isn’t currently used in Active Directory though if you have access to the Exchange cmdlets you could use Get-mailboxStatistics to discover logon and loggoff times to the mailbox which would be close

December 23, 2013  9:49 AM

Scripting Games 2014–more information



Posted by: Richard Siddaway
Scripting Games 2014

More information is available on the Games:

Logon and operational information

http://powershell.org/wp/2013/12/21/important-scripting-games-login-and-operational-information/

Events and Event authors

http://powershell.org/wp/2013/12/21/2014-winter-scripting-games-the-event-authors/

Team Foundation Tips

http://powershell.org/wp/2013/12/19/2014-winter-scripting-games-team-formation-tips/

Games schedule

http://powershell.org/wp/2013/12/16/2014-winter-scripting-games-schedule/

Registration opens 2 January 2014 with a practice event starting on 6 January

Time to get the teams organized in between the Turkey and Mince Pies


December 17, 2013  5:15 AM

Countdown to the Scripting Games–32 days and counting



Posted by: Richard Siddaway
Scripting Games

The countdown to the Winter 2014 Scripting Games has started.

Officially starting at 1am (UTC or GMT) 19 January 2014 the following dates should be noted:

2 January 2014 – registration opens

6 January 2014 – a practice event becomes available

19 January 2014 – event 1 starts

26 January 2014 – event 2 starts

2 February 2014 – event 3 starts

9 February 2014 – event 4 starts

 

Each event lasts one (1) week

As explained previously the events are designed to be tackled by teams of 2-6 people.

Coaching will be available during the Games if teams would like to use it.

The judging and coaching teams are separate.

Details from http://powershell.org/wp/2013/12/16/2014-winter-scripting-games-schedule/

£> (Get-Date -Day 19 -Month 1 -Year 2014 -Hour 1 -Minute 0 -Second 0 ) – (Get-Date) | Format-List Days, Hours, Minutes,
Seconds
Days        : 32
Hours      : 13
Minutes  : 47
Seconds  : 33

Enjoy


December 17, 2013  3:06 AM

Deal of the Day–17 December 2013



Posted by: Richard Siddaway
Books, PowerShell

Manning – www.manning.com – have multiple PowerShell books as their deal of the day – today and tomorrow. The deal started at midnight ET today ( 3am GMT) and lasts for 48 hours.   Books included:

PowerShell and WMI

PowerShell in Practice

PowerShell in Depth

PowerShell Deep Dives

Windows PowerShell in Action, Second Edition

Learn PowerShell 3 in a Month of Lunches, Second Edition

Learn PowerShell Toolmaking in a Month of Lunches.

Get 50 % off these titles today and tomorrow with code dotd1217au


December 16, 2013  2:31 PM

A new version of ADMT



Posted by: Richard Siddaway
Active Directory

A new version of the AD Migration Tool (ADMT) has been announced – http://blogs.technet.com/b/askds/archive/2013/12/13/an-update-for-admt-and-a-few-other-things-too.aspx

While not ready for download just yet at least we know its in the pipeline and supports the newer versions of Windows

 


December 16, 2013  2:20 PM

CDXML–adding search parameters



Posted by: Richard Siddaway
CDXML, CIM, PowerShell 3, PowerShell v4

Last time you saw how to create a cmdlet from the Win32_NetWorkAdapterConfiguration class:

<?xml version=’1.0′ encoding=’utf-8′?>

<PowerShellMetadata xmlns=’http://schemas.microsoft.com/cmdlets-over-objects/2009/11′>

<Class ClassName=’ROOT\cimv2\Win32_NetworkAdapterConfiguration’>

<Version>1.0</Version>

<DefaultNoun>NetworkAdapterConfiguration</DefaultNoun>

<InstanceCmdlets>

<GetCmdletParameters DefaultCmdletParameterSet=’DefaultSet’>

</GetCmdletParameters>

</InstanceCmdlets>

</Class>

</PowerShellMetadata>

 

Now its time to add some parameters that can be used for searching. This will be equivalent to performing these actions:

 

Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter “DHCPEnabled=’True’”

Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter “IPEnabled=’True’”

Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter “Index=0″

Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter “InterfaceIndex=3″

 

Lets start by looking at the DHCPEnabled property

£> $class = Get-CimClass -ClassName Win32_NetworkAdapterConfiguration

£> $class.CimClassProperties["DHCPEnabled"]

Name                            : DHCPEnabled

Value                             :

CimType                       : Boolean

Flags                              : Property, ReadOnly, NullValue

Qualifiers                      : {MappingStrings, read}

ReferenceClassName :

The parameter DHCPEnabled takes a Boolean value. At the moment I don’t want anything clever like pipeline input – just the ability to use a parameter

 

This requirement translates to:

<?xml version=’1.0′ encoding=’utf-8′?>

<PowerShellMetadata xmlns=’http://schemas.microsoft.com/cmdlets-over-objects/2009/11′>

<Class ClassName=’ROOT\cimv2\Win32_NetworkAdapterConfiguration’>

<Version>1.0</Version>

<DefaultNoun>NetworkAdapterConfiguration</DefaultNoun>

<InstanceCmdlets>

<GetCmdletParameters DefaultCmdletParameterSet=’DefaultSet’>

 

<QueryableProperties>

<Property PropertyName=”DHCPEnabled”>

<Type PSType = “System.Boolean”/>

<RegularQuery >

<CmdletParameterMetadata PSName=”DHCPEnabled” />

</RegularQuery>

</Property>

 

</QueryableProperties>

 

</GetCmdletParameters>

</InstanceCmdlets>

</Class>

</PowerShellMetadata>

 

The changes are defined by the <QueryableProperties> tags

<QueryableProperties>

 

Define the WMI property you are searching on

<Property PropertyName=”DHCPEnabled”>

Define the type of the data the parameter accepts

<Type PSType = “System.Boolean”/>

Define the query type – in this case a straight forward search

<RegularQuery >

 

Define the name you want the parameter to have – doesn’t have to match the WMI property name

<CmdletParameterMetadata PSName=”DHCPEnabled” />

</RegularQuery>

</Property>

 

</QueryableProperties>

You can use the changed cmdlet like this:

Get-NetworkAdapterConfiguration

Get-NetworkAdapterConfiguration -DHCPEnabled $true

Get-NetworkAdapterConfiguration -DHCPEnabled $false

 

The full syntax on the cmldet is:

Get-NetworkAdapterConfiguration [-DHCPEnabled <bool[]>]

[-CimSession <CimSession[]>] [-ThrottleLimit <int>]

[-AsJob] [<CommonParameters>]

 

The cmdlets over objects technology automatically adds these parameters:

-CimSession

-ThrottleLimit

-AsJob

-CommonParameters

 

Next time we’ll add the other search properties

 


December 15, 2013  9:18 AM

CDXML–network adapter configuration



Posted by: Richard Siddaway
CDXML, CIM, PowerShell 3, PowerShell v4

I’ve amended the new-cdxml function created earlier in the series:

function new-cdxml {

[CmdletBinding()]

param (

[Parameter(Mandatory=$true)]

[string]$class,

[Parameter(Mandatory=$true)]

[string]$noun,

[string]$namespace = ‘ROOT\cimv2′,

[string]$path = “C:\Scripts\Modules\Hardware”

)

$code = @”

<?xml version=’1.0′ encoding=’utf-8′?>

<PowerShellMetadata xmlns=’http://schemas.microsoft.com/cmdlets-over-objects/2009/11′>

<Class ClassName=’$namespace\$class’>

<Version>1.0</Version>

<DefaultNoun>$noun</DefaultNoun>

<InstanceCmdlets>

<GetCmdletParameters DefaultCmdletParameterSet=’DefaultSet’>

</GetCmdletParameters>

</InstanceCmdlets>

</Class>

</PowerShellMetadata>

“@

$file = Join-Path -Path $path -ChildPath “$class.cdxml”

Write-Verbose -Message $file

Set-Content -Path $file -Value $code

}

The change is making the class and noun parameters mandatory. In PowerShell 3 & 4 you can simplify the syntax slightly:

param (

[Parameter(Mandatory)]

[string]$class,

[Parameter(Mandatory)]

[string]$noun,

[string]$namespace = ‘ROOT\cimv2′,

[string]$path = “C:\Scripts\Modules\Hardware”

)

I prefer to use the PowerShell 2.0 syntax and actually state that Mandatory=$true. This is for 2 reasons. Firstly, its what I’m used to and it works – I haven’t got round to changing my default templates. Secondly, I prefer to use this syntax because its immediately apparent to me that the parameter is Mandatory.

This time I’ve used the Win32_NetworkAdapterConfiguration class because it enables me to introduce the use of search (filter) parameters in CDXML cmdlets; it has a number of very useful methods and it enables me to introduce the use of format files.

Using new-cdxml you can create the basic module

<?xml version=’1.0′ encoding=’utf-8′?>

<PowerShellMetadata xmlns=’http://schemas.microsoft.com/cmdlets-over-objects/2009/11′>

<Class ClassName=’ROOT\cimv2\Win32_NetworkAdapterConfiguration’>

<Version>1.0</Version>

<DefaultNoun>NetworkAdapterConfiguration</DefaultNoun>

<InstanceCmdlets>

<GetCmdletParameters DefaultCmdletParameterSet=’DefaultSet’>

</GetCmdletParameters>

</InstanceCmdlets>

</Class>

</PowerShellMetadata>

To add this into the module manifest amend these two lines as shown:

# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess

NestedModules = @(‘Win32_BIOS.cdxml’,

‘Win32_ComputerSystem.cdxml’,

‘Win32_DiskDrive.cdxml’,

‘Win32_NetworkAdapterConfiguration.cdxml’

)

# Functions to export from this module

FunctionsToExport = @(‘Get-Bios’,

‘Get-ComputerSystem’,

‘Get-PhysicalDisk’,

‘Get-NetworkAdapterConfiguration’

)

You now have a hardware module consisting of:

£> Get-Command -Module Hardware

CommandType Name

———– —-

Function Get-Bios

Function Get-ComputerSystem

Function Get-NetworkAdapterConfiguration

Function Get-PhysicalDisk

The output from Get-NetworkAdapterConfiguration on my Windows 8.1 virtual machine looks like this:

ServiceName     DHCPEnabled      Index     Description

———–            ———–                —–         ———–

netvsc                False                         0              Microsoft Hyper-V Network Adapter

kdnic                 True                           1              Microsoft Kernel Debug Network Adapter

tunnel               False                          3              Microsoft ISATAP Adapter

netvsc               False                          4              Microsoft Hyper-V Network Adapter #2

tunnel               False                          5              Microsoft ISATAP Adapter

Now this is the same display that Get-CimInstance produces and for my purposes it doesn’t work. I need to create a format file to produce the display I need. I also want to be able to filter on various criteria including DHCPEnabled, IPEnabled, InterfaceIndex, Index and Description. I also want to be able to search on any of these individually or in any logical combination


December 13, 2013  2:09 PM

Manning offer for Monday 16 December 2013



Posted by: Richard Siddaway
Books

On Monday 16 December Manning are offering 50% off all ebooks using code dot1216au at www.manning.com

Check http://deals.manningpublications.com/countdown2014.html for other deals between now and the end of the year


December 12, 2013  9:00 AM

Deleting domain specific profiles



Posted by: Richard Siddaway
PowerShell, WMI

I had a question regarding these posts:

http://msmvps.com/blogs/richardsiddaway/archive/2012/06.aspx

http://msmvps.com/blogs/richardsiddaway/archive/2013/12/10/1810778.aspx

The question came from someone needing to clean up a set of domain specific profiles.

You can adapt the code in the articles to identify the domain specific profiles like this:

$domain = “mydomain”
Get-CimInstance -ClassName Win32_UserProfile -Filter “Special = ‘$false’” |
select LocalPath, SID, LastUseTime,
@{N=”User”; E={Get-CimInstance -Class Win32_UserAccount -Filter “SID = ‘$($_.SID)’” | select -ExpandProperty Caption}} |
where User -Like “$domain\*”

Once you’ve identified them and ensured that your filters are giving you the correct results you can run this:

$domain = “mydomain”
Get-CimInstance -ClassName Win32_UserProfile -Filter “Special = ‘$false’” |
select LocalPath, SID, LastUseTime,
@{N=”User”; E={Get-CimInstance -Class Win32_UserAccount -Filter “SID = ‘$($_.SID)’” | select -ExpandProperty Caption}} |
where User -Like “$domain\*” |
foreach {
Get-CimInstance -ClassName Win32_UserProfile -Filter “SID = ‘$($_.SID)’” |
Remove-CimInstance -WhatIf

}

NOTICE I’ve left –whatif on the Remove-CimInstance.  It gives you an additional check before you finally commit to deleting the profiles

Alternatively, and better still, put the first set of code into an advanced function and then you can do this:

function get-domainprofile{
[CmdletBinding()]
param (
[string]$domain = “mydomain”
)
Get-CimInstance -ClassName Win32_UserProfile -Filter “Special = ‘$false’” |
select LocalPath, SID, LastUseTime,
@{N=”User”; E={Get-CimInstance -Class Win32_UserAccount -Filter “SID = ‘$($_.SID)’” | select -ExpandProperty Caption}} |
where User -Like “$domain\*”
}

get-domainprofile | foreach {
Remove-CimInstance -Query “Select * FROM Win32_UserProfile WHERE SID = ‘$($_.SID)’” -WhatIf
}

Again I’ve left –whatif in place. Remove it when you’re happy with the tests


December 11, 2013  1:57 PM

Final MEAP for AD Lunches



Posted by: Richard Siddaway
Active Directory, PowerShell

The final MEAP for AD Management in a Month of Lunches has been released. The book is on a half price offer today so still time for a Christmas bargain if you’re quick

http://www.manning.com/siddaway3/


Forgot Password

No problem! Submit your e-mail address below. We'll send you an e-mail containing your password.

Your password has been sent to: