PowerShell for Windows Admins


May 19, 2014  1:00 PM

Share Permissions – setting deny

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
CIM, WMI

The last change to the share permissions functions to modify the Set-SharePermissions functions to enable the application of Deny permissions.

The function becomes:

#requires -Version 3.0

function Set-SharePermission {

[CmdletBinding()]

param (

[Parameter(Mandatory=$true)]

[string]$sharename,

 

[string]$domain = $env:COMPUTERNAME,

 

[Parameter(Mandatory=$true)]

[string]$trusteeName,

 

[Parameter(Mandatory=$true)]

[ValidateSet(“Read”, “Change”, “FullControl”)]

[string]$permission = “Read”,

 

[string]$computername = $env:COMPUTERNAME,

 

[parameter(ParameterSetName=”AllowPerm”)]

[switch]$allow,

 

[parameter(ParameterSetName=”DenyPerm”)]

[switch]$deny

)

 

switch ($permission) {

‘Read’ {$accessmask = 1179817}

‘Change’ {$accessmask = 1245631}

‘FullControl’ {$accessmask = 2032127}

}

$tclass = [wmiclass]”\\$computername\root\cimv2:Win32_Trustee”

$trustee = $tclass.CreateInstance()

$trustee.Domain = $domain

$trustee.Name = $trusteeName

 

$aclass = [wmiclass]”\\$computername\root\cimv2:Win32_ACE”

$ace = $aclass.CreateInstance()

$ace.AccessMask = $accessmask

 

switch ($psCmdlet.ParameterSetName) {

“AllowPerm” {$ace.AceType = 0}

“DenyPerm” {$ace.AceType = 1}

default {Write-Host “Error!!! Should not be here” }

}

 

$ace.Trustee = $trustee

$shss = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -Filter “Name=’$sharename'” -ComputerName $computername

$sd = Invoke-WmiMethod -InputObject $shss -Name GetSecurityDescriptor |

select -ExpandProperty Descriptor

 

$sclass = [wmiclass]”\\$computername\root\cimv2:Win32_SecurityDescriptor”

$newsd = $sclass.CreateInstance()

$newsd.ControlFlags = $sd.ControlFlags

 

foreach ($oace in $sd.DACL){

if (($oace.Trustee.Name -eq $trusteeName) -AND ($oace.Trustee.Domain -eq $domain) ) {

continue

}

else

{

$newsd.DACL += $oace

}

}

$newsd.DACL += $ace

 

$share = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -Filter “Name=’$sharename'” -ComputerName $computername

$share.SetSecurityDescriptor($newsd)

 

} # end function

 

The changes are to add two switches –allow & –deny. Put them in different parametersets to ensure mutual exclusivity.

As you are using parametersets you can use a switch based on the parameterset name to set the ACE type.

switch ($psCmdlet.ParameterSetName) {

“AllowPerm” {$ace.AceType = 0}

“DenyPerm” {$ace.AceType = 1}

default {Write-Host “Error!!! Should not be here” }

}

 

Everything else remains the same.

 

May 18, 2014  12:44 PM

Share Permissions – adding a Deny permission

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
CIM, WMI

Modifying the Add-SharePermission function to enable the application of Deny permissions is a simple matter of adding a switch parameter –deny and modifying the way the AcreType is set:

#requires -Version 3.0

