PowerShell for Windows Admins


June 8, 2014  7:32 AM

Function parameter validation – other validation options

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Some other options you can use for validating your input include:

[ValidateCount(1,10)]

tests the number of values being passed to the parameter – must be within the range (including end points ) specified

[ValidateLength(1,10)]

test the number of characters in a parameter value – must be within the specified range
[ValidatePattern("\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b")] ## IP Address
[ValidatePattern("[A-Z]{2,8}[0-9][0-9]“)]

tests the input value against a regular expression – the value must match the pattern otherwise an error will be thrown

[ValidateRange(0,10)]

the value must be between the endpoints of the range specified

[ValidateSet("Low", "Average", "High")]

the value must be a member of the set of values specified

Using these, together with the ValidateScript and Validate  NotNullorEmpty options, provide you an easy way to test and validate your function inputs.  Much easier than writing your own code

June 7, 2014  9:33 AM

DSC Resource Kit wave 4 now available

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The next wave of the DSC resource kit has been released. Notable additions include support for configuring DNS and DHCP servers and your event logs.

Details from http://blogs.msdn.com/b/powershell/rss.aspx


June 6, 2014  7:36 AM

PowerShell Summit NA 2014 sessions

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The slides and code from my three sessions

WSMAN cmdlets

Networking administration

Cmdletize the Registry

are available from

http://powershell.org/wp/2014/05/22/na-2014-powershell-summit-wrap-up-and-speaker-slides/

You can find videos of some of the sessions – including my three here

http://powershell.org/wp/2014/05/16/powershell-summit-n-a-2014-session-videos/


June 4, 2014  1:18 PM

Function parameter validation–ValidateScript

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Sometimes you need a little bit more than the standard parameter validation options can provide – in that case use ValidateScript – you can write your own validation routine. For example:

function test {
[CmdletBinding()]
param (
[parameter(Mandatory=$true,ValueFromPipeLine=$true,ValueFromPipeLineByPropertyName=$true)]
[ValidateNotNullOrEmpty()]
[ValidateScript({Test-Path -Path $_})]
[string]$Path
)

$path

}

All I’ve done to the function used last time is that I’ve added

[ValidateScript({Test-Path -Path $_})]

This will test the path you input to determine if it exists.

Supply a path

£> test -Path C:\Test
C:\Test

and the function works as expected.

£> test -Path
test : Missing an argument for parameter ‘Path’. Specify a parameter of type ‘System.String’ and try again.
At line:1 char:6
+ test -Path
+      ~~~~~
+ CategoryInfo          : InvalidArgument: (:) [test], ParameterBindingException
+ FullyQualifiedErrorId : MissingArgument,test
Miss off the value of –path and you get the error telling you that the argument is missing. Being able to have multiple validation tests does give you the most flexibility.

£> test -Path C:\Test22
test : Cannot validate argument on parameter ‘Path’. The “Test-Path -Path $_” validation script for the argument with
value “C:\Test22″ did not return a result of True. Determine why the validation script failed, and then try the command
again.
At line:1 char:12
+ test -Path C:\Test22
+            ~~~~~~~~~
+ CategoryInfo          : InvalidData: (:) [test], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,test
In this case an invalid path is supplied and the validation script runs and determines that the path is invalid.

In case you were wondering about the order of validation – in this case it doesn’t matter if you change the order

function test {
[CmdletBinding()]
param (
[parameter(Mandatory=$true,ValueFromPipeLine=$true,ValueFromPipeLineByPropertyName=$true)]
[ValidateScript({Test-Path -Path $_})]
[ValidateNotNullOrEmpty()]
[string]$Path
)

$path

}

£> test -Path C:\Test
C:\Test

£> test -Path
test : Missing an argument for parameter ‘Path’. Specify a parameter of type ‘System.String’ and try again.
At line:1 char:6
+ test -Path
+      ~~~~~
+ CategoryInfo          : InvalidArgument: (:) [test], ParameterBindingException
+ FullyQualifiedErrorId : MissingArgument,test
£> test -Path C:\Test22
test : Cannot validate argument on parameter ‘Path’. The “Test-Path -Path $_” validation script for the argument with
value “C:\Test22″ did not return a result of True. Determine why the validation script failed, and then try the command
again.
At line:1 char:12
+ test -Path C:\Test22
+            ~~~~~~~~~
+ CategoryInfo          : InvalidData: (:) [test], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,test
The validation tests fail as expected.


June 3, 2014  11:57 AM

Function parameter validation–NotNullorEmpty

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

A question on the forum made me realise that there is still  a lot of confusion around the advanced function parameter validation options so I thought I’d spend  a few posts clearing some of the confusion.

The question was about ValidateNotNullorEmpty so I’ll start with that one.

function test {
[CmdletBinding()]
param (
[parameter(Mandatory=$true,ValueFromPipeLine=$true,ValueFromPipeLineByPropertyName=$true)]
[ValidateNotNullOrEmpty()]
[string]$Path
)

$path

}

If you supply a path – it’s echoed back to you:

£> test -Path C:\Test
C:\Test

If you don’t supply the path parameter you’ll be prompted for it:

£> test
cmdlet test at command pipeline position 1
Supply values for the following parameters:
Path: c:\test
c:\test

if you use the function and don’t supply a value:

£> test -Path
test : Missing an argument for parameter ‘Path’. Specify a parameter of type ‘System.String’ and try again.
At line:1 char:6
+ test -Path
+      ~~~~~
+ CategoryInfo          : InvalidArgument: (:) [test], ParameterBindingException
+ FullyQualifiedErrorId : MissingArgument,test

The validation routine kicks in.

The pipeline works as well:

£> Get-ChildItem -Path c:\ -Filter test | test
Test

Though notice that its returning Test instead of c:\test – that’s because Get-ChildItem doesn’t return a property called path but Name is the first string property accessible in the object which is why its used.

Now if you try to access a non-existent path in this way

£> Get-ChildItem -Path c:\ -Filter test27 | test
£>

You’ll get nothing returned  – because

Get-ChildItem -Path c:\ -Filter test27

doesn’t put anything on the pipeline so test is never called.

If you want to see the function work with a non-existent folder try this:

£> test -Path (Get-ChildItem -Path c:\ -Filter test27)
test : Cannot validate argument on parameter ‘Path’. The argument is null or empty. Provide an argument that is not null
or empty, and then try the command again.
At line:1 char:12
+ test -Path (Get-ChildItem -Path c:\ -Filter test27)
+            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidData: (:) [test], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,test

ValidateNotNullEmpty is a good test for determining if a value is present and not Null or an empty string. It should be paired where possible with mandatory=$true to ensure that the parameter is used.

This and other validation options are discussed in about_Functions_Advanced_Parameters


June 2, 2014  10:53 AM

Unavailable modules

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Windows 2012

Another question on the powershell.org forum centred on modules not available on down level versions of Windows – in this case the SmbShare module.

A large number of modules were introduced with Windows server 2012 (many are also available on Windows 8). Over 60% of this new functionality is created using CDXML. A WMI class is created to do the work. Calls to the class are wrapped in XML and the subsequent file can be published as a PowerShell module.

These are easy to spot as they have a .CDXML extension.

If you are having problems with a module that doesn’t appear to be on Windows Server 2008 R2 or earlier – check the file extension in the module folder on a Windows Server 2012 (R2) system– if its CDXML the WMI class almost certainly won’t be available on the earlier versions of Windows.


May 28, 2014  1:39 PM

File system ACLs–function to add ACL

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
NTFS permissions

I thought that today I’d start putting together a function to add an ACL to a file system object. The starting point is the code that stepped through the process in an earlier post:

http://msmvps.com/blogs/richardsiddaway/archive/2014/05/26/file-system-acls-creating-an-acl.aspx

function add-acl {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[ValidateScript({Test-Path -Path $_ })]
[string]$path,

[Parameter(Mandatory=$true)]
[string]$trusteeName,

[Parameter(Mandatory=$true)]
[ValidateSet("Read", "Write", "ListDirectory", "ReadandExecute", "Modify", "FullControl")]
[string]$permission = “Read”,

[switch]$deny

)

$fsr = [System.Security.AccessControl.FileSystemRights]::$permission
if ($deny) {
$alwdny = [System.Security.AccessControl.AccessControlType]::Deny
}
else {
$alwdny = [System.Security.AccessControl.AccessControlType]::Allow
}
$acr = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $trusteeName, $fsr, $alwdny

$acl = Get-Acl -Path $path
$acl.AddAccessRule($acr)
Set-Acl -Path $path -AclObject $acl -Passthru
}

The parameters supply the path to the object, the trustee receiving the permissions, the permission and if its being denied.

The function creates the appropriate objects for the file system rights and access control type and then creates an access rule.

Get-Acl is used to fetch the current acl to which the new access rule is added. Set-Acl is used to overwrite the ACL.

One thing that hasn’t been covered is the Inheritance flags – they will be added in the next iteration of the function.


May 28, 2014  12:51 PM

PowerShell Scripting Best Practices

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Ed Wilson is running a series on Best Practices on his Hey, Scripting Guy blog at the moment.  I especially like today’s which is on simple scripts.  I do a lot of quick and dirty scripts that end up being thrown away at the  end of the project or incorporated into more formal modules for reuse.

Simple scripts are a very powerful admin tool and one that a lot of people don’t think about as they are conditioned into the idea that everything should be a module and other big code concepts. Don’t get me wrong – modules and everything else around enterprise level scripting are very important and a lot of my work is done that way but the quick, utility style script still has its place.

Check out Ed’s article at

http://blogs.technet.com/b/heyscriptingguy/archive/2014/05/28/powershell-best-practices-simple-scripting.aspx


May 27, 2014  1:21 PM

File system ACLs – copying ACLs

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
NTFS permissions

A comment was left on the first post in the series asking if I could show how to copy ACLs from one object to another.  For the sake of this post we’ll assume that the ACLs from c:\test will be copied to c:\test2.

If this is one shot deal you can just use the PowerShell pipeline:

Get-Acl -Path C:\Test | Set-Acl -Path C:\Test2

If you need something that will be used more frequently – how about a copy-acl function:

function copy-acl {
[CmdletBinding()]
param (
[ValidateScript({Test-Path -Path $_ })]
[string]$path,

[ValidateScript({Test-Path -Path $_ })]
[string]$destination
)

try
{
Get-Acl -Path $path | Set-Acl -Path $destination -Passthru -ErrorAction Stop
}
catch
{
Throw “Error setting ACL on $destination”
}
}

Get the source and target paths as parameters – validation scripts are used to determine if the paths exist.

Use the Get—Acl  | Set-Acl combination from earlier to set the ACL on the destination.  wrap it in a try/catch and use –Passthru on Set-Acl to see some output


May 26, 2014  11:05 AM

File System ACLs – creating an ACL

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
NTFS permissions

Last time you saw that the permissions assign to a file system object are built from instances of the System.Security.AccessControl.FileSystemAccessRule class.  Run

Get-Acl -Path c:\test | fl *

and look at the Access property.

Drilling into an individual ACL they look like this:

FileSystemRights  : FullControl
AccessControlType : Allow
IdentityReference : BUILTIN\Administrators
IsInherited       : True
InheritanceFlags  : ContainerInherit, ObjectInherit
PropagationFlags  : None

You see the documentation for the class at http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.filesystemaccessrule(v=vs.110).aspx

Creating a new access rule starts by creating a new instance of the class. The documentation shows 4 constructors – ways to build an instance of the class. The simplest requires the name of a user account (or group), the type of operation associated with the rule and whether the operation is allowed or denied.

First off you need to define some data to use during the creation process:

You need to define the user

$user = “$($env:COMPUTERNAME)\Newuser”

The type of access they have

$fsr = [System.Security.AccessControl]::FullControl

See http://msdn.microsoft.com/en-us/library/system.security.accesscontrol(v=vs.110).aspx for the full list

And whether the rule is allowed or denied

$alwdny = [System.Security.AccessControl.AccessControlType]::Allow

You can then create the access rule

$acr = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $user, $fsr, $alwdny

Get the current ACL

$acl = Get-Acl -Path C:\Test

Add the new rule
$acl.AddAccessRule($acr)

And finally set the ACL on the object

Set-Acl -Path c:\test -AclObject $acl

Over the next few posts I’ll show how to simplify this process with some functions – in a similar way to those you saw recently for working with shares.

 

 

 

 

 


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: