Jonathan Medd's Blog

Scripting. Powershell, VMware, Windows, Active Directory & Exchange. All that kind of stuff…..
RSS icon Email icon Home icon
  • Basic VMware Cluster Capacity Check with PowerCLI

    Posted on January 18th, 2012 Jonathan Medd 7 comments

    I recently needed to provide a high level capacity overview per VMware cluster looking at some metrics of interest that were being used as a guide to the capacity state of a cluster. Note: these are by no means definitive or the ones you should be using in your environment, but for these purposes they met the requirements. The metrics I looked at per cluster were the ratio of vCPUs to pCPUs, the amount of Effective, Allocated and average Active Memory and the amount of Free Diskspace.

    A couple of things to note:

    1.The section below on datastore freespace filters out the local datastore which contains the name of the host.

    
    $VMHost = $Cluster | Get-VMHost | Select-Object -Last 1
    $HostName = ($VMHost.name -split ".", 0, "simplematch")[0]
    $ClusterFreeDiskspaceGB = ($VMHost | Get-Datastore | Where-Object {$_.Name -notmatch $HostName} | Measure-Object -Property FreeSpaceGB -Sum).Sum
    

    2. I’ve recently changed the way I create custom objects to output reports with. For a long time I have used the cheat way of Select-Object , partly because of performance and partly because you can’t control the order of properties in New-Object. These are being addressed in PowerShell v3 (see here and here) so I thought it was about time to make the switch. This means for the time being that when working with the output you need to pipe it to Select-Object to control the order of the output, e.g.

    Get-Cluster | Get-ClusterCapacityCheck | Select-Object Cluster,ClusterCPUCores,ClusterAllocatedvCPUs,ClustervCPUpCPURatio,ClusterEffectiveMemoryGB,

    ClusterAllocatedMemoryGB,ClusterActiveMemoryPercentage,ClusterFreeDiskspaceGB

    
    function Get-ClusterCapacityCheck {
    <#
    .SYNOPSIS
    Retrieves basic capacity info for VMware clusters
    
    .DESCRIPTION
    Retrieves basic capacity info for VMware clusters
    
    .PARAMETER  ClusterName
    Name of the computer to test the services for
    
    .EXAMPLE
    PS C:\> Get-ClusterCapacityCheck -ClusterName Cluster01
    
    .EXAMPLE
    PS C:\> Get-Cluster | Get-ClusterCapacityCheck
    
    .NOTES
    Author: Jonathan Medd
    Date: 18/01/2012
    #>
    
    [CmdletBinding()]
    param(
    [Parameter(Position=0,Mandatory=$true,HelpMessage="Name of the cluster to test",
    ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$true)]
    [System.String]
    $ClusterName
    )
    
    begin {
    $Finish = (Get-Date -Hour 0 -Minute 0 -Second 0)
    $Start = $Finish.AddDays(-1).AddSeconds(1)
    
    New-VIProperty -Name FreeSpaceGB -ObjectType Datastore -Value {
    param($ds)
    [Math]::Round($ds.FreeSpaceMb/1KB,0)
    } -Force
    
    }
    
    process {
    
    $Cluster = Get-Cluster $ClusterName
    
    $ClusterCPUCores = $Cluster.ExtensionData.Summary.NumCpuCores
    $ClusterEffectiveMemoryGB = [math]::round(($Cluster.ExtensionData.Summary.EffectiveMemory / 1KB),0)
    
    $ClusterVMs = $Cluster | Get-VM
    
    $ClusterAllocatedvCPUs = ($ClusterVMs | Measure-Object -Property NumCPu -Sum).Sum
    $ClusterAllocatedMemoryGB = [math]::round(($ClusterVMs | Measure-Object -Property MemoryMB -Sum).Sum / 1KB)
    
    $ClustervCPUpCPURatio = [math]::round($ClusterAllocatedvCPUs / $ClusterCPUCores,2)
    $ClusterActiveMemoryPercentage = [math]::round(($Cluster | Get-Stat -Stat mem.usage.average -Start $Start -Finish $Finish | Measure-Object -Property Value -Average).Average,0)
    
    $VMHost = $Cluster | Get-VMHost | Select-Object -Last 1
    $ClusterFreeDiskspaceGB = ($VMHost | Get-Datastore | Where-Object {$_.Extensiondata.Summary.MultipleHostAccess -eq $True} | Measure-Object -Property FreeSpaceGB -Sum).Sum
    
    New-Object -TypeName PSObject -Property @{
    Cluster = $Cluster.Name
    ClusterCPUCores = $ClusterCPUCores
    ClusterAllocatedvCPUs = $ClusterAllocatedvCPUs
    ClustervCPUpCPURatio = $ClustervCPUpCPURatio
    ClusterEffectiveMemoryGB = $ClusterEffectiveMemoryGB
    ClusterAllocatedMemoryGB = $ClusterAllocatedMemoryGB
    ClusterActiveMemoryPercentage = $ClusterActiveMemoryPercentage
    ClusterFreeDiskspaceGB = $ClusterFreeDiskspaceGB
    }
    }
    }
    
  • Using PowerShell To Check That Windows Server Services Set To Automatic Have Started

    Posted on January 11th, 2012 Jonathan Medd 2 comments

    Following on from the blog post Testing TCP Port Response from PowerShell  which provided a means to check that servers had fully rebooted after a patching and reboot cycle, I needed to take this one step further and check that all of the Windows Services set to Automatic successfully started after the reboot.

    This should be pretty straightforward since we have a Get-Service cmdlet. Unfortunately however, this cmdlet does not return a StartMode parameter, i.e. it’s not possible to tell whether the Startup Type has been set to Automatic, Manual or Disabled. This is quite a large gap in my opinon – if you agree with me you can vote to get it included in a future release here. Of course with PowerShell there’s usually another way to achieve the same objective and using Get-WMIObject it is possible to find out the Startup Type of the service.

    
    Get-WmiObject Win32_Service -ComputerName $ComputerName -Filter "StartMode='Auto' AND State='Stopped' AND Name!='SysmonLog'"
    

    Notice that we filter out the Perfmon service (SysmonLog) since it is rarely in a started state.

    One other thing to watch out for in this script is that the section

    
    catch [System.Exception]
    

    which is there to catch any WMI queries that fail, e.g. the server hasn’t rebooted properly or the correct permissions do not exist to make the WMI query, will not pick up any of these failures. This is because try / catch will only catch terminating errors and the WMI failures are non terminating. We can work around this by setting:

    
    $ErrorActionPreference = "Stop"
    

    and then back to normal afterwards:

    
    $ErrorActionPreference = "Continue"
    

    The script accepts pipeline input, so for example you could run it like:

    
    Get-Content servers.txt | ./Get-AutomaticServiceState.ps1
    

    Here it is:

    
    <#
    .SYNOPSIS
    Retrieves any Windows services set to Automatic and are not running
    
    .DESCRIPTION
    Retrieves any Windows services set to Automatic and are not running
    
    .PARAMETER  ComputerName
    Name of the computer to test the services for
    
    .EXAMPLE
    PS C:\> Get-AutomaticServiceState -ComputerName Server01
    
    .EXAMPLE
    PS C:\> Get-Content servers.txt | Get-AutomaticServiceState
    
    .NOTES
    Author: Jonathan Medd
    Date: 11/01/2012
    #>
    
    [CmdletBinding()]
    param(
    [Parameter(Position=0,Mandatory=$true,HelpMessage="Name of the computer to test",
    ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$true)]
    [Alias('CN','__SERVER','IPAddress','Server')]
    [System.String]
    $ComputerName
    )
    
    process {
    
    try {
    
    # Set ErrorActionPreference to Stop in order to catch non-terminating WMI errors
    $ErrorActionPreference = "Stop"
    
    # Query the server via WMI and exclude the Performance Logs and Alerts Service
    $WMI = Get-WmiObject Win32_Service -ComputerName $ComputerName -Filter "StartMode='Auto' AND State='Stopped' AND Name!='SysmonLog'"
    
    }
    
    catch [System.Exception]
    
    {
    $WMI = “” | Select-Object SystemName,Displayname,StartMode,State
    $WMI.SystemName = $ComputerName
    $WMI.Displayname = "Unable to connect to server"
    $WMI.StartMode = ""
    $WMI.State = ""
    }
    
    finally {
    
    $ErrorActionPreference = "Continue"
    
    }
    
    if ($WMI){
    
    foreach ($WMIResult in $WMI){
    
    $MYObject = “” | Select-Object ComputerName,ServiceName,StartupMode,State
    $MYObject.ComputerName = $WMIResult.SystemName
    $MYObject.ServiceName = $WMIResult.Displayname
    $MYObject.StartupMode = $WMIResult.StartMode
    $MYObject.State = $WMIResult.State
    $MYObject
    }
    }
    }
    
  • Obtaining Symantec Endpoint Protection Version Info with PowerShell

    Posted on December 23rd, 2011 Jonathan Medd No comments

    Right, let’s set this one out. I do not, have not ever, nor probably will ever will like any AV Enterprise Management Products. However, sometimes you have to work with them and frequently the data in the Management Product does not actually reflect the end user / server estate. The below function will query the registry of a remote machine(s) and report back the state of the installed Symantec SEP client to help perform a true up.

    The PatternFileDate value stored in HKEY_LOCAL_MACHINE\SOFTWARE\Symantec\Symantec Endpoint Protection\AV needs a little figuring out, this posting helps figure it out.

    You can get the Info from this Registry Location

    HKEY_LOCAL_MACHINE\SOFTWARE\Symantec\Symantec Endpoint Protection\AV

    On this Key you can find two Values  
    PatternFileDate  : Current Definition date
    PatternFileRevision : Revision

    These are Hexadecimal values

    Example:
    PatternFileDate  : 27090e – 2009 Oct 14 
    27090e – YYMMDD Format
    27 – 2009
    27 Hex is 39 Decimal, this value is since 1970. So 1970+39 = 2009

    09 is October (00- Jan, 0B – Dec)
    0e Hex - 14 in decimal

    PatternFileRevision : 16Hex – 22

    16 HEX is 22 in Decimal

     

    
    function Get-SEPVersion {
    <#
    .SYNOPSIS
    Retrieve Symantec Endpoint Version, Definition Date and Sylink Group
    
    .DESCRIPTION
    Retrieve Symantec Endpoint Version, Definition Date and Sylink Group
    
    .PARAMETER  ComputerName
    Name of the computer to query SEP info for
    
    .EXAMPLE
    PS C:\> Get-SEPVersion -ComputerName Server01
    
    .EXAMPLE
    PS C:\> $servers | Get-SEPVersion
    
    .NOTES
    Author: Jonathan Medd
    Date: 23/12/2011
    #>
    
    [CmdletBinding()]
    param(
    [Parameter(Position=0,Mandatory=$true,HelpMessage="Name of the computer to query SEP for",
    ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
    [Alias('CN','__SERVER','IPAddress','Server')]
    [System.String]
    $ComputerName
    )
    
    begin {
    # Create object to enable access to the months of the year
    $DateTimeFormat = New-Object System.Globalization.DateTimeFormatInfo
    
    # Set Registry keys to query
    $SMCKey = "SOFTWARE\\Symantec\\Symantec Endpoint Protection\\SMC"
    $AVKey = "SOFTWARE\\Symantec\\Symantec Endpoint Protection\\AV"
    $SylinkKey = "SOFTWARE\\Symantec\\Symantec Endpoint Protection\\SMC\\SYLINK\\SyLink"
    }
    
    process {
    
    try {
    
    # Connect to Registry
    $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine",$ComputerName)
    
    # Obtain Product Version value
    $SMCRegKey = $reg.opensubkey($SMCKey)
    $SEPVersion = $SMCRegKey.GetValue('ProductVersion')
    
    # Obtain Pattern File Date Value
    $AVRegKey = $reg.opensubkey($AVKey)
    $AVPatternFileDate = $AVRegKey.GetValue('PatternFileDate')
    
    # Convert PatternFileDate to readable date
    $AVYearFileDate = [string]($AVPatternFileDate[0] + 1970)
    $AVMonthFileDate = $DateTimeFormat.MonthNames[$AVPatternFileDate[1]]
    $AVDayFileDate = [string]$AVPatternFileDate[2]
    $AVFileVersionDate = $AVDayFileDate + " " + $AVMonthFileDate + " " + $AVYearFileDate
    
    # Obtain Sylink Group value
    $SylinkRegKey = $reg.opensubkey($SylinkKey)
    $SylinkGroup = $SylinkRegKey.GetValue('CurrentGroup')
    
    }
    
    catch [System.Management.Automation.MethodInvocationException]
    
    {
    $SEPVersion = "Unable to connect to computer"
    $AVFileVersionDate = ""
    $SylinkGroup = ""
    }
    
    $MYObject = “” | Select-Object ComputerName,SEPProductVersion,SEPDefinitionDate,SylinkGroup
    $MYObject.ComputerName = $ComputerName
    $MYObject.SEPProductVersion = $SEPVersion
    $MYObject.SEPDefinitionDate = $AVFileVersionDate
    $MYObject.SylinkGroup = $SylinkGroup
    $MYObject
    
    }
    }
    
  • Configuring HP EVA Recommended Settings for ESXi via PowerCLI

    Posted on December 21st, 2011 Jonathan Medd 2 comments

    The HP Enterprise Virtual Array Family with VMware vSphere 4.0 , 4.1 AND 5.0 Configuration Best Practises Guide, available here, contains many recommendations for ESXi configuration. There are a number of recommended settings in this document to enhance the storage performance, a subset of which I have picked as appropriate for the environment and then needed to configure them on all ESXi hosts.

    They can be implemented via PowerCLI and the below script demonstrates how these different types of settings can be configured. The most interesting one for me was setting the default Path Selection Policy to VMW_PSP_RR. The guide recommends you use the following command from the ESXi console:

    esxcli nmp satp setdefaultpsp -satp VMW_SATP_ALUA -psp VMW_PSP_RR

    With the introduction of the Get-ESXCLI cmdlet we can now carry out the equivalent from PowerCLI. Get-EsxCLI requires a direct connection to the ESXi host rather than from vCenter, so all the settings in this script are configured via a direct connection to the ESXi host

    Warning: Before carrying out any of these types of changes make sure you talk to your Storage Adminstrator to confirm what is appropriate for your own environment. Other array vendors offer different recommendations so be sure to check their documentation for similar settings.

    
    <#
    .SYNOPSIS
    Implement HP Recommended Settings for EVA SAN
    
    .DESCRIPTION
    Implement HP Recommended Settings for EVA SAN
    
    .PARAMETER  HostName
    Name of the ESXi host to configure the settings on
    
    .EXAMPLE
    PS C:\> ./Set-HPEVAESXiConfig.ps1 -Hostname ESX01
    
    .EXAMPLE
    PS C:\> Get-Content ESXServers.txt | ./Set-HPEVAESXiConfig.ps1
    
    .NOTES
    Author: Jonathan Medd
    Date: 21/12/2011
    #>
    
    [CmdletBinding()]
    param(
    [Parameter(Position=0,Mandatory=$true,HelpMessage="Name of the ESXi host to configure the settings on",
    ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
    [Alias('IPAddress','Server','ComputerName')]
    [System.String]
    $HostName
    )
    
    begin {
    
    Write-Host "Please enter credentials to connect to the ESXi hosts" -ForegroundColor:Yellow
    $Credential = Get-Credential
    $UserName = $Credential.GetNetworkCredential().UserName
    $Password = $Credential.GetNetworkCredential().Password
    }
    
    process {
    
    Connect-VIServer $Hostname -User $Username -Password $Password | Out-Null
    
    Write-Host "Setting Disk.DiskMaxIOSize Advanced Option"
    Set-VMHostAdvancedConfiguration -VMHost $Hostname -Name Disk.DiskMaxIOSize -Value 128 | Out-Null
    
    Write-Host "Changing any LUNs with MultipathPolicy set to MostRecentlyUsed to be RoundRobin instead"
    Get-ScsiLun -VmHost $Hostname -LunType "disk" | Where-Object {$_.MultipathPolicy –eq "MostRecentlyUsed"} | Set-ScsiLun -MultipathPolicy "RoundRobin" | Out-Null
    
    Write-Host "Setting the default PSP to be VMW_PSP_RR"
    $esxCli = Get-EsxCli –Server $Hostname
    $esxCli.nmp.satp.setdefaultpsp("VMW_PSP_RR", "VMW_SATP_ALUA")
    
    Write-Host "Disconnecting from Host"
    $DefaultVIServer | Disconnect-VIServer -Confirm:$false
    }
    

     

  • Testing TCP Port Response from PowerShell

    Posted on December 20th, 2011 Jonathan Medd 9 comments

    Recently I was listening to the PowerScripting Podcast and Hal mentioned a Test-TCPPort function he had put together a while back. I had a similar need to be able to test a bunch of machines post reboot, that they had come back successfully and a Ping test wouldn’t do since that didn’t necessarily mean that Windows has successfully booted :-)

    So taking inspiration from that post I put together the following script (I convert it to a function for my own use, but it’s easier for my colleagues to use as a script) which will test by default RDP response from servers and report the results. A few examples of how to use it:

    Test a single server

    
    .\Test-PortResponse.ps1 -ComputerName Server01 | Format-Table -AutoSize
    

    Testing multiple servers

    
    Get-Content servers.txt | .\Test-PortResponse.ps1 | Format-Table -AutoSize
    

    Testing multiple servers on port 22 and exporting the results to csv

    
    Get-Content servers.txt | .\Test-PortResponse.ps1 -Port 22 | Export-Csv Ports.csv -NoTypeInformation
    

    Here’s the code you can use.

    
    <#
    .SYNOPSIS
    Test the response of a computer to a specific TCP port
    
    .DESCRIPTION
    Test the response of a computer to a specific TCP port
    
    .PARAMETER  ComputerName
    Name of the computer to test the response for
    
    .PARAMETER  Port
    TCP Port number to test
    
    .EXAMPLE
    PS C:\> ./Test-PortResponse.ps1 -ComputerName Server01
    
    .EXAMPLE
    PS C:\> Get-Content Servers.txt | ./Test-PortResponse.ps1 -Port 22
    
    .NOTES
    Author: Jonathan Medd
    Date: 20/12/2011
    #>
    
    [CmdletBinding()]
    param(
    [Parameter(Position=0,Mandatory=$true,HelpMessage="Name of the computer to test",
    ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$true)]
    [Alias('CN','__SERVER','IPAddress','Server')]
    [System.String]
    $ComputerName,
    
    [Parameter(Position=1)]
    [ValidateRange(1,65535)]
    [Int]
    $Port = 3389
    )
    
    process {
    
    $Connection = New-Object Net.Sockets.TcpClient
    
    try {
    
    $Connection.Connect($ComputerName,$Port)
    
    if ($Connection.Connected) {
    $Response = “Open”
    $Connection.Close()
    }
    
    }
    
    catch [System.Management.Automation.MethodInvocationException]
    
    {
    $Response = “Closed / Filtered”
    }
    
    $Connection = $null
    
    $MYObject = “” | Select-Object ComputerName,Port,Response
    $MYObject.ComputerName = $ComputerName
    $MYObject.Port = $Port
    $MYObject.Response = $Response
    $MYObject
    
    }
    
  • London VMUG – 26th January 2012

    Posted on December 16th, 2011 Jonathan Medd No comments

    The next London VMUG will take place on 26th January 2012. The agenda is below and as usual there is a fantastic line up of well known members of the community to give you some knowledge from their real world experiences. I’m planning to attend so hope to see you there :-)

     

  • UK VMUG Nov 2011 Review

    Posted on December 14th, 2011 Jonathan Medd No comments

    A few weeks ago I attended the first ever UK based VMUG at the National Motorcycle Museum in Birmingham. Put together by the same folks who arrange the London VMUG events, it was a great day out and obviously a lot of hard work had been put in by Jane, Alaric, Simon , Stuart and Martyn. I know they had put the best part of 6 months into arranging it, so a lot of effort. By staging the event in the Midlands and involving other VMUGs from the UK, including the North of England, Scotland and Ireland there were over 300 attendees.

    I travelled up the night before and just about made it in time for a pre-show vCurry being held at the Museum. This gave a good chance to catch up with various tweeps, since I figured (and I think it panned out) that people wouldn’t hang around too long after the main event the next day, like they normally do at the London VUMG, with longer journeys home.

    There were also more sponsors than the London events and with involvement from the Official VMUG organisation there was even a posh looking programme to accompany the day’s events. How things have come one since I attended my first London VMUG about 3 years ago!

    The event centered around the main area below with the keynotes from the stage at the front and vendors around the outside. This was accompanied by breakout sessions in rooms off to the sides. The only downside of the day was the lack of WIFI or 3G access since we were a couple of floors down, but thanks to the distribution of some BT OpenZone cards it was possible to stay reasonably well connected.

    I had volunteered to assist Alan Renouf with a PowerCLI lab he had put together, which took place at the back of the main room.

    We turned this into a drop by area for questions about PowerCLI and PowerShell as well. While the lab proved pretty popular, the best part was taking people’s questions and showing them how PowerCLI and PowerShell might help them out in their jobs. It was quite surprising to find that there were many questions such as ‘What are they?’, ‘What can I do with them?’ and ‘How much do they cost?’ – and a lot assuming I was a VMware employee! A lot of these conversations spurned off into Alan sitting them down, demonstrating some coding and often writing a script for them to take away.

    I managed to get away to a couple of the sessions and in particular enjoyed Julian Wood’s session on upgrading to vSphere 5, which was really well attended. One of the other most intriguing parts of the day was a mock VCDX panel organised by Simon Gallager. This was an opportunity for people to practise defending a vSphere design (with a lot of onlookers for extra pressure!). You’ll notice that Duncan Epping was helping with this so the volunteers were grilled, but also received excellent feedback. The PowerCLI drop by area was positioned right next to this while it was going on and I know a number of people found the experience really useful when I talked to them as they walked away from it.

    I really enjoyed the day as a Community Booth Babe and now know how draining it is being on a stand all day (you can probably tell from my dishevelled look below!). The best thing for me was answering people’s PowerCLI and PowerShell questions, really kept me on my toes. The highlight being one guy who was driving into work every Saturday, carrying out a few tasks inside a VM, powering it off, taking a clone, powering it back on and then driving home – I showed  him how he could schedule this with a script and get his Saturday back :-)

    Hopefully the team will arrange another UK centered VMUG next year after the success of this one. In the meantime, details have just been published of the next London VMUG on January 26th. I highly recommend you attend this.

    To round things off I made my way home in very ecological style with a lift from an ex-colleague and and his awesome company vehicle :-)

  • UK PowerShell User Group December 2011 – Use the WSMAN cmdlets to retreive WMI information

    Posted on December 14th, 2011 Jonathan Medd No comments

    The UK PowerShell User Group for December 2011 will take place at 19.30 GMT on Thursday December 15t. The topic is ‘Use the WSMAN cmdlets to retreive WMI information and see a demo of the new WMI API’s CIM cmdlets in PowerShell v3 CTP 2′. I’m looking forward to seeing the new CIM cmdlets from V3 CTP2 since I haven’t had chance to play with those yet. Details from Richard Siddaway’s blog are below:

     

    When: Thursday, Dec 15, 2011 7:30 PM (GMT)
    
    Where: Virtual
    
    *~*~*~*~*~*~*~*~*~*

    Discover how to use the WSMAN cmdlets to retreive WMI information and see a demo of the new WMI API’s CIM cmdlets in PowerShell v3 CTP 2

    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: PJSH3M
      Entry Code: gG/C-75(m
      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.

     

  • Reporting on Windows File Server Shares and NTFS Permissions with PowerShell

    Posted on December 8th, 2011 Jonathan Medd No comments

    I recently had a requirement to audit the Share and NTFS permissions of a Windows File Server. PowerShell contains the Get-ACL cmdlet which makes retreving the NTFS permissions fairly straightforward, but for the Share permissions it is not so easy, but we can make use of WMI and the Win32_LogicalShareSecuritySetting class.

    The below forum post details some discussion around using this class to find the Share permissions and unsurprisingly the legendary Shay Levy provides the solution.

    http://groups.google.com/group/powershell-users/browse_thread/thread/43f06ce172e68c38?pli=1

    The following script makes use of this code and adds some parameters depending on your requirements.

    
    <#
    .SYNOPSIS
    Retrieve report of share permissions
    
    .DESCRIPTION
    Retrieve report of share permissions
    
    .PARAMETER  ComputerName
    Computer name to retrieve share permissions from
    
    .PARAMETER  Share
    Name of the share to retrieve permissions from (optional)
    
    .PARAMETER  OutputFile
    Name of the file to output the report to (optional)
    
    .EXAMPLE
    PS C:\> Get-SharePermissions.ps1 -ComputerName Server01 -Share Share01 -OutputFile C:\Scripts\SharePermissions.csv
    
    .EXAMPLE
    PS C:\> Get-SharePermissions.ps1 -ComputerName Server01
    
    .NOTES
    Author: Jonathan Medd
    Date: 06/12/2011
    Version: 0.1
    
    #>
    
    [CmdletBinding()]
    param(
    
    [Parameter(Position=0)]
    [System.String]
    $ComputerName = '.',
    
    [Parameter(Position=1)]
    [System.String]
    $Share,
    
    [Parameter(Position=2)]
    [System.String]
    $OutputFile
    )
    
    function Translate-AccessMask($val){
    Switch ($val)
    {
    2032127 {"FullControl"; break}
    1179785 {"Read"; break}
    1180063 {"Read, Write"; break}
    1179817 {"ReadAndExecute"; break}
    -1610612736 {"ReadAndExecuteExtended"; break}
    1245631 {"ReadAndExecute, Modify, Write"; break}
    1180095 {"ReadAndExecute, Write"; break}
    268435456 {"FullControl (Sub Only)"; break}
    default {$AccessMask = $val; break}
    }
    }
    
    function Translate-AceType($val){
    Switch ($val)
    {
    0 {"Allow"; break}
    1 {"Deny"; break}
    2 {"Audit"; break}
    }
    }
    
    # Create calculated properties
    $ShareProperty = @{n="Share";e={$ShareName}}
    $AccessMask = @{n="AccessMask";e={Translate-AccessMask $_.AccessMask}}
    $AceType = @{n="AceType";e={Translate-AceType $_.AceType}}
    $Trustee = @{n="Trustee";e={$_.Trustee.Name}}
    
    if ($Share){
    
    $filter="name='$Share'"
    
    $WMIQuery = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -ComputerName $ComputerName -filter $filter | ForEach-Object {
    $ShareName = $_.name
    $_.GetSecurityDescriptor().Descriptor.DACL | Select-Object $Shareproperty,$AccessMask,$AceType,$Trustee}
    }
    
    else {
    $WMIQuery = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -ComputerName $ComputerName | ForEach-Object {
    $ShareName = $_.name
    $_.GetSecurityDescriptor().Descriptor.DACL | Select-Object $Share,$AccessMask,$AceType,$Trustee }
    }
    
    if ($OutputFile){
    $WMIQuery | Export-Csv $OutputFile -NoTypeInformation
    }
    
    else {
    $WMIQuery | Format-Table -AutoSize
    }
    

     

    For NTFS permissions Jeff Hicks has a very useful post for creating NTFS ACL reports.

    http://jdhitsolutions.com/blog/2011/06/creating-acl-reports/

    The following is a script based off some of the ideas in that post which you can use for generating a report depending on your requirements.

    
    <#
    .SYNOPSIS
    Retrieve report of NTFS permissions
    
    .DESCRIPTION
    Retrieve report of NTFS permissions
    
    .PARAMETER  ComputerName
    Computer name to retrieve NTFS permissions from
    
    .PARAMETER  Folder
    Name of the NTFS path to retrieve permissions from
    
    .PARAMETER  Recurse
    Retrieve permissions from subfolders and files
    
    .PARAMETER  OutputFile
    Name of the file to output the report to (optional)
    
    .EXAMPLE
    PS C:\> Get-NTFSPermissions.ps1 -ComputerName Server01 -Folder D$\Home -OutputFile C:\Scripts\NTFSPermissions.csv
    
    .EXAMPLE
    PS C:\> Get-NTFSPermissions.ps1 -Folder D:\Home -Recurse
    
    .NOTES
    Author: Jonathan Medd
    Date: 07/12/2011
    Version: 0.1
    
    #>
    
    [CmdletBinding()]
    param(
    
    [Parameter(Position=0)]
    [System.String]
    $ComputerName = '.',
    
    [Parameter(Position=1,Mandatory=$true,HelpMessage="Name of the NTFS path to retrieve permissions from")]
    [System.String]
    $Folder,
    
    [Parameter(Position=2)]
    [Switch]
    $Recurse,
    
    [Parameter(Position=3)]
    [System.String]
    $OutputFile
    )
    
    # Set the Path variable dependent on whether its for a remote machine
    if ($ComputerName -eq '.'){
    $Path = $Folder
    }
    
    else {
    $Path = "\\$ComputerName\$Folder"
    }
    
    if ($OutputFile){
    Get-Childitem $Path -Recurse:$Recurse | ForEach-Object {Get-Acl $_.FullName} | Select-Object @{Name="Path";Expression={$_.PSPath.Substring($_.PSPath.IndexOf(":")+2) }},@{Name="Type";Expression={$_.GetType()}},Owner -ExpandProperty Access | Export-CSV $OutputFile -NoTypeInformation
    }
    
    else {
    Get-Childitem $Path -Recurse:$Recurse | ForEach-Object {Get-Acl $_.FullName} | Select-Object @{Name="Path";Expression={$_.PSPath.Substring($_.PSPath.IndexOf(":")+2) }},@{Name="Type";Expression={$_.GetType()}},Owner -ExpandProperty Access | Format-Table -AutoSize
    }
    
  • PowerShell V3 CTP2 – Now Available

    Posted on December 6th, 2011 Jonathan Medd 1 comment

    The second Community Technology Preview of PowerShell V3 is now available. This pre-beta release gives of a flavour of areas of change which may appear in the final release. A CTP has an emphasis on Community , i.e. the PowerShell team is looking for plenty of feedback for this release while they still have time to change things. Below are items logged on Connect by the community which have been fixed since the release of CTP1 – so if you find an issue in your testing, please log it on Connect so it can be reviewed and potentially resolved.

    689302 Unable to catch PSRemotingTransportException
    690139 Get-Command gets duplicated result if a requested script path contains “..”.
    676882 Out-GridView and properties with dots
    687776 ISE Editor Enhancements
    687886 2-pane “more console-like” mode for ISE
    688630 PowerShell ISE v3 – UserEnterToSelectInCommandPaneIntellisense should be on by default
    690164 V3 – out-gridview – remove a criteria close the grid window
    690556 Tab Complete in Remote Session
    690784 PS3CTP1 – Object casting regression
    690864 Import-Module should check the required PowerShell version before anything else
    690895 PS3CTP1: PowerShell.exe shows THROWN error Message in normal output color
    691206 PoshV3CTP1: PowerShell Events do not trigger when used with UI (WPF & Windows Forms)
    691439 Having an append ability in Export-CSV.
    692617 StopProcessing doesn’t work in v3
    692776 PS3CTP1: Variables as property names BROKEN with Assignment Operators
    693754 Powershell 3.0 ISE editor corrupts text
    694600 Run with Powershell not executing scripts
    694940 NestedModules are unloaded from GLOBAL scope with the parent module.
    694942 NestedModules doesn’t support specifying the version
    695755 v3 CTP1: Breaking change – DayOfWeek and left-hand rule
    695978 PS3CTP1: REGRESSION: Get-Member -Static Error
    697131 v3 CTP1: Char[] not reversed by Array.Reverse static method
    704136 Divide by Zero $? Test Returns True

     

    PowerShell V3 CTP2 is part of the Windows Management Framework (WMF) 3.0 CTP2 and can be installed on the following Windows configurations.

    Operating System SP Level SKUs Languages
    Windows 7 SP1 All English
    Windows Server 2008 R2 SP1 and greater All but IA64 English

    Full details on other changes in CTP2 are detailed on the PowerShell Team Blog:

    —————————————————————————————————————————————————————————————————————————————————-

    I’m pleased to announce that the Community Technology Preview #2 (CTP2) is available for download.

    Windows Management Framework 3.0 CTP2 makes some updated management functionality available to be installed on Windows 7 SP1 & Windows Server 2008 R2 SP1. Windows Management Framework 3.0 contains Windows PowerShell 3.0, WMI & WinRM.

    IMPORTANT: If you have WMF3.0 CTP1 installed, you must uninstall it before installing CTP2.

    Overview of changes since WMF 3.0 CTP1
    1. Customer Reported Bug Fixes
    Many customer reported bugs have been fixed since the WMF 3.0 CTP1. The release notes contains a list of bug titles, but please check Connect for full details.

    2. Single Command Pane in Windows PowerShell ISE
    The Command and Output panes in Windows PowerShell ISE have been combined into a single Command pane that looks and behaves like the Windows PowerShell console.

    3. Updatable Help
    The WMF 3.0 CTP1 release notes described a new Updatable Help system in Windows PowerShell 3.0 and included a copy of the help content. The Updatable Help system is now active on the Internet. To download and update help files, type: Update-Help.

    4. Windows PowerShell Workflows
    A number of enhancements have been made in the scripting experience for Windows PowerShell Workflows, including new keywords: Parallel, Sequence & Inlinescript. A document describing these changes will be published to the download page shortly.

    5. Remote Get-Module
    The Get-Module cmdlet now supports implicit remoting. You can now use the new PSSession and CIMSession parameters of the Get-Module cmdlet to get the modules in any remote session or CIM session. A number of other module enhancements are listed in the release notes.

    Feedback & Bugs
    We welcome any feedback or bug submissions to the Windows PowerShell Connect site: http://connect.microsoft.com/PowerShell

    Additional Information:
    This software is a pre-release version. Features and behavior are likely to change before the final release.

    This preview release is designed to enable the community to experience and review the preliminary designs and direction of key features Windows PowerShell 3.0 and to solicit feedback before features are finalized.

    For an interesting post describing what to expect with a CTP, read this very old post from Jeffrey

    Travis Jones [MSFT]
    Program Manager – Windows PowerShell
    Microsoft Corporation