function Add-SharePermission {

[CmdletBinding()]

param (

[Parameter(Mandatory=$true)]

[string]$sharename,

 

[string]$domain = $env:COMPUTERNAME,

 

[Parameter(Mandatory=$true)]

[string]$trusteeName,

 

[Parameter(Mandatory=$true)]

[ValidateSet(“Read”, “Change”, “FullControl”)]

[string]$permission = “Read”,

 

[string]$computername = $env:COMPUTERNAME,

 

[switch]$deny

)

 

switch ($permission) {

‘Read’ {$accessmask = 1179817}

‘Change’ {$accessmask = 1245631}

‘FullControl’ {$accessmask = 2032127}

}

$tclass = [wmiclass]”\\$computername\root\cimv2:Win32_Trustee”

$trustee = $tclass.CreateInstance()

$trustee.Domain = $domain

$trustee.Name = $trusteeName

 

$aclass = [wmiclass]”\\$computername\root\cimv2:Win32_ACE”

$ace = $aclass.CreateInstance()

$ace.AccessMask = $accessmask

$ace.AceFlags = 0

 

if ($deny)

{

$ace.AceType = 1

}

else

{

$ace.AceType = 0

}

 

$ace.Trustee = $trustee

 

$shss = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -Filter “Name=’$sharename'” -ComputerName $computername

$sd = Invoke-WmiMethod -InputObject $shss -Name GetSecurityDescriptor |

select -ExpandProperty Descriptor

 

$sclass = [wmiclass]”\\$computername\root\cimv2:Win32_SecurityDescriptor”

$newsd = $sclass.CreateInstance()

$newsd.ControlFlags = $sd.ControlFlags

 

foreach ($oace in $sd.DACL){$newsd.DACL += $oace}

$newsd.DACL += $ace

 

$share = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -Filter “Name=’$sharename'” -ComputerName $computername

$share.SetSecurityDescriptor($newsd)

 

} # end function

 

The hard work is done by this part of the code:

 

if ($deny)

{

$ace.AceType = 1

}

else

{

$ace.AceType = 0

}

 

 

where the value of AceType is set to 1 for deny and 0 for allow.

 

 


May 18, 2014  8:40 AM

Share Permissions – working with Deny

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
CIM, WMI

Permissions can be set to either allow access ot to deny access. The functions I’ve presented so far only work with Allow permissions. Using Deny permissions should be avoided if at all possible but sometimes there’s no alternative.

First thing is to modify Get-SharePermission so that it shows if the permission is allowed or denied.

 

#requires -Version 3.0

function Get-SharePermission {

[CmdletBinding()]

param (

[Parameter(Mandatory=$true)]

[string]$sharename,

 

[string]$computername = $env:COMPUTERNAME

)

 

$shss = Get-CimInstance -Class Win32_LogicalShareSecuritySetting -Filter “Name=’$sharename'” -ComputerName $computername

$sd = Invoke-CimMethod -InputObject $shss -MethodName GetSecurityDescriptor |

select -ExpandProperty Descriptor

 

foreach ($ace in $sd.DACL) {

 

switch ($ace.AccessMask) {

1179817 {$permission = ‘Read’}

1245631 {$permission = ‘Change’}

2032127 {$permission = ‘FullControl’}

default {$permission = ‘Special’}

}

 

$trustee = $ace.Trustee

$user = “$($trustee.Domain)\$($trustee.Name)”

 

switch ($ace.AceType) {

0 {$status = ‘Allow’}

1 {$status = ‘Deny’}

2 {$status = ‘Audit’}

}

 

$props = [ordered]@{

User = $user

Permissions = $permission

Status = $status

}

New-Object -TypeName PSObject -Property $props

} # emd foreach

} # end function

 

