Quantcast
Channel: PowerShell
Viewing all 1519 articles
Browse latest View live

Parsing Text with PowerShell (1/3)

$
0
0

This is the first post in a three part series.

  • Part 1:
    • Useful methods on the String class
    • Introduction to Regular Expressions
    • The Select-String cmdlet
  • Part 2:
    • The -split operator
    • The -match operator
    • The switch statement
    • The Regex class
  • Part 3:
    • A real world, complete and slightly bigger, example of a switch-based parser

A task that appears regularly in my workflow is text parsing. It may be about getting a token from a single line of text or about turning the text output of native tools into structured objects so I can leverage the power of PowerShell.

I always strive to create structure as early as I can in the pipeline, so that later on I can reason about the content as properties on objects instead of as text at some offset in a string. This also helps with sorting, since the properties can have their correct type, so that numbers, dates etc. are sorted as such and not as text.

There are a number of options available to a PowerShell user, and I’m giving an overview here of the most common ones.

This is not a text about how to create a high performance parser for a language with a structured EBNF grammar. There are better tools available for that, for example ANTLR.

.Net methods on the string class

Any treatment of string parsing in PowerShell would be incomplete if it didn’t mention the methods on the string class.
There are a few methods that I’m using more often than others when parsing strings:

Name Description
Substring(int startIndex) Retrieves a substring from this instance. The substring starts at a specified character position and continues to the end of the string.
Substring(int startIndex, int length) Retrieves a substring from this instance. The substring starts at a specified character position and has a specified length.
IndexOf(string value) Reports the zero-based index of the first occurrence of the specified string in this instance.
IndexOf(string value, int startIndex) Reports the zero-based index of the first occurrence of the specified string in this instance. The search starts at a specified character position.
LastIndexOf(string value) Reports the zero-based index of the first occurrence of the specified string in this instance. Often used together with Substring.
LastIndexOf(string value, int startIndex) Reports the zero-based index position of the last occurrence of a specified string within this instance. The search starts at a specified character position and proceeds backward toward the beginning of the string.

This is a minor subset of the available functions. It may be well worth your time to read up on the string class since it is so fundamental in PowerShell.
Docs are found here.

As an example, this can be useful when we have very large input data of comma-separated input with 15 columns and we are only interested in the third column from the end. If we were to use the -split ',' operator, we would create 15 new strings and an array for each line. On the other hand, using LastIndexOf on the input string a few times and then SubString to get the value of interest is faster and results in just one new string.

function parseThirdFromEnd([string]$line){
    $i = $line.LastIndexOf(",")             # get the last separator
    $i = $line.LastIndexOf(",", $i - 1)     # get the second to last separator, also the end of the column we are interested in
    $j = $line.LastIndexOf(",", $i - 1)     # get the separator before the column we want
    $j++                                    # more forward past the separator
    $line.SubString($j,$i-$j)               # get the text of the column we are looking for
}

In this sample, I ignore that the IndexOf and LastIndexOf returns -1 if they cannot find the text to search for. From experience, I also know that it is easy to mess up the index arithmetics.
So while using these methods can improve performance, it is also more error prone and a lot more to type. I would only resort to this when I know the input data is very large and performance is an issue. So this is not a recommendation, or a starting point, but something to resort to.

On rare occasions, I write the whole parser in C#. An example of this is in a module wrapping the Perforce version control system, where the command line tool can output python dictionaries. It is a binary format, and the use case was complicated enough that I was more comfortable with a compiler checked implementation language.

Regular Expressions

Almost all of the parsing options in PowerShell make use of regular expressions, so I will start with a short intro of some regular expression concepts that are used later in these posts.

Regular expressions are very useful to know when writing simple parsers since they allow us to express patterns of interest and to capture text that matches those patterns.

It is a very rich language, but you can get quite a long way by learning a few key parts. I’ve found regular-expressions.info to be a good online resource for more information. It is not written directly for the .net regex implementation, but most of the information is valid across the different implementations.

Regex Description
* Zero or more of the preceding character. a* matches the empty string, a, aa, etc, but not b.
+ One or more of the preceding character. a+ matches a, aa, etc, but not the empty string or b.
. Matches any character
[ax1] Any of a,x,1
a-d matches any of a,b,c,d
\w The \w meta character is used to find a word character. A word character is a character from a-z, A-Z, 0-9, including the _ (underscore) character. It also matches variants of the characters such as ??? and ???.
\W The inversion of \w. Matches any non-word character
\s The \s meta character is used to find white space
\S The inversion of \s. Matches any non-whitespace character
\d Matches digits
\D The inversion of \d. Matches non-digits
\b Matches a word boundary, that is, the position between a word and a space.
\B The inversion of \b. . er\B matches the er in verb but not the er in never.
^ The beginning of a line
$ The end of a line
(<expr>) Capture groups

Combining these, we can create a pattern like below to match a text like:

Text Pattern
" 42,Answer" ^\s+\d+,.+

The above pattern can be written like this using the x (ignore pattern whitespace) modifier.

Starting the regex with (?x) ignores whitespace in the pattern (it has to be specified explicitly, with \s) and also enables the comment character #.

(?x)  # this regex ignores whitespace in the pattern. Makes it possible do document a regex with comments.
^     # the start of the line
\s+   # one or more whitespace character
\d+   # one or more digits
,     # a comma
.+    # one or more characters of any kind

By using capture groups, we make it possible to refer back to specific parts of a matched expression.

Text Pattern
" 42,Answer" ^\s+(\d+),(.+)
(?x)  # this regex ignores whitespace in the pattern. Makes it possible to document a regex with comments.
^     # the start of the line
\s+   # one or more whitespace character
(\d+) # capture one or more digits in the first group (index 1)
,     # a comma
(.+)  # capture one or more characters of any kind in the second group (index 2)

Naming regular expression groups

There is a construct called named capturing groups, (?<group_name>pattern), that will create a capture group with a designated name.

The regex above can be rewritten like this, which allows us to refer to the capture groups by name instead of by index.

^\s+(?<num>\d+),(?<text>.+)

Different languages have implementation specific solutions to accessing the values of the captured groups. We will see later on in this series how it is done in PowerShell.

The Select-String cmdlet

The Select-String command is a work horse, and is very powerful when you understand the output it produces.
I use it mainly when searching for text in files, but occasionally also when looking for something in command output and similar.

The key to being efficient with Select-String is to know how to get to the matched patterns in the output. In its internals, it uses the same regex class as the -match and -split operator, but instead of populating a global variable with the resulting groups, as -match does, it writes an object to the pipeline, with a Matches property that contains the results of the match.

Set-Content twitterData.txt -value @"
Lee, Steve-@Steve_MSFT,2992
Lee Holmes-13000 @Lee_Holmes
Staffan Gustafsson-463 @StaffanGson
Tribbiani, Joey-@Matt_LeBlanc,463400
"@

# extracting captured groups
Get-ChildItem twitterData.txt |
    Select-String -Pattern "^(\w+) ([^-]+)-(\d+) (@\w+)" |
    Foreach-Object {
        $first, $last, $followers, $handle = $_.Matches[0].Groups[1..4].Value   # this is a common way of getting the groups of a call to select-string
        [PSCustomObject] @{
            FirstName = $first
            LastName = $last
            Handle = $handle
            TwitterFollowers = [int] $followers
        }
    }
FirstName LastName   Handle       TwitterFollowers
--------- --------   ------       ----------------
Lee       Holmes     @Lee_Holmes             13000
Staffan   Gustafsson @StaffanGson              463

Support for Multiple Patterns

As we can see above, only half of the data matched the pattern to Select-String.

A technique that I find useful is to take advantage of the fact that Select-String supports the use of multiple patterns.

The lines of input data in twitterData.txt contain the same type of information, but they’re formatted in slightly different ways.
Using multiple patterns in combination with named capture groups makes it a breeze to extract the groups even when the positions of the groups differ.

$firstLastPattern = "^(?<first>\w+) (?<last>[^-]+)-(?<followers>\d+) (?<handle>@.+)"
$lastFirstPattern = "^(?<last>[^\s,]+),\s+(?<first>[^-]+)-(?<handle>@[^,]+),(?<followers>\d+)"
Get-ChildItem twitterData.txt |
     Select-String -Pattern $firstLastPattern, $lastFirstPattern |
    Foreach-Object {
        # here we access the groups by name instead of by index
        $first, $last, $followers, $handle = $_.Matches[0].Groups['first', 'last', 'followers', 'handle'].Value
        [PSCustomObject] @{
            FirstName = $first
            LastName = $last
            Handle = $handle
            TwitterFollowers = [int] $followers
        }
    }
FirstName LastName   Handle        TwitterFollowers
--------- --------   ------        ----------------
Steve     Lee        @Steve_MSFT               2992
Lee       Holmes     @Lee_Holmes              13000
Staffan   Gustafsson @StaffanGson               463
Joey      Tribbiani  @Matt_LeBlanc           463400

Breaking down the $firstLastPattern gives us

(?x)                # this regex ignores whitespace in the pattern. Makes it possible do document a regex with comments.
^                   # the start of the line
(?<first>\w+)       # capture one or more of any word characters into a group named 'first'
\s                  # a space
(?<last>[^-]+)      # capture one of more of any characters but `-` into a group named 'last'
-                   # a '-'
(?<followers>\d+)   # capture 1 or more digits into a group named 'followers'
\s                  # a space
(?<handle>@.+)      # capture a '@' followed by one or more characters into a group named 'handle'

The second regex is similar, but with the groups in different order. But since we retrieve the groups by name, we don’t have to care about the positions of the capture groups, and multiple assignment works fine.

Context around Matches

Select-String also has a Context parameter which accepts an array of one or two numbers specifying the number of lines before and after a match that should be captured. All text parsing techniques in this post can be used to parse information from the context lines.
The result object has a Context property, that returns an object with PreContext and PostContext properties, both of the type string[].

This can be used to get the second line before a match:

# using the context property
Get-ChildItem twitterData.txt |
    Select-String -Pattern "Staffan" -Context 2,1 |
    Foreach-Object { $_.Context.PreContext[1], $_.Context.PostContext[0] }
Lee Holmes-13000 @Lee_Holmes
Tribbiani, Joey-@Matt_LeBlanc,463400

To understand the indexing of the Pre- and PostContext arrays, consider the following:

Lee, Steve-@Steve_MSFT,2992                  <- PreContext[0]
Lee Holmes-13000 @Lee_Holmes                 <- PreContext[1]
Staffan Gustafsson-463 @StaffanGson          <- Pattern matched this line
Tribbiani, Joey-@Matt_LeBlanc,463400         <- PostContext[0]

The pipeline support of Select-String makes it different from the other parsing tools available in PowerShell, and makes it the undisputed king of one-liners.

I would like stress how much more useful Select-String becomes once you understand how to get to the parts of the matches.

Summary

We have looked at useful methods of the string class, especially how to use Substring to get to text at a specific offset. We also looked at regular expression, a language used to describe patterns in text, and on the Select-String cmdlet, which makes heavy use of regular expression.

Next time, we will look at the operators -split and -match, the switch statement (which is surprisingly useful for text parsing), and the regex class.

Staffan Gustafsson, @StaffanGson, github

Thanks to Jason Shirk, Mathias Jessen and Steve Lee for reviews and feedback.


Announcing the PowerShell Preview Extension in VSCode

$
0
0

Preview builds of the PowerShell extension are now available in VSCode

We are excited to announce the PowerShell Preview extension in the VSCode marketplace!
The PowerShell Preview extension allows users on Windows PowerShell 5.1, Powershell 6.0, and all newer versions to get and test the latest updates to the PowerShell extension and comes with some exciting features. The PowerShell Preview extension is a substitute for the PowerShell extension so both the PowerShell extension and the PowerShell Preview
extension should not be enabled at the same time.

Features of the PowerShell Preview extension

The PowerShell Preview extension is built on .NET Standard thereby enabling simplification of our code and dependency structure.

The PowerShell Preview extension also contains PSReadLine support in the integrated console for Windows behind a
feature flag. PSReadLine provides a consistent and rich interactive experience, including syntax coloring and
multi-line editing and history, in the PowerShell console, in Cloud Shell, and now in VSCode terminal.
For more information on the benefits of PSReadLine, check out their documentation.

To enable PSReadLine support in the Preview version on Windows, please add the following to your user settings:

"powershell.developer.featureFlags": [ "PSReadLine" ]

HUGE thanks to @SeeminglyScience for all his amazing work getting PSReadLine working in PowerShell Editor Services!

Why we created the PowerShell Preview extension

By having a preview channel, which supports Windows Powershell 5.1 and PowerShell Core 6, in addition to our existing stable channel, we can get new features out faster. PSReadLine support for the VSCode integrated console is a great
example of a feature that the preview build makes possible. Having a preview channel also allows us to get more feedback
on new features and to iterate on changes before they arrive in our stable channel.

How to Get/Use the PowerShell Preview extension

If you dont already have VSCode, start here.

Once you have VSCode open, click Clt+Shift+X to open the extensions marketplace.
Next, type PowerShell Preview in the search bar.
Click Install on the PowerShell Preview page.
Finally, click Reload in order to refresh VSCode.

If you already have the PowerShell extension please disable it to use the Powershell Preview extension.
To disable the PowerShell extension find it in the Extensions sidebar view, specifically under the list of Enabled extensions, Right-click on the PowerShell extension and select Disable. Please note that it is important to only have either the
PowerShell extension or the PowerShell Preview extension endabled at one time.

Breaking Changes

As stated above, this version of the PowerShell extension only works with Windows PowerShell versions 5.1 and
PowerShell Core 6.

Reporting Feedback

An important benefit of a preview extension is getting feedback from users.
To report issues with the extension use our GitHub repo.
When reporting issues be sure to specify the version of the extension you are using.

Sydney Smith
Program Manager
PowerShell Team

The PowerShell-Docs repositories have been moved

$
0
0

The PowerShell-Docs repositories have been moved from the PowerShell organization to the MicrosoftDocs organization in GitHub.

The tools we use to build the documentation are designed to work in the MicrosoftDocs org. Moving the repository lets us build the foundation for future improvements in our documentation experience.

Impact of the move

During the move there may be some downtime. The affected repositories will be inaccessible during
the move process. Also, the documentation processes will be paused. After the move, we need to test
access permissions and automation scripts.
 

After these tasks are complete, access and operations will return to normal. GitHub automatically
redirects requests to the old repo URL to the new location.
 

For more information about transferring repositories in GitHub, see About repository transfers

If the transferred repository has any forks, then those forks will remain associated with the
repository after the transfer is complete.
  • All Git information about commits, including contributions, are preserved.
  • All of the issues and pull requests remain intact when transferring a repository.
  • All links to the previous repository location are automatically redirected to the new location.


When you use git clone, git fetch, or git push on a transferred repository, these commands will r
edirect to the new repository location or URL.

However, to avoid confusion, we strongly recommend updating any existing local clones to point to
the new repository URL.
For more information, see Changing a remote’s URL.

The following example shows how to change the “upstream” remote to point to the new location:

[Wed 06:08PM] [staging =]
PS C:\Git\PS-Docs\PowerShell-Docs> git remote -v
origin  https://github.com/sdwheeler/PowerShell-Docs.git (fetch)
origin  https://github.com/sdwheeler/PowerShell-Docs.git (push)
upstream        https://github.com/PowerShell/PowerShell-Docs.git (fetch)
upstream        https://github.com/PowerShell/PowerShell-Docs.git (push)

[Wed 06:09PM] [staging =]
PS C:\Git\PS-Docs\PowerShell-Docs> git remote set-url upstream https://github.com/MicrosoftDocs/PowerShell-Docs.git

[Wed 06:10PM] [staging =]
PS C:\Git\PS-Docs\PowerShell-Docs> git remote -v
origin  https://github.com/sdwheeler/PowerShell-Docs.git (fetch)
origin  https://github.com/sdwheeler/PowerShell-Docs.git (push)
upstream        https://github.com/MicrosoftDocs/PowerShell-Docs.git (fetch)
upstream        https://github.com/MicrosoftDocs/PowerShell-Docs.git (push)


Which repositories were moved?

 

The following repositories were transferred:

  • PowerShell/PowerShell-Docs
  • PowerShell/powerShell-Docs.cs-cz
  • PowerShell/powerShell-Docs.de-de
  • PowerShell/powerShell-Docs.es-es
  • PowerShell/powerShell-Docs.fr-fr
  • PowerShell/powerShell-Docs.hu-hu
  • PowerShell/powerShell-Docs.it-it
  • PowerShell/powerShell-Docs.ja-jp
  • PowerShell/powerShell-Docs.ko-kr
  • PowerShell/powerShell-Docs.nl-nl
  • PowerShell/powerShell-Docs.pl-pl
  • PowerShell/powerShell-Docs.pt-br
  • PowerShell/powerShell-Docs.pt-pt
  • PowerShell/powerShell-Docs.ru-ru
  • PowerShell/powerShell-Docs.sv-se
  • PowerShell/powerShell-Docs.tr-tr
  • PowerShell/powerShell-Docs.zh-cn
  • PowerShell/powerShell-Docs.zh-tw

Call to action

If you have a fork that you cloned, change your remote configuration to point to the new upstream URL.
Help us make the documentation better.
  • Submit issues when you find a problem in the docs.
  • Suggest fixes to documentation by submitting changes through the PR process.
Sean Wheeler
Senior Content Developer for PowerShell
https://github.com/sdwheeler

Parsing Text with PowerShell (2/3)

$
0
0

This is the second post in a three-part series.

  • Part 1:
    • Useful methods on the String class
    • Introduction to Regular Expressions
    • The Select-String cmdlet
  • Part 2:
    • the -split operator
    • the -match operator
    • the switch statement
    • the Regex class
  • Part 3:
    • a real world, complete and slightly bigger, example of a switch-based parser

The -split operator

The -split operator splits one or more strings into substrings.

A common pattern is a name-value pattern:
Note the usage of the Max-substrings parameter to the -split operator.
We want to ensure that is doesn’t matter if the value contains the character to split on.

$text = "Description=The '=' character is used for assigning values to a variable"
$name, $value = $text -split "=", 2

@"
Name  =  $name
Value =  $value
"@
Name  =  Description
Value =  The '=' character is used for assigning values to a variable

When the line to parse contains fields separated by a well known separator, that is never a part of the field values, we can use the -split operator
in combination with multiple assignment to get the fields into variables.

$name, $location, $occupation = "Spider Man,New York,Super Hero" -split ','

If only the location is of interest, the unwanted items can be assigned to $null.

$null, $location, $null = "Spider Man,New York,Super Hero" -split ','

$location
New York

If there are many fields, assigning to null doesn’t scale well. Indexing can be used instead, to get the fields of interest.

$inputText = "x,Staffan,x,x,x,x,x,x,x,x,x,x,Stockholm,x,x,x,x,x,x,x,x,11,x,x,x,x"
$name, $location, $age = ($inputText -split ',')[1,12,21]

$name
$location
$age
Staffan
Stockholm
11

It is almost always a good idea to create an object that gives context to the different parts.

$inputText = "x,Steve,x,x,x,x,x,x,x,x,x,x,Seattle,x,x,x,x,x,x,x,x,22,x,x,x,x"
$name, $location, $age = ($inputText -split ',')[1,12,21]
[PSCustomObject] @{
    Name = $name
    Location = $location
    Age = [int] $age
}
Name  Location Age
----  -------- ---
Steve Seattle   22

Instead of creating a PSCustomObject, we can create a class. It’s a bit more to type, but we can get more help from the engine, for example with tab completion.

The example below also shows an example of type conversion, where the default string to number conversion doesn’t work.
The age field is handled by PowerShell’s built-in type conversion. It is of type [int], and PowerShell will handle the conversion from string to int,
but in some cases we need to help out a bit. The ShoeSize field is also an [int], but the data is hexadecimal,
and without the hex specifier (‘0x’), this conversion fails for some values, and provides incorrect results for the others.

class PowerSheller {
    [string] $Name
    [string] $Location
    [int] $Age
    [int] $ShoeSize
}

$inputText = "x,Staffan,x,x,x,x,x,x,x,x,x,x,Stockholm,x,x,x,x,x,x,x,x,33,x,11d,x,x"
$name, $location, $age, $shoeSize = ($inputText -split ',')[1,12,21,23]
[PowerSheller] @{
    Name = $name
    Location = $location
    Age = $age
    # ShoeSize is expressed in hex, with no '0x' because reasons :)
    # And yes, it's in millimeters.
    ShoeSize = [Convert]::ToInt32($shoeSize, 16)
}
Name    Location  Age ShoeSize
----    --------  --- --------
Staffan Stockholm  33      285

The split operator’s first argument is actually a regex (by default, can be changed with options).
I use this on long command lines in log files (like those given to compilers) where there can be hundreds of options specified. This makes it hard to see if a certain option is specified or not, but when split into their own lines, it becomes trivial.
The pattern below uses a positive lookahead assertion.
It can be very useful to make patterns match only in a given context, like if they are, or are not, preceded or followed by another pattern.

$cmdline = "cl.exe /D Bar=1 /I SomePath /D Foo  /O2 /I SomeOtherPath /Debug a1.cpp a3.cpp a2.cpp"

$cmdline -split "\s+(?=[-/])"
cl.exe
/D Bar=1
/I SomePath
/D Foo
/O2
/I SomeOtherPath
/Debug a1.cpp a2.cpp

Breaking down the regex, by rewriting it with the x option:

(?x)      # ignore whitespace in the pattern, and enable comments after '#'
\s+       # one or more spaces
(?=[-/])  # only match the previous spaces if they are followed by any of '-' or '/'.

Splitting with a scriptblock

The -split operator also comes in another form, where you can pass it a scriptblock instead of a regular expression.
This allows for more complicated logic, that can be hard or impossible to express as a regular expression.

The scriptblock accepts two parameters, the text to split and the current index. $_ is bound to the character at the current index.

function SplitWhitespaceInMiddleOfText {
    param(
        [string]$Text,
        [int] $Index
    )
    if ($Index -lt 10 -or $Index -gt 40){
        return $false
    }
    $_ -match '\s'
}

$inputText = "Some text that only needs splitting in the middle of the text"
$inputText -split $function:SplitWhitespaceInMiddleOfText
Some text that
only
needs
splitting
in
the middle of the text

The $function:SplitWhitespaceInMiddleOfText syntax is a way to get to content (the scriptblock that implements it) of the function, just as $env:UserName gets the content of an item in the env: drive.
It provides a way to document and/or reuse the scriptblock.

The -match operator

