Quantcast
Channel: Scripting Blog
Viewing all 2129 articles
Browse latest View live

PowerTip: Use PowerShell to Open Event Log

$
0
0

Summary: Use a Windows PowerShell cmdlet to open the event log viewer.

Hey, Scripting Guy! Question How can I use a Windows PowerShell cmdlet to open the event log viewer?

Hey, Scripting Guy! Answer Use the Show-EventLog cmdlet.


Understanding XML and XPath

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, explores XML and XPath.

Microsoft Scripting Guy, Ed Wilson, is here. One of the things that confused me for a long time about using the Get-WinEvent cmdlet is the difference between the –FilterXPath parameter and the –FilterXml parameters. Part of the problem is that there are nearly no examples to be found that illustrate using –FilterXPath. A close look at the syntax of the Get-WinEvent cmdlet, however, does provide a bit of a clue. I include two examples here:

Get-WinEvent [[-LogName] <String[]>] [-ComputerName <String>] [-Credential

<PSCredential>] [-FilterXPath <String>] [-Force] [-MaxEvents <Int64>] [-Oldest]

[<CommonParameters>]

 

Get-WinEvent [-FilterXml] <XmlDocument> [-ComputerName <String>] [-Credential

<PSCredential>] [-MaxEvents <Int64>] [-Oldest] [<CommonParameters>]

So the FilterXPath parameter wants a simple string, and FilterXml wants an actual XML document. When I see XMLDocument, I think, “Structured XML.” Maybe I should back up just a little bit…

What is XPath anyway? Well, XPath is a query language that is used for selecting nodes from an XML document. In addition, I can use XPath to compute values, but this really does not have much to do with querying data from event logs. MSDN has an XPath Reference guide that is pretty good, but it is simply for reference. This is because the Windows event log does not contain full support for the XPath query language. Instead, it uses a subset of XPath 1.0. The Consuming Events topic in the Windows Dev Center has a section called XPath 1.0 limitations, which is an excellent reference about the specific limitations of the XPath 1.0 subset for querying events and log files.

An XPath query must resolve to select events, not a single event—it must resolve to events. All valid paths begin with either a * or the keyword Event. The paths operate on event nodes, and they are composed of a series of steps. Each step is a structure of three parts: Axis, Node Test, and Predicate. XPath is an industry standard that has been around since 1999. The W3C has a nice language specification (XML Path Language (XPath)), which is a good reference.

The following are limitations of XPath 1.0 in regards to working with event logs:

Axis   Only the Child (default) and Attribute (and its shorthand @) axis are supported.

Node Test   Only node names and NCName tests are supported. The "*" character, which selects any character, is supported.

Predicates   Any valid XPath expression is acceptable if the location paths conform to the following restrictions:

  • The standard operators OR, AND, =, !=, <=, <, >=, >, and parentheses are supported.
  • Generating a string value for a node name is not supported.
  • Evaluation in reverse order is not supported.
  • Node sets are not supported.
  • Namespace scoping is not supported.
  • Namespace, processing, and comment nodes are not supported.
  • Context size is not supported.
  • Variable bindings are not supported.
  • The position function and its shorthand array reference are supported (on leaf nodes only).
  • The band function is supported. The function performs a bitwise AND for two integer number arguments. If the result of the bitwise AND is nonzero, the function evaluates to True; otherwise, the function evaluates to False.
  • The timediff function is supported. The function computes the difference between the second argument and the first argument. One of the arguments must be a literal number. The arguments must use the FILETIME representation. The result is the number of milliseconds between the two times. The result is positive if the second argument represents a later time; otherwise, it is negative. When the second argument is not provided, the current system time is used.

When to use XPath

I use XPath queries when I am querying from the event log in the following situations:

  • It is a simple query from a single source.
  • It is a simple expression.
  • It is a compound expression that uses less than 20 expressions.
  • It does not use a suppressor.

I use an XML structured query when I need to do the following:

  • Use a compound query from more than one source
  • Use a suppressor to prevent events from being selected
  • Use a compound expression with more than 20 expressions

Here is an example of a structured XML query that illustrates querying the system and the application logs. In addition, events from the application log are only Level 3 and Level 1. Level 2 events are suppressed. The events occurred within the last 86400000 seconds. 

$query = @"

<QueryList>

  <Query Id="0">

    <Select Path="Application">

        *[System[(Level &lt;= 3) and

        TimeCreated[timediff(@SystemTime) &lt;= 86400000]]]

    </Select>

    <Suppress Path="Application">

        *[System[(Level = 2)]]

    </Suppress>

    <Select Path="System">

        *[System[(Level=1  or Level=2 or Level=3) and

        TimeCreated[timediff(@SystemTime) &lt;= 86400000]]]

    </Select>

  </Query>

</QueryList>

"@

 

Get-WinEvent -FilterXml $query

When I run the previous query, the following output returns:

Image of command output

Although this structured XML is really powerful and it results in a nice output, for queries that are easier to understand and easier to compose, I want to use FilterXPath.

Note  Whereas the –FilterHashTable and the –FilterXml parameters do not accept the LogName parameter (because both require the log inside the query itself),–FilterXPath requires the LogName parameter. This is how I specify which event log I want to search.

Xpath examples

The easiest Xpath query is *, which means “return everything.” I can type this directly into the Windows PowerShell console as follows (remember that the FilterXPath parameter expects a string, and therefore, quotation marks are not required):

Get-WinEvent -LogName application -FilterXPath *

On the other hand, if I put it in a script, I need to add the quotation marks, as shown here:

$xpath = "*"

Get-WinEvent -LogName application -FilterXPath $xpath

To query events from a specific provider, I need to specify Provider and use @Name to get to the provider name. Notice that there are several square brackets in the query.

$xpath = "*[System/Provider[@Name='Microsoft-Windows-DNS-Client']]"

Get-WinEvent -LogName system -FilterXPath $xpath 

If I want to add in an additional filter (for example, to only retrieve warning messages), I append it this way:

$xpath = "*[System/Provider[@Name='Microsoft-Windows-DNS-Client'] and System/Level=3] "

Get-WinEvent -LogName system -FilterXPath $xpath

If I would also like to add a date to the equation, I can specify the System/TimeCreated node and reference SystemTime as shown here:

$xpath = "*[System/Provider[@Name='Microsoft-Windows-DNS-Client']

and System/Level=3

and System/TimeCreated[@SystemTime < '2014-03-01T18:06:09.000Z']]"

Get-WinEvent -LogName system -FilterXPath $xpath

That is all there is to using XPath to query the event log. This also brings Event Log Week to a close. Join me tomorrow when I will share three way cool Windows PowerShell profile functions that Bruce Payette shared with me.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

PowerTip: View Directory List as Tree by Using PowerShell

$
0
0

Summary:  Learn how to view a directory in a tree view by using Windows PowerShell.

Hey, Scripting Guy! Question How can I use Windows PowerShell to easily view a directory list as a tree view?

Hey, Scripting Guy! Answer Use the Show-Tree cmdlet from the PowerShell Community Extension Project:

Show-Tree e:\data –depth 2

Note  For information about obtaining and installiing the free PSCX modules,
see these Hey, Scripting Guy! Blog posts.

Weekend Scripter: Cool PowerShell Profile Functions from Bruce Payette

$
0
0

Summary: Windows PowerShell principal SDE, Bruce Payette, shares a couple of cool profile functions.

