PowerShell for Windows Admins


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.


May 13, 2014  12:45 PM

Working with Server Core–renaming the machine

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

When you create a new Windows server it usually assigns a name of its own. I always prefer using my own names for servers – I usually create the name so it gives some indication of the machine’s purpose.

Renaming a computer is simple

On the local computer run

Rename-Computer -NewName test01 -Force –Restart

This will rename the computer and force the restart.

If you want to do this remotely the cmdlet has a –ComputerName parameter plus the ability to define local or domain credentials.


May 12, 2014  1:07 PM

Working with Server Core–setting IP addresses

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

When you create a new Windows machine it defaults to using DHCP to get an IP address. While that is fine for client machines most people apply a static address to their servers. Up until Windows 2012 you had 2 choices – use the GUI or use PowerShell and WMI.

Server 2012 introduced a host of cmdlets for administering your network settings.  Setting an IP address is simple as this:

New-NetIPAddress -InterfaceIndex 12 -IPAddress ‘10.10.55.101’ -AddressFamily IPv4 -PrefixLength 24

I haven’t used it but you can also set the default gateway which would make the command

New-NetIPAddress -InterfaceIndex 12 -IPAddress ‘10.10.55.101’ -AddressFamily IPv4 -PrefixLength 24 -DefaultGateway ‘10.10.55.01’

The DNS server addresses can be set like this

Set-DnsClientServerAddress -InterfaceIndex 12 -ServerAddresses ‘10.10.55.100’

The cmdlets are from the NetTCPIP and DnsClient modules respectively.

THESE MODULES ARE ONLY AVAILABLE ON WINDOWS 8/2012 AND LATER.


May 11, 2014  4:43 AM

PowerShell Summit Europe 2014 – Call for Topics

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The PowerShell Summit is the number one place where PowerShell enthusiasts gather and learn from each other in fast-paced, knowledge packed presentations. Experts from all over the world including MVP’s, Guru’s, and PowerShell team members, join together for a few days to discuss and learn how to maximize using PowerShell in the workplace.

And now the PowerShell Summit is coming to Europe. PowerShell Summit Europe 2014 will be held September 29, 30, and October 1 at the Hotel Park in Amsterdam, Holland. http://powershell.org/wp/community-events/summit/powershell-summit-europe/ If you want to share your PowerShell expertise, then this is your official call to submit presentations for selection!

Topic Areas – What we are looking for W

e are looking for 45-minute presentations covering a wide aspect of PowerShell expertise. We have three main topic areas that may assist you in building an abstract. • PowerShell Internals – A deep look into the inside workings of PowerShell and practical solutions that are built from them. These presentations are more focused on the PowerShell development community that is building extensions and solutions relating to PowerShell. • PowerShell in Production – These presentations are focused on domain specific PowerShell solutions for IT Pro’s such as managing Exchange, System Center, IIS, SharePoint, VMware and more. • PowerShell Features Deep Dive – These presentations are a deep look into configuring and working with PowerShell features and capabilities such as PowerShell Remoting, PowerShell Web Access, Reporting and more.

We are open to presentations across the entire ecosystem that has been built around PowerShell; so don’t hesitate to send an abstract for your particular area of expertise. And don’t think, “oh, I can’t do a presentation!” We aren’t looking for Toastmasters winners – we’re looking for folks to be a part of the community! Take the leap and present! Each session is only 35 minutes, with 10 minutes for Q&A!

Presentation submissions – What you should send to us

Presentations will be 45-minutes in length (planning for 30-40 minutes of material and 5-15 minutes of Q&A) and the submission should include the following: • Presentation Title • Presentation abstract – a description of the presentation and the topics covered. 100 words or less and suitable for marketing. • 50 word biography

You can submit multiple presentations in the same topic area or for different ones.

What you get if you present

The European Summit is working to a very tight budget as this is the first time we are running it. Compensation for speakers will be free admission (not free Association for Windows PowerShell Professionals membership, http://powershell.org/wp/association-for-windows-powershell-professionals, just free admission, which includes food). We will not reimburse hotel, expenses, or travel. It’s important that speakers not register for the conference, because we will not be refunding you if you do that. The financial situation may change to a certain degree if the event sells out but we can’t cover all of your expenses as a speaker and we can’t make any guarantees at this stage.

We also ask that you help publicize the event.

Presentation submission deadline – When you should send it by

Start sending your presentation submissions immediately! The selection committee will start selecting presentations as soon as they arrive so you don’t want to miss out. The last day we will accept presentation submissions will be May 23, 2014. Send your proposals to cft2014eu@powershell.org. Please either put multiple proposals in a Word doc, or send just one proposal in the body of an email, so that we can track these more easily.

When you will know you’ve been selected

The selection committee will start reviewing submissions immediately and begin the selection process. You will be informed if one or more of your presentations have been selected and sent a contract on or before June 14, 2014. You will need to return the signed contract by June 21, 2014.

The final agenda will be announced early July and posted on PowerShell.Org. We look forward to your submissions and your help in making PowerShell Summit Europe 2014 your most valuable IT/Dev conference of the year!


April 30, 2014  8:39 AM

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

We are trying to raise the money to purchase equipment to record the sessions at future PowerShell Summit’s

http://powershell.org/wp/2014/04/28/help-us-record-the-powershell-summit-sessions/

If you can help us – please do.

There have been some amazing sessions this year – when you watch people’s jaws drop you know the content is great.

If we can record the sessions attendees can see the sessions they missed and non-attendees can see what they are missing

Thank you


April 29, 2014  7:39 AM

Update on Office error

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Back in this post http://richardspowershellblog.wordpress.com/2012/10/15/powershell-3-and-word/

I showed that this code

$word = New-Object -ComObject “Word.application”

$word.visible = $true

$doc = $word.Documents.Add()

$doc.Activate()

$word.Selection.Font.Name = “Cambria”

$word.Selection.Font.Size = “20”

$word.Selection.TypeText(“PowerShell”)

$word.Selection.TypeParagraph()

$word.Selection.Font.Name = “Calibri”

$word.Selection.Font.Size = “12”

$word.Selection.TypeText(“The best scripting language in the world!”)

$word.Selection.TypeParagraph()

$file = “c:\test1.doc”

$doc.SaveAs([REF]$file)

$Word.Quit()

 

Wouldn’t work because of an error in the way [REF] was treated. I had a comment left on the post saying it worked on PowerShell v4.

I’ve tested on PowerShell v4 on Windows 8.1 with Office 2013. It works. I can’t vouch for other combinations but it looks the problem has been resolved.

If you have the opportunity please try it and let me know if it doesn’t work for your particular combination of PowerShell v4, Windows and Office


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: