12528

PowerShell remoting and upgrading to Windows 2012

I have a number of  virtual machines running Windows 2008 R2 and I upgraded one of them to Windows 2012 – an over the top upgrade rather than a format and clean install

I found that Get-PSSession –Computername didn’t work against that machine.

This parameter now looks at the remote machine endpoint and gets all remoting sessions connected to the machine. I verified that the command worked correctly against a clean install of Windows 2012. This pointed to a WSMAN configuration issue.

I found two issues:

  • PSversion remained on 2.0 after the upgrade
  • SDKversion remained on 1 after the upgrade

You can’t just do a blanket upgrade on SDKversion because some of the endpoints remain on 1 even in a clean Windows 2012 install.

This is what I ended up doing:

Set-Item -Path wsman:\localhost\plugin\microsoft.powershell\InitializationParameters\PSVersion -Value 3.0
Set-Item -Path wsman:\localhost\plugin\microsoft.ServerManager\InitializationParameters\PSVersion -Value 3.0
Set-Item -Path wsman:\localhost\plugin\Microsoft.PowerShell32\InitializationParameters\PSVersion -Value 3.0

Set-Item -Path wsman:\localhost\plugin\Microsoft.PowerShell32\SDKVersion -Value 2
Set-Item -Path wsman:\localhost\plugin\Microsoft.PowerShell\SDKVersion -Value 2
Restart-Service winrm

That didn’t completely fix it so I restarted the remote machine then ran:

Disable-PSRemoting –Force
Enable-PSRemoting –Force

That seemed to fix the problem.

At the moment all seems to be working BUT I’ve more testing to do before I’m 100% happy with this.  This isn’t a procedure I’d recommend unless you exactly what you are doing and why.

Don’t try this at home until you are sure you need to.

Using Windows 2012 Active Directory module in a Windows 2008 R2 domain

A question came up on Tuesdays UK PowerShell Group session about using the Windows 2012 Active Directory module. The recording links are here

http://msmvps.com/blogs/richardsiddaway/archive/2012/05/30/may-2012-powershell-group-recording-and-slides.aspx

The question asked if the new Site, Subnet and Site link cmdlets would work in a legacy environment.

This morning I installed a Windows Server 2012 Release Candidate member server into my Windows 2008 R2 domain. I then installed the RSAT feature on the Windows 2012 server – this includes the Active Directory module.

The site, subnet and site link cmdlets appear to work with NO changes required to the Windows 2008 R2 domain controller. I was able to view and create sites, subnets and site links.

I haven’t tested any other scenario.

BITS posts

BITS is the Background Intelligent Transfer Service.  I’ve started a series of posts on using the PowerShell BITS cmdlets on my IT Knowledge Exchange blog

http://itknowledgeexchange.techtarget.com/powershell/bits/

2 http://itknowledgeexchange.techtarget.com/powershell/download-multiple-files-by-bits/

3 http://itknowledgeexchange.techtarget.com/powershell/upload-through-bits/

More to follow

Remoting between PowerShell v3 CTP 2 and PowerShell v2

One of the questions on tonight’s Live Meeting concerned the compatibility between remoting on PowerShell v2 and PowerShell v3 CTP 2

The difference is that v3 uses a WSMAN 3.0 stack but v2 uses 2.0

I used two machines:

  • Windows 2008 R2 SP 1 with PowerShell v2
  • Windows 7 SP1 with PowerShell v3 CTP 2

 

on each machine I ensured remoting was enabled then ran

$s = New-PSSession –ComputerName <other computer name>
Invoke-Command -Session $s -ScriptBlock {get-service}

 

it worked in both cases

Looks like in this case you can remote both ways

AD account Expiry date

In many organisations AD accounts for temporary works are set to expiry when their contract ends.  Its also a good practice to put an expiry date on any one who is leaving – that way you know their account won’t available.

Setting the expiry date for all users in an OU is done like this

$date = "01/01/2012 00:00:00"            
            
$ou = [adsi]"LDAP://ou=test,dc=manticore,dc=org"            
            
$search = [System.DirectoryServices.DirectorySearcher]$ou            
$search.Filter = "(&(objectclass=user)(objectcategory=user))"            
$search.SizeLimit = 3000            
$results = $search.FindAll()            
            
foreach ($result in $results){            
            
 $target = $result.GetDirectoryEntry()            
 $target.AccountExpirationDate = $date            
 $target.SetInfo()            
}


 



The date shows the start of a day but the account expires at the end of the previous day.



The attribute is set correctly in ADSIEdit but on my Windows 2008 R2 system AD Users and Computers showed a date 1 day earlier but AD Administrative center shows the correct date!

Using AccountManagement classes to set local accounts expiry

This is a little more verbose than the WinNT example

function set-expirydate {            
[CmdletBinding(SupportsShouldProcess=$true)]            
param (            
 [parameter(ValueFromPipeline=$true,            
   ValueFromPipelineByPropertyName=$true)]            
 [string]$computer,            
             
 [parameter(ValueFromPipeline=$true,            
   ValueFromPipelineByPropertyName=$true)]            
 [string]$id              
)            
BEGIN {Add-Type -AssemblyName System.DirectoryServices.AccountManagement}             
PROCESS {               
 switch ($computer){            
  "."    {$computer = $env:computername}            
  "localhost" {$computer = $env:computername}            
 }            
             
 $ctype = [System.DirectoryServices.AccountManagement.ContextType]::Machine            
 $context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext `
    -ArgumentList $ctype, $computer            
            
 $user = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($context, $id)            
             
## set the expiry date            
if ($psCmdlet.ShouldProcess("$id", "Expiry date set ")) {            
    $user.AccountExpirationDate = (Get-Date).AddDays(2)            
    $user.Save()            
  }            
}              
}


Set the context to machine and use the machine name to define which machine.  Find the user and set the AccountExpirationDate property then save

Setting local account expiry dates

Setting expiry dates on AD accounts is a common occurrence and is well documented. Setting expiry dates on local accounts is also possible

$user = [adsi]"WinNT://./Test1, user"            
            
$expirydate = (Get-Date).AddDays(2)            
            
$user.Put("AccountExpirationDate", $expirydate)            
$user.SetInfo()            
            
$user.RefreshCache()            
            
$user | Format-List *


This uses the WinNT (remember its case sensitive) ADSI connector to get a local account.  We then set the AccountExpirationDate property to the desired date – in this case two days from now.



Quick call to SetInfo() and we are done

Windows SysInternals Administrators Reference

Windows SysInternals Administrators Reference


Title: Windows SysInternals Administrators Reference


Publisher: Microsoft Press


ISBN: 978-0-7356-5672-7


The SysInternals tool set – http://technet.microsoft.com/en-us/sysinternals/default.aspx  – should be one of a Windows administrator’s best friends. You may not need them every day but when you do they will help dig you out of the hole. The toolset was created, and is still maintained by Mark Russinovich. Originally, offered as an independent set of utilities it is now owned and supplied (as a free download) by Microsoft.  


One of the difficulties, with any troubleshooting toolset, is knowing how to get the best out of the tools, especially if you are only using them now and again. The SysInternals tools can be downloaded as a complete suite or the individual tools (or group of tools) can be downloaded independently. This approach leaves the administrator possibly using, and understanding, part of the toolset because they are used regularly but completely ignorant of the rest of the tools.  Mark Russininovich, and his co-author Aaron Margois, have created the Windows SysInternals Administrators Reference to address that gap


The book is divided into three parts:


·        Part 1 starts with the SysInternals core concepts, including some historical background. Chapter 2 follows on with a look at Windows Core Concepts including administrative rights, process, threads, user and kernel mode, handles, call stacks and sessions.


·        Part 2 is where we dive into the toolset:


o   Process Explorer


o   Process Monitor


o   Autoruns


o   PsTools


o   Process and Diagnostics Utilities


o   Security Utilities


o   Active Directory Utilities


o   Desktop Utilities


o   Network and Communications utilities


o   System Information utilities


o   Miscellaneous Utilities


·        Part 3 looks at using the tools in some real life scenarios


o   Error messages


o   Hangs and sluggish performance


o   Malware


I suspect that many readers will read parts 1 and 3 for the very valuable information. Part 2 is more of a reference which will be dipped into as needed. The breadth of the SysInternals toolset means that you won’t be using all of the tools all of the time but will need the information on using the other tools. I would strongly recommend at least skimming through the chapters in part 2. You may well find something that will help solve an incipient problem. They can also suggest a course of action to help investigate potential problems.


As a very strong advocate of using PowerShell there are some occasions where the two sets of functionality overlap. The SysInternals tools will often take over where the PowerShell functionality finishes so tend to be complimentary rather then competing.


This is a book to which I think every Windows administrator/consultant needs access. I tend to carry a netbook these days with my library of scripts and utilities plus electronic copies of the important reference works I might need. A copy of the latest version of the SysInternals tools plus this book is very definitely included in that content.  


Highly recommended for all Windows administrators and consultants. Don’t leave home without it.


 

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

HKLM:\SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}

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

This produces a bunch of subkeys of the form

{F913D3B9-DBE4-455C-8926-10E24AB4E68A}

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

function get-Registryconnectionid{             
[CmdletBinding()]             
param (             
   [string]$computer="."             
)             
BEGIN{}#begin             
PROCESS{            
            
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            
    }            
  $connection              
}            
            
            
}#process             
END{}#end            
            
<# 
.SYNOPSIS
Retrieves network connection ids 

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

.PARAMETER  Computer
Computer name

.EXAMPLE
get-Registryconnectionid

.EXAMPLE
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

Networking pains

Last week my wireless router decided that it had enough and wasn’t going to work any more. This was annoying because I was due to give a user group presentation that night.

I got a new router up and working but today discovered that connectivity from my Hyper-V environment wasn’t working. With the previous router I’d configured bridging between a Hyper-V virtual network and the wireless adapter in my host. That had to be recreated at which point I discovered that the new router didn’t want to support bridging.

I ended up using RRAS and NAT to get the connectivity. The instructions I found here

http://sqlblog.com/blogs/john_paul_cook/archive/2008/03/23/using-wireless-with-hyper-v.aspx

provide most of what you need.

Remember to set the default gateways and DNS servers properly for it all to work.