Loading

Subscribe via RSS

Subscribe by Email

Your email:

Do You Tweet Tech?

Are your tweets technology related? If so then we want to follow!
 

Admin Arsenal Blog

Current Articles | RSS Feed RSS Feed

PowerShell Tips for System Administrators: Format Views

  | Share on Twitter Twitter | Share on Facebook Facebook | Submit to Digg digg it |  Add to delicious  delicious |  Submit to StumbleUpon StumbleUpon | Submit to Reddit reddit 

Amazing View
Photo by Dave_B_

In two recent posts I went over the PowerShell formatting cmdlets and calculated properties. Today I'm going to cover Views. You'll notice that when you display a normal object (such as the built-in FileInfo objects when you run dir) you don't see all of its properties. This is because PowerShell is using a View, which is selected based on the type of object you're outputting and which type of output is being used (table, list, or wide.)

The views are stored in XML files in the PowerShell directory which you can examine to see how the formatting is being performed. Not only that but you can add your own views and even override the default views used by PowerShell.

The standard views are stored in %systemroot%\System32\WindowsPowerShell\v1.0 in a files with the extension format.ps1xml. There are several files, but the one we'll be looking at is FileSystem.format.ps1xml. This file holds the formatting for the various file system objects, such as FileInfo and DirectoryInfo.  The section that defines the normal file system table output is this:

<View>
  <Name>children</Name>
  <ViewSelectedBy>
    <SelectionSetName>FileSystemTypes</SelectionSetName>
  </ViewSelectedBy>
  <GroupBy>
    <PropertyName>PSParentPath</PropertyName>
    <CustomControlName>FileSystemTypes-GroupingFormat</CustomControlName>
  </GroupBy>
  <TableControl>
    <TableHeaders>
      <TableColumnHeader>
        <Label>Mode</Label>
        <Width>7</Width>
        <Alignment>left</Alignment>
      </TableColumnHeader>
      <TableColumnHeader>
        <Label>LastWriteTime</Label>
        <Width>25</Width>
        <Alignment>right</Alignment>
      </TableColumnHeader>
      <TableColumnHeader>
        <Label>Length</Label>
        <Width>10</Width>
        <Alignment>right</Alignment>
      </TableColumnHeader>
      <TableColumnHeader/>
    </TableHeaders>
    <TableRowEntries>
      <TableRowEntry>
        <Wrap/>
        <TableColumnItems>
          <TableColumnItem>
            <PropertyName>Mode</PropertyName>
          </TableColumnItem>
          <TableColumnItem>
            <ScriptBlock>
              [String]::Format("{0,10}  {1,8}", $_.LastWriteTime.ToString("d"), $_.LastWriteTime.ToString("t"))
            </ScriptBlock>
          </TableColumnItem>
          <TableColumnItem>
            <PropertyName>Length</PropertyName>
          </TableColumnItem>
          <TableColumnItem>
            <PropertyName>Name</PropertyName>
          </TableColumnItem>
        </TableColumnItems>
      </TableRowEntry>
    </TableRowEntries>
  </TableControl>
</View>

If you're not used to XML this may appear a bit daunting, but you can get a quick sense of how it works. There are four main sections of the file.

  1. <ViewSelectedBy> indicates which object types are used by this view. In this case, the name FileSystemTypes refers to another section in the file that lists the types. That section is <SelectionSets>. The individual type names can be listed instead, but this reference makes the code shorter.
  2. <GroupBy> tells the table of files to be grouped by thier parent path. This also refers to another section of the file called <Controls>.
  3. <TableHeaders> sets up not only the titles that appear on the table columns, but also their width and alignment.
  4. <TableRowEntry> the actual values to show in the table. Three of the colums just pull out a property by name, but the LastModifiedTime uses PowerShell code to format the date in a particular way. Any PowerShell code can be used which gives a great deal of flexibility.

There are a lot of possibilities for how to create views and the documentation is a bit limited. To learn about formatting it's best to look at the included format files to see how things are done.