Microsoft Scripting Guy, Ed Wilson, is here. The week of May 19, we had Profile Week. (To read about some great ideas that you can use for your Windows PowerShell profile, see these Hey, Scripting Guy! Blog posts.) I saved one individual's profile for a special post. Today we will look inside Bruce Payette’s profile. For anyone who may not know, Bruce is a principal software development engineer (SDE) on the Windows PowerShell team. Now you know why this is a special post.

Bruce supplied three way cool functions. The first function is a CD function that stores a list of directories that are typed. Then there is a DIRS function that will list the directories that have been typed. Each directory is associated with a number. Lastly, there is a MY function that creates directories relative to the users documents folder. I copied the functions below into my Windows PowerShell console profile. I typed ise $profile to open my profile in the Windows PowerShell ISE. Here is my Windows PowerShell ISE:

Image of console

A new CD function

In a default installation of Windows PowerShell, the CD alias is mapped to the Set-Location cmdlet. It changes directories. So the first thing that Bruce does is remove the CD alias, and then create a new function named CD. The cool thing about the new CD function is that it stores a list of directories that I visit. Each path is added once. With the new function, I can use CD, and move backwards in the directory bag.

With the DIRS function, I get a list of the directories stored in the directory bag. I can list them by typing dirs, or I can go to a specific folder by typing dirs 2, or whatever directory I want to navigate to. This is shown in the following image:

Image of command output

The MY function maps directories in reference to my personal profile. It allows me to go directly to my personal module folder by typing my modules, as shown here:

Image of command output

Following is the complete script for the three way cool profile functions:

# remove any existing cd alias...

rm -force alias:/cd 2> $null

$global:DIRLIST = @{}

# a cd function that maintains a list of directories visited. Each path is added only once (bag not stack)

# it also implements the UNIX-like ‘cd –‘ to jump back to the previous directory

# cd ...            # go up 2 levels

# cd ....           # go up three levels

# cd -              # go back to the previous directory

function cd

{

  param ($path='~', [switch] $parent, [string[]] $replace, [switch] $my, [switch] $one)

 

  if ($index = $path -as [int])

  {

    dirs $index

    return

  }

 

  if ($replace)

  {

    $path = $path -replace $replace

  }

 

  if ($parent)

  {

    $path = Split-Path path

  }

 

  if ($my)

  {

    if ($path -eq '~') { $path = '' }

    $path = "~/documents/$path"

  }

  elseif ($one)

  {

    if ($path -eq '~') { $path = '' }

    $path = "~/skydrive/documents/$path"

  }

 

  # .'ing shortcuts

  switch ($path)

  {

    '...' { $path = '..\..' }

    '....' { $path = '..\..\..' }

    '-' {

      if (test-path variable:global:oldpath)

      {

        # pop back to your old path

        Write-Host "cd'ing back to $global:OLDPATH"

       

        $temp = Get-Location

        Set-Location $global:OLDPATH

        $global:OLDPATH=$temp

      }

      else

      {

        Write-Warning 'OLDPATH not set'

      }

    }

    default {

      $temp = Get-Location

      Set-Location $path

      if ($?) {

        $global:OLDPATH = $temp

        $DIRLIST[(Get-Location).path] = $true

      }

      else

      {

        Write-Warning 'cd failed!'

      }

    }

  }

}

 

#

# lists the directories accumulated by the cd function

# dirs              # list the accumulated directories

# dirs <number>     # cd to the directory entry corresponding to <number>

function dirs

{

  param ($id = -1)

  $dl = $dirlist.keys | sort

  if ($dl)

  {

    if ($id -ge 0)

    {

      cd $dl[$id]

    }

    else

    {

      $count=0;

      foreach ($d in $dl)

      {

        '{0,3} {1}' -f $count++, $d

      }

    }

  }

}

 

# A function that cd's relative to ~/documents, with special handling for 'my modules'

# Works with the cd function

# my           # go to ~/documents

# my modules   # cd to ~/documents/windowspowershell/modules

# my foobar    # cd to ~/documents/foobar

function my ($path='', [switch] $resolve=$false)

{

  switch ($path)

  {

    modules {

      $resolvedPath = (rvpa '~/documents/windowspowershell/modules').Path

      if ($resolve) { return $resolvePath }

      cd $resolvedPath

      return

    }

  }

  $resolvedPath = $null

  $resolvedPath =  (rvpa "~/documents/$path").Path

  if (! $resolvedPath ) { return }

  if ($resolve)

  {

    return $resolvedPath

  }

  else

  {

    if ((get-item $resolvedPath).PSIsContainer)

    {

      cd "~/documents/$path"

    }

    else

    {

      return $resolvedPath

    }

  }

}

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

PowerTip: Use PowerShell to Display Windows Path

$
0
0

Summary: Learn to use Windows PowerShell to display your Windows path.

Hey, Scripting Guy! Question How can I use Windows PowerShell to inspect my Windows path to see what folders are there and in what order they appear?

Hey, Scripting Guy! Answer Use the $env PS Drive and retrieve the value of the Path variable. By default, it displays as a continuous string,
          and it can be a bit difficult to read. Here is the command:

$env:path

But if you use the –split operator to break the strings at the semicolon, it is more readable:

$env:path -split ";"

Weekend Scripter: Develop Minimal Footprint with PowerShell and Features on Demand

$
0
0

Summary: Guest blogger, Yung Chou, talks about using Windows PowerShell to develop a minimal footprint with Features on Demand.

Microsoft Scripting Guy, Ed Wilson, is here. Today I have another guest blog post from my fellow Microsoftee, Yung Chou. Yung is a developer experience evangelist; and therefore, he spends a decent amount of time talking to developers who are using Windows PowerShell. He maintains a blog on WordPress that contains some very useful information: YungChou: Witnessing a Clear Cloudy Day. Take it away Yung...

Since Windows 8 and Windows Server 2012, IT has the capability to not only disable features, but to actually remove the associated payload—that is, the binaries or source files from a Windows image, an offline VHD file, or a running Windows instance. This capability is also referred as Features on Demand.

For more information, see Windows Server 2012 R2 Installation Options and Features on Demand.

DISM and Server Manager include Windows PowerShell cmdlets. IT can easily use Windows PowerShell cmdlets to customize and develop a deployment image with a minimal footprint by removing the payloads of all unwanted features, based on business requirements.

This post presents a sample process and operations for developing a minimal server footprint by using Features on Demand with Windows PowerShell cmdlets for Server Manager. I will first describe a few important artifacts.

Side-by-side store

This is a repository of source files for Windows roles and features. Hereafter, I will use “roles and features” interchangeably with “Windows features” or simply “features.” When Windows installs, selected features are installed and a default set of source files are populated from an installation media to the side-by-side store. This store is located at: C:\Windows\WinSxS. Later, as Windows features are removed or restored, source files are deleted or copied back into the store from an installation source. Therefore, a change of the folder size of a side-by-side store is the main indicator of the change made by Features on Demand on the footprint of an associated Windows installation.

Installation source

When the source files of a Windows feature are removed from a side-by-side store, an administrator must specify an installation source when trying to restore the feature. By default, Features on Demand looks for an installation source in the following order:

  • The side-by-side store (C:\Windows\SxS of a destination server or specified locations)
    An installation source location can be a reference to: the side-by-side store of a Windows installation, the Sources\SxS folder of a Windows installation media, a network share with a copy of Sources\SxS, or a Windows image file.
  • An associated Group Policy setting, as applicable
    In a managed environment, an administrator can standardize the source file locations of Windows features in a Group Policy Object (GPO), as shown in the following image. When there is a need to restore a Windows feature, Features on Demand will reference designated locations for an installation source.

