Categories

Monthly Archives: October 2012

DnsClient module: #2 DnsClient & Cache

The DnsClient module has a number of Get- cmdlets

Get-DnsClient | Format-List InterfaceAlias, ConnectionSpecificSuffix, Register*, UseSuffix*

An example of the output is

InterfaceAlias                 : Ethernet
ConnectionSpecificSuffix       :
RegisterThisConnectionsAddress : True
UseSuffixWhenRegistering       : False

Of more interest when trouble shooting is Get-DnsClientCache

PS> Get-DnsClientCache | select -f 1 | fl


Entry      : 14.54.10.10.in-addr.arpa
RecordName : 14.54.10.10.in-addr.arpa.
RecordType : PTR
Status     : Success
Section    : Answer
TimeToLive : 86400
DataLength : 4
Data       : Win7test

You get a number of ways to interrogate the cache

PS> Get-Command Get-DnsClientCache  -Syntax

Get-DnsClientCache [[-Entry] <string[]>] [-Name <string[]>] [-Type <Type[]>] [-Status <Status[]>]
[-Section<Section[]>] [-TimeToLive <uint32[]>] [-DataLength <uint16[]>] [-Data <string[]>]
[-CimSession <CimSession[]>][-ThrottleLimit <int>] [-AsJob] [<CommonParameters>]

Its another CIM based cmdlet so you can use CimSessions to access remote machines. Very useful if you think the machine isn’t resolving DNS names properly

UK PowerShell Group–November 2012

When: Tuesday, Nov 13, 2012 7:30 PM (BST)

Where:

*~*~*~*~*~*~*~*~*~*

PowerShell workflows are one of the major new features of PowerShell v3. This session will provide an introduction to using this functionality and some ideas of where they fit into administering your systems

Notes

Richard Siddaway has invited you to attend an online meeting using Live Meeting.
Join the meeting.
Audio Information
Computer Audio
To use computer audio, you need speakers and microphone, or a headset.
First Time Users:
To save time before the meeting, check your system to make sure it is ready to use Microsoft Office Live Meeting.
Troubleshooting
Unable to join the meeting? Follow these steps:

  1. Copy this address and paste it into your web browser:
    https://www.livemeeting.com/cc/usergroups/join
  2. Copy and paste the required information:
    Meeting ID: SP6D69
    Entry Code: P\&c7-C=j
    Location: https://www.livemeeting.com/cc/usergroups

If you still cannot enter the meeting, contact support

Notice
Microsoft Office Live Meeting can be used to record meetings. By participating in this meeting, you agree that your communications may be monitored or recorded at any time during the meeting.

A question of scope

I had a question left on my blog regarding scope.  The following is a simplified version of the problem

            
function level1 {            
 $iterations++            
 Write-Host '$iterations in level 1 = ' $iterations             
 level2            
}            
            
function level2 {            
 $iterations++            
 Write-Host '$iterations in level 2 =' $iterations            
}            
            
$iterations = 0            
            
Write-Host '$iterations at start =' $iterations            
level1            
            
Write-Host '$iterations at end =' $iterations


Start with a variable $iterations. Call a function and increment the variable. Call a nested function and increment the variable and then display the result



The output is



$iterations at start = 0

$iterations in level 1 =  1


$iterations in level 2 = 2


$iterations at end = 0



Start with zero, increment in level1 and level 2 – all OK. Show the final result & its zero.



The reason is scope.  Each of the functions has its own scope. Those scopes are destroyed – along with any variables & their contents when the functions finish.



If you want to keep the results then change to this



function level1 {            
 $global:iterations++            
 Write-Host '$global:iterations in level 1 = ' $global:iterations             
 level2            
}            
            
function level2 {            
 $global:iterations++            
 Write-Host '$global:iterations in level 2 =' $global:iterations            
}            
            
$global:iterations = 0            
            
Write-Host '$global:iterations at start =' $global:iterations            
level1            
            
Write-Host '$global:iterations at end =' $global:iterations


The output becomes



$global:iterations at start = 0

$global:iterations in level 1 =  1


$global:iterations in level 2 = 2


$global:iterations at end = 2



It is recommended not to use scopes in scripts if you can possibly avoid it – it can become very confusing in cases that are more complicated than this. The issue is better handled by passing parameters



function level1 {            
 param ($l1iterations)            
 $l1iterations++            
 Write-Host '$iterations in level 1 = ' $l1iterations            
 $l1iterations = level2 $l1iterations            
 $l1iterations            
}            
            
function level2 {            
param ($l2iterations)            
  $l2iterations++            
 Write-Host '$iterations in level 2 =' $l2iterations            
 $l2iterations            
}            
            
$iterations = 0            
            
Write-Host '$iterations at start =' $iterations            
$iterations = level1 $iterations            
            
Write-Host '$iterations at end =' $iterations


Much more on scope can be found in chapter 22 of my latest book PowerShell in Depth coauthored with Don Jones and Jeff Hicks -  http://www.manning.com/jones2/

DnsClient module: #1 Get-DnsClientServerAddress

Started to investigate the DnsClient module.  First cmdlet to catch my eye was Get-DnsClientServerAddress.

Always good to know a way to find the DNS server.

PS> Get-DnsClientServerAddress

InterfaceAlias               Interface Address ServerAddresses
                             Index     Family