To make a custom view you will need to create your own format.ps1xml files since you can't edit the built in ones. If there is more than one view for an object then the first one found will be used. Otherwise they can be selected by name using the -View parameter of the format cmdlets. Once you have a file created you import the formats using the Format-UpdateData cmdlet. As an example of a new format, I've create a format file that adds a CreationTime column in addition to LastWriteTime. Download the file, save it with the extension .format.ps1xml and run the following command:

Format-UpdateData -PrependPath [filename]

Now when you list the contents of a directory you will see the new column. Alternately you could have used -AppendPath to put the file after the built in formats and then you would need to use the view by name:

dir | Format-Table -View MyFormat

To make the custom format persistent between sessions, add the Format-UpdateData command to your PowerShell profile. One of the principles of PowerShell is the ability for you to configure it to your tastes and Views are a very powerful, if somewhat complex, way to get just want you want.


Need help using formats (or anything else) in PowerShell? Post a question in our PowerShell forum to ask one of our engineers.

PowerShell Tips for System Administrators: Profiles

  | Share on Twitter Twitter | Share on Facebook Facebook | Submit to Digg digg it |  Add to delicious  delicious |  Submit to StumbleUpon StumbleUpon | Submit to Reddit reddit 

Sphinx Profile
Photo by Andrew®

A profile in PowerShell is nothing more than a script file that is run when the shell starts. This file is very handy to create variables, functions, or change settings that you find you use a lot. Instead of having to re-import a library of functions or change the shell's settings each time you start up PowerShell.

The variable $profile holds the name of the file that you are using for the current shell. PowerShell doesn't create this file, so it won't exist out of the box, but the variable will still hold the name. For example, on my box it is:

C:\Users\Adam> $profile
C:\Users\Adam\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

You can put anything in this file that you can put into a script file, so feel free to create functions, set variables and run commands. Any changes made to the file won't be used by the current shell, so you'll need to restart to see any effect. And remember that if you are going to load any other script files in the profile you need to precede the script with a single dot (.) for the functions and variables in that script file to remain visible in your new shell:

. \libs\Functions.ps1

There is also a profile on the computer that applies to all users as well as profiles for other shells. Microsoft has all of the lowdown.


Follow me on Twitter @AdamRuth


PowerShell Tips for System Administrators: Calculated Properties

  | Share on Twitter Twitter | Share on Facebook Facebook | Submit to Digg digg it |  Add to delicious  delicious |  Submit to StumbleUpon StumbleUpon | Submit to Reddit reddit 

In a previous post I went over three cmdlets for formatting data. Each of those cmdlets let you select which object properties you want to show. You aren't just limited to the existing properties on the objects, though, you can use Calculated Properties which let you format the properties in any way you like. The syntax for calculated properties looks a little odd at first, but it's actually quite simple.

For example, this expression displays the time between the creation and last write times of files:

Screen shot 2010 07 16 at 8.36.15 AM

There are a few things here that need explaining:

  • The back-tick at the end of the first line allows you to type in commands on multiple lines, making it easier to read and write long commands.
  • Calculated properties are defined as Hash Tables, which are simple name/value containers. They are created by putting the names and values inside of @{} separated by semicolons.
  • Calculated properties require that the hash table has two values: Name and Expression.
  • The Expression value in the hash table is itself enclosed in curly braces {} which is the way you pass PowerShell script code as a property to a cmdlet.
  • The value $_ inside of the Expression is the object that is being formatted. In the above example it is referenced twice to pull out the two properties CreationTime and LastWriteTime.
  • CreationTime and LastWriteTime are .NET objects called DateTime and they have a number of properties and actions themselves. The example uses the Subtract method which gives the difference between two DateTime objects.
  • The object returned from the Subtract method is called a TimeSpan. It displays as days.hours:minutes:seconds.milliseconds. It also has a number of properties to get these values individually.

As you can see, showing a TimeSpan like that is not the easiest to read. We can display just the days like this:

Screen shot 2010 07 16 at 8.57.06 AM

One PowerShell construct that is very helpful when formatting output is the -f operator. This takes text with embedded placeholders in it and replaces them with formatted values. A simple example:

Screen shot 2010 07 16 at 9.07.16 AM

There are two placeholders which insert the two values (placeholder numbering starts with 0.) Not only can the -f operator insert the given values, but it can also format numbers in a variety of ways. Consider this example:

