Categories

Monthly Archives: August 2011

Windows firewall

I normally leave the Windows firewall enabled in my test environment. It ensures I don’t forget it when testing. My recent session for the TechEd:Australia PowerShell conference involved me disabling various firewall rules on the subject machine to set up part of the demo. I had to use the GUI tools to do this. I'’ve moaned to myself that I needed some PowerShell tools for working with the firewall especially as the netsh syntax has changed in Windows 2008 R2 – the session has prompted me to do something about it.

James O’Neill has written a very nice Configurator module for setting up servers. I’ve borrowed some of his ideas but as I’m just working with the firewall I thought I’d be a bit more verbose in the way I do things.

First off I want to know which network types are enabled on my machine. I need to consider them when working with  firewall rules.

I’m creating these functions as a module so I can define my networks (firewall profiles) in the .psm1 file

## types            
Add-type @"
public enum ProfileType {
 Domain   = 1,
 Private  = 2,
 Public   = 4,
 All      = 1073741824
} 
"@            
            
## functions            
. $psScriptRoot/Get-Profile.ps1


I can use this enum in the function to display the firewall profiles



function get-profile {             
[CmdletBinding()]             
param ()             
BEGIN{}#begin             
PROCESS{            
$fw = New-Object -ComObject HNetCfg.FwPolicy2            
$fwtypes = $fw.CurrentProfileTypes            
            
@(1,2,4) |             
foreach {            
 $cpt = New-Object -TypeName PSObject -Property @{            
     Enabled = $false            
     Profile = [ProfileType]($_)             
   }            
 $cpt.PSTypeNames[0] = "FirewallProfile"            
             
 if ($_ -band $fwtypes){$cpt.Enabled = $true}            
 $cpt             
}            
            
}#process             
END{}#end            
            
<# 
.SYNOPSIS
Determines active firewall profiles

.DESCRIPTION
Determines active firewall profiles.
Possible values are:
 Domain
 Private 
 Public

.EXAMPLE
get-profile

#>            
            
}


The function gets the firewall COM object. For the three network types we create an object that gives the name and that its disabled. We change the object type and then if test if the value and the firewall CurrentProfileTypes property can band. If they do we set the profile to enabled ($true). The object is displayed.



Output looks like this



PS> get-profile | ft -a



Profile Enabled
------- -------
Domain   False
Private    True
Public    True

UK User Group sessions

This is the provisional list of meetings for the rest of the year

 

20 September Aleksandar Nikolic  7.30pm BST

25 October  WSMAN and WMI  - this is an extended version of the talk I gave over Live Meeting to the TechEd Australia PowerShell conference 7.30pm GMT

22 November Jonathan Medd “What’s new in PowerCLI 5?” 8.30pm GMT

15 December Hyper-V with PowerShell 7.30pm GMT

 

All sessions will be delivered by Live Meeting. Full details to follow

Webcast: Get the most from PowerShell and WMI

I will be presenting the above webcast next week.

Date: Wednesday, September 7, 2011

Time: 12:00 PM - 1:00 PM CST

 

Thats 6pm UK time

 

Register for the web cast at

http://powershell.com/cs/media/p/11256.aspx

Testing services

A forum question about testing services and if they weren’t running got me thinking. I created an function to solve the question

function test-service{             
[CmdletBinding(SupportsShouldProcess=$true)]             
param (             
[parameter(Position=0,            
   ValueFromPipeline=$true,             
   ValueFromPipelineByPropertyName=$true)]            
   [Alias("CN", "ComputerName")]              
   [string]$computer="." ,            
               
   [string]$service="BITS" ,            
               
[parameter(Mandatory=$true)]            
   [string]$file            
               
)             
BEGIN {            
 if (!(Test-Path -Path $file)){Throw "log file not found"}            
}            
PROCESS {            
$result =  Get-WmiObject -Class Win32_Service -ComputerName $computer -Filter "Name='$service'"            
            
Write-Verbose "$($result.State)"            
            
if ($($result.State) -eq "Running"){            
  $logdata = "{0,14} {1} {2}" -f $computer, $($result.State), (get-date -Format f )            
}            
else{             
 $start = $result.StartService()             
 if ($start.ReturnValue -eq 0){            
   $logdata = "{0,14} {1} {2}" -f $computer, "Service Started", (get-date -Format f )            
 }            
 else {            
  $logdata = "{0,14} {1} {2}" -f $computer, "Service FAILED to Start", (get-date -Format f )            
 }              
}            
Add-Content -Path $file -Value $logdata             
}            
} ## end function


But I don’t like the answer for a number of reasons:



  • end up out putting text
  • log files involve extra work in parsing
  • will other people know where the log file is


A better solution, in my mind, is to write the data to the event log.  In this case I would use the system log because we are testing services. The application log could be used or we could even create a specific event log for the purpose.



 



function test-service2{             
[CmdletBinding(SupportsShouldProcess=$true)]             
param (             
[parameter(Position=0,            
   ValueFromPipeline=$true,             
   ValueFromPipelineByPropertyName=$true)]            
   [Alias("CN", "ComputerName")]              
   [string]$computer="." ,            
               
   [string]$service="BITS"            
)             
PROCESS {            
$result =  Get-WmiObject -Class Win32_Service -ComputerName $computer -Filter "Name='$service'"            
            
Write-Verbose "$($result.State)"            
            
if ($($result.State) -eq "Running"){            
  $type = "Information"            
  $msg = "$computer - $service is $($result.State) "            
}            
else{             
 $start = $result.StartService()             
 if ($start.ReturnValue -eq 0){            
   $type = "Warning"            
   $msg = "$computer - $service  was started "            
 }            
 else {            
   $type = "Error"            
   $msg = "$computer - $service  FAILED to start"            
 }              
}            
Write-EventLog -LogName Application -Source ServiceTest -EntryType $type -Message $msg -EventId 9999            
            
}            
} ## end function


 