The modification is to add a switch based on the AceType property of the Win32_ACE object (http://msdn.microsoft.com/en-us/library/aa394063(v=vs.85).aspx) to determine the status of the permission. Add a property called Status to the output object and set it equal to the status determined in the switch.

 


May 18, 2014  8:24 AM

Error trapping when getting AD objects

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Active Directory Administration

How many times have you done this:

£> Get-ADComputer -Identity “bleh”

Get-ADComputer : Cannot find an object with identity: ‘bleh’ under: ‘DC=Manticore,DC=org’.

At line:1 char:1

+ Get-ADComputer -Identity “bleh”

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

+ CategoryInfo : ObjectNotFound: (bleh:ADComputer) [Get-ADComputer], ADIdentityNotFoundException

+ FullyQualifiedErrorId : ActiveDirectoryCmdlet:Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException,

Microsoft.ActiveDirectory.Management.Commands.GetADComputer

 

Its the same with all of the AD cmdlets – if the object isn’t found you get an error thrown. That’s OK when working interactively but can wreck you script execution – you don’t want to come to work in the morning to find that you script failed on the fifth of fifty (or five hundred) computers.

Your first though might be to use the –ErrorAction parameter:

£> Get-ADComputer -Identity “bleh” -ErrorAction SilentlyContinue

Get-ADComputer : Cannot find an object with identity: ‘bleh’ under: ‘DC=Manticore,DC=org’.

At line:1 char:1

+ Get-ADComputer -Identity “bleh” -ErrorAction SilentlyContinue

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

+ CategoryInfo : ObjectNotFound: (bleh:ADComputer) [Get-ADComputer], ADIdentityNotFoundException

+ FullyQualifiedErrorId : ActiveDirectoryCmdlet:Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException,

Microsoft.ActiveDirectory.Management.Commands.GetADComputer

 

£> Get-ADComputer -Identity “bleh” -ErrorAction Ignore

Get-ADComputer : Cannot find an object with identity: ‘bleh’ under: ‘DC=Manticore,DC=org’.

At line:1 char:1

+ Get-ADComputer -Identity “bleh” -ErrorAction Ignore

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

+ CategoryInfo : ObjectNotFound: (bleh:ADComputer) [Get-ADComputer], ADIdentityNotFoundException

+ FullyQualifiedErrorId : ActiveDirectoryCmdlet:Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException,

Microsoft.ActiveDirectory.Management.Commands.GetADComputer

 

Neither SilentlyContinue or Ignore will work – the default is Continue.

 

You can use the $ErrorActionPreference variable:

£> $ErrorActionPreference = ‘SilentlyContinue’

£> Get-ADComputer -Identity “bleh”

£> $ErrorActionPreference = ‘Continue’

 

Set the variable to SilentlyContinue, run your command and then remember to set it back!

Another way is to use a try-catch block:

 

try {

Get-ADComputer -Identity “bleh”

}

catch {}

 

You can put any code needed to handle the object not been found into the catch block.

The catch works because it will pick up ANY exceptions. You can use the specific exception if you need to possibly handle other errors.

try {

Get-ADComputer -Identity “bleh”

}

catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException]

{

Write-Warning “AD computer object not found”

}

catch {}

 

The trick with using multiple catch blocks is to always ensure that the exceptions start with the most specific and work down to the most generic. In this case the Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException exception comes first – its what Get-ADComputer uses when it can’t find the object. If you’re wondering where that information comes from look at the first error message in the post – the exception has been highlighted.

The final catch block will catch any other exceptions that come through.

 


May 18, 2014  5:16 AM

Share Permissions – changing

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
CIM, PowerShell v3, WMI

So far you’ve seen how to read, remove and add permissions to a share. The final scenario to be covered is modifying a permission.

The functions I’ve presented to date only enable you to set Allow permissions on a share. I’ll be covering Deny permissions in later posts. This mimics the way that I tend to develop functionality – get part working then add more in increments until you have what you need.

For now this is function will enable you to modify permissions on a share:

#requires -Version 3.0

function Set-SharePermission {

[CmdletBinding()]

param (

[Parameter(Mandatory=$true)]

[string]$sharename,

 

[string]$domain = $env:COMPUTERNAME,

 

[Parameter(Mandatory=$true)]

[string]$trusteeName,

 

[Parameter(Mandatory=$true)]

[ValidateSet(“Read”, “Change”, “FullControl”)]

[string]$permission = “Read”,

 

[string]$computername = $env:COMPUTERNAME

)

 

switch ($permission) {

‘Read’ {$accessmask = 1179817}

‘Change’ {$accessmask = 1245631}

‘FullControl’ {$accessmask = 2032127}

}

 

 

$tclass = [wmiclass]”\\$computername\root\cimv2:Win32_Trustee”

$trustee = $tclass.CreateInstance()

$trustee.Domain = $domain

$trustee.Name = $trusteeName

 

$aclass = [wmiclass]”\\$computername\root\cimv2:Win32_ACE”

$ace = $aclass.CreateInstance()

$ace.AccessMask = $accessmask

$ace.AceFlags = 0

$ace.AceType = 0

$ace.Trustee = $trustee

 

$shss = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -Filter “Name=’$sharename'” -ComputerName $computername

$sd = Invoke-WmiMethod -InputObject $shss -Name GetSecurityDescriptor |

select -ExpandProperty Descriptor

 

$sclass = [wmiclass]”\\$computername\root\cimv2:Win32_SecurityDescriptor”

$newsd = $sclass.CreateInstance()

$newsd.ControlFlags = $sd.ControlFlags

 

foreach ($oace in $sd.DACL){

 

if (($oace.Trustee.Name -eq $trusteeName) -AND ($oace.Trustee.Domain -eq $domain) ) {

continue

}

else

{

$newsd.DACL += $oace

}

}

$newsd.DACL += $ace

 

$share = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -Filter “Name=’$sharename'” -ComputerName $computername

$share.SetSecurityDescriptor($newsd)

 

} # end function

 