Screen shot 2010 07 16 at 9.13.09 AM

This example shows the size of each file in megabytes, formatted out to two decimal places. It starts by dividing the Length of the file by 1Mb (which is a built-in PowerShell value handy when dealing with file sizes along with 1kb, 1gb, and 1tb.) This value is then passed to a format placeholder {0:0.00}. The text after the colon defines how the number is to be displayed. In this case, it will show one at least one digit to the left and no more than 2 digits to the right of the decimal. There are many different types of formatting rules you can use, here's Microsoft's documentation for more details.

Once you understand the basics of Calculated Properties, there really isn't any limit to how values can be formatted. Calculated properties aren't just for making output easy to read, but they come in very handy when you need to pass the output of some command to a program that expects things to be in a specific format. Consider using them any time you have to massage data manually.


Need help with PowerShell? Post a question in our new PowerShell forum and get an answer quick.


PowerShell Tip: Formatting Output

  | Share on Twitter Twitter | Share on Facebook Facebook | Submit to Digg digg it |  Add to delicious  delicious |  Submit to StumbleUpon StumbleUpon | Submit to Reddit reddit 

In PowerShell everything is a .NET object, each with a variety of different properties. You'll notice that most of the time the output you see from basic commands only gives you a small subset of what's available. This is because PowerShell has built-in rules for how and what to display for most of the standard objects. Usually this is done so that you normally only see what's most important and aren't overwhelmed with too much data. For example, the dir command returns a set of FileSystemInfo objects but only shows you a few of the 20+ properties that are available.

Screen shot 2010 07 12 at 8.57.21 AM

You can override the default output for any object and PowerShell provides a set of cmdlets for just this purpose: Format-Wide, Format-Table, Format-List, and Format-Custom. I'll cover Format-Custom in another post, so for now here's a brief description of the first 3.

Format-Wide

This cmdlet simple takes one property of each object and writes them out across the window. This is similar to the /w option when using dir in cmd.exe.

Screen shot 2010 07 12 at 9.02.42 AM

Notice that to use the cmdlet you need to pipe the output of the dir command to Format-Wide. Unlike the pipe command in cmd.exe, you aren't just sending the text from the first command but actual .NET objects which allows the second command to have full control when dealing with them.

With Format-Wide you can select the property to show with the -Property parameter. You can also adjust the width of the columns with -Column.

Screen shot 2010 07 12 at 9.06.21 AM

Format-Table

This cmdlet formats objects just like the default dir command, but you have control over what properties show up and how they are formatted. For example:

Screen shot 2010 07 12 at 9.17.21 AM

In order to adjust the widths of the columns independently you need to create a View and pass it to the cmdlet, but that's a topic for its own posting. You can even group the output by unique properties of the files.

Screen shot 2010 07 12 at 9.26.39 AM

Format-List

This cmdlet formats the output as a list of properties. It's similar to the table output, but rotated 90 degrees. 

Screen shot 2010 07 12 at 9.29.09 AM

Just like Format-Table you can decide which properties to show. You can use wildcards to select multiple properties (this also works with Format-Table.)

Screen shot 2010 07 12 at 9.31.35 AM

If you just use * for the property list you'll see all of the properties of the object. This is handy while exploring objects to see what information you can work with.

Hopefully this quick overview will get you exploring the different ways to output data in PowerShell. In future posts I'll discuss more advanced topics such as Format-Custom, Views, and Calculated Properties. 


Follow me on Twitter @AdamRuth.


System Management Tools - Command Line Service Control

  | Share on Twitter Twitter | Share on Facebook Facebook | Submit to Digg digg it |  Add to delicious  delicious |  Submit to StumbleUpon StumbleUpon | Submit to Reddit reddit 

Cat's provide good service
    Photo by *yasuhiro
I find myself having to deal with Windows services quite a lot, probably more than the average system administrator. The two most common tools administrators use are the services.msc MMC snap-in and net.exe (net start and net stop, in particular.) One more tool that I keep close is sc.exe because it gives capabilities that you can't find in the other tools. 

It provides pretty much everything that a developer can do when programming directly to the Service Control Manager. The commands that I use most often are create and delete. These are particularly useful when I'm writing a service and I need to test it on one or more machines.