The -match operator works in conjunction with the $matches automatic variable.
Each time a -match or a -notmatch succeeds, the $matches variable is populated so that each capture group gets its own entry.
If the capture group is named, the key will be the name of the group, otherwise it will be the index.

As an example:

if ('a b c' -match '(\w) (?<named>\w) (\w)'){
    $matches
}
Name                           Value
----                           -----
named                          b
2                              c
1                              a
0                              a b c

Notice that the indices only increase on groups without names. I.E. the indices of later groups change when a group is named.

Armed with the regex knowledge from the earlier post, we can write the following:

PS> "    10,Some text" -match '^\s+(\d+),(.+)'
True
PS> $matches
Name                           Value
----                           -----
2                              Some text
1                              10
0                              10,Some text

or with named groups

PS> "    10,Some text" -match '^\s+(?<num>\d+),(?<text>.+)'
True
PS> $matches
Name                           Value
----                           -----
num                            10
text                           Some text
0                              10,Some text

The important thing here is that the parts of the pattern that we want to extract has parenthesis around them.
That is what creates the capture groups that allow us to reference those parts of the matching text, either by name or by index.

Combining this into a function makes it easy to use:

function ParseMyString($text){
    if ($text -match '^\s+(\d+),(.+)') {
        [PSCustomObject] @{
            Number = [int] $matches[1]
            Text    = $matches[2]
        }
    }
    else {
        Write-Warning "ParseMyString: Input `$text` doesn't match pattern"
    }
}

ParseMyString "    10,Some text"
Number  Text
------- ----
     10 Some text

Notice the type conversion when assigning the Number property. As long as the number is in range of an integer, this will always succeed, since we have made a successful match in the if statement above. ([long] or [bigint] could be used. In this case I provide the input, and I have promised myself to stick to a range that fits in a 32-bit integer.)
Now we will be able to sort or do numerical operations on the Number property, and it will behave like we want it to – as a number, not as a string.

The switch statement

Now we’re at the big guns 🙂

The switch statement in PowerShell has been given special functionality for parsing text.
It has two flags that are useful for parsing text and files with text in them. -regex and -file.

When specifying -regex, the match clauses that are strings are treated as regular expressions. The switch statement also sets the $matches automatic variable.

When specifying -file, PowerShell treats the input as a file name, to read input from, rather than as a value statement.

Note the use of a ScriptBlock instead of a string as the match clause to determine if we should skip preamble lines.

class ParsedOutput {
    [int] $Number
    [string] $Text

    [string] ToString() { return "{0} ({1})" -f $this.Text, $this.Number }
}

$inputData =
    "Preamble line",
    "LastLineOfPreamble",
    "    10,Some Text",
    "    Some other text,20"

$inPreamble = $true
switch -regex ($inputData) {

    {$inPreamble -and $_ -eq 'LastLineOfPreamble'} { $inPreamble = $false; continue }

    "^\s+(?<num>\d+),(?<text>.+)" {  # this matches the first line of non-preamble input
        [ParsedOutput] @{
            Number = $matches.num
            Text = $matches.text
        }
        continue
    }

    "^\s+(?<text>[^,]+),(?<num>\d+)" { # this matches the second line of non-preamble input
        [ParsedOutput] @{
            Number = $matches.num
            Text = $matches.text
        }
        continue
    }
}
Number  Text
------ ----
    10 Some Text
    20 Some other text

The pattern [^,]+ in the text group in the code above is useful. It means match anything that is not a comma ,. We are using the any-of construct [], and within those brackets, ^ changes meaning from the beginning of the line to anything but.

That is useful when we are matching delimited fields. A requirement is that the delimiter cannot be part of the set of allowed field values.

The regex class

regex is a type accelerator for System.Text.RegularExpressions.Regex. It can be useful when porting code from C#, and sometimes when we want to get more control in situations when we have many matches of a capture group. It also allows us to pre-create the regular expressions which can matter in performance sensitive scenarios, and to specify a timeout.

One instance where the regex class is needed is when you have multiple captures of a group.

Consider the following:

Text Pattern
a,b,c, (\w,)+

If the match operator is used, $matches will contain

Name                           Value
----                           -----
1                              c,
0                              a,b,c,

The pattern matched three times, for a,, b, and c,. However, only the last match is preserved in the $matches dictionary.
However, the following will allow us to get to all the captures of the group:

[regex]::match('a,b,c,', '(\w,)+').Groups[1].Captures
Index Length Value
----- ------ -----
    0      2 a,
    2      2 b,
    4      2 c,

Below is an example that uses the members of the Regex class to parse input data

class ParsedOutput {
    [int] $Number
    [string] $Text

    [string] ToString() { return "{0} ({1})" -f $this.Text, $this.Number }
}

$inputData =
    "    10,Some Text",
    "    Some other text,20"  # this text will not match

[regex] $pattern = "^\s+(\d+),(.+)"

foreach($d in $inputData){
    $match = $pattern.Match($d)
    if ($match.Success){
        $number, $text = $match.Groups[1,2].Value
        [ParsedOutput] @{
            Number = $number
            Text = $text
        }
    }
    else {
        Write-Warning "regex: '$d' did not match pattern '$pattern'"
    }
}
WARNING: regex: '    Some other text,20' did not match pattern '^\s+(\d+),(.+)'
Number Text
------ ----
    10 Some Text

It may surprise you that the warning appears before the output. PowerShell has a quite complex formatting system at the end of the pipeline, which treats pipeline output different than other streams. Among other things, it buffers output in the beginning of a pipeline to calculate sensible column widths. This works well in practice, but sometimes gives strange reordering of output on different streams.

Summary

In this post we have looked at how the -split operator can be used to split a string in parts, how the -match operator can be used to extract different patterns from some text, and how the powerful switch statement can be used to match against multiple patterns.

We ended by looking at how the regex class, which in some cases provides a bit more control, but at the expense of ease of use.

This concludes the second part of this post. Next time, we will look at a complete, real world, example of a switch-based parser.

Thanks to Jason Shirk, Mathias Jessen and Steve Lee for reviews and feedback.

Staffan Gustafsson, @StaffanGson, powercode@github

Staffan works at DICE in Stockholm, Sweden, as a Software Engineer and has been using PowerShell since the first public beta.
He was most seriously pleased when PowerShell was open sourced, and has since contributed bug fixes, new features and performance improvements.
Staffan is a speaker at PSConfEU and is always happy to talk PowerShell.

Parsing Text with PowerShell (3/3)

$
0
0

This is the third and final post in a three-part series.

  • Part 1:
    • Useful methods on the String class
    • Introduction to Regular Expressions
    • The Select-String cmdlet
  • Part 2:
    • the -split operator
    • the -match operator
    • the switch statement
    • the Regex class
  • Part 3:
    • a real world, complete and slightly bigger, example of a switch-based parser
      • General structure of a switch-based parser
      • The real world example

In the previous posts, we looked at the different operators what are available to us in PowerShell.

When analyzing crashes at DICE, I noticed that some of the C++ runtime binaries where missing debug symbols. They should be available for download from Microsoft’s public symbol server, and most versions were there. However, due to some process errors at DevDiv, some builds were released publicly without available debug symbols.
In some cases, those missing symbols prevented us from debugging those crashes, and in all cases, they triggered my developer OCD.

So, to give actionable feedback to Microsoft, I scripted a debugger (cdb.exe in this case) to give a verbose list of the loaded modules, and parsed the output with PowerShell, which was also later used to group and filter the resulting data set. I sent this data to Microsoft, and 5 days later, the missing symbols were available for download. Mission accomplished!

This post will describe the parser I wrote for this task (it turned out that I had good use for it for other tasks later), and the general structure is applicable to most parsing tasks.

The example will show how a switch-based parser would look when the input data isn’t as tidy as it normally is in examples, but messy – as the real world data often is.

General Structure of a switch Based Parser

Depending on the structure of our input, the code must be organized in slightly different ways.

Input may have a record start that differs by indentation or some distinct token like

Foo                    <- Record start - No whitespace at the beginning of the line
    Prop1=Staffan      <- Properties for the record - starts with whitespace
    Prop3 =ValueN
Bar
    Prop1=Steve
    Prop2=ValueBar2

If the data to be parsed has an explicit start record, it is a bit easier than if it doesn’t have one.
We create a new data object when we get a record start, after writing any previously created object to the pipeline.
At the end, we need to check if we have parsed a record that hasn’t been written to the pipeline.

The general structure of a such a switch-based parser can be as follows:

$inputData = @"
Foo
    Prop1=Value1
    Prop3=Value3
Bar
    Prop1=ValueBar1
    Prop2=ValueBar2
"@ -split '\r?\n'   # This regex is useful to split at line endings, with or without carriage return

class SomeDataClass {
    $ID
    $Name
    $Property2
    $Property3
}

# map to project input property names to the properties on our data class
$propertyNameMap = @{
    Prop1 = "Name"
    Prop2 = "Property2"
    Prop3 = "Property3"
}

$currentObject = $null
switch -regex ($inputData) {

    '^(\S.*)' {
        # record start pattern, in this case line that doesn't start with a whitespace.
        if ($null -ne $currentObject) {
            $currentObject                   # output to pipeline if we have a previous data object
        }
        $currentObject = [SomeDataClass] @{  # create new object for this record
            Id = $matches.1                  # with Id like Foo or Bar
        }
        continue
    }

    # set the properties on the data object
    '^\s+([^=]+)=(.*)' {
        $name, $value = $matches[1, 2]
        # project property names
        $propName = $propertyNameMap[$name]
        if ($propName = $null) {
            $propName = $name
        }
        # assign the parsed value to the projected property name
        $currentObject.$propName = $value
        continue
    }
}

if ($currentObject) {
    # Handle the last object if any
    $currentObject # output to pipeline
}
ID  Name      Property2 Property3
--  ----      --------- ---------
Foo Value1              Value3
Bar ValueBar1 ValueBar2

Alternatively, we may have input where the records are separated by a blank line, but without any obvious record start.

commitId=1234                         <- In this case, a commitId is first in a record
description=Update readme.md
                                      <- the blank line separates records
user=Staffan                          <- For this record, a user property comes first
commitId=1235
description=Fix bug.md

In this case the structure of the code looks a bit different. We create an object at the beginning, but keep track of if it’s dirty or not.
If we get to the end with a dirty object, we must output it.

$inputData = @"

commit=1234
desc=Update readme.md

user=Staffan
commit=1235
desc=Bug fix

"@ -split "\r?\n"

class SomeDataClass {
    [int] $CommitId
    [string] $Description
    [string] $User
}

# map to project input property names to the properties on our data class
# we only need to provide the ones that are different. 'User' works fine as it is.
$propertyNameMap = @{
    commit = "CommitId"
    desc   = "Description"
}

$currentObject = [SomeDataClass]::new()
$objectDirty = $false
switch -regex ($inputData) {
    # set the properties on the data object
    '^([^=]+)=(.*)$' {
        # parse a name/value
        $name, $value = $matches[1, 2]
        # project property names
        $propName = $propertyNameMap[$name]
        if ($null -eq $propName) {
            $propName = $name
        }
        # assign the projected property
        $currentObject.$propName = $value
        $objectDirty = $true
        continue
    }

    '^\s*$' {
        # separator pattern, in this case any blank line
        if ($objectDirty) {
            $currentObject                           # output to pipeline
            $currentObject = [SomeDataClass]::new()  # create new object
            $objectDirty = $false                    # and mark it as not dirty
        }
    }
    default {
        Write-Warning "Unexpected input: '$_'"
    }
}

if ($objectDirty) {
    # Handle the last object if any
    $currentObject # output to pipeline
}
CommitId Description      User
-------- -----------      ----
    1234 Update readme.md
    1235 Bug fix          Staffan

The Real World Example

I have adapted this sample slightly so that I get the loaded modules from a running process instead of from my crash dumps. The format of the output from the debugger is the same.
The following command launches a command line debugger on notepad, with a script that gives a verbose listing of the loaded modules, and quits:

# we need to muck around with the console output encoding to handle the trademark chars
# imagine no encodings
# it's easy if you try
# no code pages below us
# above us only sky
[Console]::OutputEncoding = [System.Text.Encoding]::GetEncoding("iso-8859-1")

$proc = Start-Process notepad -passthru
Start-Sleep -seconds 1
$cdbOutput = cdb -y 'srv*c:\symbols*http://msdl.microsoft.com/download/symbols' -c ".reload -f;lmv;q" -p $proc.ProcessID

The output of the command above is here for those who want to follow along but who aren’t running windows or don’t have cdb.exe installed.

The (abbreviated) output looks like this:

Microsoft (R) Windows Debugger Version 10.0.16299.15 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.

*** wait with pending attach

