tirsdag 11. november 2014

PowerShell: Parse netstat for Remote Connections and more...

I needed a way to find out who was connected to my Operations Manager Management Servers.

Of course you can use the GetConnectedUserNames method of the Management Group object in PowerShell like this:
Import-Module OperationsManager

But this will only give you the names and not the remote computername. To do this I wrote a PowerShell function that parse netstat output, and also use Invoke-Expression to get the user of a specific process. To use it to list computers/users connected to a specific Operations Manager Management Server, I execute this on the Management Server:
. \RemoteConnections.ps1
Get-RemoteConnection -Port 5724 -ProcessName 'Microsoft.EnterpriseManagement.Monitoring.Console'

You can also list computers/users connected to a specific Service Manager Management Server, like this:
. \RemoteConnections.ps1
Get-RemoteConnection -Port 5724 -ProcessName 'Microsoft.EnterpriseManagement.ServiceManager.UI.Console'

Or list computers/users connected to a specific Virtual Machine Manager Management Server, like this:
. \RemoteConnections.ps1
Get-RemoteConnection -Port 8100 -ProcessName 'VmmAdminUI'

This is how the content of RemoteConnections.ps1 looks like:
function Get-ConnectionData{
  param ( 

  process {
    try {
      $IPv4Address = ''
      $IPv6Address = ''
      $ComputerName = ''
      $UserName = ''
      if($remoteAddress -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'){
        $IPv4Address = $remoteAddress
        $ComputerName = [System.Net.DNS]::GetHostByAddress($remoteAddress).hostname
        $IPv6Address = $remoteAddress
        $tmp = nslookup $remoteAddress 2>$null
        if($tmp[3]){$ComputerName = $tmp[3].split(' ')[4]}

      if($ComputerName -and $ProcessName){
        $UserName = (Invoke-Command -ComputerName $ComputerName -ScriptBlock {param($ProcessName) $owners = @{}; gwmi win32_process -Filter ("Name LIKE '"+$ProcessName+"%'")|% {$owners[$_.handle] = $_.getowner().user};Get-Process -ProcessName $ProcessName -ErrorAction SilentlyContinue|select Id,@{l='Owner';e={$owners[$]}}} -ArgumentList $ProcessName).Owner
    catch [System.Exception] {
      Write-Error $_.Exception.Message
    New-Object PSObject -Property @{  
      IPv4Address = $IPv4Address
      IPv6Address = $IPv6Address
      ComputerName = $ComputerName
      Username = $UserName

function Get-RemoteConnection{
  Use this function to list Remote Connections
  This function will list remote connections
  Get-RemoteConnection -Port 5724 -ProcessName 'Microsoft.EnterpriseManagement.Monitoring.Console'
  Get-RemoteConnection -Port 5724 -ProcessName 'Microsoft.EnterpriseManagement.ServiceManager.UI.Console'
  Get-RemoteConnection -Port 8100 -ProcessName 'VmmAdminUI'
  The Port to list connections for
  .PARAMETER Protocol
  The Protocol for the connection. May be any of TCP, TCPv6, UDP or UDPv6.
  If unspecified all protocols are listed
  .PARAMETER ProcessName
  The process name of remote application responsible for the connection.
  If this is specified, we try to get the username that started the process.
  param (
      HelpMessage='What port would you like to list connections for?')]
      HelpMessage='What protocol would you like to list connections for?')]
      HelpMessage='What remote process on the connected computer do you want owner name for?')]
  if($Protocol -eq ''){
    $lines = netstat -ano
    $lines = netstat -ano -p $Protocol
  foreach($line in $lines){
    $cols = $line.Split(' ',[System.StringSplitOptions]::RemoveEmptyEntries)
    if($cols[1] -notmatch '^\[::' -and ($cols[0] -eq 'TCP' -or $cols[0] -eq 'UDP')){
      if(($la = $cols[1] -as [ipaddress]).AddressFamily -eq 'InterNetworkV6'){
        $localPort = $cols[1].split('\]:')[-1]
        $localPort = $cols[1].split(':')[-1]
      if(($ra = $cols[2] -as [ipaddress]).AddressFamily -eq 'InterNetworkV6'){
        $remoteAddress = $ra.IPAddressToString
        $remoteAddress = $cols[2].split(':')[0]
      if($localPort -like $Port -and $remoteAddress -ne '' -and $remoteAddress -ne '' -and $remoteAddress -ne '' -and $remoteAddress -notlike 'fe80*'){
        Get-ConnectionData -RemoteAddress $RemoteAddress

tirsdag 2. september 2014

tirsdag 19. august 2014

OpsMgr: Properties with brackets in PowerShell

Have you tried to select or filter on properties using brackets in PowerShell? Did you figure out how to do it? If not, read on...

For example, I execute this command in Operations Manager Shell:
Get-SCOMClass -DisplayName 'Windows Computer'|Get-SCOMClassInstance|select -First 1 *

And the result:
[Microsoft.Windows.Server.Computer].IsVirtualNode            : (null)
[Microsoft.Windows.Computer].PrincipalName                   :
[Microsoft.Windows.Computer].DNSName                         :
[Microsoft.Windows.Computer].NetbiosComputerName             : dc1
[Microsoft.Windows.Computer].NetbiosDomainName               : CONTOSO
[Microsoft.Windows.Computer].IPAddress                       :
[Microsoft.Windows.Computer].NetworkName                     :
[Microsoft.Windows.Computer].ActiveDirectoryObjectSid        : S-0-0-00-000000000-0000000000-000000000-0000
[Microsoft.Windows.Computer].IsVirtualMachine                : True
[Microsoft.Windows.Computer].DomainDnsName                   :
[Microsoft.Windows.Computer].OrganizationalUnit              : OU=Computers,DC=contoso,DC=com
[Microsoft.Windows.Computer].ForestDnsName                   :
[Microsoft.Windows.Computer].ActiveDirectorySite             : contoso
[Microsoft.Windows.Computer].LogicalProcessors               : 1
[Microsoft.Windows.Computer].PhysicalProcessors              : 1
[Microsoft.Windows.Computer].HostServerName                  : (null)
[Microsoft.Windows.Computer].VirtualMachineName              : (null)
[Microsoft.Windows.Computer].OffsetInMinuteFromGreenwichTime : (null)
[Microsoft.Windows.Computer].LastInventoryDate               : (null)
[Microsoft.SystemCenter.ManagedComputer].InstallDirectory    : C:\Program Files\Microsoft Monitoring Agent\Agent\
[Microsoft.Windows.Server.2008.Computer].InstallType         : Full
[System.ConfigItem].ObjectStatus                             : System.ConfigItem.ObjectStatusEnum.Active
[System.ConfigItem].AssetStatus                              : (null)
[System.ConfigItem].Notes                                    : (null)
[System.Entity].DisplayName                                  :
IsManaged                                                    : True
HealthState                                                  : Success
StateLastModified                                            : 8/19/2014 10:00:00 AM
IsAvailable                                                  : True
AvailabilityLastModified                                     : 8/19/2014 10:00:00 AM
InMaintenanceMode                                            : False
MaintenanceModeLastModified                                  :
MonitoringClassIds                                           : {e817d034-02e8-294c-3509-01ca25481689, ea99500d-8d52-fc52-b5a5-10dcd1ba-33f801db7d37...}
LeastDerivedNonAbstractMonitoringClassId                     : ea99500d-8d52-fc52-b5a5-10dcd1e9d2bd
ManagementGroup                                              : SCOMMG
Name                                                         :
Path                                                         :
DisplayName                                                  :
FullName                                                     :
ManagementPackClassIds                                       : {e817d034-02e8-294c-3509-01ca25481689, ea99500d-8d52-fc52-b5a5-10dcd1ba-33f801db7d37...}
LeastDerivedNonAbstractManagementPackClassId                 : ea99500d-8d52-fc52-b5a5-10dcd1e9d2bd
TimeAdded                                                    : 8/19/2014 10:00:00 AM
LastModifiedBy                                               :
Values                                                       : {(null),,, dc1...}
LastModified                                                 : 8/19/2014 10:00:00 AM
IsNew                                                        : False
HasChanges                                                   : False
Id                                                           : 83f8d115-ccc8-5d88-2345-00d0148ecbd3
ManagementGroupId                                            : c6f7583b-f37e-101a-30fa-e53639ee0d80

Now you may wonder, how do I use Select-Object to view only Name and IPAddress? Well, square brackets require double-escaping in PowerShell (see this Microsoft Connect Feedback), so this is how:
Get-SCOMClass -DisplayName 'Windows Computer'|Get-SCOMClassInstance|select -First 1 Name,``[Microsoft.Windows.Computer`].IPAddress

Great, but what if I would like to use Where-Object to filter on IPAddress? Well, in this case we do not need to backtick-escape these brackets, instead we need to put single quotes around the entire property name, like this:
Get-SCOMClass -DisplayName 'Windows Computer'|Get-SCOMClassInstance|where{$_.'[Microsoft.Windows.Computer].IPAddress' -match ''}|select Name,``[Microsoft.Windows.Computer`].IPAddress

onsdag 13. august 2014

SQL Server: Unable to modify a Maintenance Plan

Are you unable to modify an existing Maintenance Plan in SQL Server Management Studio?

If you have installed the Microsoft SQL Server Management Studio tools in a Basic edition, try to install the Complete tools.

You can use "Installed SQL Server features discovery report" in Tools section of SQL Server Installation Center to see what features you have installed.

You may find that you also need to install Microsoft SQL Server Shared Management Objects. This is part of Microsoft SQL Server Feature Pack. You can find it at Microsoft Download Center. Be sure to select the version that correspond to the SQL Server you have installed.

mandag 28. juli 2014

Outlook Reply / Forward prefixes

Email clients can’t cope as well with a mix of prefixes from across the globe. It’s best to stick with RE and FW as a courtesy to other people. Outlook lets non-English language users do that with two setting buried in the options.
  • Use English for message flag labels
  • Use English for message headers on replies and forwards [and for forward notifications]

Go to File | Options | Advanced | International Options

Go to Tools | Options | Mail Format | International Options

søndag 27. juli 2014

Windows: Time Synchronization

Hyper-V Integration Services synchronizes the time of virtual machines with the physical host because virtual machines tend to experience time drift over time. Never disable Hyper-V Time Synchronization, it's important when the virtual machine boots and resumes saved states.

Benjamin Armstrong talk about this topic in more detail in his Virtualization Blog. Here are some of the PowerShell commands I use to configure Time Synchronization in a domain.

# If the computer is a virtual machine running in Hyper-V, disable aspects of time synchronization from Hyper-V with:
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\VMICTimeProvider' -Name 'Enabled' -Value 0

# For the Domain Controller holding the PDC emulator role (chech with netdom /query fsmo), configure a remote time source:
& C:\Windows\System32\w32tm.exe /config /manualpeerlist:",0×1,0×1,0×1,0×1" /syncfromflags:manual /reliable:YES /update
Restart-Service w32time
& C:\Windows\System32\w32tm.exe /resync /rediscover

For member servers, configure synchronization with the domain:
& C:\Windows\System32\w32tm.exe /config /syncfromflags:DOMHIER /update
Restart-Service w32time
& C:\Windows\System32\w32tm.exe /resync /rediscover /force

lørdag 26. juli 2014

DPM: Configure a Backup Network

Let's say I have a production network, with subnet I already have two domain controllers (dc1 and dc2), a backup server (dpm1) and other member servers. The domain controllers and DPM servers are running Windows Server 2012 R2. I wan't to add a backup network. This is how I would do it:

First I add a network interface to each server. This will be used by the backup network. I name the interface BackupNet on each server.

The backup network will use subnet

I create a DNS Zone,, using Powershell:
Add-DnsServerPrimaryZone -Name -ReplicationScope 'Domain' -PassThru -DynamicUpdate Secure -ComputerName dc1

On each DNS Server I open DNS Properties > Interfaces and verify that the backup interface is selected.

I configure backup interface on all servers using PowerShell:
Invoke-Command -ComputerName dc1 -ScriptBlock {Set-DnsClientServerAddress -InterfaceAlias 'BackupNet' -ServerAddresses ('','')}
Invoke-Command -ComputerName dc2 -ScriptBlock {Set-DnsClientServerAddress -InterfaceAlias 'BackupNet' -ServerAddresses ('','')}
Invoke-Command -ComputerName dpm1 -ScriptBlock {Set-DnsClientServerAddress -InterfaceAlias 'BackupNet' -ServerAddresses ('','')}
Invoke-Command -ComputerName dc1,dc2,dpm1 -ScriptBlock {Set-DnsClient –InterfaceAlias 'BackupNet' -ConnectionSpecificSuffix '' –RegisterThisConnectionsAddress $true –UseSuffixWhenRegistering $true}
Invoke-Command -ComputerName dc1,dc2,dpm1 -ScriptBlock {ipconfig /registerdns}

Then I add Backup and Production Networks to DPM:
Add-DPMBackupNetworkAddress –DPMServerName –Address –SequenceNumber 1
Add-DPMBackupNetworkAddress –DPMServerName –Address –SequenceNumber 2
Restart-Service DPM