Creating a Service

The create command has the following syntax:

sc.exe <server> create [service name] [binPath= ] <option1> <option2>…

Run "sc.exe create" to see all of the options. The ones you'll use most are:
  • start= (auto, manual, disabled)
  • obj= (account name)
  • password= (password)
  • DisplayName= (friendly name)

There are some gotchas that you may run into (I know I have!):

  • If using PowerShell you need to use sc.exe instead of just sc since sc is an alias for the built-in cmdlet Set-Content.
  • If you get the syntax wrong you won't get an explanation of what why, you'll only get the usage description so it can be difficult to track down typos.
  • All of the options follow the same syntax of "binPath= path." Note that there is no space before the equal sign and a space afterwards. That's caught me many times, the command will choke on "binPath = path" and "binPath=path."  
  • You'll most likely need quotes in the binPath= parameter. For example if the service path is "C:\Program Files\Company\Name\Service.exe" -service you'll need to escape the quotes. This is done differently if you're using PowerShell or cmd.exe:
    • PowerShell:  sc.exe create name binPath= '\"C:\Program Files\Company\Name\Service.exe\" -service'
      Note the \ before the double-quotes and the whole thing is wrapped in single-quotes.
    • cmd.exe: sc.exe create name binPath= """"C:\Program Files\Company\Name\Service.exe""" -service"
      Note that it's wrapped in double-quotes and the inner quotes are three sets of double-quotes.

Editing a Service

There is a config command that lets you change all of the service's settings without re-creating it. It has the same options as the create command.

Deleting a Service

Deleting a service is a lot simpler:

sc.exe <computer> delete [service name]

If the service is still running when you do this, it will be "marked for deletion" which is a kind of limbo state where the service can't be controlled any more (can't be stopped.) If that happens, most of the time you can flush the delete by killing the service's process. In the rare case where that doesn't work, a reboot will be required. 

Services on Other Computers

In order to work with services remotely on other computers you need to have File Sharing turned on and opened through a firewall. If you can get to a file share on the computer, you'll be able to modify its services.




Are you using the correct Powershell version?

  | Share on Twitter Twitter | Share on Facebook Facebook | Submit to Digg digg it |  Add to delicious  delicious |  Submit to StumbleUpon StumbleUpon | Submit to Reddit reddit 

Author: Shane Corellian 

Tobias Weltner wrote this article on the Powershell.com site. It is definitely worth the read. For those of you planning on implementing Powershell Version 2, pay special heed.

 An excerpt:

"When you search for PowerShell V2 downloads, you will find tons of articles and download links. Only some of them point to the correct final "RTM" link. A lot of people are still blogging about "CTP" versions which really were beta versions with limited functionality. Even worse, it turned out that these out-dated PowerShell versions are still up for download from the Microsoft Download center, so when you follow the "wrong" link, you could get the impression that these CTP versions really were official and up-to date releases."

 I have been playing with V2 now for about 3 weeks and so far I am pretty excited. Extending Admin Arsenal with a good CLI is important and Powershell will definitely be the foundation on which it is built.

 

 

 

 


System Administration Scripting - PowerShell and Current Directory

  | Share on Twitter Twitter | Share on Facebook Facebook | Submit to Digg digg it |  Add to delicious  delicious |  Submit to StumbleUpon StumbleUpon | Submit to Reddit reddit 

Current Folder
    Photo by Tim Morgan
I was recently bitten by a PowerShell quirk that took me quite a while to find. It has to do with how PowerShell deals with the current directory when making .NET function calls. I created a script to make changes to an XML file that looked similar to this:

cd c:\some-directory
$xml = [xml](get-content "file.xml")
$xml.Parent.Node.Id = [system.guid]::newguid().tostring()
echo $xml.Save("file.xml")

When I ran the script, the file didn't change. I couldn't for the life of me figure out why. This was the first time I was working the XML libraries in PowerShell and I was certain it must be due to how I was using the library. Finally, after about a half hour of searching I discovered that the change file was being saved to the original directory, not to the directory I had changed to.  It turns out that when you change directories in PowerShell, you don't change the current directory in the environment and so the .NET libraries think you're still in the original directory. Since I read the file using PowerShell with get-content and saved using the .NET XML library, I was properly reading the file, but saving it in the wrong place.