************* Path validation summary **************
Response                         Time (ms)     Location
Deferred                                       srv*c:\symbols*http://msdl.microsoft.com/download/symbols
Symbol search path is: srv*c:\symbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
ModLoad: 00007ff6`e9da0000 00007ff6`e9de3000   C:\Windows\system32\notepad.exe
...
ModLoad: 00007ffe`97d80000 00007ffe`97db1000   C:\WINDOWS\SYSTEM32\ntmarta.dll
(98bc.40a0): Break instruction exception - code 80000003 (first chance)
ntdll!DbgBreakPoint:
00007ffe`9cd53050 cc              int     3
0:007> cdb: Reading initial command '.reload -f;lmv;q'
Reloading current modules
.....................................................
start             end                 module name
00007ff6`e9da0000 00007ff6`e9de3000   notepad    (pdb symbols)          c:\symbols\notepad.pdb\2352C62CDF448257FDBDDA4081A8F9081\notepad.pdb
    Loaded symbol image file: C:\Windows\system32\notepad.exe
    Image path: C:\Windows\system32\notepad.exe
    Image name: notepad.exe
    Image was built with /Brepro flag.
    Timestamp:        329A7791 (This is a reproducible build file hash, not a timestamp)
    CheckSum:         0004D15F
    ImageSize:        00043000
    File version:     10.0.17763.1
    Product version:  10.0.17763.1
    File flags:       0 (Mask 3F)
    File OS:          40004 NT Win32
    File type:        1.0 App
    File date:        00000000.00000000
    Translations:     0409.04b0
    CompanyName:      Microsoft Corporation
    ProductName:      Microsoft??? Windows??? Operating System
    InternalName:     Notepad
    OriginalFilename: NOTEPAD.EXE
    ProductVersion:   10.0.17763.1
    FileVersion:      10.0.17763.1 (WinBuild.160101.0800)
    FileDescription:  Notepad
    LegalCopyright:   ??? Microsoft Corporation. All rights reserved.
...
00007ffe`9ccb0000 00007ffe`9ce9d000   ntdll      (pdb symbols)          c:\symbols\ntdll.pdb\B8AD79538F2730FD9BACE36C9F9316A01\ntdll.pdb
    Loaded symbol image file: C:\WINDOWS\SYSTEM32\ntdll.dll
    Image path: C:\WINDOWS\SYSTEM32\ntdll.dll
    Image name: ntdll.dll
    Image was built with /Brepro flag.
    Timestamp:        E8B54827 (This is a reproducible build file hash, not a timestamp)
    CheckSum:         001F20D1
    ImageSize:        001ED000
    File version:     10.0.17763.194
    Product version:  10.0.17763.194
    File flags:       0 (Mask 3F)
    File OS:          40004 NT Win32
    File type:        2.0 Dll
    File date:        00000000.00000000
    Translations:     0409.04b0
    CompanyName:      Microsoft Corporation
    ProductName:      Microsoft??? Windows??? Operating System
    InternalName:     ntdll.dll
    OriginalFilename: ntdll.dll
    ProductVersion:   10.0.17763.194
    FileVersion:      10.0.17763.194 (WinBuild.160101.0800)
    FileDescription:  NT Layer DLL
    LegalCopyright:   ??? Microsoft Corporation. All rights reserved.
quit:

The output starts with info that I’m not interested in here. I only want to get the detailed information about the loaded modules. It is not until the line

start             end                 module name

that I care about the output.

Also, at the end there is a line that we need to be aware of:

quit:

that is not part of the module output.

To skip the parts of the debugger output that we don’t care about, we have a boolean flag initially set to true.
If that flag is set, we check if the current line, $_, is the module header in which case we flip the flag.

    $inPreamble = $true
    switch -regex ($cdbOutput) {

        { $inPreamble -and $_ -eq "start             end                 module name" } { $inPreamble = $false; continue }

I have made the parser a separate function that reads its input from the pipeline. This way, I can use the same function to parse module data, regardless of how I got the module data. Maybe it was saved on a file. Or came from a dump, or a live process. It doesn’t matter, since the parser is decoupled from the data retrieval.

After the sample, there is a breakdown of the more complicated regular expressions used, so don’t despair if you don’t understand them at first.
Regular Expressions are notoriously hard to read, so much so that they make Perl look readable in comparison.

# define an class to store the data
class ExecutableModule {
    [string]   $Name
    [string]   $Start
    [string]   $End
    [string]   $SymbolStatus
    [string]   $PdbPath
    [bool]     $Reproducible
    [string]   $ImagePath
    [string]   $ImageName
    [DateTime] $TimeStamp
    [uint32]   $FileHash
    [uint32]   $CheckSum
    [uint32]   $ImageSize
    [version]  $FileVersion
    [version]  $ProductVersion
    [string]   $FileFlags
    [string]   $FileOS
    [string]   $FileType
    [string]   $FileDate
    [string[]] $Translations
    [string]   $CompanyName
    [string]   $ProductName
    [string]   $InternalName
    [string]   $OriginalFilename
    [string]   $ProductVersionStr
    [string]   $FileVersionStr
    [string]   $FileDescription
    [string]   $LegalCopyright
    [string]   $LegalTrademarks
    [string]   $LoadedImageFile
    [string]   $PrivateBuild
    [string]   $Comments
}

<#
.SYNOPSIS Runs a debugger on a program to dump its loaded modules
#>
function Get-ExecutableModuleRawData {
    param ([string] $Program)
    $consoleEncoding = [Console]::OutputEncoding
    [Console]::OutputEncoding = [System.Text.Encoding]::GetEncoding("iso-8859-1")
    try {
        $proc = Start-Process $program -PassThru
        Start-Sleep -Seconds 1  # sleep for a while so modules are loaded
        cdb -y srv*c:\symbols*http://msdl.microsoft.com/download/symbols -c ".reload -f;lmv;q" -p $proc.Id
        $proc.Close()
    }
    finally {
        [Console]::OutputEncoding = $consoleEncoding
    }
}

<#
.SYNOPSIS Converts verbose module data from windows debuggers into ExecutableModule objects.
#>
function ConvertTo-ExecutableModule {
    [OutputType([ExecutableModule])]
    param (
        [Parameter(ValueFromPipeline)]
        [string[]] $ModuleRawData
    )
    begin {
        $currentObject = $null
        $preamble = $true
        $propertyNameMap = @{
            'File flags'      = 'FileFlags'
            'File OS'         = 'FileOS'
            'File type'       = 'FileType'
            'File date'       = 'FileDate'
            'File version'    = 'FileVersion'
            'Product version' = 'ProductVersion'
            'Image path'      = 'ImagePath'
            'Image name'      = 'ImageName'
            'FileVersion'     = 'FileVersionStr'
            'ProductVersion'  = 'ProductVersionStr'
        }
    }
    process {
        switch -regex ($ModuleRawData) {

            # skip lines until we get to our sentinel line
            { $preamble -and $_ -eq "start             end                 module name" } { $preamble = $false; continue }

            #00007ff6`e9da0000 00007ff6`e9de3000   notepad    (deferred)
            #00007ffe`9ccb0000 00007ffe`9ce9d000   ntdll      (pdb symbols)          c:\symbols\ntdll.pdb\B8AD79538F2730FD9BACE36C9F9316A01\ntdll.pdb
            '^([0-9a-f`]{17})\s([0-9a-f`]{17})\s+(\S+)\s+\(([^\)]+)\)\s*(.+)?' {
                # see breakdown of the expression later in the post
                # on record start, output the currentObject, if any is set
                if ($null -ne $currentObject) {
                    $currentObject
                }
                $start, $end, $module, $pdbKind, $pdbPath = $matches[1..5]
                # create an instance of the object that we are adding info from the current record into.
                $currentObject = [ExecutableModule] @{
                    Start        = $start
                    End          = $end
                    Name         = $module
                    SymbolStatus = $pdbKind
                    PdbPath      = $pdbPath
                }
                continue
            }
            '^\s+Image was built with /Brepro flag.' {
                $currentObject.Reproducible = $true
                continue
            }
            '^\s+Timestamp:\s+[^\(]+\((?<timestamp>.{8})\)' {
                # see breakdown of the regular  expression later in the post
                # Timestamp:        Mon Jan  7 23:42:30 2019 (5C33D5D6)
                $intValue = [Convert]::ToInt32($matches.timestamp, 16)
                $currentObject.TimeStamp = [DateTime]::new(1970, 01, 01, 0, 0, 0, [DateTimeKind]::Utc).AddSeconds($intValue)
                continue
            }
            '^\s+TimeStamp:\s+(?<value>.{8}) \(This' {
                # Timestamp:        E78937AC (This is a reproducible build file hash, not a timestamp)
                $currentObject.FileHash = [Convert]::ToUInt32($matches.value, 16)
                continue
            }
            '^\s+Loaded symbol image file: (?<imageFile>[^\)]+)' {
                $currentObject.LoadedImageFile = $matches.imageFile
                continue
            }
            '^\s+Checksum:\s+(?<checksum>\S+)' {
                $currentObject.Checksum = [Convert]::ToUInt32($matches.checksum, 16)
                continue
            }
            '^\s+Translations:\s+(?<value>\S+)' {
                $currentObject.Translations = $matches.value.Split(".")
                continue
            }
            '^\s+ImageSize:\s+(?<imageSize>.{8})' {
                $currentObject.ImageSize = [Convert]::ToUInt32($matches.imageSize, 16)
                continue
            }
            '^\s{4}(?<name>[^:]+):\s+(?<value>.+)' {
                # see breakdown of the regular expression later in the post
                # This part is any 'name: value' pattern
                $name, $value = $matches['name', 'value']

                # project the property name
                $propName = $propertyNameMap[$name]
                $propName = if ($null -eq $propName) { $name } else { $propName }

                # note the dynamic property name in the assignment
                # this will fail if the property doesn't have a member with the specified name
                $currentObject.$propName = $value
                continue
            }
            'quit:' {
                # ignore and exit
                break
            }
            default {
                # When writing the parser, it can be useful to include a line like the one below to see the cases that are not handled by the parser
                # Write-Warning "missing case for '$_'. Unexpected output format from cdb.exe"

                continue # skip lines that doesn't match the patterns we are interested in, like the start/end/modulename header and the quit: output
            }
        }
    }
    end {
        # this is needed to output the last object
        if ($null -ne $currentObject) {
            $currentObject
        }
    }
}


Get-ExecutableModuleRawData Notepad |
    ConvertTo-ExecutableModule |
    Sort-Object ProductVersion, Name
    Format-Table -Property Name, FileVersion, Product_Version, FileDescription
Name               FileVersionStr                             ProductVersion FileDescription
----               --------------                             -------------- ---------------
PROPSYS            7.0.17763.1 (WinBuild.160101.0800)         7.0.17763.1    Microsoft Property System
ADVAPI32           10.0.17763.1 (WinBuild.160101.0800)        10.0.17763.1   Advanced Windows 32 Base API
bcrypt             10.0.17763.1 (WinBuild.160101.0800)        10.0.17763.1   Windows Cryptographic Primitives Library
...
uxtheme            10.0.17763.1 (WinBuild.160101.0800)        10.0.17763.1   Microsoft UxTheme Library
win32u             10.0.17763.1 (WinBuild.160101.0800)        10.0.17763.1   Win32u
WINSPOOL           10.0.17763.1 (WinBuild.160101.0800)        10.0.17763.1   Windows Spooler Driver
KERNELBASE         10.0.17763.134 (WinBuild.160101.0800)      10.0.17763.134 Windows NT BASE API Client DLL
wintypes           10.0.17763.134 (WinBuild.160101.0800)      10.0.17763.134 Windows Base Types DLL
SHELL32            10.0.17763.168 (WinBuild.160101.0800)      10.0.17763.168 Windows Shell Common Dll
...
windows_storage    10.0.17763.168 (WinBuild.160101.0800)      10.0.17763.168 Microsoft WinRT Storage API
CoreMessaging      10.0.17763.194                             10.0.17763.194 Microsoft CoreMessaging Dll
gdi32full          10.0.17763.194 (WinBuild.160101.0800)      10.0.17763.194 GDI Client DLL
ntdll              10.0.17763.194 (WinBuild.160101.0800)      10.0.17763.194 NT Layer DLL
RMCLIENT           10.0.17763.194 (WinBuild.160101.0800)      10.0.17763.194 Resource Manager Client
RPCRT4             10.0.17763.194 (WinBuild.160101.0800)      10.0.17763.194 Remote Procedure Call Runtime
combase            10.0.17763.253 (WinBuild.160101.0800)      10.0.17763.253 Microsoft COM for Windows
COMCTL32           6.10 (WinBuild.160101.0800)                10.0.17763.253 User Experience Controls Library
urlmon             11.00.17763.168 (WinBuild.160101.0800)     11.0.17763.168 OLE32 Extensions for Win32
iertutil           11.00.17763.253 (WinBuild.160101.0800)     11.0.17763.253 Run time utility for Internet Explorer

Regex pattern breakdown

Here is a breakdown of the more complicated patterns, using the ignore pattern whitespace modifier x:

([0-9a-f`]{17})\s([0-9a-f`]{17})\s+(\S+)\s+\(([^\)]+)\)\s*(.+)?

# example input: 00007ffe`9ccb0000 00007ffe`9ce9d000   ntdll      (pdb symbols)          c:\symbols\ntdll.pdb\B8AD79538F2730FD9BACE36C9F9316A01\ntdll.pdb

(?x)                # ignore pattern whitespace
^                   # the beginning of the line
([0-9a-f`]{17})     # capture expression like 00007ff6`e9da0000 - any hex number or backtick, and exactly 17 of them
\s                  # a space
([0-9a-f`]{17})     # capture expression like 00007ff6`e9da0000 - any hex number or backtick, and exactly 17 of them
\s+                 # skip any number of spaces
(\S+)               # capture until we get a space - this would match the 'ntdll' part
\s+                 # skip one or more spaces
\(                  # start parenthesis
    ([^\)])         # capture anything but end parenthesis
\)                  # end parenthesis
\s*                 # skip zero or more spaces
(.+)?               # optionally capture any symbol file path

Breakdown of the name-value pattern:

^\s+(?<name>[^:]+):\s+(?<value>.+)

# example input:  File flags:       0 (Mask 3F)

(?x)                # ignore pattern whitespace
^                   # the beginning of the line
\s+                 # require one or more spaces
(?<name>[^:]+)      # capture anything that is not a `:` into the named group "name"
:                   # require a comma
\s+                 # require one or more spaces
(?<value>.+)        # capture everything until the end into the name group "value"

Breakdown of the timestamp pattern:

^\s{4}Timestamp:\s+[^\(]+\((?<timestamp>.{8})\)

#example input:     Timestamp:        Mon Jan  7 23:42:30 2019 (5C33D5D6)

(?x)                # ignore pattern whitespace
^                   # the beginning of the line
\s+                 # require one or more spaces
Timestamp:          # The literal text 'Timestamp:'
\s+                 # require one or more spaces
[^\(]+              # one or more of anything but a open parenthesis
\(                  # a literal '('
(?<timestamp>.{8})  # 8 characters of anything, captured into the group 'timestamp'
\)                  # a literal ')'

Gotchas – the Regex Cache

Something that can happen if you are writing a more complicated parser is the following:
The parser works well. You have 15 regular expressions in your switch statement and then you get some input you haven’t seen before, so you add a 16th regex.
All of a sudden, the performance of your parser tanks. WTF?

The .net regex implementation has a cache of recently used regexs. You can check the size of it like this:

PS> [regex]::CacheSize
15

# bump it
[regex]::CacheSize = 20

And now your parser is fast(er) again.

Bonus tip

I frequently use PowerShell to write (generate) my code:

Get-ExecutableModuleRawData pwsh |
    Select-String '^\s+([^:]+):' |       # this pattern matches the module detail fields
    Foreach-Object {$_.matches.groups[1].value} |
    Select-Object -Unique |
    Foreach-Object -Begin   { "class ExecutableModuleData {" }`
                   -Process { "    [string] $" + ($_ -replace "\s.", {[char]::ToUpperInvariant($_.Groups[0].Value[1])}) }`
                   -End     { "}" }

The output is

class ExecutableModuleData {
    [string] $LoadedSymbolImageFile
    [string] $ImagePath
    [string] $ImageName
    [string] $Timestamp
    [string] $CheckSum
    [string] $ImageSize
    [string] $FileVersion
    [string] $ProductVersion
    [string] $FileFlags
    [string] $FileOS
    [string] $FileType
    [string] $FileDate
    [string] $Translations
    [string] $CompanyName
    [string] $ProductName
    [string] $InternalName
    [string] $OriginalFilename
    [string] $ProductVersion
    [string] $FileVersion
    [string] $FileDescription
    [string] $LegalCopyright
    [string] $Comments
    [string] $LegalTrademarks
    [string] $PrivateBuild
}

It is not complete – I don’t have the fields from the record start, some types are incorrect and when run against some other executables a few other fields may appear.
But it is a very good starting point. And way more fun than typing it 🙂

Note that this example is using a new feature of the -replace operator – to use a ScriptBlock to determine what to replace with – that was added in PowerShell Core 6.1.

Bonus tip #2

A regular expression construct that I often find useful is non-greedy matching.
The example below shows the effect of the ? modifier, that can be used after * (zero or more) and + (one or more)

# greedy matching - match to the last occurrence of the following character (>)
if("<Tag>Text</Tag>" -match '<(.+)>') { $matches }
Name                           Value
----                           -----
1                              Tag>Text</Tag
0                              <Tag>Text</Tag>
# non-greedy matching - match to the first occurrence of the the following character (>)
if("<Tag>Text</Tag>" -match '<(.+?)>') { $matches }
Name                           Value
----                           -----
1                              Tag
0                              <Tag>

See Regex Repeat for more info on how to control pattern repetition.

Summary

In this post, we have looked at how the structure of a switch-based parser could look, and how it can be written so that it works as a part of the pipeline.
We have also looked at a few slightly more complicated regular expressions in some detail.

As we have seen, PowerShell has a plethora of options for parsing text, and most of them revolve around regular expressions.
My personal experience has been that the time I’ve invested in understanding the regex language was well invested.

Hopefully, this gives you a good start with the parsing tasks you have at hand.

Thanks to Jason Shirk, Mathias Jessen and Steve Lee for reviews and feedback.

Staffan Gustafsson, @StaffanGson, github

Staffan works at DICE in Stockholm, Sweden, as a Software Engineer and has been using PowerShell since the first public beta.
He was most seriously pleased when PowerShell was open sourced, and has since contributed bug fixes, new features and performance improvements.
Staffan is a speaker at PSConfEU and is always happy to talk PowerShell.

DSC Resource Kit Release February 2019

$
0
0

We just released the DSC Resource Kit!

This release includes updates to 14 DSC resource modules. In the past 6 weeks, 126 pull requests have been merged and 102 issues have been closed, all thanks to our amazing community!

The modules updated in this release are:

  • ActiveDirectoryCSDsc
  • CertificateDsc
  • ComputerManagementDsc
  • DFSDsc
  • NetworkingDsc
  • PSDscResources
  • SharePointDsc
  • SqlServerDsc
  • StorageDsc
  • xActiveDirectory
  • xExchange
  • xHyper-V
  • xPSDesiredStateConfiguration
  • xWebAdministration

For a detailed list of the resource modules and fixes in this release, see the Included in this Release section below.

Our latest community call for the DSC Resource Kit was last Wednesday, February 13. We were not able to record the call this time, apologies. We will fix this for the next call. You can join us for the next call at 12PM (Pacific time) on March 27 to ask questions and give feedback about your experience with the DSC Resource Kit.

The next DSC Resource Kit release will be on Wednesday, April 3.

We strongly encourage you to update to the newest version of all modules using the PowerShell Gallery, and don’t forget to give us your feedback in the comments below, on GitHub, or on Twitter (@PowerShell_Team)!

Please see our documentation here for information on the support of these resource modules.

Included in this Release

You can see a detailed summary of all changes included in this release in the table below. For past release notes, go to the README.md or CHANGELOG.md file on the GitHub repository page for a specific module (see the How to Find DSC Resource Modules on GitHub section below for details on finding the GitHub page for a specific module).

Module Name Version Release Notes
ActiveDirectoryCSDsc 3.2.0.0
  • Added “DscResourcesToExport” to manifest to improve information in PowerShell Gallery – fixes Issue 68.
  • Removed unused CAType variables and references in AdcsOnlineResponder – fixes issue 52.
  • Updated Examples to enable publising to PowerShell Gallery – fixes issue 54.
  • Cleaned up property alignment in module manifest file.
  • Added new resource AdcsOcspExtension – see Issue 70.
    • Added new ActiveDirectoryCSDsc.CommonHelper.psm1 helper module and unit test.
    • Added stub function to /Tests/TestHelpers (ADCSStub.psm1) so Pester tests can run without having to install ADCSAdministration module.
  • Converted module to auto-documentation Wiki – fixes Issue 53.
  • Enabled Example publishing to PSGallery.
  • Moved change log to CHANGELOG.MD.
  • Opted into Common Tests “Validate Example Files To Be Published”, “Validate Markdown Links” and “Relative Path Length”.
  • Correct AppVeyor Invoke-AppveyorAfterTestTask – fixes Issue 73.
CertificateDsc 4.4.0.0
  • Minor style corrections from PR for Issue 161 that were missed.
  • Opt-in to Example publishing to PowerShell Gallery – fixes Issue 177.
  • Changed Test-CertificateAuthority to return the template name if it finds the display name of the template in the certificate -fixes Issue 147.
ComputerManagementDsc 6.2.0.0
  • WindowsEventLog:
    • Migrated the xWinEventLog from xWinEventLog and renamed to WindowsEventLog.
    • Moved strings in localization file.
    • LogMode is now set with Limit-EventLog,
    • Fixes Issue 18.
DFSDsc 4.3.0.0
  • Fixes PSSA style violation issues resulting – fixes Issue 84.
  • Added “DscResourcesToExport” to manifest to improve information in PowerShell Gallery – fixes Issue 86.
  • Set FunctionsToExport, CmdletsToExport, VariablesToExport, AliasesToExport to empty list in manifest to meet best practice.
  • Explicitly removed extra hidden files from release package
NetworkingDsc 7.0.0.0
  • Refactored module folder structure to move resource to root folder of repository and remove test harness – fixes Issue 372.
  • Removed module conflict tests because only required for harness style modules.
  • Opted into Common Tests “Validate Example Files To Be Published”, “Validate Markdown Links” and “Relative Path Length”.
  • Added “DscResourcesToExport” to manifest to improve information in PowerShell Gallery and removed wildcards from “FunctionsToExport”, “CmdletsToExport”, “VariablesToExport” and “AliasesToExport” – fixes Issue 376.
  • MSFT_NetIPInterface:
    • Added Dhcp, WeakHostReceive and WeakHostSend parameters so that MSFT_DHCPClient, MSFT_WeakHostReceive, MSFT_WeakHostSend can be deprecated – fixes Issue 360.
  • MSFT_DhcpClient:
    • BREAKING CHANGE: Resource has been deprecated and replaced by Dhcp parameter in MSFT_NetIPInterface.
  • MSFT_WeakHostReceive:
    • BREAKING CHANGE: Resource has been deprecated and replaced by WeakHostReceive parameter in MSFT_NetIPInterface.
  • MSFT_WeakHostSend:
    • BREAKING CHANGE: Resource has been deprecated and replaced by WeakHostSend parameter in MSFT_NetIPInterface.
  • MSFT_IPAddress:
    • Updated examples to use NetIPInterface.
  • MSFT_NetAdapterName:
    • Updated examples to use NetIPInterface.
  • MSFT_DnsServerAddress:
    • Updated examples to use NetIPInterface.
  • MSFT_NetworkTeam:
    • Change Get-TargetResource to return actual TeamMembers if network team exists and “Ensure” returns “Present” even when actual TeamMembers do not match “TeamMembers” parameter – fixes Issue 342.
  • Updated examples to format required for publishing to PowerShell Gallery – fixes Issue 374.
  • MSFT_NetAdapterAdvancedProperty:
  • Fixes NetworkAdapterName being returned in Name property when calling Get-TargetResourceFixes – fixes Issue 370.
PSDscResources 2.10.0.0
  • Fixed CompanyName typo – Fixes Issue 100
  • Update LICENSE file to match the Microsoft Open Source Team standard – Fixes Issue 120.
  • Update CommonResourceHelper unit tests to meet Pester 4.0.0 standards (issue 129).
  • Update ResourceHelper unit tests to meet Pester 4.0.0 standards (issue 129).
  • Ported fixes from xPSDesiredStateConfiguration:
    • xArchive
      • Fix end-to-end tests.
      • Update integration tests to meet Pester 4.0.0 standards.
      • Update end-to-end tests to meet Pester 4.0.0 standards.
      • Update unit and integration tests to meet Pester 4.0.0 standards.
      • Wrapped all path and identifier strings in verbose messages with quotes to make it easier to identify the limit of the string when debugging.
      • Refactored date/time checksum code to improve testability and ensure tests can run on machines with localized datetime formats that are not US.
      • Fix “Get-ArchiveEntryLastWriteTime” to return [datetime].
      • Improved verbose logging to make debugging path issues easier.
  • Added .gitattributes file to ensure CRLF settings are configured correctly for the repository.
  • Updated “.vscode\settings.json” to refer to AnalyzerSettings.psd1 so that custom syntax problems are highlighted in Visual Studio Code.
  • Fixed style guideline violations in CommonResourceHelper.psm1.
  • Updated “appveyor.yml” to meet more recent standards.
  • Removed OS image version from “appveyor.yml” to use default image (Issue 127).
  • Removed code to install WMF5.1 from “appveyor.yml” because it is already installed in AppVeyor images (Issue 128).
  • Removed .vscode from .gitignore so that Visual Studio code environment settings can be committed.
  • Environment
    • Update tests to meet Pester 4.0.0 standards (issue 129).
  • Group
    • Update tests to meet Pester 4.0.0 standards (issue 129).
    • Fix unit tests to run on Nano Server.
    • Refactored unit tests to enclude Context fixtures and change functions to Describe fixtures.
  • GroupSet
    • Update tests to meet Pester 4.0.0 standards (issue 129).
SharePointDsc 3.2.0.0
  • Changes to SharePointDsc unit testing
    • Implemented Strict Mode version 1 for all code run during unit tests.
    • Changed InstallAccount into PSDscRunAsCredential parameter in examples
  • SPAuthenticationRealm
    • New resource for setting farm authentication realm
  • SPConfigWizard
    • Updated PSConfig parameters according recommendations in blog post of Stefan Gossner
  • SPDistributedCacheService
    • Fixed exception on Stop-SPServiceInstance with SharePoint 2019
  • SPFarm
    • Improved logging
    • Added ability to manage the Developer Dashboard settings
  • SPFarmSolution
    • Fixed issue where uninstalling a solution would not work as expected if it contained web application resources.
  • SPIncomingEmailSettings
    • New resource for configuring incoming email settings
  • SPInstallPrereqs
    • Improved logging
    • Corrected detection for Windows Server 2019
    • Corrected support for Windows Server 2019 for SharePoint 2016
  • SPProductUpgrade
    • Fixed issue where upgrading SP2013 would not properly detect the installed version
    • Fixed issue where the localized SharePoint 2019 CU was detected as a Service Pack for a Language Pack
  • SPSearchAuthorativePage
    • Fixed issue where modifying search query would not target the correct search application
  • SPSearchResultSource
    • Updated resource to allow localized ProviderTypes
  • SPServiceAppSecurity
    • Updated resource to allow localized permission levels
  • SPServiceInstance
    • Added -All switch to resolve ‘Unable to locate service application’ in SP2013
  • SPSite
    • Improved logging
  • SPUserProfileProperty
    • Fix user profile property mappings does not work
  • SPUserProfileServiceApp
    • Added warning message when MySiteHostLocation is not specified. This is currently not required, which results in an error. Will be corrected in SPDsc v4.0 (is a breaking change).
  • SPUserProfileSyncConnection
    • Fixed issue where test resource never would return true for any configurations on SharePoint 2016/2019
    • Fixed issue where updating existing connection never would work for any configurations on SharePoint 2016/2019
    • Updated documentation to reflect that Fore will not impact configurations for SharePoint 2016/2019. Updated the test method accordingly.
  • SPUserProfileSyncService
    • Fixed issue where failure to configure the sync service would not throw error
  • SPWebAppPeoplePickerSettings
    • Converted password for access account to secure string. Previsouly the resource would fail setting the password and an exeption was thrown that printed the password in clear text.
  • SPWebAppPolicy
    • Fixed issue where parameter MembersToExclude did not work as expected
  • SPWorkflowService
    • Added support for specifying scope name.
    • Added support for detecting incorrect configuration for scope name and WorkflowHostUri
SqlServerDsc 12.3.0.0
  • Changes to SqlServerDsc
    • Reverting the change that was made as part of the issue 1260 in the previous release, as it only mitigated the issue, it did not solve the issue.
    • Removed the container testing since that broke the integration tests, possible due to using excessive amount of memory on the AppVeyor build worker. This will make the unit tests to take a bit longer to run (issue 1260).
    • The unit tests and the integration tests are now run in two separate build workers in AppVeyor. One build worker runs the integration tests, while a second build worker runs the unit tests. The build workers runs in parallel on paid accounts, but sequentially on free accounts (issue 1260).
    • Clean up error handling in some of the integration tests that was part of a workaround for a bug in Pester. The bug is resolved, and the error handling is not again built into Pester.
    • Speeding up the AppVeyor tests by splitting the common tests in a separate build job.
    • Updated the appveyor.yml to have the correct build step, and also correct run the build step only in one of the jobs.
    • Update integration tests to use the new integration test template.
    • Added SqlAgentOperator resource.
  • Changes to SqlServiceAccount
    • Fixed Get-ServiceObject when searching for Integration Services service. Unlike the rest of SQL Server services, the Integration Services service cannot be instanced, however you can have multiple versions installed. Get-Service object would return the correct service name that you are looking for, but it appends the version number at the end. Added parameter VersionNumber so the search would return the correct service name.
    • Added code to allow for using Managed Service Accounts.
    • Now the correct service type string value is returned by the function Get-TargetResource. Previously one value was passed in as a parameter (e.g. DatabaseEngine), but a different string value as returned (e.g. SqlServer). Now Get-TargetResource return the same values that can be passed as values in the parameter ServiceType (issue 981).
  • Changes to SqlServerLogin
    • Fixed issue in Test-TargetResource to valid password on disabled accounts (issue 915).
    • Now when adding a login of type SqlLogin, and the SQL Server login mode is set to "Integrated", an error is correctly thrown (issue 1179).
  • Changes to SqlSetup
    • Updated the integration test to stop the named instance while installing the other instances to mitigate issue 1260.
    • Add parameters to configure the Tempdb files during the installation of the instance. The new parameters are SqlTempdbFileCount, SqlTempdbFileSize, SqlTempdbFileGrowth, SqlTempdbLogFileSize and SqlTempdbLogFileGrowth (issue 1167).
  • Changes to SqlServerEndpoint
StorageDsc 4.5.0.0
  • Opt-in to Example publishing to PowerShell Gallery – fixes Issue 186.
  • DiskAccessPath:
    • Updated the resource to not assign a drive letter by default when adding a disk access path. Adding a Set-Partition -NoDefaultDriveLetter $NoDefaultDriveLetter block defaulting to true. When adding access paths the disks will no longer have drive letters automatically assigned on next reboot which is the desired behavior – Fixes Issue 145.
xActiveDirectory 2.24.0.0
  • Added parameter to xADDomainController to support InstallationMediaPath (issue 108).
  • Updated xADDomainController schema to be standard and provide Descriptions.
xExchange 1.27.0.0
  • Added additional parameters to the MSFT_xExchTransportService resource
  • Added additional parameters to the MSFT_xExchEcpVirtualDirectory resource
  • Added additional unit tests to the MSFT_xExchAutodiscoverVirutalDirectory resource
  • Added additional parameters to the MSFT_xExchExchangeCertificate resource
  • MSFT_xExchMailboxDatabase: Fixes issue with DataMoveReplicationConstraint parameter (401)
  • Added additional parameters and comment based help to the MSFT_xExchMailboxDatabase resource
  • Move code that sets $global:DSCMachineStatus into a dedicated helper function. Issue 407
  • Add missing parameters for xExchMailboxDatabaseCopy, adds comment based help, and adds remaining Unit tests.
xHyper-V 3.16.0.0
  • MSFT_xVMHyperV:
    • Moved localization string data to own file.
    • Fixed code styling issues.
    • Fixed bug where StartupMemory was not evaluated in Test-TargetResource.
    • Redo of abandoned PRs:
    • Fixed Get throws error when NetworkAdapters are not attached or missing properties.
xPSDesiredStateConfiguration 8.5.0.0
  • Pull server module publishing
    • Removed forced verbose logging from CreateZipFromSource, Publish-DSCModulesAndMof and Publish-MOFToPullServer as it polluted the console
  • Corrected GitHub Pull Request template to remove referral to BestPractices.MD which has been combined into StyleGuidelines.md (issue 520).
  • xWindowsOptionalFeature
    • Suppress useless verbose output from Import-Module cmdlet. (issue 453).
  • Changes to xRemoteFile
    • Corrected a resource name in the example xRemoteFile_DownloadFileConfig.ps1
  • Fix MSFT_xDSCWebService to find Microsoft.Powershell.DesiredStateConfiguration.Service.Resources.dll when server is configured with pt-BR Locales (issue 284).
  • Changes to xDSCWebService
    • Fixed an issue which prevented the removal of the IIS Application Pool created during deployment of an DSC Pull Server instance. (issue 464)
    • Fixed an issue where a Pull Server cannot be deployed on a machine when IIS Express is installed aside a full blown IIS (issue 191)
  • Update CommonResourceHelper unit tests to meet Pester 4.0.0 standards (issue 473).
  • Update ResourceHelper unit tests to meet Pester 4.0.0 standards (issue 473).
  • Update MSFT_xDSCWebService unit tests to meet Pester 4.0.0 standards (issue 473).
  • Update MSFT_xDSCWebService integration tests to meet Pester 4.0.0 standards (issue 473).
  • Refactored MSFT_xDSCWebService integration tests to meet current standards and to use Pester TestDrive.
  • xArchive
    • Fix end-to-end tests (issue 457).
    • Update integration tests to meet Pester 4.0.0 standards.
    • Update end-to-end tests to meet Pester 4.0.0 standards.
    • Update unit and integration tests to meet Pester 4.0.0 standards.
    • Wrapped all path and identifier strings in verbose messages with quotes to make it easier to identify the limit of the string when debugging.
    • Refactored date/time checksum code to improve testability and ensure tests can run on machines with localized datetime formats that are not US.
    • Fix “Get-ArchiveEntryLastWriteTime” to return [datetime] (issue 471).
    • Improved verbose logging to make debugging path issues easier.
    • Added handling for “/” as a path seperator by backporting code from PSDscResources – (issue 469).
    • Copied unit tests from PSDscResources.
    • Added .gitattributes file and removed git configuration from AppVeyor to ensure CRLF settings are configured correctly for the repository.
  • Updated “.vscode\settings.json” to refer to AnalyzerSettings.psd1 so that custom syntax problems are highlighted in Visual Studio Code.
  • Fixed style guideline violations in CommonResourceHelper.psm1.
  • Changes to xService
    • Fixes issue where Get-TargetResource or Test-TargetResource will throw an exception if the target service is configured with a non-existent dependency.
    • Refactored Get-TargetResource Unit tests.
  • Changes to xPackage
    • Fixes an issue where incorrect verbose output was displayed if product found. (issue 446)
  • Fixes files which are getting triggered for re-encoding after recent pull request (possibly 472).
  • Moves version and change history from README.MD to new file, CHANGELOG.MD.
  • Fixes markdown issues in README.MD and HighQualityResourceModulePlan.md.
  • Opted in to “Common Tests – Validate Markdown Files”
  • Changes to xPSDesiredStateConfiguration
    • In AppVeyor CI the tests are split into three separate jobs, and also run tests on two different build worker images (Windows Server 2012R2 and Windows Server 2016). The common tests are only run on the Windows Server 2016 build worker image. Helps with issue 477.
  • xGroup
    • Corrected style guideline violations. (issue 485)
  • xWindowsProcess
    • Corrected style guideline violations. (issue 496)
  • Changes to PSWSIISEndpoint.psm1
    • Fixes most PSScriptAnalyzer issues.
  • Changes to xRegistry
    • Fixed an issue that fails to remove reg key when the Key is specified as common registry path. (issue 444)
  • Changes to xService
    • Added support for Group Managed Service Accounts
  • Adds new Integration tests for MSFT_xDSCWebService and removes old Integration test file, MSFT_xDSCWebService.xxx.ps1.
  • xRegistry
    • Corrected style guideline violations. (issue 489)
  • Fix script analyzer issues in UseSecurityBestPractices.psm1. issue 483
  • Fixes script analyzer issues in xEnvironmentResource. issue 484
  • Fixes script analyzer issues in MSFT_xMsiPackage.psm1. issue 486
  • Fixes script analyzer issues in MSFT_xPackageResource.psm1. issue 487
  • Adds spaces between variable types and variables, and changes Type Accelerators to Fully Qualified Type Names on affected code.
  • Fixes script analyzer issues in MSFT_xPSSessionConfiguration.psm1 and convert Type Accelerators to Fully Qualified Type Names issue 488.
  • Adds spaces between array members.
  • Fixes script analyzer issues in MSFT_xRemoteFile.psm1 and correct general style violations. (issue 490)
  • Remove unnecessary whitespace from line endings.
  • Add statement to README.md regarding the lack of testing of this module with PowerShell 4 issue 522.
  • Fixes script analyzer issues in MSFT_xWindowsOptionalFeature.psm1 and correct general style violations. issue 494)
  • Fixes script analyzer issues in MSFT_xRemoteFile.psm1 missed from issue 490.
  • Fix script analyzer issues in MSFT_xWindowsFeature.psm1. issue 493
  • Fix script analyzer issues in MSFT_xUserResource.psm1. issue 492
  • Moves calls to set $global:DSCMachineStatus = 1 into a helper function to reduce the number of locations where we need to suppress PSScriptAnalyzer rules PSAvoidGlobalVars and PSUseDeclaredVarsMoreThanAssignments.
  • Adds spaces between comment hashtags and comments.
  • Fixes script analyzer issues in MSFT_xServiceResource.psm1. issue 491
  • Fixes script analyzer issues in MSFT_xWindowsPackageCab.psm1. issue 495
  • xFileUpload:
    • Fixes script analyzer issues in xFileUpload.schema.psm1. issue 497
    • Update to meet style guidelines.
    • Added Integration tests.
    • Updated manifest Author, Company and Copyright to match standards.
  • Updated module manifest Copyright to match standards and remove year.
  • Auto-formatted the module manifest to improve layout.
  • Fix Run-On Words in README.md.
  • Changes to xPackage
    • Fix an misnamed variable that causes an error during error message output. issue 449)
  • Fixes script analyzer issues in MSFT_xPSSessionConfiguration.psm1. issue 566
  • Fixes script analyzer issues in xGroupSet.schema.psm1. issue 498
  • Fixes script analyzer issues in xProcessSet.schema.psm1. issue 499
  • Fixes script analyzer issues in xServiceSet.schema.psm1. issue 500
  • Fixes script analyzer issues in xWindowsFeatureSet.schema.psm1. issue 501
  • Fixes script analyzer issues in xWindowsOptionalFeatureSet.schema.psm1 issue 502
  • Updates Should statements in Pester tests to use dashes before parameters.
  • Added a CODE_OF_CONDUCT.md with the same content as in the README.md issue 562
  • Replaces Type Accelerators with fully qualified type names.
xWebAdministration 2.5.0.0
  • Added SiteId to xWebSite to address [396]
  • xWebSite: Full path is used to get list of default documents
  • xIISLogging: Added support for LogTargetW3C
  • xWebsite: Added support for LogTargetW3C

How to Find Released DSC Resource Modules

To see a list of all released DSC Resource Kit modules, go to the PowerShell Gallery and display all modules tagged as DSCResourceKit. You can also enter a module’s name in the search box in the upper right corner of the PowerShell Gallery to find a specific module.

Of course, you can also always use PowerShellGet (available starting in WMF 5.0) to find modules with DSC Resources:

<span class="pl-c"><span class="pl-c">#</span> To list all modules that tagged as DSCResourceKit</span>
<span class="pl-c1">Find-Module</span> <span class="pl-k">-</span>Tag DSCResourceKit 
<span class="pl-c"><span class="pl-c">#</span> To list all DSC resources from all sources </span>
<span class="pl-c1">Find-DscResource</span>

Please note only those modules released by the PowerShell Team are currently considered part of the ‘DSC Resource Kit’ regardless of the presence of the ‘DSC Resource Kit’ tag in the PowerShell Gallery.

To find a specific module, go directly to its URL on the PowerShell Gallery:
http://www.powershellgallery.com/packages/< module name >
For example:
http://www.powershellgallery.com/packages/xWebAdministration

How to Install DSC Resource Modules From the PowerShell Gallery

We recommend that you use PowerShellGet to install DSC resource modules:

<span class="pl-c1">Install-Module</span> <span class="pl-k">-</span>Name <span class="pl-k">&lt;</span> module name <span class="pl-k">&gt;</span>

For example:

<span class="pl-c1">Install-Module</span> <span class="pl-k">-</span>Name xWebAdministration

To update all previously installed modules at once, open an elevated PowerShell prompt and use this command:

<span class="pl-c1">Update-Module</span>

After installing modules, you can discover all DSC resources available to your local system with this command:

<span class="pl-c1">Get-DscResource</span>

How to Find DSC Resource Modules on GitHub

All resource modules in the DSC Resource Kit are available open-source on GitHub.
You can see the most recent state of a resource module by visiting its GitHub page at:
https://github.com/PowerShell/< module name >
For example, for the CertificateDsc module, go to:
https://github.com/PowerShell/CertificateDsc.

All DSC modules are also listed as submodules of the DscResources repository in the DscResources folder and the xDscResources folder.

How to Contribute

You are more than welcome to contribute to the development of the DSC Resource Kit! There are several different ways you can help. You can create new DSC resources or modules, add test automation, improve documentation, fix existing issues, or open new ones.
See our contributing guide for more info on how to become a DSC Resource Kit contributor.

If you would like to help, please take a look at the list of open issues for the DscResources repository.
You can also check issues for specific resource modules by going to:
https://github.com/PowerShell/< module name >/issues
For example:
https://github.com/PowerShell/xPSDesiredStateConfiguration/issues

Your help in developing the DSC Resource Kit is invaluable to us!

Questions, comments?

If you’re looking into using PowerShell DSC, have questions or issues with a current resource, or would like a new resource, let us know in the comments below, on Twitter (@PowerShell_Team), or by creating an issue on GitHub.

Katie Kragenbrink
Software Engineer
PowerShell DSC Team
@katiedsc (Twitter)
@kwirkykat (GitHub)

The post DSC Resource Kit Release February 2019 appeared first on PowerShell.

Generating PowerShell Cmdlets from OpenAPI/Swagger with AutoRest

$
0
0

Today, we’re announcing beta support for PowerShell in AutoRest, so that you can now generate PowerShell modules from Swagger/OpenAPI JSON documents.

AutoRest is the SDK generation tool that we use in Azure to produce SDKS for 90+ management services across 7+ languages.
Its pluggable architecture allows fine-grained control over the generation process, and allows extensions to be written in any language that can read/write JSON via stdin/stdout (we use the JSON-RPC protocol that Visual Studio Code uses )

Along the way, we had to go back and make some updates to the core of AutoRest (to begin support of OpenAPI 3, and introduce some changes to support generating multiple API versions with Azure Profiles.)

Getting Started

Requirements

Use of the beta version of autorest.powershell requires the following:

  • Node.js LTS (10.15.x LTS preferred. Will not function with a Node version less than 10.x. Be wary of 11.x builds as they may introduce instability or breaking changes. )

If you want an easy way to install and update Node, I recommend NVS – Node Version Switcher or NVM – Node Version Manager

  • AutoRest v3 beta:
    npm install -g autorest@beta
  • PowerShell 6.1 – If you don’t have it installed, you can use the cross-platform npm package
    npm install -g pwsh
  • Dotnet SDK 2 or greater – If you don’t have it installed, you can use the cross-platform .NET 2.1 npm package
    npm install -g dotnet-sdk-2.1 

Using AutoRest Powershell

At a bare minimum, you can generate a PowerShell module using a Swagger or OpenAPI file and using --powershell.

The output will be in the ./generated folder by default:

autorest --powershell --input-file:<path-to-swagger-file> [...options]

Be sure to check out these additional samples that use the PowerShell generator.

Features

Modules work on both Windows PowerShell and PowerShell

Due to the use of netstandard2.0 and PowerShellStandard.Library, once compiled, the cmdlets work on both Windows PowerShell 5.1 and PowerShell 6.x. PowerShell 6.x is required during development.

Generates modules from OpenAPI files without any external dependencies

Most language SDKs generated with AutoRest required the use of at least a ‘client runtime’ package, and often pulls in a few other libraries (ie, JSON.NET) that are required to compile the output of the generator.

The new PowerShell generator creates modules that require no dependencies outside of netstandard2.0 and the PowerShellStandard.Library which drastically reduces the chances of having assembly loading conflicts.

Cmdlets have no weird base-classes or force hierarchy

All the generated cmdlets inherit PSCmdlet and are fairly straightforward. For ARM resources, we already support generating -AsJob support for long-running-operations, and this can be expanded in the future to support more patterns.

An incredible number of extensibility points

After generation of a module, the developer may wish to augment the module in many ways (custom work when the module loads, changing the HTTP pipeline, adding additional variants of cmdlets, and more). The generated cmdlets offer number of ways to be customized and enhanced, and we’ll be posting some documentation on how to do that in the near future.

Many variants of cmdlets are created to offer several ParameterSets

Behind-the-scenes, many different flavors of a cmdlet can get created, and these are tied together into a single cmdlet with multiple parameter sets. These can be joined with manually written cmdlets that are written in .ps1scripts or C# classes.

No reflection for serialization

The generated module has custom-created JSON serialization (using an embedded copy of Carbon.JSON) This significantly improves serialization performance.

FAQs

What happened to ‘PSSwagger’?

In order to get to the point where we can generate the Az modules for all the Azure management services, we needed more control in the fine-grained details of the resulting cmdlets. After consulting with the PowerShell team, the decision was made to integrate more closely with the existing mechanism for generating Azure SDKs (AutoRest) and build a full-featured generator extension to create PowerShell cmdlets. All future work to generate cmdlets be done in the AutoRest PowerShell generator, as we’ve discontinued work on PSSwagger.

Source code?

Of course! You probably should get started with the by reading the developer documentation.

Are there any PowerShell specific generation options?

Yes! You can modify the entire output folder layout, and tweak the way it generates cmdlets, including cmdlet names, parameters, etc. (Check out our additional documentation on these options). If you have feedback about these code generation options, feel free to post an issue on the AutoRest GitHub repo.

Known Issues

As with all beta software, there are bound to be a few glitches or things that are not working.

We’ve cataloged some known issues with this first beta we encourage you to read before reporting any issues you experience.

Support

We’re working as fast as we can to finish up the generator, as we have a lot of modules to generate internally.

I should also have deeper design documentation over the next month or two, explaining a bit more of the “why-does-it-work-this-way?” category.

General feedback can be left in the PowerShell Generator thread in the github repo.

If you run into problems, feel free to post an issue on the github repo and tag it with the powershell label, and we’ll try to take a look.

Quick Links

The post Generating PowerShell Cmdlets from OpenAPI/Swagger with AutoRest appeared first on PowerShell.

Invoke-Sqlcmd is Now Available Supporting Cross-Platform


The PowerShell Extension is now in the Azure Data Studio Marketplace

$
0
0

We are excited to announce the PowerShell Extension is available in the Azure Data Studio (ADS)
marketplace!
Now you can write PowerShell scripts with the full benefits of PowerShell Editor Services
using the excellent IDE-like interface that Azure Data Studio provides.

Key Features this Brings to PowerShell Editing in Azure Data Studio

  • Syntax highlighting
  • Code snippets
  • IntelliSense for cmdlets and more
  • Rule-based analysis provided by PowerShell Script Analyzer
  • Go to Definition of cmdlets and variables
  • Find References of cmdlets and variables
  • Document and workspace symbol discovery
  • Run selected selection of PowerShell code using F8
  • Launch online help for the symbol under the cursor using Ctrl+F1
  • Basic interactive console support!

How to get the PowerShell extension in Azure Data Studio

If you don’t already have Azure Data Studio, start here.

Once you have Azure Data Studio open, click Clt+Shift+X to open the extensions marketplace.
Next, type PowerShell in the search bar.
Click Install on the PowerShell page.
Finally, click Reload in order to refresh Azure Data Studio.

Why we joined the Azure Data Studio Marketplace

Azure Data Studio is a powerful cross-platform database tool for data professionals using the
Microsoft family of on-premises and cloud data platforms on Windows, MacOS, and Linux.
Since PowerShell is a great tool for data management it just made sense to bring the full PowerShell
editing experience to this marketplace.

An example for getting started with SQL PowerShell

In order to use this example (below), you need to install the SqlServer module from the PowerShell Gallery.

Install-Module SqlServer AllowPrerelease

NOTE: With version 21.1.18095-preview and up, the SqlServer module supports PowerShell Core 6.2 and up in addion to Windows PowerShell.

In this example we take all of the .CSV files in a directory, turn each one into a SQL Server, and insert the data.

Whether you have 7 files, like in our example, or hundreds, using PowerShell to accomplish this task can be huge time saver!

In the below example you’ll notice the PowerShell script in the green box used to navigate to the directory, turn each file into a SQL server, and insert the data. With the PowerShell extension it is easy to run your script – simply select the snippet you want to run and type F8. You’ll also notice the output in the terminal highlighted with an orange box. The arrow from this box shows the newly generated SQL tables.

PowerShellExample

As you begin to write your own scripts you’ll notice you get suggestions from the PowerShell extension, this intellisense will help you to efficently write scripts in Azure Data Studio with PowerShell. As you navigate down the suggestions you will see descriptions of what each cmdlet can do.

In the example below, typing Write-S gives you suggestions like Write-SQLTableData, and tells you that this cmdlet writes data to the table of a SQL database.

intellisense example

For more examples of how to take advantage of PowerShell for data management check out this documentation

Reporting Feedback

An important benefit of being open source is getting feedback from users.
To report issues with the extension use our GitHub repo.
When reporting issues be sure to specify that you are using Azure Data Studio.

Sydney Smith
Program Manager
PowerShell Team

The post The PowerShell Extension is now in the Azure Data Studio Marketplace appeared first on PowerShell.

PowerShell ScriptAnalyzer Version 1.18.0 Released

$
0
0

PSScriptAnalyzer (PSSA1.18.0 is now available on the PSGallery and brings a lot of improvements in the following areas:

  • Better compatibility analysis of commands, types and syntax across different platforms and versions of PowerShell
  • Better formatting and customization. New capabilities are:
    • Multi-line pipeline indentation styles
    • Cmdlet casing for better consistency and readability
    • Consistent whitespace inside braces and pipes
  • Custom rules can now be suppressed and preserve the RuleSuppressionID
  • Better DSC support by being able to understand different syntaxes of Import-DscResource
  • Better user experience by being able to pipe to Invoke-ScriptAnalyzer and added tab completion of the returned objects that are piped to the next pipeline
  • Better handling of parsing errors by emitting them as a diagnostic record with a new Severity type
  • Improved Performance: Expect it to be about twice as fast in most cases and even more when re-analyzing a file. More on this below
  • Fixes and enhancements to the engine, rules, and documentation

There are some minor breaking changes such as e.g. requiring the minimum version of PowerShell Core to 6.1 as 6.0 has reached the end of its support lifecycle. With this, it was possible to update the used version of Newtonsoft.Json to 11.0.2. On Windows PowerShell, the minimum required runtime was upped from4.5.0 to4.5.2, which is the lowest version that is still supported by Microsoft but Windows update will have taken care of upgrading the to this patched version anyway, therefore no disruption is expected. We have also replaced old command data files of PowerShell 6.0 with a newer version for theUseCompatibleCmdletsrule.

Formatting

New rules and new features/customization of existing rules were added and in an upcoming release of the PowerShell vscode extension, those new features will also be configurable from within the extension in an upcoming update.

New PSUseConsistentWhitespace options

The PSUseConsistentWhitespace rule has 2 new configuration options that are both enabled by default:

  • CheckInnerBrace: Checks if there is a space after the opening brace and a space before the closing brace. E.g. if ($true) { foo } instead of if ($true) {bar}.
  • CheckPipe: Checks if a pipe is surrounded on both sides by a space. E.g. foo | bar instead offoo|bar.

In an upcoming update of the PowerShell vscode extension, this feature will be configurable in the editor via the settings powershell.WhitespaceInsideBrace and powershell.WhitespaceAroundPipe.

New PipelineIndentation option for PSUseConsistentIndentation

The PSUseConsistentIndentation rule was fixed to handle multi-line pipeline (before, the behavior was a bit ill-defined) and as part of that we decided to expose 3 options for a new configuration option calledPipelineIndentation. This allows PSSA to cater to different tastes of the user whether to increase indentation after a pipeline for multi-line statements. The settings are:

  • IncreaseIndentationForFirstPipeline (default): Indent once after the first pipeline and keep this indentation. Example:
foo |
    bar |
    baz
  • IncreaseIndentationAfterEveryPipeline: Indent more after the first pipeline and keep this indentation. Example:
foo |
    bar |
        baz
  • NoIndentation: Do not increase indentation. Example:
foo |
bar |
baz

In an upcoming update of the PowerShell vscode extension, this feature will be configurable in the editor via the setting powershell.codeFormatting.

New PSUseConsistentCasing rule

By popular request, this rule can correct the casing of cmdlet names. This can correct e.g. get-azadapplicaTION to Get-AzADApplication. This not only makes code more consistent but can improve readability in most cases. In an upcoming update of the PowerShell vscode extension, this feature will be configurable in the editor via the settingpowershell.useCorrectCasingsettings.

Compatibility Analysis

The UseCompatibleCmdlets rule requires JSON files in the Settings folder of PSSA’s installation and their file name is mapped to directly the compatibility configuration. In the new version we have replaced the JSON files for PowerShell 6.0 with files for 6.1 and also added new files for e.g. ARM on Linux (Raspian) and also PowerShell 2.0 that is still being used by some despite it being deprecated. If desired, one can always add custom JSON files to the Settings folder and it will just work by using the filename without the need to re-compile. To generate your custom JSON file for your environment, you can use the New-CommandDataFile.ps1 script.

To further add more analysis, 3 more rules were being added:

These rules do not follow the definition style of the UseCompatibleCmdlets rule. For usage and examples please refer to the rule documentation links of the 3 new rules above, there will be a more detailed blog post about them in the future.

Better DSC Support

Invoke-ScriptAnalyzer has a -SaveDscDependency switch that will download the required module from the PSGalleryto allow for parsing of the DSC files. In order to do that is has to parse calls to Import-DscResource correctly. Previously it could neither take the version into account or parse the hashtable syntax (Import-DscResource -ModuleName (@{ModuleName="SomeDscModule1";ModuleVersion="1.2.3.4"})). We added support for both of them. But because there could be different variations of the first one (different parameter name order or not using named paramters, etc.), please use it in the form Import-DscResource -ModuleName MyModuleName -ModuleVersion 1.2.3.4.

Custom Rules

We added the capability of being able to suppress violations from custom rules the same way how you can already suppress rules from the built-in rules. It is worth noting though that the rulename of custom rules has to be of the format CustomRuleModuleFileName\CustomRuleName, this is to uniquely identify the rule as it could be possible that 2 custom rule modules emit a rule of the same name.

When a custom rule emits a DiagnosticRecord, then the engine has to translate all properties of the object as it has to be re-created when emitting it via Invoke-ScriptAnalyzer. We added the translation of the SuggestedCorrectionsproperty already in the last release (1.17.1) to allow for auto-correction in the editor or via the -Fix switch. However, we also found that customers want to also use the RuleSuppressionID property in their custom rules, so we added translation for this as well.

Engine Improvements

PSScriptAnalyzer is highly multi-threaded by executing each rule (excluding custom or DSC rules) in parallel in each own thread. But there are some global resources such as e.g. a CommandInfo cache that needs to be accessed using a lock. Caching and lock granularity has been improved and are therefore reducing congestion which leads to much better performance. You can expect PSScriptAnalyzer to be about twice as fast for ‘cold runs’ (where Invoke-ScriptAnalyzerhas not been called before) and magnitudes faster when re-analyzing the same file. To you as a user, this will mean that you will see the squiggles faster when opening a new file in VS-Code and you will get faster updates when editing a file whilst reducing the CPU consumption in the background. We have more optimizations planned in this area, you can expect further improvements of similar scale in future versions and we hope to release future versions more frequent as well.

Miscellaneous Fixes

We received reports of some functionality not working when using Turkish culture and made a fix for and as part reviewed some culture critical points and made sure they work better across all cultures. The bug was very specific to Turkish culture, therefore we are confident that PSSA should work with any other cultures as well.

The Changelog has more details on the various fixes that were made to other rules.

On behalf of the Script Analyzer team,

Chris Bergmeister, Project Maintainer
Jim Truher, Senior Software Engineer, Microsoft

The post PowerShell ScriptAnalyzer Version 1.18.0 Released appeared first on PowerShell.

Announcing General Availability of the Windows Compatibility Module 1.0.0

$
0
0

The Windows Compatibility module (WindowsCompatibility) is a PowerShell module that lets PowerShell Core 6 scripts access Windows PowerShell modules that are not yet natively available on PowerShell Core. (Note: the list of unavailable commands is getting smaller with each new release of PowerShell Core. This module is just for things aren’t natively supported yet.)

You can install the module from the PowerShell Gallery using the command

Install-Module WindowsCompatibility

and the source code is available on GitHub. (This is where you should open issues or make suggestions.)

Once you have WindowsCompatibility installed, you can start using it. The first thing you might want to run is Get-WinModule which will show you the list of available modules. From that list, choose a module, say PKI and and load it. To do this, run the following command:

Import-WinModule PKI

and you’ll have the commands exported by the PKI module in your local session. You can run them just like any other command. For example:

New-SelfSignedCertificate -DnsName localhost

As always, you can see what a module exported by doing:

Get-Command -module PKI

just like any other module.

These are the most important commands but the WindowsCompatibility module provides some others:

  • Invoke-WinCommand allows you to invokes a one-time command in the compatibility session.
  • Add-WinFunction allows you to define new functions that operate implicitly in the compatibility session.
  • Compare-WinModule lets you compare what you have against what’s available.
  • Copy-WinModule will let you copy Window PowerShell modules that are known to work in PowerShell 6 to the PowerShell 6 command path.
  • Initialize-WinSession gives you more control on where and how the compatibility session is created. For example. it will allow you to place the compatibility session on another machine.

(See the module’s command help for more details and examples on how to use the WindowsCompatibility functions.)

How It Works

The WindowsCompatibility module takes advantage of the ‘Implicit Remoting‘ feature that has been available in PowerShell since version 2. Implicit remoting works by retrieving command metadata from a remote session and synthesizing proxy functions in the local session. When you call one of these proxy function, it takes all of the parameters passed to it and forwards them to the real command in the “remote” session. Wait a minute you may be thinking – what does remoting have to do with the WindowsCompatibility module? WindowsCompatibility automatically creates and manages a ‘local remote’ session, called the ‘compatibility session’ that runs with Windows PowerShell on the local machine. It imports the specified module and then creates local proxy functions for all of commands defined in that module.

OK – what about modules that exist in both Windows PowerShell and PowerShell core? Yes – you can import them. After all, there are still a fair number of base cmdlets that aren’t available in PowerShell core yet.

So how does this work? WindowsCompatibility is very careful to not overwrite native PowerShell core commands. It only imports the ones that are available with Windows PowerShell but not with PowerShell Core. For example, the following will import the PowerShell default management module

 Import-WinModule  Microsoft.PowerShell.Management

which contains, among others, the Get-EventLog cmdlet. None of the native PowerShell Core cmdlets get overwritten but now you have Get-EventLog available in your session.

At this point, if you call Get-Module, you will see something a bit strange:

Get-Module | ForEach-Object Name

results in output that looks like:

Microsoft.PowerShell.Management
Microsoft.PowerShell.Management.WinModule
Microsoft.PowerShell.Utility
NetTCPIP

Import-WinModule renames the compatibility module at load time to prevent collisions with identically named modules. This is so the module qualified commands will resolve against the current module. In fact, if you want to see what additional commands were imported, you can run:

Get-Command -Module  Microsoft.PowerShell.Management.WinModule

Limitations

Because WindowsCompatibility is based on implicit remoting, there are a number of significant limitations on the cmdlets imported by the module. First, because everything is done using the remoting protocol, the imported cmdlets will return deserialized objects that only contain properties. Much of the time, this won’t matter because the parameter binder binds by property name rather than by object type. As long as the required properties are present on the object, it doesn’t matter what type the object actually is. There are, however, cases where the cmdlet actually requires that the object be of a specific type or that it have methods. WindowsCompatibility won’t work for these cmdlets.

Windows Forms and other graphical tools

The remoting session is considered non-interactive so graphical tools such as notepad or Winforms scripts will either fail, or worse hang.

Linux and Mac support

This module depends on WinRM and the client libraries on these platforms are known to be unstable and limited. So for this release, only PowerShell Core running on Windows is supported. (This may change in the future. But you’ll still need a Windows machine with Windows PowerShell to host the compatibility session.)

PowerShell 6.1 Dependency

WindowsCompatibility depends on a feature introduced in PowerShell Core 6.1 for keeping the current working directory in both the local and compatibility sessions synchronized. Earlier versions of PowerShell will work with WindowsCompatibility but won’t have this directory synchronization feature. So if you’re running PowerShell Core 6.0, import a command that writes to files, do Set-Location to a new directory, then use that command to write to a file with an unqualified path; it will use the original path from when the module was imported rather than your sessions current working directory. On PowerShell Core 6.1, it will correctly use the current working directory.

Summary

To sum it all up, the WindowsCompatibility module provides a set of commands that allow you to access Window PowerShell modules from PowerShell Core 6. There are however, some limitations that make it unsuitable for all scenarios. Over time, as more and more modules are ported to .NET Core/PowerShell 6 natively there will be less need for this module.

Cheers!
Bruce Payette,
PowerShell Team.

PowerShell Constrained Language mode and the Dot-Source Operator

$
0
0

PowerShell Constrained Language mode and the Dot-Source Operator

PowerShell works with application control systems, such as AppLocker and Windows Defender Application Control (WDAC), by automatically running in
ConstrainedLanguage mode. ConstrainedLanguage mode restricts some exploitable aspects of PowerShell while still giving you a rich shell to run commands and scripts in. This is different from usual application white listing rules, where an application is either allowed to run or not.

But there are times when the full power of PowerShell is needed, so we allow script files to run in FullLanguage mode when they are trusted by the policy. Trust can be indicated through file signing or other policy mechanisms such as file hash. However, script typed into the interactive shell is always run constrained.

Since PowerShell can run script in both Full and Constrained language modes, we need to protect the boundary between them. We don’t want to leak variables or functions between sessions running in different language modes.

The PowerShell dot-source operator brings script files into the current session scope. It is a way to reuse script. All script functions and variables defined in the script file become part of the script it is dot sourced into. It is like copying and pasting text from the script file directly into your script.

# HelperFn1, HelperFn2 are defined in HelperFunctions.ps1
# Dot-source the file here to get access to them (no need to copy/paste)
. c:\Scripts\HelperFunctions.ps1
HelperFn1
HelperFn2

This presents a problem when language modes are in effect with system application control. If an untrusted script is dot-sourced into a script with full trust then it has access to all those functions that run in FullLanguage mode, which can result in application control bypass through arbitrary code execution or privilege escalation. Consequently, PowerShell prevents this by throwing an error when dot-sourcing is attempted across language modes.

Example 1:

System is in WDAC policy lock down. To start with, neither script is trusted and so both run in ConstrainedLanguage mode. But the HelperFn1 function uses method invocation which isn’t allowed in that mode.

PS> type c:\MyScript.ps1
Write-Output "Dot sourcing MyHelper.ps1 script file"
. c:\MyHelper.ps1
HelperFn1
PS> type c:\MyHelper.ps1
function HelperFn1
{
    "Language mode: $($ExecutionContext.SessionState.LanguageMode)"
    [System.Console]::WriteLine("This can only run in FullLanguage mode!")
}
PS> c:\MyScript.ps1
Dot sourcing MyHelper.ps1 script file
Language mode: ConstrainedLanguage
Cannot invoke method. Method invocation is supported only on core types in this language mode.
At C:\MyHelper.ps1:4 char:5
+     [System.Console]::WriteLine("This cannot run in ConstrainedLangua ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodInvocationNotSupportedInConstrainedLanguage

Both scripts are untrusted and run in ConstrainedLanguage mode, so dot-sourcing the MyHelper.ps1 file works. However, the HelperFn1 function performs method invocation that is not allowed in ConstrainedLanguage and fails when run. MyHelper.ps1 needs to be signed as trusted so it can run at FullLanguage.

Next we have mixed language modes. MyHelper.ps1 is signed and trusted, but MyScript.ps1 is not.

PS> c:\MyScript.ps1
Dot sourcing MyHelper.ps1 script file
C:\MyHelper.ps1 : Cannot dot-source this command because it was defined in a different language mode. To invoke this command without importing its contents, omit the '.' operator.
At C:\MyScript.ps1:2 char:1
+ . 'c:\MyHelper.ps1'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [MyHelper.ps1], NotSupportedException
    + FullyQualifiedErrorId : DotSourceNotSupported,MyHelper.ps1
...

And we get a dot-source error because we are trying to dot-source script that has a different language mode than the session it is being dot-sourced into.

Finally, we sign as trusted both script files and everything works.

PS> c:\MyScript.ps1
Dot sourcing MyHelper.ps1 script file
Language mode: FullLanguage
This can only run in FullLanguage mode!

The lesson here is to ensure all script components run in the same language mode on policy locked down systems. If one component must run in FullLanguage mode, then all components should run in FullLanguage mode. This means validating that each component is safe to run in FullLanguage and indicating they are trusted to the application control policy.

So this solves all language mode problems, right? If FullLanguage is not needed then just ensure all script components run untrusted, which is the default condition. If they require FullLanguage then carefully validate all components and mark them as trusted. Unfortuantely, there is one case where this best practice doesn’t work.

PowerShell Profile File

The PowerShell profile file (profile.ps1) is loaded and run at PowerShell start up. If that script requires FullLanguage mode on policy lock down systems, you just validate and sign the file as trusted, right?

Example 2:

PS> type c:\users\<user>\Documents\WindowsPowerShell\profile.ps1
Write-Output "Running Profile"
[System.Console]::WriteLine("This can only run in FullLanguage!")
# Sign file so it is trusted and will run in FullLanguage mode
PS> Set-AuthenticodeSignature -FilePath .\Profile.ps1 -Certificate $myPolicyCert
# Start a new PowerShell session and run the profile script
PS> powershell.exe
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
C:\Users\<user>\Documents\WindowsPowerShell\profile.ps1 : Cannot dot-source this command because it was defined in a different language mode. To invoke this command without importing its contents, omit the '.' operator.
At line:1 char:1
+ . 'C:\Users\<user>\Documents\WindowsPowerShell\profile.ps1'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [profile.ps1], NotSupportedException
    + FullyQualifiedErrorId : DotSourceNotSupported,profile.ps1

What gives? The profile.ps1 file was signed and is policy trusted. Why the error?
Well, the issue is that PowerShell dot-sources the profile.ps1 file into the default PowerShell session, which must run in ConstrainedLanguage because of the policy. So we are attempting to dot-source a FullLanguage script into a ConstrainedLanguage session, and that is not allowed. This is a catch 22 because if the profile.ps1 is not signed, it may not run if it needs FullLanguage privileges (e.g., invoke methods). But if you sign it, it still won’t run because of how it is dot-sourced into the current ConstrainedLanguage interactive session.

Unfortunately, the only solution is to keep the profile.ps1 file fairly simple so that it does not need FullLanguage, and refrain from making it trusted. Keep in mind that this is only an issue when running with application control policy. Otherwise, language modes do not come into play and PowerShell profile files run normally.

Paul Higinbotham
Senior Software Engineer
PowerShell Team

DSC Resource Kit Release November 2018

$
0
0

We just released the DSC Resource Kit!

This release includes updates to 9 DSC resource modules. In the past 6 weeks, 61 pull requests have been merged and 67 issues have been closed, all thanks to our amazing community!

The modules updated in this release are:

  • AuditPolicyDsc
  • DFSDsc
  • NetworkingDsc
  • SecurityPolicyDsc
  • SharePointDsc
  • StorageDsc
  • xBitlocker
  • xExchange
  • xHyper-V

For a detailed list of the resource modules and fixes in this release, see the Included in this Release section below.

Our latest community call for the DSC Resource Kit was supposed to be today, November 28, but the public link to the call expired, so the call was cancelled. I will update the link for next time. If there is interest in rescheduling this call, the new call time will be announced on Twitter (@katiedsc or @migreene) The call for the next release cycle is also getting moved a week later than usual to January 9 at 12PM (Pacific standard time). Join us to ask questions and give feedback about your experience with the DSC Resource Kit.

The next DSC Resource Kit release will be on Wednesday, January 9.

We strongly encourage you to update to the newest version of all modules using the PowerShell Gallery, and don’t forget to give us your feedback in the comments below, on GitHub, or on Twitter (@PowerShell_Team)!

Please see our documentation here for information on the support of these resource modules.

Included in this Release

You can see a detailed summary of all changes included in this release in the table below. For past release notes, go to the README.md or CHANGELOG.md file on the GitHub repository page for a specific module (see the How to Find DSC Resource Modules on GitHub section below for details on finding the GitHub page for a specific module).

Module Name Version Release Notes
AuditPolicyDsc 1.3.0.0
  • Update LICENSE file to match the Microsoft Open Source Team standard.
  • Added the AuditPolicyGuid resource.
DFSDsc 4.2.0.0
  • Add support for modifying staging quota size in MSFT_DFSReplicationGroupMembership – fixes Issue 77.
  • Refactored module folder structure to move resource to root folder of repository and remove test harness – fixes Issue 74.
  • Updated Examples to support deployment to PowerShell Gallery scripts.
  • Remove exclusion of all tags in appveyor.yml, so all common tests can be run if opt-in.
  • Added .VSCode settings for applying DSC PSSA rules – fixes Issue 75.
  • Updated LICENSE file to match the Microsoft Open Source Team standard – fixes Issue 79
NetworkingDsc 6.2.0.0
  • Added .VSCode settings for applying DSC PSSA rules – fixes Issue 357.
  • Updated LICENSE file to match the Microsoft Open Source Team standard – fixes Issue 363
  • MSFT_NetIPInterface:
    • Added a new resource for configuring the IP interface settings for a network interface.
SecurityPolicyDsc 2.6.0.0
  • Added SecurityOption – Network_access_Restrict_clients_allowed_to_make_remote_calls_to_SAM
  • Bug fix – Issue 105 – Spelling error in SecurityOption”User_Account_Control_Behavior_of_the_elevation_prompt_for_standard_users”
  • Bug fix – Issue 90 – Corrected value for Microsoft_network_server_Server_SPN_target_name_validation_level policy
SharePointDsc 3.0.0.0
  • Changes to SharePointDsc
    • Added support for SharePoint 2019
    • Added CredSSP requirement to the Readme files
    • Added VSCode Support for running SharePoint 2019 unit tests
    • Removed the deprecated resources SPCreateFarm and SPJoinFarm (replaced in v2.0 by SPFarm)
  • SPBlobCacheSettings
    • Updated the Service Instance retrieval to be language independent
  • SPConfigWizard
    • Fixed check for Ensure=Absent in the Set method
  • SPInstallPrereqs
    • Added support for detecting updated installation of Microsoft Visual C++ 2015/2017 Redistributable (x64) for SharePoint 2016 and SharePoint 2019.
  • SPSearchContentSource
    • Added support for Business Content Source Type
  • SPSearchMetadataCategory
    • New resource added
  • SPSearchServiceApp
    • Updated resource to make sure the presence of the service app proxy is checked and created if it does not exist
  • SPSecurityTokenServiceConfig
    • The resource only tested for the Ensure parameter. Added more parameters
  • SPServiceAppSecurity
    • Added support for specifying array of access levels.
    • Changed implementation to use Grant-SPObjectSecurity with Replace switch instead of using a combination of Revoke-SPObjectSecurity and Grant-SPObjectSecurity
    • Added all supported access levels as available values.
    • Removed unknown access levels: Change Permissions, Write, and Read
  • SPUserProfileProperty
    • Removed obsolete parameters (MappingConnectionName, MappingPropertyName, MappingDirection) and introduced new parameter PropertyMappings
  • SPUserProfileServiceApp
    • Updated the check for successful creation of the service app to throw an error if this is not done correctly The following changes will break v2.x and earlier configurations that use these resources:
  • Implemented IsSingleInstance parameter to force that the resource can only be used once in a configuration for the following resources:
    • SPAntivirusSettings
    • SPConfigWizard
    • SPDiagnosticLoggingSettings
    • SPFarm
    • SPFarmAdministrators
    • SPInfoPathFormsServiceConfig
    • SPInstall
    • SPInstallPrereqs
    • SPIrmSettings
    • SPMinRoleCompliance
    • SPPasswordChangeSettings
    • SPProjectServerLicense
    • SPSecurityTokenServiceConfig
    • SPShellAdmin
  • Standardized Url/WebApplication parameter to default WebAppUrl parameter for the following resources:
    • SPDesignerSettings
    • SPFarmSolution
    • SPSelfServiceSiteCreation
    • SPWebAppBlockedFileTypes
    • SPWebAppClientCallableSettings
    • SPWebAppGeneralSettings
    • SPWebApplication
    • SPWebApplicationAppDomain
    • SPWebAppSiteUseAndDeletion
    • SPWebAppThrottlingSettings
    • SPWebAppWorkflowSettings
  • Introduced new mandatory parameters
    • SPSearchResultSource: Added option to create Result Sources at different scopes.
    • SPServiceAppSecurity: Changed parameter AccessLevel to AccessLevels in MSFT_SPServiceAppSecurityEntry to support array of access levels.
    • SPUserProfileProperty: New parameter PropertyMappings
SharePointDsc 3.1.0.0
  • Changes to SharePointDsc
    • Updated LICENSE file to match the Microsoft Open Source Team standard.
  • ProjectServerConnector
    • Added a file hash validation check to prevent the ability to load custom code into the module.
  • SPFarm
    • Fixed localization issue where TypeName was in the local language.
  • SPInstallPrereqs
    • Updated links in the Readme.md file to docs.microsoft.com.
    • Fixed required prereqs for SharePoint 2019, added MSVCRT11.
  • SPManagedMetadataServiceApp
    • Fixed issue where Get-TargetResource method throws an error when the service app proxy does not exist.
  • SPSearchContentSource
    • Corrected issue where the New-SPEnterpriseSearchCrawlContentSource cmdlet was called twice.
  • SPSearchServiceApp
    • Fixed issue where Get-TargetResource method throws an error when the service application pool does not exist.
    • Implemented check to make sure cmdlets are only executed when it actually has something to update.
    • Deprecated WindowsServiceAccount parameter and moved functionality to new resource (SPSearchServiceSettings).
  • SPSearchServiceSettings
    • Added new resource to configure search service settings.
  • SPServiceAppSecurity
    • Fixed unavailable utility method (ExpandAccessLevel).
    • Updated the schema to no longer specify username as key for the sub class.
  • SPUserProfileServiceApp
    • Fixed issue where localized versions of Windows and SharePoint would throw an error.
  • SPUserProfileSyncConnection
    • Corrected implementation of Ensure parameter.
StorageDsc 4.3.0.0
  • WaitForDisk:
    • Added readonly-property isAvailable which shows the current state of the disk as a boolean – fixes Issue 158.
xBitlocker 1.3.0.0
  • Update appveyor.yml to use the default template.
  • Added default template files .gitattributes, and .vscode settings.
  • Fixes most PSScriptAnalyzer issues.
  • Fix issue where AutoUnlock is not set if requested, if the disk was originally encrypted and AutoUnlock was not used.
  • Add remaining Unit Tests for xBitlockerCommon.
  • Add Unit tests for MSFT_xBLTpm
  • Add remaining Unit Tests for xBLAutoBitlocker
  • Add Unit tests for MSFT_xBLBitlocker
  • Moved change log to CHANGELOG.md file
  • Fixed Markdown validation warnings in README.md
  • Added .MetaTestOptIn.json file to root of module
  • Add Integration Tests for module resources
  • Rename functions with improper Verb-Noun constructs
  • Add comment based help to any functions without it
  • Update Schema.mof Description fields
  • Fixes issue where Switch parameters are passed to Enable-Bitlocker even if the corresponding DSC resource parameter was set to False (Issue 12)
xExchange 1.25.0.0
  • Opt-in for the common test flagged Script Analyzer rules (issue 234).
  • Opt-in for the common test testing for relative path length.
  • Removed the property PSDscAllowPlainTextPassword from all examples so the examples are secure by default. The property PSDscAllowPlainTextPassword was previously needed to (test) compile the examples in the CI pipeline, but now the CI pipeline is using a certificate to compile the examples.
  • Opt-in for the common test that validates the markdown links.
  • Fix typo of the word “Certificate” in several example files.
  • Add spaces between array members.
  • Add initial set of Unit Tests (mostly Get-TargetResource tests) for all remaining resource files.
  • Add WaitForComputerObject parameter to xExchWaitForDAG
  • Add spaces between comment hashtags and comments.
  • Add space between variable types and variables.
  • Fixes issue where xExchMailboxDatabase fails to test for a Journal Recipient because the module did not load the Get-Recipient cmdlet (335).
  • Fixes broken Integration tests in MSFT_xExchMaintenanceMode.Integration.Tests.ps1 (336).
  • Fix issue where Get-ReceiveConnector against an Absent connector causes an error to be logged in the MSExchange Management log.
  • Rename poorly named functions in xExchangeDiskPart.psm1 and MSFT_xExchAutoMountPoint.psm1, and add comment based help.
xHyper-V 3.14.0.0
  • MSFT_xVMHost:
    • Added support to Enable / Disable VM Live Migration. Fixes Issue 155.

How to Find Released DSC Resource Modules

To see a list of all released DSC Resource Kit modules, go to the PowerShell Gallery and display all modules tagged as DSCResourceKit. You can also enter a module’s name in the search box in the upper right corner of the PowerShell Gallery to find a specific module.

Of course, you can also always use PowerShellGet (available starting in WMF 5.0) to find modules with DSC Resources:

# To list all modules that tagged as DSCResourceKit
Find-Module -Tag DSCResourceKit 
# To list all DSC resources from all sources 
Find-DscResource

Please note only those modules released by the PowerShell Team are currently considered part of the ‘DSC Resource Kit’ regardless of the presence of the ‘DSC Resource Kit’ tag in the PowerShell Gallery.

To find a specific module, go directly to its URL on the PowerShell Gallery:
http://www.powershellgallery.com/packages/< module name >
For example:
http://www.powershellgallery.com/packages/xWebAdministration

How to Install DSC Resource Modules From the PowerShell Gallery

We recommend that you use PowerShellGet to install DSC resource modules:

Install-Module -Name < module name >

For example:

Install-Module -Name xWebAdministration

To update all previously installed modules at once, open an elevated PowerShell prompt and use this command:

Update-Module

After installing modules, you can discover all DSC resources available to your local system with this command:

Get-DscResource

How to Find DSC Resource Modules on GitHub

All resource modules in the DSC Resource Kit are available open-source on GitHub.
You can see the most recent state of a resource module by visiting its GitHub page at:
https://github.com/PowerShell/< module name >
For example, for the CertificateDsc module, go to:
https://github.com/PowerShell/CertificateDsc.

All DSC modules are also listed as submodules of the DscResources repository in the DscResources folder and the xDscResources folder.

How to Contribute

You are more than welcome to contribute to the development of the DSC Resource Kit! There are several different ways you can help. You can create new DSC resources or modules, add test automation, improve documentation, fix existing issues, or open new ones.
See our contributing guide for more info on how to become a DSC Resource Kit contributor.

If you would like to help, please take a look at the list of open issues for the DscResources repository.
You can also check issues for specific resource modules by going to:
https://github.com/PowerShell/< module name >/issues
For example:
https://github.com/PowerShell/xPSDesiredStateConfiguration/issues

Your help in developing the DSC Resource Kit is invaluable to us!

Questions, comments?

If you’re looking into using PowerShell DSC, have questions or issues with a current resource, or would like a new resource, let us know in the comments below, on Twitter (@PowerShell_Team), or by creating an issue on GitHub.

Katie Kragenbrink
Software Engineer
PowerShell DSC Team
@katiedsc (Twitter)
@kwirkykat (GitHub)

DSC Resource Kit Release January 2019

$
0
0

We just released the DSC Resource Kit!

This release includes updates to 14 DSC resource modules. In the past 6 weeks, 41 pull requests have been merged and 54 issues have been closed, all thanks to our amazing community!

The modules updated in this release are:

  • ActiveDirectoryCSDsc
  • AuditPolicyDsc
  • CertificateDsc
  • ComputerManagementDsc
  • NetworkingDsc
  • SecurityPolicyDsc
  • SqlServerDsc
  • StorageDsc
  • xActiveDirectory
  • xBitlocker
  • xExchange
  • xFailOverCluster
  • xHyper-V
  • xWebAdministration

Several of these modules were released to remove the hidden files/folders from this issue. This issue should now be fixed for all modules except DFSDsc which is waiting for some fixes to its tests.

For a detailed list of the resource modules and fixes in this release, see the Included in this Release section below.

Our latest community call for the DSC Resource Kit was today, January 9. A recording is available on YouTube here. Join us for the next call at 12PM (Pacific time) on February 13 to ask questions and give feedback about your experience with the DSC Resource Kit.

The next DSC Resource Kit release will be on Wednesday, February 20.

We strongly encourage you to update to the newest version of all modules using the PowerShell Gallery, and don’t forget to give us your feedback in the comments below, on GitHub, or on Twitter (@PowerShell_Team)!

Please see our documentation here for information on the support of these resource modules.

Included in this Release

You can see a detailed summary of all changes included in this release in the table below. For past release notes, go to the README.md or CHANGELOG.md file on the GitHub repository page for a specific module (see the How to Find DSC Resource Modules on GitHub section below for details on finding the GitHub page for a specific module).

Module Name Version Release Notes
ActiveDirectoryCSDsc 3.1.0.0
  • Updated LICENSE file to match the Microsoft Open Source Team standard.
  • Added .VSCode settings for applying DSC PSSA rules – fixes Issue 60.
  • Added fix for two tier PKI deployment fails on initial deployment, not error – fixes Issue 57.
AuditPolicyDsc 1.4.0.0
  • Explicitly removed extra hidden files from release package
CertificateDsc 4.3.0.0
  • Updated certificate import to only use Import-CertificateEx – fixes Issue 161
  • Update LICENSE file to match the Microsoft Open Source Team standard -fixes Issue 164.
  • Opted into Common Tests – fixes Issue 168:
    • Required Script Analyzer Rules
    • Flagged Script Analyzer Rules
    • New Error-Level Script Analyzer Rules
    • Custom Script Analyzer Rules
    • Validate Example Files To Be Published
    • Validate Markdown Links
    • Relative Path Length
  • CertificateExport:
    • Fixed bug causing PFX export with matchsource enabled to fail – fixes Issue 117
ComputerManagementDsc 6.1.0.0
  • Updated LICENSE file to match the Microsoft Open Source Team standard. Fixes Issue 197.
  • Explicitly removed extra hidden files from release package
NetworkingDsc 6.3.0.0
  • MSFT_IPAddress:
    • Updated to allow retaining existing addresses in order to support cluster configurations as well
SecurityPolicyDsc 2.7.0.0
  • Bug fix – Issue 83 – Network_access_Remotely_accessible_registry_paths_and_subpaths correctly applies multiple paths
  • Update LICENSE file to match the Microsoft Open Source Team standard
SqlServerDsc 12.2.0.0
  • Changes to SqlServerDsc
    • During testing in AppVeyor the Build Worker is restarted in the install step to make sure the are no residual changes left from a previous SQL Server install on the Build Worker done by the AppVeyor Team (issue 1260).
    • Code cleanup: Change parameter names of Connect-SQL to align with resources.
    • Updated README.md in the Examples folder.
      • Added a link to the new xADObjectPermissionEntry examples in ActiveDirectory, fixed a broken link and a typo. Adam Rush (@adamrushuk)
    • Change to SqlServerLogin so it doesn”t check properties for absent logins.
StorageDsc 4.4.0.0
  • Refactored module folder structure to move resource to root folder of repository and remove test harness – fixes Issue 169.
  • Updated Examples to support deployment to PowerShell Gallery scripts.
  • Removed limitation on using Pester 4.0.8 during AppVeyor CI.
  • Moved the Code of Conduct text out of the README.md and into a CODE_OF_CONDUCT.md file.
  • Explicitly removed extra hidden files from release package
xActiveDirectory 2.23.0.0
  • Explicitly removed extra hidden files from release package
xBitlocker 1.4.0.0
  • Change double quoted string literals to single quotes
  • Add spaces between array members
  • Add spaces between variable types and variable names
  • Add spaces between comment hashtag and comments
  • Explicitly removed extra hidden files from release package
xExchange 1.26.0.0
  • Add support for Exchange Server 2019
  • Added additional parameters to the MSFT_xExchUMService resource
  • Rename improperly named functions, and add comment based help in MSFT_xExchClientAccessServer, MSFT_xExchDatabaseAvailabilityGroupNetwork, MSFT_xExchEcpVirtualDirectory, MSFT_xExchExchangeCertificate, MSFT_xExchImapSettings.
  • Added additional parameters to the MSFT_xExchUMCallRouterSettings resource
  • Rename improper function names in MSFT_xExchDatabaseAvailabilityGroup, MSFT_xExchJetstress, MSFT_xExchJetstressCleanup, MSFT_xExchMailboxDatabase, MSFT_xExchMailboxDatabaseCopy, MSFT_xExchMailboxServer, MSFT_xExchMaintenanceMode, MSFT_xExchMapiVirtualDirectory, MSFT_xExchOabVirtualDirectory, MSFT_xExchOutlookAnywhere, MSFT_xExchOwaVirtualDirectory, MSFT_xExchPopSettings, MSFT_xExchPowershellVirtualDirectory, MSFT_xExchReceiveConnector, MSFT_xExchWaitForMailboxDatabase, and MSFT_xExchWebServicesVirtualDirectory.
  • Add remaining unit and integration tests for MSFT_xExchExchangeServer.
xFailOverCluster 1.12.0.0
  • Explicitly removed extra hidden files from release package
xHyper-V 3.15.0.0
  • Explicitly removed extra hidden files from release package
xWebAdministration 2.4.0.0
  • Explicitly removed extra hidden files from release package

How to Find Released DSC Resource Modules

To see a list of all released DSC Resource Kit modules, go to the PowerShell Gallery and display all modules tagged as DSCResourceKit. You can also enter a module’s name in the search box in the upper right corner of the PowerShell Gallery to find a specific module.

Of course, you can also always use PowerShellGet (available starting in WMF 5.0) to find modules with DSC Resources:

# To list all modules that tagged as DSCResourceKit
Find-Module -Tag DSCResourceKit 
# To list all DSC resources from all sources 
Find-DscResource

Please note only those modules released by the PowerShell Team are currently considered part of the ‘DSC Resource Kit’ regardless of the presence of the ‘DSC Resource Kit’ tag in the PowerShell Gallery.

To find a specific module, go directly to its URL on the PowerShell Gallery:
http://www.powershellgallery.com/packages/< module name >
For example:
http://www.powershellgallery.com/packages/xWebAdministration

How to Install DSC Resource Modules From the PowerShell Gallery

We recommend that you use PowerShellGet to install DSC resource modules:

Install-Module -Name < module name >

For example:

Install-Module -Name xWebAdministration

To update all previously installed modules at once, open an elevated PowerShell prompt and use this command:

Update-Module

After installing modules, you can discover all DSC resources available to your local system with this command:

Get-DscResource

How to Find DSC Resource Modules on GitHub

All resource modules in the DSC Resource Kit are available open-source on GitHub.
You can see the most recent state of a resource module by visiting its GitHub page at:
https://github.com/PowerShell/< module name >
For example, for the CertificateDsc module, go to:
https://github.com/PowerShell/CertificateDsc.

All DSC modules are also listed as submodules of the DscResources repository in the DscResources folder and the xDscResources folder.

How to Contribute

You are more than welcome to contribute to the development of the DSC Resource Kit! There are several different ways you can help. You can create new DSC resources or modules, add test automation, improve documentation, fix existing issues, or open new ones.
See our contributing guide for more info on how to become a DSC Resource Kit contributor.

If you would like to help, please take a look at the list of open issues for the DscResources repository.
You can also check issues for specific resource modules by going to:
https://github.com/PowerShell/< module name >/issues
For example:
https://github.com/PowerShell/xPSDesiredStateConfiguration/issues

Your help in developing the DSC Resource Kit is invaluable to us!

Questions, comments?

If you’re looking into using PowerShell DSC, have questions or issues with a current resource, or would like a new resource, let us know in the comments below, on Twitter (@PowerShell_Team), or by creating an issue on GitHub.

Katie Kragenbrink
Software Engineer
PowerShell DSC Team
@katiedsc (Twitter)
@kwirkykat (GitHub)

Windows Security change affecting PowerShell

$
0
0

Windows Security change affecting PowerShell

January 9, 2019

The recent (1/8/2019) Windows security patch CVE-2019-0543, has introduced a breaking change for a PowerShell remoting scenario. It is a narrowly scoped scenario that should have low impact for most users.

The breaking change only affects local loopback remoting, which is a PowerShell remote connection made back to the same machine, while using non-Administrator credentials.

PowerShell remoting endpoints do not allow access to non-Administrator accounts by default. However, it is possible to modify endpoint configurations, or create new custom endpoint configurations, that do allow non-Administrator account access. So you would not be affected by this change, unless you explicitly set up loopback endpoints on your machine to allow non-Administrator account access.

Example of broken loopback scenario

# Create endpoint that allows Users group access
PS > Register-PSSessionConfiguration -Name MyNonAdmin -SecurityDescriptorSddl 'O:NSG:BAD:P(A;;GA;;;BA)(A;;GA;;;BU)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)' -Force

# Create non-Admin credential
PS > $nonAdminCred = Get-Credential ~\NonAdminUser

# Create a loopback remote session to custom endpoint using non-Admin credential
PS > $session = New-PSSession -ComputerName localhost -ConfigurationName MyNonAdmin -Credential $nonAdminCred

New-PSSession : [localhost] Connecting to remote server localhost failed with the following error message : The WSMan
service could not launch a host process to process the given request.  Make sure the WSMan provider host server and
proxy are properly registered. For more information, see the about_Remote_Troubleshooting Help topic.
At line:1 char:1
+ New-PSSession -ComputerName localhost -ConfigurationName MyNonAdmin - ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [New-PSSession], PSRemotin
   gTransportException
    + FullyQualifiedErrorId : -2146959355,PSSessionOpenFailed

The above example fails only when using non-Administrator credentials, and the connection is made back to the same machine (localhost). Administrator credentials still work. And the above scenario will work when remoting off-box to another machine.

Example of working loopback scenario

# Create Admin credential
PS > $adminCred = Get-Credential ~\AdminUser

# Create a loopback remote session to custom endpoint using Admin credential
PS > $session = New-PSSession -ComputerName localhost -ConfigurationName MyNonAdmin -Credential $adminCred
PS > $session

 Id Name            ComputerName    ComputerType    State         ConfigurationName     Availability
 -- ----            ------------    ------------    -----         -----------------     ------------
  1 WinRM1          localhost       RemoteMachine   Opened        MyNonAdmin               Available

The above example uses Administrator credentials to the same MyNonAdmin custom endpoint, and the connection is made back to the same machine (localhost). The session is created successfully using Administrator credentials.

The breaking change is not in PowerShell but in a system security fix that restricts process creation between Windows sessions. This fix is preventing WinRM (which PowerShell uses as a remoting transport and host) from successfully creating the remote session host, for this particular scenario. There are no plans to update WinRM.

This affects Windows PowerShell and PowerShell Core 6 (PSCore6) WinRM based remoting.

This does not affect SSH remoting with PSCore6.

This does not affect JEA (Just Enough Administration) sessions.

A workaround for a loopback connection is to always use Administrator credentials.

Another option is to use PSCore6 with SSH remoting.

Paul Higinbotham
Senior Software Engineer
PowerShell Team


DSC Resource Kit Release February 2019

$
0
0

We just released the DSC Resource Kit!

This release includes updates to 14 DSC resource modules. In the past 6 weeks, 126 pull requests have been merged and 102 issues have been closed, all thanks to our amazing community!

The modules updated in this release are:

  • ActiveDirectoryCSDsc
  • CertificateDsc
  • ComputerManagementDsc
  • DFSDsc
  • NetworkingDsc
  • PSDscResources
  • SharePointDsc
  • SqlServerDsc
  • StorageDsc
  • xActiveDirectory
  • xExchange
  • xHyper-V
  • xPSDesiredStateConfiguration
  • xWebAdministration

For a detailed list of the resource modules and fixes in this release, see the Included in this Release section below.

Our latest community call for the DSC Resource Kit was last Wednesday, February 13. We were not able to record the call this time, apologies. We will fix this for the next call. You can join us for the next call at 12PM (Pacific time) on March 27 to ask questions and give feedback about your experience with the DSC Resource Kit.

The next DSC Resource Kit release will be on Wednesday, April 3.

We strongly encourage you to update to the newest version of all modules using the PowerShell Gallery, and don’t forget to give us your feedback in the comments below, on GitHub, or on Twitter (@PowerShell_Team)!

Please see our documentation here for information on the support of these resource modules.

Included in this Release

You can see a detailed summary of all changes included in this release in the table below. For past release notes, go to the README.md or CHANGELOG.md file on the GitHub repository page for a specific module (see the How to Find DSC Resource Modules on GitHub section below for details on finding the GitHub page for a specific module).

Module Name Version Release Notes
ActiveDirectoryCSDsc 3.2.0.0
  • Added “DscResourcesToExport” to manifest to improve information in PowerShell Gallery – fixes Issue 68.
  • Removed unused CAType variables and references in AdcsOnlineResponder – fixes issue 52.
  • Updated Examples to enable publising to PowerShell Gallery – fixes issue 54.
  • Cleaned up property alignment in module manifest file.
  • Added new resource AdcsOcspExtension – see Issue 70.
    • Added new ActiveDirectoryCSDsc.CommonHelper.psm1 helper module and unit test.
    • Added stub function to /Tests/TestHelpers (ADCSStub.psm1) so Pester tests can run without having to install ADCSAdministration module.
  • Converted module to auto-documentation Wiki – fixes Issue 53.
  • Enabled Example publishing to PSGallery.
  • Moved change log to CHANGELOG.MD.
  • Opted into Common Tests “Validate Example Files To Be Published”, “Validate Markdown Links” and “Relative Path Length”.
  • Correct AppVeyor Invoke-AppveyorAfterTestTask – fixes Issue 73.
CertificateDsc 4.4.0.0
  • Minor style corrections from PR for Issue 161 that were missed.
  • Opt-in to Example publishing to PowerShell Gallery – fixes Issue 177.
  • Changed Test-CertificateAuthority to return the template name if it finds the display name of the template in the certificate -fixes Issue 147.
ComputerManagementDsc 6.2.0.0
  • WindowsEventLog:
    • Migrated the xWinEventLog from xWinEventLog and renamed to WindowsEventLog.
    • Moved strings in localization file.
    • LogMode is now set with Limit-EventLog,
    • Fixes Issue 18.
DFSDsc 4.3.0.0
  • Fixes PSSA style violation issues resulting – fixes Issue 84.
  • Added “DscResourcesToExport” to manifest to improve information in PowerShell Gallery – fixes Issue 86.
  • Set FunctionsToExport, CmdletsToExport, VariablesToExport, AliasesToExport to empty list in manifest to meet best practice.
  • Explicitly removed extra hidden files from release package
NetworkingDsc 7.0.0.0
  • Refactored module folder structure to move resource to root folder of repository and remove test harness – fixes Issue 372.
  • Removed module conflict tests because only required for harness style modules.
  • Opted into Common Tests “Validate Example Files To Be Published”, “Validate Markdown Links” and “Relative Path Length”.
  • Added “DscResourcesToExport” to manifest to improve information in PowerShell Gallery and removed wildcards from “FunctionsToExport”, “CmdletsToExport”, “VariablesToExport” and “AliasesToExport” – fixes Issue 376.
  • MSFT_NetIPInterface:
    • Added Dhcp, WeakHostReceive and WeakHostSend parameters so that MSFT_DHCPClient, MSFT_WeakHostReceive, MSFT_WeakHostSend can be deprecated – fixes Issue 360.
  • MSFT_DhcpClient:
    • BREAKING CHANGE: Resource has been deprecated and replaced by Dhcp parameter in MSFT_NetIPInterface.
  • MSFT_WeakHostReceive:
    • BREAKING CHANGE: Resource has been deprecated and replaced by WeakHostReceive parameter in MSFT_NetIPInterface.
  • MSFT_WeakHostSend:
    • BREAKING CHANGE: Resource has been deprecated and replaced by WeakHostSend parameter in MSFT_NetIPInterface.
  • MSFT_IPAddress:
    • Updated examples to use NetIPInterface.
  • MSFT_NetAdapterName:
    • Updated examples to use NetIPInterface.
  • MSFT_DnsServerAddress:
    • Updated examples to use NetIPInterface.
  • MSFT_NetworkTeam:
    • Change Get-TargetResource to return actual TeamMembers if network team exists and “Ensure” returns “Present” even when actual TeamMembers do not match “TeamMembers” parameter – fixes Issue 342.
  • Updated examples to format required for publishing to PowerShell Gallery – fixes Issue 374.
  • MSFT_NetAdapterAdvancedProperty:
  • Fixes NetworkAdapterName being returned in Name property when calling Get-TargetResourceFixes – fixes Issue 370.
PSDscResources 2.10.0.0
  • Fixed CompanyName typo – Fixes Issue 100
  • Update LICENSE file to match the Microsoft Open Source Team standard – Fixes Issue 120.
  • Update CommonResourceHelper unit tests to meet Pester 4.0.0 standards (issue 129).
  • Update ResourceHelper unit tests to meet Pester 4.0.0 standards (issue 129).
  • Ported fixes from xPSDesiredStateConfiguration:
    • xArchive
      • Fix end-to-end tests.
      • Update integration tests to meet Pester 4.0.0 standards.
      • Update end-to-end tests to meet Pester 4.0.0 standards.
      • Update unit and integration tests to meet Pester 4.0.0 standards.
      • Wrapped all path and identifier strings in verbose messages with quotes to make it easier to identify the limit of the string when debugging.
      • Refactored date/time checksum code to improve testability and ensure tests can run on machines with localized datetime formats that are not US.
      • Fix “Get-ArchiveEntryLastWriteTime” to return [datetime].
      • Improved verbose logging to make debugging path issues easier.
  • Added .gitattributes file to ensure CRLF settings are configured correctly for the repository.
  • Updated “.vscode\settings.json” to refer to AnalyzerSettings.psd1 so that custom syntax problems are highlighted in Visual Studio Code.
  • Fixed style guideline violations in CommonResourceHelper.psm1.
  • Updated “appveyor.yml” to meet more recent standards.
  • Removed OS image version from “appveyor.yml” to use default image (Issue 127).
  • Removed code to install WMF5.1 from “appveyor.yml” because it is already installed in AppVeyor images (Issue 128).
  • Removed .vscode from .gitignore so that Visual Studio code environment settings can be committed.
  • Environment
    • Update tests to meet Pester 4.0.0 standards (issue 129).
  • Group
    • Update tests to meet Pester 4.0.0 standards (issue 129).
    • Fix unit tests to run on Nano Server.
    • Refactored unit tests to enclude Context fixtures and change functions to Describe fixtures.
  • GroupSet
    • Update tests to meet Pester 4.0.0 standards (issue 129).
SharePointDsc 3.2.0.0
  • Changes to SharePointDsc unit testing
    • Implemented Strict Mode version 1 for all code run during unit tests.
    • Changed InstallAccount into PSDscRunAsCredential parameter in examples
  • SPAuthenticationRealm
    • New resource for setting farm authentication realm
  • SPConfigWizard
    • Updated PSConfig parameters according recommendations in blog post of Stefan Gossner
  • SPDistributedCacheService
    • Fixed exception on Stop-SPServiceInstance with SharePoint 2019
  • SPFarm
    • Improved logging
    • Added ability to manage the Developer Dashboard settings
  • SPFarmSolution
    • Fixed issue where uninstalling a solution would not work as expected if it contained web application resources.
  • SPIncomingEmailSettings
    • New resource for configuring incoming email settings
  • SPInstallPrereqs
    • Improved logging
    • Corrected detection for Windows Server 2019
    • Corrected support for Windows Server 2019 for SharePoint 2016
  • SPProductUpgrade
    • Fixed issue where upgrading SP2013 would not properly detect the installed version
    • Fixed issue where the localized SharePoint 2019 CU was detected as a Service Pack for a Language Pack
  • SPSearchAuthorativePage
    • Fixed issue where modifying search query would not target the correct search application
  • SPSearchResultSource
    • Updated resource to allow localized ProviderTypes
  • SPServiceAppSecurity
    • Updated resource to allow localized permission levels
  • SPServiceInstance
    • Added -All switch to resolve ‘Unable to locate service application’ in SP2013
  • SPSite
    • Improved logging
  • SPUserProfileProperty
    • Fix user profile property mappings does not work
  • SPUserProfileServiceApp
    • Added warning message when MySiteHostLocation is not specified. This is currently not required, which results in an error. Will be corrected in SPDsc v4.0 (is a breaking change).
  • SPUserProfileSyncConnection
    • Fixed issue where test resource never would return true for any configurations on SharePoint 2016/2019
    • Fixed issue where updating existing connection never would work for any configurations on SharePoint 2016/2019
    • Updated documentation to reflect that Fore will not impact configurations for SharePoint 2016/2019. Updated the test method accordingly.
  • SPUserProfileSyncService
    • Fixed issue where failure to configure the sync service would not throw error
  • SPWebAppPeoplePickerSettings
    • Converted password for access account to secure string. Previsouly the resource would fail setting the password and an exeption was thrown that printed the password in clear text.
  • SPWebAppPolicy
    • Fixed issue where parameter MembersToExclude did not work as expected
  • SPWorkflowService
    • Added support for specifying scope name.
    • Added support for detecting incorrect configuration for scope name and WorkflowHostUri
SqlServerDsc 12.3.0.0
  • Changes to SqlServerDsc
    • Reverting the change that was made as part of the issue 1260 in the previous release, as it only mitigated the issue, it did not solve the issue.
    • Removed the container testing since that broke the integration tests, possible due to using excessive amount of memory on the AppVeyor build worker. This will make the unit tests to take a bit longer to run (issue 1260).
    • The unit tests and the integration tests are now run in two separate build workers in AppVeyor. One build worker runs the integration tests, while a second build worker runs the unit tests. The build workers runs in parallel on paid accounts, but sequentially on free accounts (issue 1260).
    • Clean up error handling in some of the integration tests that was part of a workaround for a bug in Pester. The bug is resolved, and the error handling is not again built into Pester.
    • Speeding up the AppVeyor tests by splitting the common tests in a separate build job.
    • Updated the appveyor.yml to have the correct build step, and also correct run the build step only in one of the jobs.
    • Update integration tests to use the new integration test template.
    • Added SqlAgentOperator resource.
  • Changes to SqlServiceAccount
    • Fixed Get-ServiceObject when searching for Integration Services service. Unlike the rest of SQL Server services, the Integration Services service cannot be instanced, however you can have multiple versions installed. Get-Service object would return the correct service name that you are looking for, but it appends the version number at the end. Added parameter VersionNumber so the search would return the correct service name.
    • Added code to allow for using Managed Service Accounts.
    • Now the correct service type string value is returned by the function Get-TargetResource. Previously one value was passed in as a parameter (e.g. DatabaseEngine), but a different string value as returned (e.g. SqlServer). Now Get-TargetResource return the same values that can be passed as values in the parameter ServiceType (issue 981).
  • Changes to SqlServerLogin
    • Fixed issue in Test-TargetResource to valid password on disabled accounts (issue 915).
    • Now when adding a login of type SqlLogin, and the SQL Server login mode is set to "Integrated", an error is correctly thrown (issue 1179).
  • Changes to SqlSetup
    • Updated the integration test to stop the named instance while installing the other instances to mitigate issue 1260.
    • Add parameters to configure the Tempdb files during the installation of the instance. The new parameters are SqlTempdbFileCount, SqlTempdbFileSize, SqlTempdbFileGrowth, SqlTempdbLogFileSize and SqlTempdbLogFileGrowth (issue 1167).
  • Changes to SqlServerEndpoint
StorageDsc 4.5.0.0
  • Opt-in to Example publishing to PowerShell Gallery – fixes Issue 186.
  • DiskAccessPath:
    • Updated the resource to not assign a drive letter by default when adding a disk access path. Adding a Set-Partition -NoDefaultDriveLetter $NoDefaultDriveLetter block defaulting to true. When adding access paths the disks will no longer have drive letters automatically assigned on next reboot which is the desired behavior – Fixes Issue 145.
xActiveDirectory 2.24.0.0
  • Added parameter to xADDomainController to support InstallationMediaPath (issue 108).
  • Updated xADDomainController schema to be standard and provide Descriptions.
xExchange 1.27.0.0
  • Added additional parameters to the MSFT_xExchTransportService resource
  • Added additional parameters to the MSFT_xExchEcpVirtualDirectory resource
  • Added additional unit tests to the MSFT_xExchAutodiscoverVirutalDirectory resource
  • Added additional parameters to the MSFT_xExchExchangeCertificate resource
  • MSFT_xExchMailboxDatabase: Fixes issue with DataMoveReplicationConstraint parameter (401)
  • Added additional parameters and comment based help to the MSFT_xExchMailboxDatabase resource
  • Move code that sets $global:DSCMachineStatus into a dedicated helper function. Issue 407
  • Add missing parameters for xExchMailboxDatabaseCopy, adds comment based help, and adds remaining Unit tests.
xHyper-V 3.16.0.0
  • MSFT_xVMHyperV:
    • Moved localization string data to own file.
    • Fixed code styling issues.
    • Fixed bug where StartupMemory was not evaluated in Test-TargetResource.
    • Redo of abandoned PRs:
    • Fixed Get throws error when NetworkAdapters are not attached or missing properties.
xPSDesiredStateConfiguration 8.5.0.0
  • Pull server module publishing
    • Removed forced verbose logging from CreateZipFromSource, Publish-DSCModulesAndMof and Publish-MOFToPullServer as it polluted the console
  • Corrected GitHub Pull Request template to remove referral to BestPractices.MD which has been combined into StyleGuidelines.md (issue 520).
  • xWindowsOptionalFeature
    • Suppress useless verbose output from Import-Module cmdlet. (issue 453).
  • Changes to xRemoteFile
    • Corrected a resource name in the example xRemoteFile_DownloadFileConfig.ps1
  • Fix MSFT_xDSCWebService to find Microsoft.Powershell.DesiredStateConfiguration.Service.Resources.dll when server is configured with pt-BR Locales (issue 284).
  • Changes to xDSCWebService
    • Fixed an issue which prevented the removal of the IIS Application Pool created during deployment of an DSC Pull Server instance. (issue 464)
    • Fixed an issue where a Pull Server cannot be deployed on a machine when IIS Express is installed aside a full blown IIS (issue 191)
  • Update CommonResourceHelper unit tests to meet Pester 4.0.0 standards (issue 473).
  • Update ResourceHelper unit tests to meet Pester 4.0.0 standards (issue 473).
  • Update MSFT_xDSCWebService unit tests to meet Pester 4.0.0 standards (issue 473).
  • Update MSFT_xDSCWebService integration tests to meet Pester 4.0.0 standards (issue 473).
  • Refactored MSFT_xDSCWebService integration tests to meet current standards and to use Pester TestDrive.
  • xArchive
    • Fix end-to-end tests (issue 457).
    • Update integration tests to meet Pester 4.0.0 standards.
    • Update end-to-end tests to meet Pester 4.0.0 standards.
    • Update unit and integration tests to meet Pester 4.0.0 standards.
    • Wrapped all path and identifier strings in verbose messages with quotes to make it easier to identify the limit of the string when debugging.
    • Refactored date/time checksum code to improve testability and ensure tests can run on machines with localized datetime formats that are not US.
    • Fix “Get-ArchiveEntryLastWriteTime” to return [datetime] (issue 471).
    • Improved verbose logging to make debugging path issues easier.
    • Added handling for “/” as a path seperator by backporting code from PSDscResources – (issue 469).
    • Copied unit tests from PSDscResources.
    • Added .gitattributes file and removed git configuration from AppVeyor to ensure CRLF settings are configured correctly for the repository.
  • Updated “.vscode\settings.json” to refer to AnalyzerSettings.psd1 so that custom syntax problems are highlighted in Visual Studio Code.
  • Fixed style guideline violations in CommonResourceHelper.psm1.
  • Changes to xService
    • Fixes issue where Get-TargetResource or Test-TargetResource will throw an exception if the target service is configured with a non-existent dependency.
    • Refactored Get-TargetResource Unit tests.
  • Changes to xPackage
    • Fixes an issue where incorrect verbose output was displayed if product found. (issue 446)
  • Fixes files which are getting triggered for re-encoding after recent pull request (possibly 472).
  • Moves version and change history from README.MD to new file, CHANGELOG.MD.
  • Fixes markdown issues in README.MD and HighQualityResourceModulePlan.md.
  • Opted in to “Common Tests – Validate Markdown Files”
  • Changes to xPSDesiredStateConfiguration
    • In AppVeyor CI the tests are split into three separate jobs, and also run tests on two different build worker images (Windows Server 2012R2 and Windows Server 2016). The common tests are only run on the Windows Server 2016 build worker image. Helps with issue 477.
  • xGroup
    • Corrected style guideline violations. (issue 485)
  • xWindowsProcess
    • Corrected style guideline violations. (issue 496)
  • Changes to PSWSIISEndpoint.psm1
    • Fixes most PSScriptAnalyzer issues.
  • Changes to xRegistry
    • Fixed an issue that fails to remove reg key when the Key is specified as common registry path. (issue 444)
  • Changes to xService
    • Added support for Group Managed Service Accounts
  • Adds new Integration tests for MSFT_xDSCWebService and removes old Integration test file, MSFT_xDSCWebService.xxx.ps1.
  • xRegistry
    • Corrected style guideline violations. (issue 489)
  • Fix script analyzer issues in UseSecurityBestPractices.psm1. issue 483
  • Fixes script analyzer issues in xEnvironmentResource. issue 484
  • Fixes script analyzer issues in MSFT_xMsiPackage.psm1. issue 486
  • Fixes script analyzer issues in MSFT_xPackageResource.psm1. issue 487
  • Adds spaces between variable types and variables, and changes Type Accelerators to Fully Qualified Type Names on affected code.
  • Fixes script analyzer issues in MSFT_xPSSessionConfiguration.psm1 and convert Type Accelerators to Fully Qualified Type Names issue 488.
  • Adds spaces between array members.
  • Fixes script analyzer issues in MSFT_xRemoteFile.psm1 and correct general style violations. (issue 490)
  • Remove unnecessary whitespace from line endings.
  • Add statement to README.md regarding the lack of testing of this module with PowerShell 4 issue 522.
  • Fixes script analyzer issues in MSFT_xWindowsOptionalFeature.psm1 and correct general style violations. issue 494)
  • Fixes script analyzer issues in MSFT_xRemoteFile.psm1 missed from issue 490.
  • Fix script analyzer issues in MSFT_xWindowsFeature.psm1. issue 493
  • Fix script analyzer issues in MSFT_xUserResource.psm1. issue 492
  • Moves calls to set $global:DSCMachineStatus = 1 into a helper function to reduce the number of locations where we need to suppress PSScriptAnalyzer rules PSAvoidGlobalVars and PSUseDeclaredVarsMoreThanAssignments.
  • Adds spaces between comment hashtags and comments.
  • Fixes script analyzer issues in MSFT_xServiceResource.psm1. issue 491
  • Fixes script analyzer issues in MSFT_xWindowsPackageCab.psm1. issue 495
  • xFileUpload:
    • Fixes script analyzer issues in xFileUpload.schema.psm1. issue 497
    • Update to meet style guidelines.
    • Added Integration tests.
    • Updated manifest Author, Company and Copyright to match standards.
  • Updated module manifest Copyright to match standards and remove year.
  • Auto-formatted the module manifest to improve layout.
  • Fix Run-On Words in README.md.
  • Changes to xPackage
    • Fix an misnamed variable that causes an error during error message output. issue 449)
  • Fixes script analyzer issues in MSFT_xPSSessionConfiguration.psm1. issue 566
  • Fixes script analyzer issues in xGroupSet.schema.psm1. issue 498
  • Fixes script analyzer issues in xProcessSet.schema.psm1. issue 499
  • Fixes script analyzer issues in xServiceSet.schema.psm1. issue 500
  • Fixes script analyzer issues in xWindowsFeatureSet.schema.psm1. issue 501
  • Fixes script analyzer issues in xWindowsOptionalFeatureSet.schema.psm1 issue 502
  • Updates Should statements in Pester tests to use dashes before parameters.
  • Added a CODE_OF_CONDUCT.md with the same content as in the README.md issue 562
  • Replaces Type Accelerators with fully qualified type names.
xWebAdministration 2.5.0.0
  • Added SiteId to xWebSite to address [396]
  • xWebSite: Full path is used to get list of default documents
  • xIISLogging: Added support for LogTargetW3C
  • xWebsite: Added support for LogTargetW3C

How to Find Released DSC Resource Modules

To see a list of all released DSC Resource Kit modules, go to the PowerShell Gallery and display all modules tagged as DSCResourceKit. You can also enter a module’s name in the search box in the upper right corner of the PowerShell Gallery to find a specific module.

Of course, you can also always use PowerShellGet (available starting in WMF 5.0) to find modules with DSC Resources:

# To list all modules that tagged as DSCResourceKit
Find-Module -Tag DSCResourceKit 
# To list all DSC resources from all sources 
Find-DscResource

 

Please note only those modules released by the PowerShell Team are currently considered part of the ‘DSC Resource Kit’ regardless of the presence of the ‘DSC Resource Kit’ tag in the PowerShell Gallery.

To find a specific module, go directly to its URL on the PowerShell Gallery:
http://www.powershellgallery.com/packages/< module name >
For example:
http://www.powershellgallery.com/packages/xWebAdministration

How to Install DSC Resource Modules From the PowerShell Gallery

We recommend that you use PowerShellGet to install DSC resource modules:

Install-Module -Name < module name >

 

For example:

Install-Module -Name xWebAdministration

 

To update all previously installed modules at once, open an elevated PowerShell prompt and use this command:

Update-Module

 

After installing modules, you can discover all DSC resources available to your local system with this command:

Get-DscResource

 

How to Find DSC Resource Modules on GitHub

All resource modules in the DSC Resource Kit are available open-source on GitHub.
You can see the most recent state of a resource module by visiting its GitHub page at:
https://github.com/PowerShell/< module name >
For example, for the CertificateDsc module, go to:
https://github.com/PowerShell/CertificateDsc.

All DSC modules are also listed as submodules of the DscResources repository in the DscResources folder and the xDscResources folder.

How to Contribute

You are more than welcome to contribute to the development of the DSC Resource Kit! There are several different ways you can help. You can create new DSC resources or modules, add test automation, improve documentation, fix existing issues, or open new ones.
See our contributing guide for more info on how to become a DSC Resource Kit contributor.

If you would like to help, please take a look at the list of open issues for the DscResources repository.
You can also check issues for specific resource modules by going to:
https://github.com/PowerShell/< module name >/issues
For example:
https://github.com/PowerShell/xPSDesiredStateConfiguration/issues

Your help in developing the DSC Resource Kit is invaluable to us!

Questions, comments?

If you’re looking into using PowerShell DSC, have questions or issues with a current resource, or would like a new resource, let us know in the comments below, on Twitter (@PowerShell_Team), or by creating an issue on GitHub.

Katie Kragenbrink
Software Engineer
PowerShell DSC Team
@katiedsc (Twitter)
@kwirkykat (GitHub)

The post DSC Resource Kit Release February 2019 appeared first on PowerShell.

Generating PowerShell Cmdlets from OpenAPI/Swagger with AutoRest

$
0
0

Today, we’re announcing beta support for PowerShell in AutoRest, so that you can now generate PowerShell modules from Swagger/OpenAPI JSON documents.

AutoRest is the SDK generation tool that we use in Azure to produce SDKS for 90+ management services across 7+ languages.
Its pluggable architecture allows fine-grained control over the generation process, and allows extensions to be written in any language that can read/write JSON via stdin/stdout (we use the JSON-RPC protocol that Visual Studio Code uses )

Along the way, we had to go back and make some updates to the core of AutoRest (to begin support of OpenAPI 3, and introduce some changes to support generating multiple API versions with Azure Profiles.)

Getting Started

Requirements

Use of the beta version of autorest.powershell requires the following:

  • Node.js LTS (10.15.x LTS preferred. Will not function with a Node version less than 10.x. Be wary of 11.x builds as they may introduce instability or breaking changes. )

If you want an easy way to install and update Node, I recommend NVS – Node Version Switcher or NVM – Node Version Manager

Using AutoRest Powershell

At a bare minimum, you can generate a PowerShell module using a Swagger or OpenAPI file and using --powershell.

The output will be in the ./generated folder by default:

autorest --powershell --input-file:<path-to-swagger-file> [...options]

Be sure to check out these additional samples that use the PowerShell generator.

Features

Modules work on both Windows PowerShell and PowerShell

Due to the use of netstandard2.0 and PowerShellStandard.Library, once compiled, the cmdlets work on both Windows PowerShell 5.1 and PowerShell 6.x. PowerShell 6.x is required during development.

Generates modules from OpenAPI files without any external dependencies

Most language SDKs generated with AutoRest required the use of at least a ‘client runtime’ package, and often pulls in a few other libraries (ie, JSON.NET) that are required to compile the output of the generator.

The new PowerShell generator creates modules that require no dependencies outside of netstandard2.0 and the PowerShellStandard.Library which drastically reduces the chances of having assembly loading conflicts.

Cmdlets have no weird base-classes or force hierarchy

All the generated cmdlets inherit PSCmdlet and are fairly straightforward. For ARM resources, we already support generating -AsJob support for long-running-operations, and this can be expanded in the future to support more patterns.

An incredible number of extensibility points

After generation of a module, the developer may wish to augment the module in many ways (custom work when the module loads, changing the HTTP pipeline, adding additional variants of cmdlets, and more). The generated cmdlets offer number of ways to be customized and enhanced, and we’ll be posting some documentation on how to do that in the near future.

Many variants of cmdlets are created to offer several ParameterSets

Behind-the-scenes, many different flavors of a cmdlet can get created, and these are tied together into a single cmdlet with multiple parameter sets. These can be joined with manually written cmdlets that are written in .ps1scripts or C# classes.

No reflection for serialization

The generated module has custom-created JSON serialization (using an embedded copy of Carbon.JSON) This significantly improves serialization performance.

FAQs

What happened to ‘PSSwagger’?

In order to get to the point where we can generate the Az modules for all the Azure management services, we needed more control in the fine-grained details of the resulting cmdlets. After consulting with the PowerShell team, the decision was made to integrate more closely with the existing mechanism for generating Azure SDKs (AutoRest) and build a full-featured generator extension to create PowerShell cmdlets. All future work to generate cmdlets be done in the AutoRest PowerShell generator, as we’ve discontinued work on PSSwagger.

Source code?

Of course! You probably should get started with the by reading the developer documentation.

Are there any PowerShell specific generation options?

Yes! You can modify the entire output folder layout, and tweak the way it generates cmdlets, including cmdlet names, parameters, etc. (Check out our additional documentation on these options). If you have feedback about these code generation options, feel free to post an issue on the AutoRest GitHub repo.

Known Issues

As with all beta software, there are bound to be a few glitches or things that are not working.

We’ve cataloged some known issues with this first beta we encourage you to read before reporting any issues you experience.

Support

We’re working as fast as we can to finish up the generator, as we have a lot of modules to generate internally.

I should also have deeper design documentation over the next month or two, explaining a bit more of the “why-does-it-work-this-way?” category.

General feedback can be left in the PowerShell Generator thread in the github repo.

If you run into problems, feel free to post an issue on the github repo and tag it with the powershell label, and we’ll try to take a look.

Quick Links

The post Generating PowerShell Cmdlets from OpenAPI/Swagger with AutoRest appeared first on PowerShell.

Invoke-Sqlcmd is Now Available Supporting Cross-Platform

$
0
0

The official SqlServer module now includes a version of the Invoke-Sqlcmd cmdlet that runs in PSCore 6.2 and above. The version of the SqlServer module which contains this cmdlet is 21.1.18095-preview and is available in the PowerShell Gallery. In order to install this preview version of the module, you must run Install-Module (or Update-Module if you already have it installed) with the -AllowPrerelease. (Without that parameter you will receive the previous version of the module.)

Install-Module -Name SqlServer -AllowPrerelease

Why is Invoke-Sqlcmd Important

Invoke-Sqlcmd is probably the most crucial cmdlet in the SQL PowerShell space because of its broad capabilities. This cmdlet has a large number of parameters and can serve as a bridge when cmdlets are not yet available.

For example, the Backup-SqlDatabase is already available in PSCore. However as of this writing, the Restore-SqlDatabase cmdlet is not yet available. Without the Invoke-Sqlcmd cmdlet, you would either have to exit PowerShell, or rely on borderline-cryptic SMO code in order to restore your database. That is not a good situation to be in if you’re striving for consistency in your environment.

However, with the Invoke-Sqlcmd cmdlet’s ability to run any valid T-SQL command, you can bridge the gap of the missing Restore-SqlDatabase cmdlet by passing in a RESTORE DATABASE command in the -Query parameter of Invoke-Sqlcmd.

What is Invoke-Sqlcmd

If you don’t spend you working life in the SQL Server world, or you’re just new to SQL Server, you might not even know what Invoke-Sqlcmd is in the first place.

From the Help file: “The Invoke-Sqlcmd cmdlet runs a script containing the languages and commands supported by the SQL Server SQLCMD utility.” In other words, you’re getting a lot of PowerShell object-goodness, but it’s really being handed over to the database engine by a much older, very stable, utility.

What Can You Do With Invoke-Sqlcmd

Since Invoke-Sqlcmd has already been around for over a decade, there are already many examples for how you can leverage Invoke-Sqlcmd. However, one of the most important things to know about Invoke-Sqlcmd is that you can output the rows of data that are returned as a single object, in the form of a .Net DataTable. This allows for high speed transfer of data between servers when combined with the Write-SqlTableData cmdlet. Just add the -OutputAs parameter and specify DataTables.

As just one example, consider the situation where you want to collect information about the amount of disk space used by each data file across all of your databases on ServerA, but you want to store that information on Server B. The example below shows you how easy it is to pipe all of the rows from the query and pipe them directly into a table on ServerB.

Invoke-Sqlcmd -ServerInstance ServerA -DatabaseName master -OutputAs DataTables -Query "
SELECT @@ServerName AS 'ServerName'
            , DB_NAME(dbid) AS 'DatabaseName'
            , name AS 'LogicalName'
            , GETDATE() AS 'CheckDate'
            , CONVERT(BIGINT, size) * 8 AS 'SizeInKB'
            , filename AS 'DBFileName'
            , SYSDATETIMEOFFSET() 'DiscoveryOccured'
  FROM master..sysaltfiles
 WHERE dbid != 32767" |
Write-SqlTableData -ServerInstance ServerB -DatabaseName BlankDB -SchemaName dbo -TableName DatabaseSizeHistory -Force;

Again, since Invoke-Sqlcmd is outputting a .Net DataTable this allows the Write-SqlTableData cmdlet to write the rows at high speed using the SqlBulkCopy method. Also of note: By using the -Force parameter, it the table doesn’t exist yet, the Write-SqlTableData cmdlet will create it for you.

Multi-Server Operations

While the above code is certainly very useful for anyone who works with SQL Server, it gets even better. One of the other updates in v21.1.18095-preview of the SqlServer module is that Registered Server / CMS are now available in the SQL Provider in PSCore.

dir 'SQLSERVER:\SQLRegistration\Database Engine Server Group' -Recurse

Mode Name
---- ----
-    localhost\SQL2016
-    localhost\SQL2017
-    ServerA
-    ServerB

When you combine the SQLRegistrations with Invoke-Sqlcmd or any other cmdlet that accepts a -ServerInstance parameter, you very easily multiply what you’re doing across many instances and/or databases.

In the example below, by getting making a call to the SQLRegistration provider, you get back a list of all the SQL Server Instances you have added to your Registered Servers. You can then pipe this list to foreach and provide the name of the instance to the -ServerInstance parameter of the Invoke-Sqlcmd cmdlet in the form of a pipeline property $_.Name. However, since we want all results written back to a single table, we don’t pass that pipeline property to Write-SqlTableData cmdlet, and instead provide it with a fixed SQL Server Instance to write to.

dir 'SQLSERVER:\SQLRegistration\Database Engine Server Group' -Recurse |
WHERE {$_.Mode -ne 'd' } |
    foreach {
    Invoke-Sqlcmd -ServerInstance $_.Name -Database master -OutputAs DataTables -Query "
    SELECT @@ServerName AS 'ServerName',
           DB_NAME(dbid) AS 'DatabaseName',
           name AS 'LogicalName',
           GETDATE() AS 'CheckDate',
           CONVERT(BIGINT, size) * 8 AS 'SizeInKB',
           filename AS 'DBFileName',
           SYSDATETIMEOFFSET() 'DiscoveryOccured'
      FROM master..sysaltfiles
     WHERE dbid != 32767" |
    Write-SqlTableData -ServerInstance ServerB -DatabaseName BlankDB -SchemaName dbo -TableName DatabaseSizeHistory -Force;
    }

You can leverage this capability to do a lot of other tasks as well. Deploying code, collecting error log information, auditing your database user security, and searching your SQL Servers for object references are just a few examples.

Please Report Issues

You will probably find issues with the Invoke-Sqlcmd cmdlet in PSCore. Please report them by commenting on the PowerShell Gallery page for the SqlServer module.

The SQL Server Tools Team has automated test scripts that they run every time they make a change to the code base. However, since the Invoke-Sqlcmd cmdlet is being opened up to a completely new user base, it’s understandable that they are probably still building new test cases.

If you do find issues, please report them by commenting on the PowerShell Gallery page for the SqlServer module. Include as much of the code and error message as you can, but be sure to remove any sensitive information. Please make sure to use an account tied to a real email address so that you can be notified when the SQL Server Tools Team replies to your comment.

If the SQL Server Tools Team is able to reproduce the issue you reported, they may ask you to open an item on aka.ms/sqlfeedback. This will help them keep track of the issue and allow others customers who are running into the same issue to provide their feedback as well.

Additional Information:

Installing the PSCore Preview on Your OS

For instructions on how to install the preview version of PowerShell on your OS, see the official documentation.

Capabilities of Invoke-Sqlcmd on PSCore 6.2

The initial release of the Invoke-Sqlcmd cmdlet in PSCore does not include all of the parameters and capabilities of the Invoke-Sqlcmd cmdlet in Windows PowerShell. Specifically “-Variable-DisableVariables-DisableCommand-QueryTimeout-ConnectionTimeout-Hostname not supported yet.”

The 58 cmdlets Currently Available

While the SqlServer module currently has 106 cmdlets available in Windows PowerShell, only 58 of those 106 are available in PSCore. In the interests of making the current capabilities of the SqlServer module on PSCore more widely known, a full list of 58 current cmdlets is included below.

Get-Command -Module SqlServer -CommandType Cmdlet

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Cmdlet          Add-SqlAvailabilityDatabase                        21.1.18095 SqlServer
Cmdlet          Add-SqlAvailabilityGroupListenerStaticIp           21.1.18095 SqlServer
Cmdlet          Add-SqlColumnEncryptionKeyValue                    21.1.18095 SqlServer
Cmdlet          Add-SqlLogin                                       21.1.18095 SqlServer
Cmdlet          Backup-SqlDatabase                                 21.1.18095 SqlServer
Cmdlet          Convert-UrnToPath                                  21.1.18095 SqlServer
Cmdlet          ConvertFrom-EncodedSqlName                         21.1.18095 SqlServer
Cmdlet          ConvertTo-EncodedSqlName                           21.1.18095 SqlServer
Cmdlet          Get-SqlAgent                                       21.1.18095 SqlServer
Cmdlet          Get-SqlAgentJob                                    21.1.18095 SqlServer
Cmdlet          Get-SqlAgentJobHistory                             21.1.18095 SqlServer
Cmdlet          Get-SqlAgentJobSchedule                            21.1.18095 SqlServer
Cmdlet          Get-SqlAgentJobStep                                21.1.18095 SqlServer
Cmdlet          Get-SqlAgentSchedule                               21.1.18095 SqlServer
Cmdlet          Get-SqlBackupHistory                               21.1.18095 SqlServer
Cmdlet          Get-SqlColumnEncryptionKey                         21.1.18095 SqlServer
Cmdlet          Get-SqlColumnMasterKey                             21.1.18095 SqlServer
Cmdlet          Get-SqlCredential                                  21.1.18095 SqlServer
Cmdlet          Get-SqlDatabase                                    21.1.18095 SqlServer
Cmdlet          Get-SqlErrorLog                                    21.1.18095 SqlServer
Cmdlet          Get-SqlInstance                                    21.1.18095 SqlServer
Cmdlet          Get-SqlLogin                                       21.1.18095 SqlServer
Cmdlet          Get-SqlSmartAdmin                                  21.1.18095 SqlServer
Cmdlet          Grant-SqlAvailabilityGroupCreateAnyDatabase        21.1.18095 SqlServer
Cmdlet          Invoke-Sqlcmd                                      21.1.18095 SqlServer
Cmdlet          Join-SqlAvailabilityGroup                          21.1.18095 SqlServer
Cmdlet          New-SqlAvailabilityGroup                           21.1.18095 SqlServer
Cmdlet          New-SqlAvailabilityGroupListener                   21.1.18095 SqlServer
Cmdlet          New-SqlAvailabilityReplica                         21.1.18095 SqlServer
Cmdlet          New-SqlBackupEncryptionOption                      21.1.18095 SqlServer
Cmdlet          New-SqlCngColumnMasterKeySettings                  21.1.18095 SqlServer
Cmdlet          New-SqlColumnMasterKey                             21.1.18095 SqlServer
Cmdlet          New-SqlCredential                                  21.1.18095 SqlServer
Cmdlet          New-SqlCspColumnMasterKeySettings                  21.1.18095 SqlServer
Cmdlet          New-SqlHADREndpoint                                21.1.18095 SqlServer
Cmdlet          Read-SqlTableData                                  21.1.18095 SqlServer
Cmdlet          Read-SqlViewData                                   21.1.18095 SqlServer
Cmdlet          Remove-SqlAvailabilityDatabase                     21.1.18095 SqlServer
Cmdlet          Remove-SqlAvailabilityGroup                        21.1.18095 SqlServer
Cmdlet          Remove-SqlAvailabilityReplica                      21.1.18095 SqlServer
Cmdlet          Remove-SqlColumnEncryptionKey                      21.1.18095 SqlServer
Cmdlet          Remove-SqlColumnEncryptionKeyValue                 21.1.18095 SqlServer
Cmdlet          Remove-SqlColumnMasterKey                          21.1.18095 SqlServer
Cmdlet          Remove-SqlCredential                               21.1.18095 SqlServer
Cmdlet          Remove-SqlLogin                                    21.1.18095 SqlServer
Cmdlet          Resume-SqlAvailabilityDatabase                     21.1.18095 SqlServer
Cmdlet          Revoke-SqlAvailabilityGroupCreateAnyDatabase       21.1.18095 SqlServer
Cmdlet          Set-SqlAvailabilityGroup                           21.1.18095 SqlServer
Cmdlet          Set-SqlAvailabilityGroupListener                   21.1.18095 SqlServer
Cmdlet          Set-SqlAvailabilityReplica                         21.1.18095 SqlServer
Cmdlet          Set-SqlAvailabilityReplicaRoleToSecondary          21.1.18095 SqlServer
Cmdlet          Set-SqlCredential                                  21.1.18095 SqlServer
Cmdlet          Set-SqlErrorLog                                    21.1.18095 SqlServer
Cmdlet          Set-SqlHADREndpoint                                21.1.18095 SqlServer
Cmdlet          Set-SqlSmartAdmin                                  21.1.18095 SqlServer
Cmdlet          Suspend-SqlAvailabilityDatabase                    21.1.18095 SqlServer
Cmdlet          Switch-SqlAvailabilityGroup                        21.1.18095 SqlServer
Cmdlet          Write-SqlTableData                                 21.1.18095 SqlServer

Aaron Nelson ( blog | twitter ) is a Microsoft MVP for SQL Server (Data Platform) and leads the PowerShell Virtual Chapters of PASS, and volunteers for the local PASS Chapter AtlantaMDF, and helps organize SQL Saturday events in Atlanta. The PowerShell VC of PASS hosts monthly sessions on SQL Server and PowerShell, and you can find the recordings of those sessions on their YouTube channel.

The post Invoke-Sqlcmd is Now Available Supporting Cross-Platform appeared first on PowerShell.

The PowerShell Extension is now in the Azure Data Studio Marketplace

$
0
0

We are excited to announce the PowerShell Extension is available in the Azure Data Studio (ADS)
marketplace!
Now you can write PowerShell scripts with the full benefits of PowerShell Editor Services
using the excellent IDE-like interface that Azure Data Studio provides.

Key Features this Brings to PowerShell Editing in Azure Data Studio

  • Syntax highlighting
  • Code snippets
  • IntelliSense for cmdlets and more
  • Rule-based analysis provided by PowerShell Script Analyzer
  • Go to Definition of cmdlets and variables
  • Find References of cmdlets and variables
  • Document and workspace symbol discovery
  • Run selected selection of PowerShell code using F8
  • Launch online help for the symbol under the cursor using Ctrl+F1
  • Basic interactive console support!

How to get the PowerShell extension in Azure Data Studio

If you don’t already have Azure Data Studio, start here.

Once you have Azure Data Studio open, click Clt+Shift+X to open the extensions marketplace.
Next, type PowerShell in the search bar.
Click Install on the PowerShell page.
Finally, click Reload in order to refresh Azure Data Studio.

Why we joined the Azure Data Studio Marketplace

Azure Data Studio is a powerful cross-platform database tool for data professionals using the
Microsoft family of on-premises and cloud data platforms on Windows, MacOS, and Linux.
Since PowerShell is a great tool for data management it just made sense to bring the full PowerShell
editing experience to this marketplace.

An example for getting started with SQL PowerShell

In order to use this example (below), you need to install the SqlServer module from the PowerShell Gallery.

Install-Module SqlServer AllowPrerelease

NOTE: With version 21.1.18095-preview and up, the SqlServer module supports PowerShell Core 6.2 and up in addion to Windows PowerShell.

In this example we take all of the .CSV files in a directory, turn each one into a SQL Server, and insert the data.

Whether you have 7 files, like in our example, or hundreds, using PowerShell to accomplish this task can be huge time saver!

In the below example you’ll notice the PowerShell script in the green box used to navigate to the directory, turn each file into a SQL server, and insert the data. With the PowerShell extension it is easy to run your script – simply select the snippet you want to run and type F8. You’ll also notice the output in the terminal highlighted with an orange box. The arrow from this box shows the newly generated SQL tables.

PowerShellExample

As you begin to write your own scripts you’ll notice you get suggestions from the PowerShell extension, this intellisense will help you to efficently write scripts in Azure Data Studio with PowerShell. As you navigate down the suggestions you will see descriptions of what each cmdlet can do.

In the example below, typing Write-S gives you suggestions like Write-SQLTableData, and tells you that this cmdlet writes data to the table of a SQL database.

intellisense example

For more examples of how to take advantage of PowerShell for data management check out this documentation

Reporting Feedback

An important benefit of being open source is getting feedback from users.
To report issues with the extension use our GitHub repo.
When reporting issues be sure to specify that you are using Azure Data Studio.

Sydney Smith
Program Manager
PowerShell Team

The post The PowerShell Extension is now in the Azure Data Studio Marketplace appeared first on PowerShell.

PowerShell ScriptAnalyzer Version 1.18.0 Released

$
0
0

PSScriptAnalyzer (PSSA1.18.0 is now available on the PSGallery and brings a lot of improvements in the following areas:

  • Better compatibility analysis of commands, types and syntax across different platforms and versions of PowerShell
  • Better formatting and customization. New capabilities are:
    • Multi-line pipeline indentation styles
    • Cmdlet casing for better consistency and readability
    • Consistent whitespace inside braces and pipes
  • Custom rules can now be suppressed and preserve the RuleSuppressionID
  • Better DSC support by being able to understand different syntaxes of Import-DscResource
  • Better user experience by being able to pipe to Invoke-ScriptAnalyzer and added tab completion of the returned objects that are piped to the next pipeline
  • Better handling of parsing errors by emitting them as a diagnostic record with a new Severity type
  • Improved Performance: Expect it to be about twice as fast in most cases and even more when re-analyzing a file. More on this below
  • Fixes and enhancements to the engine, rules, and documentation

There are some minor breaking changes such as e.g. requiring the minimum version of PowerShell Core to 6.1 as 6.0 has reached the end of its support lifecycle. With this, it was possible to update the used version of Newtonsoft.Json to 11.0.2. On Windows PowerShell, the minimum required runtime was upped from4.5.0 to4.5.2, which is the lowest version that is still supported by Microsoft but Windows update will have taken care of upgrading the to this patched version anyway, therefore no disruption is expected. We have also replaced old command data files of PowerShell 6.0 with a newer version for theUseCompatibleCmdletsrule.

Formatting

New rules and new features/customization of existing rules were added and in an upcoming release of the PowerShell vscode extension, those new features will also be configurable from within the extension in an upcoming update.

New PSUseConsistentWhitespace options

The PSUseConsistentWhitespace rule has 2 new configuration options that are both enabled by default:

  • CheckInnerBrace: Checks if there is a space after the opening brace and a space before the closing brace. E.g. if ($true) { foo } instead of if ($true) {bar}.
  • CheckPipe: Checks if a pipe is surrounded on both sides by a space. E.g. foo | bar instead offoo|bar.

In an upcoming update of the PowerShell vscode extension, this feature will be configurable in the editor via the settings powershell.WhitespaceInsideBrace and powershell.WhitespaceAroundPipe.

New PipelineIndentation option for PSUseConsistentIndentation

The PSUseConsistentIndentation rule was fixed to handle multi-line pipeline (before, the behavior was a bit ill-defined) and as part of that we decided to expose 3 options for a new configuration option calledPipelineIndentation. This allows PSSA to cater to different tastes of the user whether to increase indentation after a pipeline for multi-line statements. The settings are:

  • IncreaseIndentationForFirstPipeline (default): Indent once after the first pipeline and keep this indentation. Example:
foo |
    bar |
    baz
  • IncreaseIndentationAfterEveryPipeline: Indent more after the first pipeline and keep this indentation. Example:
foo |
    bar |
        baz
  • NoIndentation: Do not increase indentation. Example:
foo |
bar |
baz

In an upcoming update of the PowerShell vscode extension, this feature will be configurable in the editor via the setting powershell.codeFormatting.

New PSUseConsistentCasing rule

By popular request, this rule can correct the casing of cmdlet names. This can correct e.g. get-azadapplicaTION to Get-AzADApplication. This not only makes code more consistent but can improve readability in most cases. In an upcoming update of the PowerShell vscode extension, this feature will be configurable in the editor via the settingpowershell.useCorrectCasingsettings.

Compatibility Analysis

The UseCompatibleCmdlets rule requires JSON files in the Settings folder of PSSA’s installation and their file name is mapped to directly the compatibility configuration. In the new version we have replaced the JSON files for PowerShell 6.0 with files for 6.1 and also added new files for e.g. ARM on Linux (Raspian) and also PowerShell 2.0 that is still being used by some despite it being deprecated. If desired, one can always add custom JSON files to the Settings folder and it will just work by using the filename without the need to re-compile. To generate your custom JSON file for your environment, you can use the New-CommandDataFile.ps1 script.

To further add more analysis, 3 more rules were being added:

These rules do not follow the definition style of the UseCompatibleCmdlets rule. For usage and examples please refer to the rule documentation links of the 3 new rules above, there will be a more detailed blog post about them in the future.

Better DSC Support

Invoke-ScriptAnalyzer has a -SaveDscDependency switch that will download the required module from the PSGalleryto allow for parsing of the DSC files. In order to do that is has to parse calls to Import-DscResource correctly. Previously it could neither take the version into account or parse the hashtable syntax (Import-DscResource -ModuleName (@{ModuleName="SomeDscModule1";ModuleVersion="1.2.3.4"})). We added support for both of them. But because there could be different variations of the first one (different parameter name order or not using named paramters, etc.), please use it in the form Import-DscResource -ModuleName MyModuleName -ModuleVersion 1.2.3.4.

Custom Rules

We added the capability of being able to suppress violations from custom rules the same way how you can already suppress rules from the built-in rules. It is worth noting though that the rulename of custom rules has to be of the format CustomRuleModuleFileName\CustomRuleName, this is to uniquely identify the rule as it could be possible that 2 custom rule modules emit a rule of the same name.

When a custom rule emits a DiagnosticRecord, then the engine has to translate all properties of the object as it has to be re-created when emitting it via Invoke-ScriptAnalyzer. We added the translation of the SuggestedCorrectionsproperty already in the last release (1.17.1) to allow for auto-correction in the editor or via the -Fix switch. However, we also found that customers want to also use the RuleSuppressionID property in their custom rules, so we added translation for this as well.

Engine Improvements

PSScriptAnalyzer is highly multi-threaded by executing each rule (excluding custom or DSC rules) in parallel in each own thread. But there are some global resources such as e.g. a CommandInfo cache that needs to be accessed using a lock. Caching and lock granularity has been improved and are therefore reducing congestion which leads to much better performance. You can expect PSScriptAnalyzer to be about twice as fast for ‘cold runs’ (where Invoke-ScriptAnalyzerhas not been called before) and magnitudes faster when re-analyzing the same file. To you as a user, this will mean that you will see the squiggles faster when opening a new file in VS-Code and you will get faster updates when editing a file whilst reducing the CPU consumption in the background. We have more optimizations planned in this area, you can expect further improvements of similar scale in future versions and we hope to release future versions more frequent as well.

Miscellaneous Fixes

We received reports of some functionality not working when using Turkish culture and made a fix for and as part reviewed some culture critical points and made sure they work better across all cultures. The bug was very specific to Turkish culture, therefore we are confident that PSSA should work with any other cultures as well.

The Changelog has more details on the various fixes that were made to other rules.

On behalf of the Script Analyzer team,

Chris Bergmeister, Project Maintainer
Jim Truher, Senior Software Engineer, Microsoft

The post PowerShell ScriptAnalyzer Version 1.18.0 Released appeared first on PowerShell.

Viewing all 1519 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>