PowerShell for Windows Admins


February 4, 2016  7:47 AM

Some thoughts on finding a users OU

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Active Directory, Powershell

Back in this post http://itknowledgeexchange.techtarget.com/powershell/discovering-a-users-ou/

I showed how to get the OU of a user from the distinguished name of the user object. if you want to display that as part of your output you can create a calculated field

Get-ADUser -Filter * -Properties DisplayName |
select Name, DisplayName, UserPrincipalname, @{N= “Organanisational Unit” ;
E = {($_.DistinguishedName -split ‘,’, 2)[1]}}

In your select statement take the Distinguishedname and split it on the comma – make sure you split it into 2 parts – the second is the OU

Don’t rely on the Displayname alone as its not present for some built in accounts such as administrator

 

February 2, 2016  8:15 AM

AD Management MoL Deal – – 3 February 2016

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Active Directory, Books, Powershell

My Learn Active Directory Management in a Month of Lunches will be part of Manning’s Deal of the Day on 3 February 2016.

Half off my book Learn Active Directory Management in a Month of Lunches. Use code dotd020316au at https://www.manning.com/books/learn-active-directory-management-in-a-month-of-lunches

As usual the deal starts at midnight US ET and is usually active for about 48 hours

 


February 1, 2016  4:41 AM

PowerShell Summit 2016 – – 3 day registration open

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

Three day registration is now open

https://eventloom.com/event/login/PSNA16


January 31, 2016  5:57 AM

Scripting Game puzzle – – January 2016

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
CIM, Powershell

Here’s how I’d solve the puzzle