This quirk is apparently deliberate, having something to do with enhancements in a future version of PowerShell which will allow suspending of jobs in the background. I'm not sure that this is the best way to deal with that eventuality, but there you go.

There are two ways around this problem. The first, and simplest is to use the resolve-path cmdlet:

echo $xml.Save(resolve-path "file.xml")

This will ensure that the full path to the file will be sent to the .NET class, ensuring that the file is saved in the correct location.

The second option, which may be preferable in some situations, is to change the directory using the .NET Directory class:

[IO.Directory]::SetCurrentDirectory("c:\foo")

This will change the current directory in the environment. It's probably safer to use resolve-path, but it will not be sufficient if a .NET class must work on the current directory and you can't pass in another path.

Writing to the Void

  | Share on Twitter Twitter | Share on Facebook Facebook | Submit to Digg digg it |  Add to delicious  delicious |  Submit to StumbleUpon StumbleUpon | Submit to Reddit reddit 

 

Writing to the void - nul null | Admin Arsenal
    Photo by Redvers
One thing that always bothered me about the normal Windows command line was the lack of an equivalent to /dev/null in UNIX. When running a command whose output you wanted to ignore (i.e. not have it cluttering up your console window) you had to redirect it to a real file. This always seemed a bit sloppy to me, because you ended up with file laying around containing who knows what that you really just wanted to ignore.

 

PowerShell, however, does have an equivalent. You can redirect to the built-in variable $null to get the same effect.

PS C:\> dir > $null

In addition to the $null variable you can also pipe output to the out-null cmdlet.

PS C:\> dir | out-null

This second version also has a little trick up its sleeve. Normally when running a GUI app from PowerShell, control is returned immediately to the command line and PowerShell doesn't wait for the GUI app to exit. This may not be what you want. For example, in my build scripts I have a program that generates the documentation, it's actually a GUI app that takes parameters and writes out the help files. I want my script to wait for this process to finish, so the normal behavior doesn't work for me. But, by piping the output of the GUI app to out-null then PowerShell will wait for the app to finish. You can see this yourself by running notepad.

PS C:\> notepad | out-null


Deploy Windows PowerShell with Admin Arsenal

  | Share on Twitter Twitter | Share on Facebook Facebook | Submit to Digg digg it |  Add to delicious  delicious |  Submit to StumbleUpon StumbleUpon | Submit to Reddit reddit 

Want to deploy Windows PowerShell to your all your organization's computers? You can deploy PowerShell using Admin Arsenal. (A free, fully functional trial version is available.)

First things first: Go download Windows PowerShell. (note: PowerShell is included with Windows 7)

In the example below, I used Admin Arsenal to deploy PowerShell to all of my Windows 2003 x86 servers.

Deploy Microsoft PowerShell - Admin Arsenal

Make certain to use the appropriate installation for your OS (XP, Vista, 2003)

The installation will automatically add the PowerShell directory in your System Path.


Using PowerShell to extract WMI values

  | Share on Twitter Twitter | Share on Facebook Facebook | Submit to Digg digg it |  Add to delicious  delicious |  Submit to StumbleUpon StumbleUpon | Submit to Reddit reddit 

If you aren't using Windows 7 and you haven't installed Windows PowerShell yet, then go here to download and install.

Here are a couple of useful PowerShell examples for common tasks:

Example of Extracting the Total Physical Memory from WMI - Admin Arsenal
Example of Extracting the Total Physical Memory from WMI
Use PowerShell to directly query WMI | Admin Arsenal
Use PowerShell to directly query WMI

The two examples above show how you can use the "-filter" cmdlet to narrow down the results. In this case we filtered out any device where the DeviceId wasn't "C:". The second example shows how you can pass a WMI query using the "-query" cmdlet. In this case we only returned disks that are registered as Fixed Disks ("DriveType = 3")

You can also query remote computers | Admin Arsenal
You can also query remote computers

Using the "-ComputerName" cmdlet you can specify a remote system. This should work for any object under the "get-WmiObject" cmdlet.


All Posts