Image of menu

  • Windows Update
    This can be prevented by using the previous GPO setting.

The considerations of an installation source is well documented in the Add Roles and Features Wizard in Server Manager as shown in the following images:

Image of menu

Image of menu

Notice that in a default installation of Windows, .NET Framework 3.5 is removed, and it needs to be installed from Windows Update or a specified installation source using Features on Demand. I will further discuss this later in this post.

Windows PowerShell cmdlets for Server Manager

There are three cmdlets that are directly relevant to Features on Demand:

  • Get-WindowsFeature
  • Install-WindowsFeature
  • Uninstall-WindowsFeature

For more information, see Server Manager PowerShell Cmdlets.

Get-WindowsFeature is used to query the current states of features that are included in the manifest (metadata or all features recognized by a Windows installation). This should always be the first cmdlet run in a Features on Demand process to verify the states and object names of target features.

Install-WindowsFeature is used to install a feature or to restore one if it was previously removed (with the source files deleted).

Uninstall-WindowsFeature is used to uninstall a feature or remove the feature including source files from a Windows installation.

Install-WindowsFeature and Uninstall-WindowsFeature include the important -Source parameter and a number of useful switches, including –Remove, -WhatIf, -Confirm, -Computer, -VHD, -IncludeAllSubFeature, and -IncludeManagementTools.

This post focuses on the overall process and operations of Features on Demand, and it does not repeat what has already well been documented. If you need a better understanding of how these three cmdlets work, take time to review the Windows PowerShell Help file. It provides a great and convenient reference about the usage, including available parameters, switches, and examples.

Minimal footprint of a Windows installation

Let's consider Server Core as an example. Assume the objective is to produce a minimal footprint of a default Server Core installation. One approach is to do a clean Server Core installation followed by installing and removing features, based on business requirements. For simplicity, here I simply do a clean Server Core installation followed by removing all the features that are not installed by default. This demonstrates producing a minimal server footprint by removing the source files of all unwanted features.

Notice that this scenario is hypothetical, and it is designed to demonstrate the effectiveness and operations of Features on Demand. It is not necessarily a typical or recommended approach. In a real-world implementation, IT should verify that target functionality is continually performing as expected in a Windows installation as unwanted Windows features are incrementally removed or added. IT should also examine the size of a destination server’s side-by-side store to conclude a minimal footprint, based on business requirements.

Features on Demand process and operations

Before making any changes, we should always review and document the before and after states of target features and the sizes of the side-by-side store of a destination server. First, record the current sizes of the side-by-side store (C:\Windows\SxS) in a clean Server Core installation. This information is for later confirming the changes made. The following image shows the results of dir/s from the command prompt of a clean Windows Server 2012 R2 Server Core installation.

Image of command output

Then run Get-WindowsFeature to review the states of target features, as shown here:

Image of command output

Notice that there are three columns in the output of Get-WindowsFeature:

  • On the left are the display names, which are those names displayed in the Add Roles and Feature Wizard of Server Manager.
  • In the middle, Name, is the class or object name of a role or a feature. An object name is how to specify a feature with the three Server Manager Windows PowerShell cmdlets.
  • The Install State column includes three regular states. Available implies the source files of a feature are locally available in the side-by-side store. Installed is self-explanatory. Removed denotes that the source files of a feature are removed from the side-by-side store.

The following image shows using Get-WindowsFeature with a Where clause to filter the InstallState to easily verify what features are installed by default in a Server Core installation.

Image of command output

After identifying the features and changes to be made, it is a time to take a snapshot of the destination server. This ensures that the destination server can fall back to the state before changes were made, if necessary. In this example, the changes are to remove all features that are not currently installed, and this can be carried out with the following statement:

Get-WindowsFeature | Where {$_.InstallState -Match "Available"} | Uninstall-WindowsFeature  -Remove -Confirm -WhatIf

It first pipes all features of a destination server into the Where clause. Then all those features not installed yet with source code in the side-by-side store (that is, with the state as Available) are passed to the Uninstall-WindowsFeature statement for deletion.

When you use the Uninstall-WindowsFeature cmdlet to delete source files of a feature, all features that depend on the files being deleted are also removed. If you delete source files and no other dependencies for the parent feature remain installed, files for the entire parent feature are deleted. There are a number of switches important to consider with Uninstall-WindowsFeature, including:

  • -Remove
    Use to uninstall and delete source files of specified features from the current side-by-side store.
  • -IncludeManagementTools
    Use to uninstall associated management tools of a feature.
  • -Confirm
    Use to prompt for user confirmation before running the cmdlet.
  • -WhatIf
    Use to show what would happen if the cmdlet runs.
  • -VHD
    Use to provide the path to an offline VHD file.
  • -Restart
    Use to specify that the destination computer is to be restarted automatically.

Importantly, Uninstall-WindowsFeature works similarly to (yet, not exactly the same) as Server Manager Remove Roles and Features Wizard, which is shown in the following image.

Image of menu

Unlike the Remove Roles and Features Wizard, the cmdlet by default does not remove the management tools and snap-ins for a feature. To remove associated management tools, you must include the -IncludeManagementTools switch with the cmdlet. When uninstalling features from a Server Core installation beginning with Windows Server 2012, this switch removes the command-line and Windows PowerShell management tools for the specified features.

To remove features from an offline VHD, the best practice is to include both -ComputerName and -VHD. The former specifies the server for mounting the VHD file, and the latter provides a path to the VHD file on the specified server. Providing the server name and the VHD file location ensures that the mount operation is carried out as specified for accessing the VHD file.

The best practice for implementing Uninstall-WindowsFeature is to always use the –WhatIf switch to verify and document the changes to be made. Then run the statement without –WhatIf and with –Confirm. The following images show a test run followed by an implementation.

Image of command output

Image of command output

Now examine the side-by-side store information with dir/s after the deletion, as presented in the following image:

Image of command output

The following table shows statistics for the side-by-side store when we compare the clean installation with the removal of all uninstalled features:

Image of table

So the size reduction of the side-by-side store is about 641 MB after removing 8,270 files. The physical size of the VHD file is reduced by 65 MB. In addition:

  • The installation is cleaner, without extraneous code (hence, the minimal footprint of current configuration).
  • Removed features can be restored on demand.

If we compare the overall delta of drive C, the increased free space is about 942 MB. The 300 MB difference between the increased free space and the reduced size of the side-by-side store is due to user profile, temp storage, application data, and so on. Hence, these numbers may vary case by case. Above all, a fundamental strategy to minimize the footprint of a standardized Windows installation is to eliminate the source code of unwanted Windows features, based on business requirements.  

Minimal server interface

With Features on Demand, one capability is that an administrator can switch among installation types on demand. For more information, see Windows Server 2012 R2 Installation Options and Features on Demand (Part 4 of 5).

In addition, there is a Minimal Server Interface option available by changing Windows GUI components after an initial installation is completed. The Minimal Server Interface is similar to a server with a GUI installation, but Internet Explorer, Windows Explorer, the desktop, and the Start screen are not installed. However, the Microsoft Management Console (MMC), Windows PowerShell ISE, Server Manager, and a subset of Control Panel are in place.