function get-starttime {
[CmdletBinding()]
param(
[parameter(
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[Alias(‘CN’, ‘Computer’)]
[ValidateNotNullOrEmpty()]
[string[]]$computername = $env:COMPUTERNAME
)

PROCESS {

foreach ($computer in $computername){
$props = [ordered]@{
ComputerName = $computer
StartTime = ”
‘UpTime (Days)’ = 0.0
Status = ‘OFFLINE’
}

if (Test-WSMan -ComputerName $computer -ErrorAction SilentlyContinue) {
$lbt = Get-CimInstance -ClassName Win32_OperatingSystem -ComputerName $computer -ErrorAction SilentlyContinue

if ($lbt) {

$props[‘StartTime’] = $lbt.LastBootUpTime

$upt = [math]::round(((Get-Date) – $lbt.LastBootUpTime).TotalDays, 1)
$props[‘UpTime (Days)’] = $upt

$props[‘Status’] = ‘OK’
}
else {
$props[‘Status’] = ‘ERROR’
}

} ## endif

New-Object -TypeName PSObject -Property $props

} ## end foreach

} ## end PROCESS
}

Create an advanced function. Yes I know I’ve used lower case for the function name. I always do to visually separate my code from cmdlets and other functions.

Use the [parameter] decorator to enable pipeline input. Only a single parameter so don’t need to bother woth positional parameters. Function is supposed to default to local machien so can’t make parameter mandatory.

Requirement to process multiple computers at once presumably means the computername parameter has to take an array – sumultaneous processing implies a work flow which negates the initial requirement to create a function

Use the PROCESS block to run a foreach loop that iterates over the collection of computernames.

Create a hash table for the results – I’ve used an ordered hash table to preserve the property order. Set the values to a failed connection.

use Test-Wsman to see if can reach the computer. If can’t the output object is created. If you can reach the machine then run Get-CimInstance – preferred over Get-WmiObject because it returns the date ready formatted

Assuming that works set the start time and status properties. Calculate the uptime in days. I’d prefer to see  just an integer here – tenths of days doesn’t mean anything to most people

If the call to Get-CimInstance  fails then set the status to ERROR

Output the object.

The requirement to add a proeprty for patching is not clear but I’m assuming it means if the machine has been up for more than 30 days with the 1/10 month as a typo

if you want to add that then

Add a property

MightNeedPatching = $false

to the hash table when you create it

and add this line

if ($upt -ge 30){$props[‘MightNeedPatching’] = $true}

after

$upt = [math]::round(((Get-Date) – $lbt.LastBootUpTime).TotalDays, 1)
$props[‘UpTime (Days)’] = $upt


January 30, 2016  3:47 AM

PowerShell Deal of the Day – – 31 January 2016

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Books, Powershell

PowerShell in Action, Third Edition is Manning’s Deal of the Day Sunday 31 January 2016

Deal of the Day January 31: Half off Windows PowerShell in Action, Third Edition. Use code dotd013116au at https://www.manning.com/books/windows-powershell-in-action-third-edition

PowerShell in Depth, Second Edition is also available as part of the deal

Deal of the Day January 31: Half off my book PowerShell in Depth, Second Edition. Use code dotd013116au at https://www.manning.com/books/powershell-in-depth-second-edition

The deal will go live at Midnight US ET and will stay active for about 48 hours to account for time zones.

 


January 28, 2016  6:01 AM

PowerShell editing options

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

I’ve used the ISE since it first appeared in PowerShell 2.0 but there are a couple of recent annocements that increase your code editing options

ISE previews will become available out of band rather than being tied to WMF/OS releases

http://blogs.msdn.com/b/powershell/archive/2016/01/20/introducing-the-windows-powershell-ise-preview.aspx

The preview ISE is a module you can download from the PowerShell gallery and runs side-by-side with your existing version of ISE

Currently this is a PowerShell 5.0 only option

The current preview  hasn’t changed much – its just to test the delivery mechanism. Look for updates approximately monthly.

The second interesting editing option is Visual Studio Code which has PowerShell support

http://blogs.msdn.com/b/powershell/archive/2015/11/17/announcing-windows-powershell-for-visual-studio-code-and-more.aspx

as well as a host of other languages. if you have to work across multiple languages this may be an option for you

Alternativley, if you use Visual Studio a lot you have the PowerShell Tools for Visual Studio option

http://blogs.msdn.com/b/powershell/archive/2015/04/19/do-not-delete-publish-powershell-tools-for-visual-studio-now-available.aspx


January 27, 2016  9:37 AM

Which filter

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Active Directory, Powershell

Get-ADUser has 2 filter parameters.

The –Filter takes a PowerShell syntax filter e.g.

Get-ADUser -Filter {Name -eq ‘Richard’}

The –LDAPfilter takes an LDAP search filter e.g.

Get-ADUser -LDAPFilter “(Name=Richard)”

Mixing them up will ensure you don’t get the results you want


January 26, 2016  11:28 AM

Rescuing IE favourites

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

I received the new Windows Insider Windows 10 build over the wekend and have just discovered that installing it wiped out my IE favourites – or at least those in folders.

I’d copied my favourites to Microsoft Edge when installing Windows 10 so I can copy everything back

IE favourites are stored at

Get-ChildItem -Path ‘C:\Users\<user>\Favorites’

Yoy can clean out the favourites:

Get-ChildItem -Path ‘C:\Users\<user>\Favorites’ | Remove-Item –Force

You will be asked to confirm the action.

Microsft Edge favourites are at

Get-ChildItem -Path ‘C:\Users\<user>\AppData\Local\Packages\Microsoft.MicrosoftEdge_8wekyb3d8bbwe\AC\MicrosoftEdge\
User\Default\Favorites’ –Recurse

Copy them into the IE favourites folder

Get-ChildItem -Path ‘C:\Users\<user>\AppData\Local\Packages\Microsoft.MicrosoftEdge_8wekyb3d8bbwe\AC\MicrosoftEdge\
User\Default\Favorites’ | Copy-Item -Destination ‘C:\Users\<user>\Favorites’ -Force -Recurse

Job done


January 26, 2016  8:21 AM

FQDN

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

How do you find the FQDN of the machine you’re using.  The simplest way is to combine a couple of environmental variables:

PS> “$env:COMPUTERNAME.$env:USERDNSDOMAIN”
SERVER02.MANTICORE.ORG

If you like using CIM (and who doesn’t) you can try this

PS> Get-CimInstance -ClassName Win32_ComputerSystem |
>> select @{N=’FQDN’; E={“$($_.DNSHostName).$($_.Domain)”}}
>>

FQDN
—-
server02.Manticore.org

This could easily be used for remote machines as well by adding the –ComputerName parameter to Get-CimInstance

If you want to go down the .NET route you have:

PS> [System.Net.Dns]::GetHostByName(”).HostName
server02.Manticore.org


January 24, 2016  4:56 AM

CDXML filter parameters

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
CIM, Powershell, WMI

I was recently asked about adding a filter parameter to a cmdlet created through CDXML. If you’ve not seen it before (see PowerShell and WMI Chapters 18 & 19 from www.manning.com) CDXML allows you to creat ecmdlets by wrapping a WMI class in some simple XML.

The resultaing CDXML (Cmdlet Definition XML) is thn published as a module.  Here’s a simple example using 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>

The first 2 lines are boilerplate. The NameSpace and WMI class are defined on line 3, follwoed by a version number (arbitary) and a default noun for you cmdlet to use.  Instance cmdlets defines how you’ll pull the data for existing instances of the class – in other words the Get-NetworkAdapterConfiguration cmdlet.

Save as a CDXML file and import as a module

Import-Module .\NetworkAdapterConfiguration.cdxml

Get-Module will sjow it as a Cim module with a single exported command.   Use it like any other cmdlet

PS> Get-NetworkAdapterConfiguration | ft -a

ServiceName  DHCPEnabled Index Description
———–  ———– —– ———–
kdnic        True        0     Microsoft Kernel Debug Network Adapter
mwlu97w8     True        1     Marvell AVASTAR Wireless Composite Device
msu64w8      False       2     Surface Ethernet Adapter
mwlu97w8     True        3     Marvell AVASTAR 350N Wireless Network Controller
RFCOMM       False       4     Bluetooth Device (RFCOMM Protocol TDI)
BthPan       True        5     Bluetooth Device (Personal Area Network)
vwifimp      True        6     Microsoft Wi-Fi Direct Virtual Adapter
vwifimp      True        7     Microsoft Wi-Fi Direct Virtual Adapter
RasSstp      False       8     WAN Miniport (SSTP)
RasAgileVpn  False       9     WAN Miniport (IKEv2)
Rasl2tp      False       10    WAN Miniport (L2TP)
PptpMiniport False       11    WAN Miniport (PPTP)
RasPppoe     False       12    WAN Miniport (PPPOE)
NdisWan      False       13    WAN Miniport (IP)
NdisWan      False       14    WAN Miniport (IPv6)
NdisWan      False       15    WAN Miniport (Network Monitor)

Using the cmdlet is equivalent to

Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration

but is easier and requires less typing.

Very often you’ll want to pick a specific adapter – for instance

Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter ‘Index=3′

You can implement the same kind of filters using CDXML. You add a queryable properties section as shown below:

<?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=’Index’>
<Type PSType =’UInt32’/>
<RegularQuery AllowGlobbing=’true’>
<CmdletParameterMetadata PSName=’Index’  ValueFromPipelineByPropertyName=’true’ CmdletParameterSets=’DefaultSet’ />
</RegularQuery>
</Property>
</QueryableProperties>

</GetCmdletParameters>
</InstanceCmdlets>
</Class>
</PowerShellMetadata>

Set the paraemter name – same as property to use here – and the type (unsigned integer). Decide whether pipeline input and wildcards (globbing) are allowed and save the file.

Re-import the module (use the Force) and your new parameter is available

Get-NetworkAdapterConfiguration -Index 3

Its important to understand CDXML – even if you never create a CDXML module – because 2/3 of the cmdlets in Windows Server 2012 and later are created this way.


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: