Tuesday, March 31, 2009

SMS Module Updated

I updated the SMS Module (old post here) for PowerShell v2. I'm using it with v2 CTP3. Now you can type "help " to get help on these functions, and check out the old post for more examples of how you can use the Get-SmsWmi and Find-SmsId functions.

Functions included are:
  • Get-SmsWmi - Makes it easy to get WMI objects from the SMS Provider. (Note: call this function with no parameters to get a list of acceptable class nicknames)
  • Find-SmsId - Look up SMS WMI objects by ResourceID, CollectionID, PackageID, or AdvertisementID
  • Get-SmsCollectionTree - Inspired by tree.com from DOS, prints out the Collection structure of your site, with CollectionIDs and names.
  • Approve-Client - Marks an SCCM client as Approved in the SCCM DB.
Don't forget to set the $default_wmi_provider_server and $default_site variables at the top of the module to match your environment.



Wednesday, February 18, 2009

Get-ChildItem (dir) Results Color-Coded by Type

I always liked the way you can color code your directory items in Linux. I always set alias ls='ls -al --color' the minute I log into a system. It makes it easier to scan results and instantly know some extra data about the items in a directory.

I decided that I wanted to be able to do this in PowerShell. If you do a few Google searches you'll see I'm not the first, and it's not without it's quirks, but I decided not to worry about being true to the Linux form and just go with the spirit of what I wanted to get out of it. I've included the code below. There are a couple of things of note, though it's mostly waht I wanted:
  • I would rather if the header at the top wasn't always the same color as the first item, but I can't think of any way around that.
  • Rather than coloring results by permissions, I've colored them by type, with four major types: Directory, Executable, Compressed, and Text.
  • If you use sort or select you'll lose the color, but otherwise the color change should last down the pipeline for each obect.
  • This was made to be used with v2.0 CTP3 of PowerShell. If you want to use it with earlier versions you have to remove the documentation block at the beginning of the function, but you also lose the ability to use the help command to find out more about the function.
  • Note that I compile the Regular Expressions at the beginning. If I just used -match to check the regular expressions for each file, I would add a lot of extra overhead, because the regular expressions would be compiled each time a file was checked. This boosts performance, and there is an analogue in each language that supports regular expressions.




Thursday, November 6, 2008

Like VIM? Like PowerShell? This link's for you!

Vim is a text editor that is popular with *nix users, but it works just fine on Windows, too.  

I subscribe to Andy Schneider's Get-PowerShell blog, and today he had an entry about a new extension for Vim that does your syntax highlighting, etc, for PowerShell.  I recommend checking out the Get-PowerShell blog, but if you just want the file, follow the link from Peter Provost's blog.

Tuesday, November 4, 2008

Did I Mention PrimalForms is free?

Here's that link again.

Oh, and for some reason this post shows up under the Google search , but click here if you want a PrimalForms example.

Windows Forms with PowerShell

SAPIEN came out with an awesome form builder for PowerShell called PrimalForms.  I decided to give it a whirl.  It really makes short work of making a native Windows GUI.  For my first project I made a quick and dirty app that allows me to get disk fragmentation data for a remote server using the DefragAnalysis method of Win32_Volume.  I used the PrimalForms GUI to create my form, and then I only had to fill in the button1 click handler and the form load handler, add a small function for printing to the text box, and voila!






Friday, October 31, 2008

Defrag Your Servers Remotely with PowerShell

Another quick and dirty script.  I've got a couple servers that are running applications that suffer from disk thrashing, and are running Windows Server 2003.  A defrag tends to noticeably increase performance.  With this script I can kick off a defrag from my desk whenever I want.






Friday, October 3, 2008

Get-SmsWmi and Find-SmsID

I work with SMS (Systems Management Server) at work a lot, so I whipped up two functions that I've found invaluable for automating tasks in SMS, which I alluded to briefly in this post, which contains the source for the functions.

I thoght I'd post today about how these can be used and why they would be useful.  Think of it as the beginnings of a Get-SmsWmi cookbook.

Note:  I alias Get-SmsWmi to 'gsms', so keep that in mind for the examples.

Get a list of all available object nicknames.

C:\PSScripts> gsms

ERROR: You must enter a class name or nickname.

Valid nicknames are:

  AddRemovePrograms
  AdStatus
  Advertisement
  Collection
  ComputerSystem
  DistributionPoint
  LogicalDisk
  MembershipRule
  NetworkAdapter
  NetworkAdapterConfiguration
  OperatingSystem
  Package
  PackageStatus
  Program
  Query
  Server
  Service
  Site
  StatusMessage
  System
  WorkstationStatus
  User

Note: You only need to type as many characters as necessary to be unambiguous.


Get all computers with 'tojo' in the name.

gsms sys 'Name LIKE "%tojo%"' |
  Format-List ResourceId, 
  Name, 
  LastLogonUserName, 
  LastLogonUserDomain, 
  IPAddresses


ResourceId          : 220647
Name                : SOMETOJO-CORP
LastLogonUserName   : sometojo
LastLogonUserDomain : MYDOMAIN
IPAddresses         : {1.1.1.1}


Get all advertisements for the package with PackageID 'S01002BE'

gsms adv 'PackageId = "S00002BE"' |
  select AdvertisementID,
  AdvertisementName,
  @{Name = 'PackageName'; Expression = {(Find-SmsId -p 'S00002BE').Name}},
  PackageID,
  ProgramName |
    Format-List

AdvertisementID   : MV12071F
AdvertisementName : iPass Upgrade
PackageName       : iPass Upgrade
PackageID         : S00002BE
ProgramName       : Update iPass


Delete all packages for a particular distribution point.

gsms pack 'ServerNALPath LIKE "%servername%"' | % {$_.Delete()}


Get a directory listing of all Collections and their subcollections.

# Get-SmsCollectionTree
#
# Writes an indented list of collecitons by parent
#
# Args:
#   $root: The CollectionID of the parent collection
#   $indent: The indentation level for screen output

function Get-SmsCollectionTree {
  param([string]$root = 'COLLROOT',
        [int]$indent = 0)

  Get-SmsWmi SMS_CollectToSubCollect "parentCollectionID = '$root'" |
    % {$name =  (Find-SmsID -c $_.subCollectionID).Name
       Add-Member -InputObject $_ -Name 'sub_name' NoteProperty $name
       $_} |
      sort sub_name |
        % {Write-Host (('    ' * $indent) +
                        "+ $($_.sub_name) : $($_.subCollectionID)")
           Get-CollectionTree $_.subCollectionID ($indent + 1)}
}

Add all packages to a DP.

$dp = gsms SMS_SystemResourceList 'ServerName = "sms-dp-01" and RoleName = "SMS Distribution Point"'

foreach ($pkg in (gsms package)) {
  $new_object = ([wmiclass]"\\sms_srv\root\sms\site_MV1:SMS_DistributionPoint").CreateInstance()
  $new_object.ServerNALPath = $server.NALPath
  $new_object.PackageID = $pkg.PackageID
  $new_object.SiteCode = 'S00'
  $new_object.SiteName = 'My SMS Site'
  $new_object.Put()
}

Note:  That wmiclass/CreateInstance trick I did isn't very well documented, but if you need to create an instance of a class then that's how you can do it.  Also remember that when reading and writing to WMI for SMS, you should be connecting to the server with the SMS Provider, not necessarily the site server.  If you have a separate SQL Server then it might be that server.

That's it for today, but you can see how easy it is to start grabbing data directly from WMI and using it in a script.  If you have any questions drop them in the comments or shoot me an email, I don't get that much traffic.

For a complete list of the WMI classes, download the Configuration Manager 2007 SDK.