Here’s how to change from Server Core to Minimal Server Interface by adding the GUI component, server-gui-mgmt-infra. For more information about Windows installation types and GUI components, see my series: Windows Server 2012 R2 Installation Options and Features on Demand.

Image of command output

In the previous example, I used Windows installation media to demonstrate how to reference a particular installation type with –Source. Notice that a Server Core installation does not include the GUI components, so referencing index 1 or index 3 for installing a GUI-related feature will result in an error message. This message warns the system is not able to locate the installation source as specified by –Source; although when adding other features, the same location seems to be working fine.

After the server-gui-mgmt-infra component is installed with a Server Core installation, Minimal Server Interface is in place. After a reboot, Server Manager will start automatically. This is by design. At this time, the MMC and the Windows PowerShell ISE, which have a dependency on server-gui-mgmt-infra are also available as shown here:

Image of menu

Installing .NET Framework 3.5

Another vivid example of Features on Demand is the installation of .NET Framework 3.5. Beginning with Windows 8 and Windows Server 2012, installations do not include the source files of .NET Framework 3.5. However, it is listed an add-on in Programs and Features on the Control Panel of Windows 8 and in the Add Roles and Features Wizard from Server Manager in Windows Server. The following two images show these menus:

Image of menu

Image of menu

Beginning with Windows 8 and Windows Server 2012, the source code for .NET Framework 3.5 is included in folder, Sources\SxS.

Essentially, in a default installation of Windows, .NET Framework 3.5 is installed by design from Windows Update, based on Features on Demand. Therefore, without accessibility to Internet, or more specifically Microsoft Windows Update, installation of .NET Framework 3.5 will fail unless an alternative installation source is provided and available without accessing Internet.

By using Windows PowerShell cmdlets for Server Manager, the following statement will install .NET Framework 3.5 at a destination server in an isolated environment. Here Windows installation media is available on drive D.

Image of command output

Features on Demand enables IT pros to minimize the footprint of a Windows installation by eliminating the source code of unwanted Windows features, based on business requirements. Windows PowerShell is a productive and readily available tool to use with Features on Demand. Features on Demand is essential to better deliver and secure the workload, and Windows PowerShell scripting is becoming a critical skill for performing day-to-day work.

~Yung

Thank you, Yung, for a most interesting and comprehensive post. Join me tomorrow for more way cool Windows PowerShell stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

PowerTip: Does PowerShell Array Contain a Value?

$
0
0

Summary: Learn how to verify if a Windows PowerShell array contains a value.

Hey, Scripting Guy! Question I have an array that contains various numbers and I want to see if one of the array elements contains
          a specific number. Is there an easy way to use Windows PowerShell so I don't have to iterate through
          the array and compare each element to the specific number?

Hey, Scripting Guy! Answer Use the Contains method from an array. In the following example, the $array variable contains an array.
          The next line checks to see if the number 2 is in the array. It is, and the method returns True.
          Next, the Contains method checks for the number 12. It is not present and the method returns False.

PS C:\> $array = 1,2,5,8,3,4,5

PS C:\> $array.Contains(2)

True

PS C:\> $array.Contains(12)

False

Creating an XML Document for Admins

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about creating XML files.

Microsoft Scripting Guy, Ed Wilson, is here. I will be the first to admit that I am not a huge fan of XML. I mean, if I can use a CSV file to store and retrieve the information I need, why do I need XML? Well, there are many times when the nested structure of XML is a more robust option. When dealing with objects inside of objects, a CSV file breaks down. In addition, reading a CSV file is a bit cumbersome when I need to look at the actual CSV file in something like Notepad. For XML, there is Notepad and XML Notepad.

XML Notepad

XML Notepad is still the best choice, in my opinion, for working with XML files for the average network administrator/ IT pro/dev ops type of person. For one thing, it is free. For another thing, it is really simple to use. I have written about XML Notepad in the past, in particular about exploring XML files to discover schema and data relationships. Unfortunately (or maybe fortunately depending on your perspective), we have not done anything to XML Notepad since 2007. I did notice that now there is a CodePlex site for XML Notepad. But the download link still takes one to the Microsoft Download Center for XML Notepad 2007.

One of the things I do not like about creating XML from scratch is typing all the tags. This is where XML Notepad shines. I can add in Elements, Attributes, and Text, and it automatically creates the right scheme. After I have created my relationships, I can then duplicate my node and fill in the data that I need to complete.

This makes it really easy to create an XML document. I could play around with trying to write a script, and at some point I may do so, but for now, I like using XML Notepad. By the way, even though the program was last updated in 2007, it works fine on my laptop running Windows 8.1. After installation, all I needed to do was find the program, right-click, and pin it to my Start page.

Getting started

The first thing I do after opening XML Notepad is select File> New to create a new blank XML document. There are two tabs, XML Tree View and XSL Output. As shown in the following image, neither have very much going on when the program opens a blank XML document:

Image of menu

Now I need to add in an element. To do this, I right-click the Tree View tab, and click Element from the action menu. That part makes sense, but then I have to click Before from the where to place it question to get it at the top.

Image of menu

Now I give it a name. In this example, it will be named Users. At this point, what I have is a Users node that appears with a little blue ball. This will change in a second.

I want to add an attribute to my element that I will call ID. I right-click the Users element, and click Attribute from the action menu. There is only one thing I can do here, and that is add a Child element to the Users element. This will be an internally used user ID. This is shown here:

Image of menu

If I click the XSL Output tab, I see that the following XML has been generated:

<Users ID=""/>

The Tree View tab now has the Users element and the ID attribute, as shown here:

Image of menu

I click, then right-click the Users element, and I add a Child element. I give it the name UserName. This is shown here:

Image of menu

I continue with this process:

  1. Click the Users element.
  2. Right-click Users.
  3. Click Element in the action menu.
  4. Click Child from the menu.
  5. Type a name for the element. I do this for UserName, FirstName, LastName, Password, and Address.

The XSL output now looks like this:

<Users ID="">

 <UserName/>

 <FirstName/>

 <LastName/>

 <Password/>

 <Address/>

 </Users>

And the Tree View looks like this:

Image of menu

It is probably a good time to save the XML file to ensure that it is working properly and that things are going as I expect them to. I click File> Save, and I give it a name. I open the XML file to see if it looks like what I might expect:

Image of code

I now add Child elements for the Address, which include Street, City, State, and Zip. I use the same process:

  1. Click the Address element.
  2. Right-click, and click Element.
  3. Click Child.
  4. Type Street, City, State, and Zip.

I can now fill in the XML file by clicking each element and typing the value I want to store. I select the element from the left side of the Tree View, and I type the value on the right side of the screen. For Attributes, nothing happens, except that the tool stores the value. For Elements, it automatically adds a #Text child.

Image of menu

To see if it looks correct, I use the Format-XML cmdlet from the PSCX. The output is shown here:

Image of command output

Now all I need to do is to go back to the Tree View tab, and click Duplicate. But there is a problem. Users is the root node, and each element of Users is actually an element for User. So how can I fix it?

This is easy! Right-click Users, and add a Child element named User. Now drag-and-drop each of the other elements under User. The only thing I cannot drag-and-drop is the ID attribute of Users. But that is simple enough to re-create. I delete the ID attribute of Users, and I re-create it in the User element. Now I can right-click User and click Duplicate, and that gives me everything I need. Now I can simply click and type to fill the User object.

The rearranged and modified Users.xml file is shown here:

Image of menu

I didn’t do any coding today, but I have a custom XML file that I can use if I need it. It gives me a great template to use and shows how easy it is to create an XML file by using XML Notepad.

That is all there is to creating an XML file. XML Week will continue tomorrow when I will talk about more cool stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy


PowerTip: Display Formatted XML with PowerShell

$
0
0

Summary: Use a free cmdlet to display formatted XML with Windows PowerShell.

Hey, Scripting Guy! Question How can I display formatted XML from within Windows PowerShell?

Hey, Scripting Guy! Answer Use the Format-XML cmdlet from the PSCX project:

Format-Xml C:\fso\users.xml

Note  For information about the PSCX project, this collection of Hey, Scripting Guy! Blog posts.

Exploring XML Document by Using the [XML] Type Accelerator

$
0
0

Summary: Learn how to use the [XML] type accelerator to explore XML documents.

Microsoft Scripting Guy, Ed Wilson, is here. The Scripting Wife bought me a pound of English Breakfast tea that she found online somewhere. It is long leaf, robust, and has a hint of earth tones in the bouquet. It makes a wonderfully rich pot of tea. It was a complete surprise when the box showed up on the door step. I added a cinnamon stick, like I normally do, but I thought I would try this tea basically unaltered to get a sense of what it has to offer. In a way, the tea is similar to today’s excursion into XML.

Note  This is the second in a series of posts about XML. Yesterday, I talked about using XML Notepad in Creating an XML Document for Admins. You might want to explore that post before continuing with today’s.

There are several tools that can be used to explore an XML document. I can simply double-click the XML document and view it in Internet Explorer (assuming that is the default file association with XML). The following image provides an example of the output:

Image of command output

To be honest, Internet Explorer (or any browser for that matter) is not a very good XML viewer. I would rather view it in Notepad than Internet Explorer. On my system, the default application for XML files is not Internet Explorer, but rather XML Notepad, which in addition to being lightweight, actually has facilities for dealing with XML. So the Users.xml file looks like this in XML Notepad:

Image of menu

The way I prefer to look at XML documents, however, is via Windows PowerShell.

Use PowerShell to peruse XML docs

Using Windows PowerShell to open an XML document is so easy that people have a tendency to lock up. At its most basic, an XML document is a text file. What do I use to open a text file in Windows PowerShell? I use the Get-Content cmdlet. And that is the same cmdlet I use for XML. The only difference is that I use the [XML] type accelerator to convert the plain text into an XML document. This is really easy. Because when I use Get-Content to read a text file, most of the time I store the resulting text in a variable. This is the same thing I do with XML. The technique is shown here:

[XML]$users = Get-Content C:\fso\users.xml

I now have an XMLDocument object. The object members are shown here:

PS C:\> $users | Get-Member

 

   TypeName: System.Xml.XmlDocument

 

Name                        MemberType            Definition

----                        ----------            ----------