--------------               --------- ------- ---------------
Bluetooth Network Connection        19 IPv4    {}
Bluetooth Network Connection        19 IPv6    {fec0:0:0:ffff::1, fec0:0:0:ffff::2, fec0:0:0:ffff::3}
WiFi                                12 IPv4    {192.168.1.1}
WiFi                                12 IPv6    {}
isatap.tiscali.co.uk                14 IPv4    {192.168.1.1}
isatap.tiscali.co.uk                14 IPv6    {}
Ethernet                            13 IPv4    {}
Ethernet                            13 IPv6    {fec0:0:0:ffff::1, fec0:0:0:ffff::2, fec0:0:0:ffff::3}
Loopback Pseudo-Interface 1          1 IPv4    {}
Loopback Pseudo-Interface 1          1 IPv6    {fec0:0:0:ffff::1, fec0:0:0:ffff::2, fec0:0:0:ffff::3}
Teredo Tunneling Pseudo-I...        15 IPv4    {}
Teredo Tunneling Pseudo-I...        15 IPv6    {}

Now thats OK but I’d like a bit more information – especially the adapter and IP version.  We can get that data using Get-NetAdapter from the NetAdapter module.

Get-DnsClientServerAddress |             
where {$_.ServerAddresses -and $_.InterfaceAlias -notlike "Loop*" }|            
foreach {            
 $nic = $_            
 Get-NetAdapter -IncludeHidden -InterfaceIndex $($nic.InterfaceIndex) |            
 Add-Member -MemberType NoteProperty -Name ServerAddresses -Value $($nic.ServerAddresses) -PassThru |            
 Add-Member -MemberType NoteProperty -Name AddressFamily -Value $(if ($nic.AddressFamily -eq 2){"IPv4"}else{"IPv6"} ) -PassThru|            
 select Name, InterfaceDescription, ifIndex, Status, MacAddress, LinkSpeed, AddressFamily, ServerAddresses             
 }


 



I restricted the output to those interfaces that had DNS server addresses. Used the interface to get the adapter – notice the use of –IncludeHidden – and then used Add-Member to add the addresses and Address family to the data.



These may be CDXML cmdlets but they work the same as any other cmdlet

PowerShell 3 and Word

 

This is a common scenario

$word = New-Object -ComObject "Word.application"            
$word.visible = $true            
$doc = $word.Documents.Add()            
$doc.Activate()            
            
$word.Selection.Font.Name = "Cambria"            
$word.Selection.Font.Size = "20"            
$word.Selection.TypeText("PowerShell")            
$word.Selection.TypeParagraph()            
            
$word.Selection.Font.Name = "Calibri"            
$word.Selection.Font.Size = "12"            
$word.Selection.TypeText("The best scripting language in the world!")            
$word.Selection.TypeParagraph()            
            
$file = "c:\scripts\office\test1.doc"            
$doc.SaveAs([REF]$file)            
            
$Word.Quit()


Create a new Word document – put some text into it and save it with a given file name.  I’ve used it successfully to create server documentation.



Unfortunately with PowerShell v3 it fails with this message



 



Exception calling "SaveAs" with "1" argument(s): "This is not a valid file name.

Try one or more of the following:


* Check the path to make sure it was typed correctly.


* Select a file from the list of files and folders."


At line:17 char:1


+ $doc.SaveAs([REF]$file)


+ ~~~~~~~~~~~~~~~~~~~~~~~


    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException


    + FullyQualifiedErrorId : COMException



It appears not to like the [ref] but if you leave it out you get this



Argument: '1' should be a System.Management.Automation.PSReference. Use [ref].

At line:18 char:1


+ $doc.SaveAs($file)


+ ~~~~~~~~~~~~~~~~~~


    + CategoryInfo          : NotSpecified: (:) [], MethodException


    + FullyQualifiedErrorId : NonRefArgumentToRefParameterMsg



[ref] isn’t case sensitive.



The only way round it that I know of is to create a blank Word document to use as a template



Copy-Item -Path mydoc.doc  -Destination testdoc.doc -Force            
            
$file = "C:\MyData\SkyDrive\Data\Scripts\Office-Word\testdoc.doc"            
            
$word = New-Object -ComObject "Word.application"            
$word.visible = $true            
$doc = $word.Documents.Open($file)            
            
$word.Selection.Font.Name = "Cambria"            
$word.Selection.Font.Size = "20"            
$word.Selection.TypeText("PowerShell")            
$word.Selection.TypeParagraph()            
            
$word.Selection.Font.Name = "Calibri"            
$word.Selection.Font.Size = "12"            
$word.Selection.TypeText("The best scripting language in the world!")            
$word.Selection.TypeParagraph()            
            
$doc.Save()            
$doc.Close()            
$Word.Quit()


Notice that you need to give the full path to the file. Use the Open method and add the text. You can then save, close and quit the application.



I’ve tested this using office 2010 & office 2013 on Windows 7 & 8



Unfortunately we are still left with the problem that we can’t save the Word document into different formats.

PowerShell summit

April 22-14  2013 – Microsoft campus.  PowerShell team and MVPs

http://powershell.org/summit/

Tickets going fast

CDXML modules and nouns

CDXML modules don’t expose the verb and the noun of the cmdlets they publish.  If you want to discover the set of nouns in a CDXML module you need a bit of brute force:

Get-Command -Module DhcpServer |
foreach {
  ($_.Name -split "-")[1]
}  | sort | group -NoElement | sort count –Descending

Windows 8 update

The first Windows 8 update became available this week.  This fixes some issues that have come up during the OEM process.  Fast and frequent updates sound good to me.

In addition number of apps have been updated – one I really like is the addition of conversation groupings to the mail app.  That’s made it a good bit more useful for me.

A recycle bin for Skydrive also appears to be new – at least I haven’t noticed it before