before using the function run this to create the event log source



New-EventLog -LogName Application -Source ServiceTest



The actions are all written to the event log as information, Warning or Error messages as appropriate.



Get-EventLog -LogName Application -Source ServiceTest



Shows the messages.



Enjoy

Testing computer existence in AD

Forum question wanted to take a list of computer names in a csv

Using the Quest cmdlets it becomes

Import-Csv computers2.csv |            
foreach {            
 $comp =  Get-QADComputer -Name $($_.Name)            
             
 if ($comp) {$location = $comp.DN}            
 else {$location = "Does NOT exist in AD"}            
             
 New-Object -TypeName Psobject -Property @{            
  Name = $_.Name            
  Location = $location            
 }            
            
} | Export-Csv complocs.csv -NoTypeInformation


 



Read the CSV and for each computer see if we can find it in AD.  I’m searching whole AD and assuming less than 1000 machines. Alter the search properties if these don’t match your needs. Put the name and distinguished name (DN) in an object and write to CSV



Its just as easy with the Microsoft cmdlets



Import-Csv computers2.csv |            
foreach {            
 $comp =  Get-ADComputer -LDAPFilter "(name=$($_.Name))"            
             
 if ($comp) {$location = $comp.DistinguishedName}            
 else {$location = "Does NOT exist in AD"}            
             
 New-Object -TypeName Psobject -Property @{            
  Name = $_.Name            
  Location = $location            
 }            
            
} | Export-Csv complocs2.csv -NoTypeInformation


Main difference is that we have to use an LDAP filter in Get-ADComputer. Also we pick up the DistinguishedName not DN property

Deal of the Day–PowerShell

PowerShell and WMI is Manning’s deal of the day – 50% off print or e-book.

 

The deal also extends to PowerShell in Practice and PowerShell in Action 2E

See www.manning.com for details

Reminder: TechEd Australia PowerShell conference

The TechEd Australia PowerShell conference starts tomorrow at midnight UK time (9am in Australia).  Details from

http://msmvps.com/blogs/richardsiddaway/archive/2011/08/22/teched-australia-powershell-conference.aspx

 

I will be presenting on WSMAN and WMI

Network Adapter vendors

The NDis WMI classes expose some information about the vendors that produce the various adapters in our systems

function get-adaptervendor {            
param(            
 [string]$computer="."            
)            
Get-WmiObject -Namespace root\wmi -Class MSNdis_CoVendorDescription `
-ComputerName $computer |            
foreach {            
                
  $id = Get-WmiObject -Namespace root\wmi  `
  -Class MSNdis_CoVendorId -ComputerName $computer `
  -Filter "InstanceName='$($_.InstanceName)'"            
            
  New-Object -TypeName PSobject -Property @{            
    Computer = $_.__SERVER            
    Adapter = $_.InstanceName            
    Active = $_.Active            
    Description = $_.NdisCoVendorDescription            
    Vendorid = $id.NdisCoVendorID            
  }            
}            
}

Msndis class

The MSNdis class from the root\wmi namespace calls the MSNdis_CoHardwareStatus and MSNdis_CoDriverVersion classes. On my Windows 7 system it tries to call something else but I get a “Get-WmiObject : Not supported” error. Neither of these classes seems to have much in the way of documentation available.

Rather than calling MSNdis and getting a lot of WMI objects it would be better to combine the output. There are a set of MSNdis-co* classes

gwmi -Namespace root\wmi -List *ndis_co* | sort name

MSNdis_CoDriverVersion
MSNdis_CoHardwareStatus
MSNdis_CoLinkSpeed
MSNdis_CoMacOptions
MSNdis_CoMediaConnectStatus
MSNdis_CoMediaInUse
MSNdis_CoMediaSupported
MSNdis_CoMinimumLinkSpeed
MSNdis_CoReceivePduErrors
MSNdis_CoReceivePdusNoBuffer
MSNdis_CoReceivePdusOk
MSNdis_CoTransmitPduErrors
MSNdis_CoTransmitPdusOk
MSNdis_CountedString
MSNdis_CoVendorDescription
MSNdis_CoVendorDriverVersion
MSNdis_CoVendorId

Lets see what we can find out about them

 

 

function get-adaptercoinfo {            
param(            
 [string]$computer="."            
)            
Get-WmiObject -Namespace root\wmi -Class MSNdis_CoHardwareStatus `
-ComputerName $computer |            
foreach {            
                
  $drv = Get-WmiObject -Namespace root\wmi  `
  -Class MSNdis_CoDriverVersion -ComputerName $computer `
  -Filter "InstanceName='$($_.InstanceName)'"            
            
  New-Object -TypeName PSobject -Property @{            
    Computer = $_.__SERVER            
    Adapter = $_.InstanceName            
    Active = $_.Active            
    HardwareStatus = $_.NdisCoHardwareStatus            
    DriverVersion = $drv.NdisCoDriverVersion             
  }            
}            
}


Start with the MSNdis_CoHardwareStatus and match to MSNdis_CoDriverVersion  on instance name (associators don’t seem to be created for these classes). Put the appropriate properties into an object and output.



The output is best displayed like this



get-adaptercoinfo | ft -a

European PowerShell Deep Dive–presenting

I was notified last night that my submission to the Deep Dive was successful and I will be presenting. There will be a good number of PowerShell MVPs attending. This will be the PowerShell event of the year in Europe. The one in April in the USA was brilliant – this will be at least as good.

Event details from http://blogs.msdn.com/b/powershell/archive/2011/08/02/extending-discounted-registration-amp-session-proposal-deadline.aspx