If you compare this to the Add-SharePermission and Remove-SharePermission you’ll see that the Set-SharePermission is really the Add-SharePermission function with the code to add the old ACE to the new DACL modified to be similar to Remove-SharePermission.

if (($oace.Trustee.Name -eq $trusteeName) -AND ($oace.Trustee.Domain -eq $domain) ) {

continue

}

else

{

$newsd.DACL += $oace

}

The code loops through the old ACEs and as long as the name AND domain don’t match the trustee for whom you’re changing permissions they’re added to the new DACL. In other worlds the old permissions for the trustee are removed from the DACL.

 


May 17, 2014  7:02 AM

Share Permissions – Removing

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
CIM, PowerShell v3, WMI

You’ve seen how to read share permissions and how to add share permissions – now its time to remove share permissions. Most of the code we need is in the Add-Sharepermission function – it just needs a bit of a tweak.

#requires -Version 3.0

function Remove-SharePermission {

[CmdletBinding()]

param (

[Parameter(Mandatory=$true)]

[string]$sharename,

 

[string]$domain = $env:COMPUTERNAME,

 

[Parameter(Mandatory=$true)]

[string]$trusteeName,

 

[Parameter(Mandatory=$true)]

[ValidateSet(“Read”, “Change”, “FullControl”)]

[string]$permission = “Read”,

 

[string]$computername = $env:COMPUTERNAME

)

 

switch ($permission) {

‘Read’ {$accessmask = 1179817}

‘Change’ {$accessmask = 1245631}

‘FullControl’ {$accessmask = 2032127}

}

 

$shss = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -Filter “Name=’$sharename'” -ComputerName $computername

$sd = Invoke-WmiMethod -InputObject $shss -Name GetSecurityDescriptor |

select -ExpandProperty Descriptor

 

$sclass = [wmiclass]”\\$computername\root\cimv2:Win32_SecurityDescriptor”

$newsd = $sclass.CreateInstance()

$newsd.ControlFlags = $sd.ControlFlags

 

foreach ($oace in $sd.DACL){

if (($oace.Trustee.Name -eq $trusteeName) -AND ($oace.Trustee.Domain -eq $domain) -AND ($oace.Accessmask -eq $accessmask)) {

continue

}

else

{

$newsd.DACL += $oace

}

}

 

$share = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -Filter “Name=’$sharename'”

$share.SetSecurityDescriptor($newsd)

 

} # end function

 

The function uses the same parameters as Add-Permission i.e. mandatory share name, trustee name and permission with optional computer and domain names. The switch statement converts the permission into an access mask.

Use Get-WmiObject to get the current security descriptor and use [wmiclass] to create a new one.

Copy the control flags and the ACE except for the any that correspond to the trustee name, domain and the permission you want to remove.

Use SetSecurityDescriptor to apply the new permissions

 

 


May 16, 2014  1:23 PM

Share Permissions – adding

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
CIM, PowerShell v3, WMI

Having seen how to read the permissions on a share its time to turn to one of the other common tasks associated with shares – adding permissions. This is usually done when the share is created but there are scenarios where you need to add extra permissions.

I’ve written the function Add-SharePermission to accomplish this task:

#requires -Version 3.0

function Add-SharePermission {

[CmdletBinding()]

param (

[Parameter(Mandatory=$true)]

[string]$sharename,

 

[string]$domain = $env:COMPUTERNAME,

 

[Parameter(Mandatory=$true)]

[string]$trusteeName,

 

[Parameter(Mandatory=$true)]

[ValidateSet(“Read”, “Change”, “FullControl”)]

[string]$permission = “Read”,

 

[string]$computername = $env:COMPUTERNAME

)

switch ($permission) {

‘Read’ {$accessmask = 1179817}

‘Change’ {$accessmask = 1245631}

‘FullControl’ {$accessmask = 2032127}

}

$tclass = [wmiclass]”\\$computername\root\cimv2:Win32_Trustee”

$trustee = $tclass.CreateInstance()

$trustee.Domain = $domain

$trustee.Name = $trusteeName

 

$aclass = [wmiclass]”\\$computername\root\cimv2:Win32_ACE”

$ace = $aclass.CreateInstance()

$ace.AccessMask = $accessmask

$ace.AceFlags = 0

$ace.AceType = 0

$ace.Trustee = $trustee

 

$shss = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -Filter “Name=’$sharename'” -ComputerName $computername

$sd = Invoke-WmiMethod -InputObject $shss -Name GetSecurityDescriptor |

select -ExpandProperty Descriptor

 

$sclass = [wmiclass]”\\$computername\root\cimv2:Win32_SecurityDescriptor”

$newsd = $sclass.CreateInstance()

$newsd.ControlFlags = $sd.ControlFlags

 

foreach ($oace in $sd.DACL){$newsd.DACL += $oace}

$newsd.DACL += $ace

 

$share = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -Filter “Name=’$sharename'”

$share.SetSecurityDescriptor($newsd)

 

} # end function

 

The function starts with a requires restricting the function to version 3 and above. The function would run on version 2 so this is for consistency with the Get-SharePermission function I showed last time.

The parameter block includes a mandatory sharename and trusteename (user or group). Optional parameters allow a domain and computername to be set – both default to the local machine. A final mandatory parameter allows the specification of the permissions to be applied – read, change or full control – these values are validated at input using the ValidateSet option.

The next step in the function is to take the permission and turn it into an access mask using a switch – its the inverse of the one you saw in Get-SharePermission.

I’ve had to use the [wmiclass] type accelerator to to create the Win32_Trustee and Win32_ACE instances I need. The CIM cmdlets can’t be used because these classes don’t have keys defined.

The properties are set on the 2 objects.

Get-WmiObject is used to get the SecurityDescriptor of the share.

A new security descriptor is created with the relevant properties from the existing one copied across – the current ACEs have to be copied individually as shown. The new ACE is added to the DACL

Finally Get-WmiObject is used to retrieve the share object and the SetSEcurityDescriptor method is used to apply the new security descriptor.

Some interesting uses the wmiclass accelerator to make this work but the function shows it is doable without too much effort.

 

 


May 15, 2014  1:40 PM

Share Permissions – getting

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

I’ve written about working with share permissions a couple of times but a post on the forum (powershell.org) got me thinking about it again. This time I’m going to use the CIM cmdlets rather than the WMI cmdlets I’ve used in the past.

My test machine has a test share called Test2April so that’s what we’ll work with. The first job is to understand the permissions assigned to the share. There are 3 possibilities for share permissions:

Read

Change

Full control

I assigned these to distinct users – Everyone, ChangeUser and Fulluser respectively.

Discovering the permissions can be performed using this function:

#requires -Version 3.0

function Get-SharePermission {

[CmdletBinding()]

param (

[Parameter(Mandatory=$true)]

[string]$sharename,

[string]$computername = $env:COMPUTERNAME

)

$shss = Get-CimInstance -Class Win32_LogicalShareSecuritySetting -Filter “Name=’$sharename'” -ComputerName $computername

$sd = Invoke-CimMethod -InputObject $shss -MethodName GetSecurityDescriptor |

select -ExpandProperty Descriptor

foreach ($ace in $sd.DACL) {

switch ($ace.AccessMask) {

1179817 {$permission = ‘Read’}

1245631 {$permission = ‘Change’}

2032127 {$permission = ‘FullControl’}

default {$permission = ‘Special’}

}

$trustee = $ace.Trustee

$user = “$($trustee.Domain)\$($trustee.Name)”

$props = [ordered]@{

User = $user

Permissions = $permission

}

New-Object -TypeName PSObject -Property $props

} # emd foreach

} # end function

 

The function takes a mandatory parameter of the share name with an option parameter of computername that defaults to the local machine.