ToString                    CodeMethod            static string XmlNode(psobject insta...

AppendChild                 Method                System.Xml.XmlNode AppendChild(Syste...

Clone                       Method                System.Xml.XmlNode Clone(), System.O...

CloneNode                   Method                System.Xml.XmlNode CloneNode(bool deep)

CreateAttribute             Method                System.Xml.XmlAttribute CreateAttrib...

CreateCDataSection          Method                System.Xml.XmlCDataSection CreateCDa...

CreateComment               Method                System.Xml.XmlComment CreateComment(...

CreateDocumentFragment      Method                System.Xml.XmlDocumentFragment Creat...

CreateDocumentType          Method                System.Xml.XmlDocumentType CreateDoc...

CreateElement               Method                System.Xml.XmlElement CreateElement(...

CreateEntityReference       Method                System.Xml.XmlEntityReference Create...

CreateNavigator             Method                System.Xml.XPath.XPathNavigator Crea...

CreateNode                  Method                System.Xml.XmlNode CreateNode(System...

CreateProcessingInstruction Method                System.Xml.XmlProcessingInstruction ...

CreateSignificantWhitespace Method                System.Xml.XmlSignificantWhitespace ...

CreateTextNode              Method                System.Xml.XmlText CreateTextNode(st...

CreateWhitespace            Method                System.Xml.XmlWhitespace CreateWhite...

CreateXmlDeclaration        Method                System.Xml.XmlDeclaration CreateXmlD...

Equals                      Method                bool Equals(System.Object obj)

GetElementById              Method                System.Xml.XmlElement GetElementById...

GetElementsByTagName        Method                System.Xml.XmlNodeList GetElementsBy...

GetEnumerator               Method                System.Collections.IEnumerator GetEn...

GetHashCode                 Method                int GetHashCode()

GetNamespaceOfPrefix        Method                string GetNamespaceOfPrefix(string p...

GetPrefixOfNamespace        Method                string GetPrefixOfNamespace(string n...

GetType                     Method                type GetType()

ImportNode                  Method                System.Xml.XmlNode ImportNode(System...

InsertAfter                 Method                System.Xml.XmlNode InsertAfter(Syste...

InsertBefore                Method                System.Xml.XmlNode InsertBefore(Syst...

Load                        Method                void Load(string filename), void Loa...

LoadXml                     Method                void LoadXml(string xml)

Normalize                   Method                void Normalize()

PrependChild                Method                System.Xml.XmlNode PrependChild(Syst...

ReadNode                    Method                System.Xml.XmlNode ReadNode(System.X...

RemoveAll                   Method                void RemoveAll()

RemoveChild                 Method                System.Xml.XmlNode RemoveChild(Syste...

ReplaceChild                Method                System.Xml.XmlNode ReplaceChild(Syst...

Save                        Method                void Save(string filename), void Sav...

SelectNodes                 Method                System.Xml.XmlNodeList SelectNodes(s...

SelectSingleNode            Method                System.Xml.XmlNode SelectSingleNode(...

Supports                    Method                bool Supports(string feature, string...

Validate                    Method                void Validate(System.Xml.Schema.Vali...

WriteContentTo              Method                void WriteContentTo(System.Xml.XmlWr...

WriteTo                     Method                void WriteTo(System.Xml.XmlWriter w)

Item                        ParameterizedProperty System.Xml.XmlElement Item(string na...

Users                       Property              System.Xml.XmlElement Users {get;}

xml                         Property              string xml {get;set;}

I can see from the previous output that there are a lot of methods for dealing with XMLDocument objects via the .NET Framework. I can look up the System.XML.XMLDocument object on MSDN and find additional information about each of these methods. Today, I am interested in the properties. There are two properties: Users and XML. There is also a parameterized property called Item. Other than that, everything is a method of some sort.

To look at the values of the two properties, all I need to do is to look at the variable. I type the $users variable in the Windows PowerShell console and press ENTER. The output is less than impressive. It is shown here:

PS C:\> $users

 

xml                                          Users

---                                          -----

version="1.0" encoding="utf-8"               Users

I decide to look at what is in the XML property first:

PS C:\> $users.xml

version="1.0" encoding="utf-8"

Is there anything else? When I pipe it to Get-Member, I see that I have a System.String:

PS C:\> $users.xml | gm

 

   TypeName: System.String

 

Name             MemberType            Definition

----             ----------            ----------

Clone            Method                System.Object Clone(), System.Object

CompareTo        Method                int CompareTo(System.Object value),

Contains         Method                bool Contains(string value)

CopyTo           Method                void CopyTo(int sourceIndex, char[]

EndsWith         Method                bool EndsWith(string value), bool En

Equals           Method                bool Equals(System.Object obj), bool

GetEnumerator    Method                System.CharEnumerator GetEnumerator(

GetHashCode      Method                int GetHashCode()

<output truncated>

When I look at the Users property, I receive a series of user objects:

PS C:\> $users.Users

 

User

----

{User, User, User, User...}

So, I continue to drill down.

The User node:

PS C:\> $users.Users.User

 

ID                            UserName                      Address

--                            --------                      -------

0                             UserName                      Address

0                             UserName                      Address

0                             UserName                      Address

0                             UserName                      Address

0                             UserName                      Address

The UserName node:

PS C:\> $users.Users.User.username

 

FirstName              LastName               #text                 Password

---------              --------               -----                 --------

Bob                    Smith                  BobSmith              password

Bob                    Smith                  BobSmith              password

Bob                    Smith                  BobSmith              password

Bob                    Smith                  BobSmith              password

Bob                    Smith                  BobSmith              password

And finally, the #Text property that contains the actual user name:

PS C:\> $users.Users.User.username."#text"

BobSmith

BobSmith

BobSmith

BobSmith

BobSmith

PS C:\>

Dude, all these look like the same thing. Is this right?

As a matter of a fact, it is—because all I did yesterday was duplicate each of the user objects. I did not go to the trouble of modifying any of the values. I can easily prove this by opening the XML document in XML Notepad and expanding a few of the nodes. This is shown here:

Image of menu

That is all there is to parsing XML. XML Week will continue tomorrow when I will talk about more cool stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

PowerTip: Validate XML Document with PowerShell

$
0
0

Summary: Learn to use Windows PowerShell to validate that an XML document is well formed.

Hey, Scripting Guy! Question How can I use Windows PowerShell to test that anXML document is well formed?

Hey, Scripting Guy! Answer Use the Test-XML cmdlet from the PSCX:

test-xml C:\fso\users.xml

Note  PSCX is a community-produced project that is available for free from CodePlex.
I have written quite a bit about downloading, installing, and using this great resource.
For more information, see this collection of Hey, Scripting Guy! Blog posts.

Using PowerShell to Explore Structure of an XML Document

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to explore the structure of an XML document.

Microsoft Scripting Guy, Ed Wilson, is here. I don’t know about you, but when I decide to script, I often do a cost/benefit analysis. I am not talking about anything extensive or anything that is even formalized. But I do estimate how long it will take to do something manually, and then I estimate how long it will take to do the same thing with Windows PowerShell. As you may well know, quite often Windows PowerShell wins. But not always. The not always areas are often because I may not know or understand an underlying technology well enough to script it.

     Note  This is the third in a series of posts about XML. You might also enjoy reading:

Windows PowerShell is not "magic pixie dust." It is an automation technology. To successfully automate, I often must know and understand the underlying technology. The better the Windows PowerShell cmdlets abstract this requirement, the easier it is for a non-expert to automate.

But at some point, I need to know what I am doing. For example, there are 27 cmdlets that contain the characters *firewall* in the noun. To successfully automate firewall stuff, I need to know the relationship between the firewall rules, address, application, interface, and port filters. I also need to understand the relationship between rules, filters, settings, and profiles.

Clearly, there is going to be a bit of reading before I really mess stuff up. In general, I like to ease into things gently by using the Get* types of cmdlets before I get to carried away with the Set*, New*, Enable*, and Disable* cmdlets.

XML document structure

When I read an XML document into a variable, I like to see what is available. I like to pipe the XMLDocument to Format-List and look at the values of all properties. This is shown here:

Image of command output

I can see that the XML node does not contain a lot of extremely useful information. I see that Users says Users, and that the Name and the LocalName are both #Document. The DocumentElement is Users. Nothing I need here.

Although this is interesting, I am trying to see the data. One area that looks promising is InnerXML. It definitely contains the data for all of the user nodes. It is shown here:

Image of command output

I can, call the Split method, and split on both < and />. This command will clean up the output a bit:

$users.InnerXml.Split('</>')

The output associated with the command is shown here:

Image of command output

Of course, that is not really working with XML, it is simply avoiding the problem of how to work with XML. I go back to my Format-List output, and I can see that there are more interesting properties exposed,  such as the ChildNodes property that lists the child nodes, the LastChild property, and the HasChildNodes property.

All of these could be useful from a navigation perspective. The OuterXML looks an awful lot like the InnerXML, so I do not need to mess with that. The following image shows the properties and their associated values:

Image of command output

From all of this, I can see the best path for me to pursue, is to go into the Users node, and look at the individual User objects. This is shown here—and it takes us back to where we left off yesterday.

PS C:\> $users.Users.User

 

ID                            UserName                      Address

--                            --------                      -------

0                             UserName                      Address

0                             UserName                      Address

0                             UserName                      Address

0                             UserName                      Address

0                             UserName                      Address

The point to all this?

Well, it helps to know a bit about XML to avoid doing a lot of extra work, such as manually trying to parse (by using string methods) XML data. XML data is already formatted. I only need to know what it looks like, and I can easily use Windows PowerShell to retrieve the data I need or want.

That is all there is to using Windows PowerShell to work with XML. XML Week will continue tomorrow when I will talk about more cool Windows PowerShell stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

PowerTip: Split String with PowerShell

$
0
0

Summary: Easily split a string on multiple characters with Windows PowerShell.

Hey, Scripting Guy! Question How can I use Windows PowerShell to split a string that contains multiple separator characters (for example, a comma and a semicolon)?

Hey, Scripting Guy! Answer Specify a string with the characters in it to the Split method:

PS C:\> $string = "This,is;a;string"

PS C:\> $string.Split(',;')

This

is

a

string

Calling XML Document Properties from Within PowerShell

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about calling XML document properties from within Windows PowerShell.

Microsoft Scripting Guy, Ed Wilson, is here. Craig Liebendorfer is back. No, he is not working on the Hey, Scripting Guy! Blog, but he is working on the Script Center as a whole. My old collaborator brings a lot to the table when it comes to bouncing ideas around, taking chances, and thinking outside the box. In fact, in our first recent meeting, we both came up with (about the same time) an idea for a new Script Center Home page. I think it looks really cool, let me know what you think.

By the way, each of the lines takes you to different places in the Script Center. We thought it was an appropriate way to navigate around the Script Center. Yep! The Windows PowerShell console. Here is an image of the new Home page:

Image of menu

   Note  This is the fourth in a series of posts about working with XML. You might also enjoy reading:

The first thing I do when I call XML document properties is read the XML file into a variable. Today I am going to call the variable XMLDocument to make the script easier to read. I use the [xml] type accelerator to cast the text into an XMLDocument object. The following image shows the document I am going to work with in XML Notepad:

Image of menu

When looking around at the properties that are available for working with XML documents, I like to use the MSDN reference for XMLDocument Class. I keep it open in Internet Explorer on one of my monitors so it will be available if I need it.

From looking at the document in XML Notepad, I can see that the root node is called Users, and that each child node is called User. Beneath that, I can find the UserName and the Address nodes. So how does this work in the Windows PowerShell console?

The first thing I do is read in the XML file, cast it to XMLDocument, and store it in a variable. This is shown here:

[xml]$xmldocument = Get-Content C:\fso\users.xml

I know the root node is called Users, and so I address it as shown here:

PS C:\> $xmldocument.Users

 

User

----

{User, User, User, User...}

I can see that the child nodes are called User, User, User... Therefore, I can simply call this from here:

PS C:\> $xmldocument.Users.User

 

ID                            UserName                      Address

--                            --------                      -------

0                             UserName                      Address

0                             UserName                      Address

0                             UserName                      Address

0                             UserName                      Address

0                             UserName                      Address

But, I can also call the ChildNodes property. It returns the same thing, as shown here:

PS C:\> $xmldocument.Users.ChildNodes

 

ID                            UserName                      Address

--                            --------                      -------

0                             UserName                      Address

0                             UserName                      Address

0                             UserName                      Address

0                             UserName                      Address

0                             UserName                      Address

I can always use ChildNodes to get child nodes in an XML document. For example, if I did not know that Users was at the root of the XML document, I could have used ChildNodes there. This technique is shown here:

$xmldocument.ChildNodes

The command and the output are shown here:

Image of command output

I see from the previous output, that the child nodes are named User. So I can gain access to them by calling them directly, as shown here:

PS C:\> $xmldocument.ChildNodes.user

 

ID                            UserName                      Address

--                            --------                      -------

0                             UserName                      Address

0                             UserName                      Address

0                             UserName                      Address

0                             UserName                      Address

0                             UserName                      Address

But I also see in the previous image that the root is Users, and then I have User. So I can go back, change my command, and access them by name. This is shown here:

PS C:\> $xmldocument.users.user

 

ID                            UserName                      Address

--                            --------                      -------

0                             UserName                      Address

0                             UserName                      Address

0                             UserName                      Address

0                             UserName                      Address

0                             UserName                      Address

But, because I know these are child nodes, I can also go back to my original script, and simply tack on ChildNodes, as shown here:

PS C:\> $xmldocument.ChildNodes.childnodes

 

ID                            UserName                      Address

--                            --------                      -------

0                             UserName                      Address

0                             UserName                      Address

0                             UserName                      Address

0                             UserName                      Address

0                             UserName                      Address

What is cool about this approach is that even if I do not know what the nodes are called, I can still find the information. All three of these techniques and their associated output (which is the same in each case) are shown in the following image:

Image of command output

Whichever approach I decide to take, the technique is the same. I can address the first node by indexing into it. This is shown here:

PS C:\> $xmldocument.ChildNodes.childnodes[0]

 

ID                            UserName                      Address

--                            --------                      -------

0                             UserName                      Address

I can now find the UserName information:

PS C:\> $xmldocument.ChildNodes.childnodes[0].UserName

 

FirstName              LastName               #text                 Password

---------              --------               -----                 --------

Bob                    Smith                  BobSmith              password

I use the same technique to get the Address information:

PS C:\> $xmldocument.ChildNodes.childnodes[0].Address

 

Street                 City                   State                 Zip

------                 ----                   -----                 ---

123 main street        anytown                wa                    1234567

But what if I did not know the names? Once again, I can use the more generic approach. Here is the FirstChild from the first child node. I can see that it is the same as UserName.

PS C:\> $xmldocument.ChildNodes.childnodes[0].FirstChild

 

FirstName              LastName               #text                 Password

---------              --------               -----                 --------

Bob                    Smith                  BobSmith              password

The LastChild gives me the address information. This is shown here:

PS C:\> $xmldocument.ChildNodes.childnodes[0].LastChild

 

Street                 City                   State                 Zip

------                 ----                   -----                 ---

123 main street        anytown                wa                    1234567

I can take this technique further, and address specific nodes or properties:

PS C:\> $xmldocument.Users.User.username

 

FirstName              LastName               #text                 Password

---------              --------               -----                 --------

Bob                    Smith                  BobSmith              password

Bob                    Smith                  BobSmith              password

Bob                    Smith                  BobSmith              password

Bob                    Smith                  BobSmith              password

Bob                    Smith                  BobSmith              password

 

PS C:\> $xmldocument.Users.User.username.LastName

Smith

Smith

Smith

Smith

Smith

That is all there is to using some of the XMLDocument properties. XML Week will continue tomorrow when I will talk about more cool stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

PowerTip: Find Other Ways to Use Split Method

$
0
0

Summary: Find other ways to use the Windows PowerShell Split method.

Hey, Scripting Guy! Question How can I use Windows PowerShell to find if there are other ways to use the Split method from a String object?

Hey, Scripting Guy! Answer Use the PSMethod object that returns from the method when not calling it with parenthesis,
          and then call the OverLoadDefinitions property, for example:

PS C:\> "string".split.OverloadDefinitions

string[] Split(Params char[] separator)

string[] Split(char[] separator, int count)

string[] Split(char[] separator, System.StringSplitOptions options)

string[] Split(char[] separator, int count, System.StringSplitOptions options)

string[] Split(string[] separator, System.StringSplitOptions options)

string[] Split(string[] separator, int count, System.StringSplitOptions options)


Calling XMLDocument Methods in PowerShell

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about calling XMLDocument methods in Windows PowerShell.

Microsoft Scripting Guy, Ed Wilson, is here. Today is Friday the 13th. Cool. Luckily, I do not have to go anywhere tonight around midnight, by the light of a full moon. But I am going to use Windows PowerShell methods to slice and dice some XML. Luckily, this is a very neat technique, and it will not leave any wayward bits of data laying around. Besides, I am listening to Scripting Cmdlet Style, and that should scare off anything that is non-PowerShell related.

    Note  This is the fifth in a series of posts about working with XML. You might also enjoy reading:

Although Windows PowerShell makes it easy to navigate XML documents, at times (because of the size of the files, the numbers of nodes, or some other non-PowerShell related element), one may want to drop down to the .NET Framework to do some work.

To make things a bit more interesting today, I decided to use an XML document from MSDN called Sample XML File (books.xml). All one needs to do to use it is to copy the code from the MSDN page, paste it into a plain Notepad text file, and rename the file Books.xml. After I have done that, I open it in XML Notepad for fun. This is what I find:

Image of menu

One of my favorite XMLDocument methods is the SelectNodes method. It will accept an XPATH path, which is simply a specially formatted string. The easiest XPATH query to use is “*”, which means, "Dude, show me everything."

In the following example, I first read in the XML by using Get-Content and the [XML] type accelerator. I then use the ChildNodes property and the SelectNodes method.

[xml]$xmldocument = Get-Content C:\fso\books.xml

$xmldocument.ChildNodes.selectNodes("*")

The commands and the associated output from the commands is shown here:

Image of command output

Because I see that my query with the wildcard character (“*”) worked as I thought it would, I decide to get brave and return only the titles. I do this by using the forward slash ( / ) symbol as the separator, and I simply call the Title node that I saw in the output from my first query. The query is shown here:

$xmldocument.ChildNodes.selectNodes("*/title")

The following image shows the query and the associated output:

Image of command output

I can also pick up the Genre of the books, as shown here:

$xmldocument.ChildNodes.selectNodes("*/genre")

The command and associated output are shown here:

Image of command output

The list of genres looks cool, but I really only want to know what genres are represented—that is, I want a unique list. Because this is Windows PowerShell, I can easily find this information in a couple of ways. The way I like to do this is to use Select-Object and specify the –Unique switch:

$xmldocument.ChildNodes.selectNodes("*/genre") | select '#text' –Unique

The output is nice, and it lets me know only the genres that are unique in the list:

Image of command output

Maybe I want to know the value of all of my books, and how many books I actually have. This is easy to do with Windows PowerShell, XML, and XPath. Here is the command I use:

$xmldocument.ChildNodes.SelectNodes("*/price") | measure '#text' –Sum

Here is the command and the output from the command:

Image of command output

Now I want to add one of my books to the Books.xml file. To do this, I will first clone one of the book nodes, as shown here:

$copy = $xmldocument.catalog.book[0].Clone()

Now, I simply assign new values for each of the properties. This appears here:

$copy.id = 'bk113'

$copy.author = 'Wilson, Ed'

$copy.title = 'Windows PowerShell Best Practices'

$copy.price = '59.99'

$copy.publish_date = '2014-01-25'

$copy.description = 'Automate system administration using Windows PowerShell best practices’

Now, I want to add the new node to the XML. I do this by calling the appendchild method and passing the $copy. This appears here:

$xmldocument.catalog.appendchild($copy)

I can now check the child nodes to ensure that it is added:

$xmldocument.ChildNodes.childnodes

Now I write the InnerXML to a text file with the XML extension:

$xmldocument.InnerXml >>c:\fso\modified.xml

I can now open it in XML Notepad to see if it worked properly. Here is my output:

Image of menu

That is all there is to using XML methods. Join me tomorrow for the Weekend Scripter when I will talk about non-PowerShell books for Windows PowerShell people.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

PowerTip: Use PowerShell to Create DateTime Object for Any Date

$
0
0

Summary: Use Windows PowerShell to easily create a DateTime object X days in the future.

Hey, Scripting Guy! Question How can I use Windows PowerShell to create a DateTime object for a date at some point in the future?

Hey, Scripting Guy! Answer Use the AddDays method from the DateTime object, for example:

(get-date).AddDays(8)

Weekend Scripter: Non-PowerShell Books for PowerShell People

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, collects a list of cool book recommendations.

Microsoft Scripting Guy, Ed Wilson, is here. One of the things I constantly find myself doing is reading. I try to read a lot of different things, fiction, non-fiction, classic literature, and technical. I am always cycling back and reading technical books. I find that I need to know more these days, and I have less time to come up to speed on various topics.

Although my primary focus is on Windows PowerShell, I see the need to constantly be learning and reading about various technical topics. In this way, I guess I am a holistic Windows PowerShell scripter, something not entirely different than a holistic detective.

I do have a nearly unlimited need to read and learn new stuff, but I do not have an unlimited budget or unlimited time. Therefore, I do not want to waste my resources on useless books. So I reached out to various experts for recommendations of great non-PowerShell books that might be of interest to Windows PowerShell people. Here are the results:

Jim Christopher, Windows PowerShell MVP, suggests the following two books:

Chris Bellee, Microsoft PFE, and my good friend from Australia (also, literally the coolest person I know) sends the following recommendations:

Mike Kline, Microsoft PFE, suggested the following books about Active Directory:

Tom Nolan, Microsoft PFE, suggests the following books: 

  • Head First C# by Jennifer Greene and Andrew Stellman
    This is hands down the best book I can recommend for anyone wanting to dig into .NET who isn’t really a programmer type.  It is also one of the best books for anyone who is a programmer type who appreciates visual/immersive learning and doesn’t know C# very well. I have read this book cover-to-cover and, even as a developer, I loved every bit of it.
  • Programming Windows Store Apps with C# by Matthew Baxter-Reynolds and Iris Classon
    I think this one is really good because a lot of people, when learning programming, want to learn things that apply to something they are interested in. App development is definitely high on a lot of peoples’ lists. I haven’t read this one cover-to-cover, but what I have paged through looks really good.
  • Windows 8 and Windows Phone 8 Game Development by Adam Dawes
    I think game programming is another place that really tends to spark the interest of many, so I would be remiss to not include this one. I have read a fair chunk of it.
  • Beginning ASP.NET 4.5: in C# and VB by Imar Spaanjaars
    Some folks would prefer to go the path of learning to develop websites, so this is probably the best beginner book I would put on the list. Also, really great for web developers lacking .NET experience.
  • Professional C# 5.0 and .NET 4.5.1 by Christian Nagel, Jay Glynn, and Morgan Skinner
    For anyone who has some experience and wants the serious dive into things, this is a great book. It will require a bit more general .NET experience than the others, and it will not be as forgiving introducing topics before diving in, but it has a lot of good information. 

Yung Chou, Microsoft DPE, suggests:

Doug Finke, Windows PowerShell MVP, says this book is how he learned to search XML:

Blain Barton, Microsoft IT pro evangelist, provided this list:

Here are some books that I (the Scripting Guy) have found helpful:

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

PowerTip: Get Unique Numbers by Using PowerShell

$
0
0

Summary: Easily get unique numbers from a list by using Windows PowerShell.

Hey, Scripting Guy! Question How can I use Windows PowerShell to get unique numbers from a list of numbers?

Hey, Scripting Guy! Answer Use the Get-Unique cmdlet, for example:

PS C:\> 1,2,2,3,4,4,5 | Get-Unique

1

2

3

4

5

Weekend Scripter: Use PowerShell to Explore Dates

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, shows how to use Windows PowerShell to explore dates in the future.

Microsoft Scripting Guy, Ed Wilson, is here. This afternoon, I am sipping a nice cup of Kwai Flower Organic Oolong tea. It is a slightly sweet, mild tea that goes well with jasmine blossoms. It makes for a nice relaxing afternoon, and the slightly woody flavor goes well with Macadamia nuts.

Now contrast a nice relaxing afternoon with Friday the 13th. If I want to be prepared for the next Friday the 13th, how can I use Windows PowerShell to get that information for me? Well, it literally took me less than five minutes to come up with an answer.

The key to finding dates in the future is to use the DateTime object. I am lucky because the Get-Date cmdlet returns a DateTime object. I can then directly call the AddDays method to it. I create an array of 1000 numbers and pipe it to the AddDays method to create a thousand days in the future. That should give me enough warning. If not, I can easily change it to ten thousand days.

To get my thousand numbers to the AddDays method, I need to use the Foreach-Object cmdlet. I pipe my array of numbers to the Foreach-Object cmdlet, and I use the $_ automatic variable to represent the individual number as it comes across. I then store the newly create DateTime object in a variable I call $dte. This is shown here:

1..1000 |

ForEach-Object {

       $dte = (Get-Date).AddDays($_)

Now all I need to do is to use two properties from the DateTime object. The first is the DayOfWeek property. This returns the day name, and I am interested in Friday. I am only interested in Friday if the Day property is also 13. This is a simple IF statement:

If ($dte.DayOfWeek -eq 'Friday' -AND $dte.Day -eq 13)

If I find a match for the two conditions of a DayOfWeek of Friday and a Day equal to 13, all I need to do is to print the DateTime object for that date. This is shown here:

{ $dte }

And that is all there is to the script. When I run it in the Windows PowerShell ISE, I see the following in the output pane.

Image of command output

Surprisingly, according to my Windows PowerShell script, Friday the 13th only occurs two or three times a year. Sometimes less. In 2016, it only occurs once, but in 2015, it occurs three times. Dude, better start making plans now.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Viewing all 2129 articles
Browse latest View live


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