Use the Win32_LogicalShareSecuritySetting class to get the security information. The security descriptor is retrieved using its GetSecurityDescriptor method. The security descriptor stores the DACL for the share.

Each ACE in the DACL is interrogated to determine its access mask and the trustee associated with that permission. I’ve given the access mask for the 3 common permissions (Read, Change, Full Control) – anything else is listed as special. You can use the techniques in technique 51 form PowerShell and WMI or download my PAM module from codeplex (http://psam.codeplex.com/) and use Get-ShareAccessMask.

The domain and name of the trustee is put into the $user variable – it could just as easily be a group that comes through.

Create an ordered hash table with the results and output as an object.

The output will look something like this:

£> Get-SharePermission -sharename Test2April | ft -AutoSize

User Permissions

—- ———–

RSsurfacePro2\ChangeUser Change

\Everyone Read

RSsurfacePro2\FullUser FullControl

 

 


May 14, 2014  1:09 PM

Domain Controllers and their sites

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Its relatively straightforward to find the domain controllers in your AD domain and its equally as straightforward to find the sites in your AD forest. Discovering which domain controllers are in which site is a bit more problematic.

One way is look at the nTDSDSA objects. These are in the configuration naming context and their distinguished names take the form:

CN=NTDS Settings,CN=SERVER02,CN=Servers,CN=Site1,CN=Sites,CN=Configuration,DC=Manticore,DC=org

Similar to the information you see in AD Sites and Services.

This script produces a table of domain controllers and sites.

Get-ADObject -SearchBase (Get-ADRootDSE | select -ExpandProperty configurationNamingContext) -LDAPFilter “(ObjectClass=nTDSDSA)” |

select -ExpandProperty DistinguishedName |

foreach {

$data = $psitem -split “,”

$props = [ordered]@{

DC = ($data[1] -split “=”)[1]

Site = ($data[3] -split “=”)[1]

}

New-Object -TypeName PSObject -Property $props

}

 

Start by getting the rootdse, using Get-ADRootDSE, of the domain and finding the the distinguished name of the configuration naming context. Use that as the value for the –SearchBase parameter of Get-ADObject. An LDAP filter restricts the return to objects of type nTDSDSA.

Select the distinguished name and pipe into a foreach-object block.

Split the distinguishednames on the comma separator and then use elements 1 and 3 of the resultant array which are, respectively:

CN=SERVER02

CN=Site1

Split each on the = sign and take the second element. This gives you the DC name and the corresponding site name. Use this to create an object for output.

 


May 14, 2014  10:51 AM

Provider is not capable of the attempted operation

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

A question on the (powershell.org) forum described a situation where the user was trying to use Set-WmiInstance to set a property on a particular WMI class instance.

The attempt failed and the message “Provider is not capable of the attempted operation” was part of the reported exception.

This message very often indicates that you are trying to write to a readonly property – which was the case here.  The class was Win32_SystemEnclosure and the property was SMBIOSAssetTag.

If you use get-member

Get-WmiObject -Class Win32_SystemEnclosure | Get-Member

and look at the SMBIOSAssetTag property you’ll see this

SMBIOSAssetTag            Property      string SMBIOSAssetTag {get;set;}

BUT that’s not right because if you look at the documentation at http://msdn.microsoft.com/en-us/library/aa394474%28v=vs.85%29.aspx

you’ll see this:

SMBIOSAssetTag

Data type: string
Access type: Read-only

Asset tag number of the system enclosure.

Get-Member doesn’t report correctly on whether a WMI class’ property is readonly.  The best way to find out is to use Get-CimClass

£> $class = Get-CimClass Win32_SystemEnclosure

£> $class.CimClassProperties[‘SMBIOSAssetTag’]

Name               : SMBIOSAssetTag

Value              :

CimType            : String

Flags              : Property, ReadOnly, NullValue

Qualifiers         : {MappingStrings, read}

ReferenceClassName :

And you can see in the flags that the property is ReadOnly.

Get-CimClass should be your starting point when investigating WMI classes.


Forgot Password

No problem! Submit your e-mail address below. We'll send you an e-mail containing your password.

Your password has been sent to: