Thursday, January 31, 2008

Free GP PowerShell cmdlets


SDM Software provides FREE products for managing Windows Group Policy with Windows PowerShell.

SDM Group Policy Refresh Cmdlet 1.0, lets you trigger remote Group Policy refreshes on Windows systems running Windows 2000 and above.

SDM GPMC PowerShell Cmdlets 1.0 is a set of 9 PowerShell cmdlets that wrap the functionality around managing Group Policy Objects available within the GPMC and lets you perform GPO management tasks like creating and deleting GPOs, linking them to sites, domains and OUs, modifying GPO security and backing


You can download both products here.

Wednesday, January 30, 2008

TechNet Spotlight videos


New videos on TechNet Spotlight!

Advanced Windows PowerShell Scripting session (Jeffrey Snover)

This session provides a deep drill into advanced Windows PowerShell scripting techniques. Windows PowerShell provides an incredibly large dynamic range of capabilities from simple to very sophisticated. This session is for those people that have mastered the simple range and want to explore the high end techniques and mechanisms. This session will include a preview and demonstration of features from the next release of PowerShell including remoting and many other wonderful features.


Microsoft Exchange 2007 Service Pack 1 Tips and Tricks (Scott Schnoll)

This session will provide information on how to get more out of Exchange Server 2007 and Exchange Server 2007 SP1. It includes tips and tricks on configuring Exchange, managing Exchange, using the Exchange Management Shell, and more.

Thursday, January 24, 2008

Validating password strength


A question asked in the PowerShell news group:

I have a script that takes user input of a desired username\password for a local account to be created. However, the complex password policy is in effect so a simple password will not work. So if a simple password is put in, it won't ask again for a password, it will just fail and continue. How do i get the PS script to check if it was successful or if it failed and if it failed, prompt again for the information?


I ended up converting a VB.NET code from MSDN. Here's the PowerShell version:

Function Validate-Password{

        [string]$pwd = $(throw "Please specify password"),
        [int]$numUpper = 2,
        [int]$numLower = 2,
        [int]$numNumbers = 2, 
        [int]$numSpecial = 2

    $upper = [regex]"[A-Z]"
    $lower = [regex]"[a-z]"
    $number = [regex]"[0-9]"
    #Special is "none of the above"
    $special = [regex]"[^a-zA-Z0-9]"

    # Check the length.
    if($pwd.length -lt $minLength) {$false; return}
# Check for minimum number of occurrences. if($upper.Matches($pwd).Count -lt $numUpper ) {$false; return} if($lower.Matches($pwd).Count -lt $numLower ) {$false; return} if($number.Matches($pwd).Count -lt $numNumbers ) {$false; return} if($special.Matches($pwd).Count -lt $numSpecial ) {$false; return} # Passed all checks. $true } # Demonstrate that "Password" is not complex. PS > $password = "Password" PS > "'{0}'is complex: {1}" -f $password,(Validate-Password $password)
'Z9f%a>2kQ' is complex: False
# Demonstrate that "Password" is complex. 
PS > $password = "Z9f%a>2kQ"
PS > "'{0}' is complex: {1}" -f $password,(Validate-Password $password)
'Z9f%a>2kQ' is complex: True

When writing this post I got an answer back that the code is too complicated. At first, it may look intimidating.. but this function lets you control how complex you want the password to be. You just need to specify the parameters, they are all self explanatory. All parameters are optional except for password :

# call it with default parameters
if (Validate-Password -pwd "password") {"password is valid"}


The following (one line) validates a password that:

1. Contains at list 10 characters
2. Contains at list 2 upper case characters (default)
3. Contains at list 2 lower case characters (default)
4. Containa at list 3 numbers
5. Contains at list 3 special cahracters


if (Validate-Password -pwd "password" -minLength 10 -numUpper 2 -numLower 2 -numNumbers 3 -numSpecial 3) {"password is valid"}

Wednesday, January 23, 2008

PowerScripting Podcast #17


In this episode you'll get to meet the Girls and Boys, Jean and Greg, the "Guy's" behind the "Scripting Guy's" TechNet column. BTW, you can watch a video on MSDN TV The .NET Show: WMI Scripting (recorded April 07, 2006) where you can actually see them.

P.S. Best regards to Jonathan, be well!

Tuesday, January 22, 2008


I've noticed that some of my older posts has lost their formatting, not sure why, so I'm going to reformat and repost them again.

Monday, January 21, 2008

PowerShell at the tip of your browser


I've created a PowerShell browser toolbar using Conduit community toolbars. It provides one-click access to many PowerShell related resources. Any changes I'll make to the toolbar will automatically be seen by users who installed it, no need to reinstall. The toolbar works on IE and also on any platform that Firefox runs on: Mac, Linux and Windows. If you want the toolbar to be available for both browsers, run setup on each one separately.

If what preventing you from installing it is your precious screen space, remember, you can always hide it.

If you feel I missed something or someone please leave a comment at the bottom of this page. The toolbar is still in progress and will be updated constantly. Here's how it looks:


(The image is sliced due to display width restrictions)




You can access the toolbar (display it) on any windows explorer window, not necessarily Internet Explorer, Just go to View > Toolbars > PowerShell Toolbar






Click the Toolbar Options menu arrow:


In the Toolbar Options you can configure additional components to appear on your toolbar including Email notifier, add or remove buttons or gadgets like the Radio Player or add shortcuts to your favorite commonly-used applications.  

Notice that you can "Refresh Toolbar" for the last changes to appear.


Web Search


All web search is powered by Google. Besides the default "Search" entry I've added additional search providers to the bar. For example, the "Google Microsoft search" option allows you to search inside Microsoft related sites. There's also the option to search blogs with "Google blog search".

Here's how it looks when searching for PowerShell.
There is a button in the toolbar to highlight the search term inside the page.

highlight copy1 
highlight copy  


Your search terms history can be viewed and cleared by clicking on the search arrow.





Various PowerShell blogs. Drop me a line if you blog doesn't appear.

blogs copy



Need to download PowerShell? Get All PowerShell versions and requirement software.

download copy










Here you can define additional radio stations based on your location. Notice that you can listen to all PowerScripting Podcasts directly from the toolbar.




The Chat button provides you with a way to communicate with all other users that use this toolbar. So, click Chat and choose a nick name to start chatting.


chat copy



The Message box allows communication with users in "real time" (15 min). I'll use this feature to send notifications when new content is added to the toolbar.




What's it like outside? Click the Weather button to see your local forecast. the Weather icon changes dynamically according to your current weather conditions.

This component automatically configures itself to your current location, according to your computer's IP. You ca also use this component to check out the weather in thousands of locations around the world.


IE Uninstall
  • Click Start, Settings, and go to Control Panel.
  • Locate the Add/Remove Programs.
  • Search for "PowerShell Toolbar".
  • Select Change/Remove.




    Firefox Uninstall

  • Open the browser and select Tools from the menu.
  • Select Add-ons.
  • Select the Extensions tab.
  • Find the toolbar and select Uninstall.



    That's it. You're all invited to install and explore it. If you find it useful or having improvement suggestion, drop me a line. Click here to install the toolbar.

  • Sunday, January 20, 2008

    Free NetCmdlets license

    via Lance Robinson

    netcmdlets/n software's NetCmdlets extend the features of Microsoft Windows PowerShell with a broad range of network management and messaging capabilities. The current release contains more than 30 Cmdlets providing access to network and host protocols such as SNMP, LDAP, DNS, Syslog, HTTP, WebDav, FTP, SMTP, POP, IMAP, Rexec/RShell, Telnet, and more.


    NetCmdlets is available for free for non-commercial use.  Check out the NetCmdlets hobbyist license here.

    The ordering process does not require a credit card unless you request a physical cd shipment.  For electronic download, just be sure to enter your name and email address!

    Friday, January 18, 2008

    Releasing the Source Code for the .NET Framework Libraries

    This may be outdated but I've just found it :)

    ScottGu's Blog reports that the Microsoft's .NET Framework Library Source Code is available for viewing and debugging with .NET 3.5 and VS 2008.

    The first .NET Base Class Libraries to be released (with source file comments included) are:

    • System
    • System.IO
    • System.Collections
    • System.Configuration
    • System.Threading
    • System.Net
    • System.Security
    • System.Runtime
    • System.Text
    • ASP.NET (System.Web)
    • Windows Forms (System.Windows.Forms)
    • ADO.NET (System.Data)
    • XML (System.Xml)
    • WPF (System.Windows)

    New libraries will be released in the months ahead (including WCF, Workflow, and LINQ). The source code will be released under the Microsoft Reference License (MS-RL).

    The .NET Framework source libraries will be available for download via a standalone install. and can be viewed with any text editor. It will also provide integrated debugging support from within VS 2008, enabling developers to step through and review the source.

    To learn more about the source release plans and how the debugger integration works, please check out this Podcast that Scott Hanselman and Shawn Burke recently recorded.  There is also a video by Shawn Burke on Channel9 that shows how integrated debugging support works in VS 2008.

    Professional Windows PowerShell for Exchange Server 2007 SP1


    New book, by WROX, on managing Exchange 2007 SP1 with Windows PowerShell has just released.





    Book Description

    If you want to dramatically improve your implementation and administration of Exchange Server 2007, then this is the book for you. It walks you through the ins and outs of PowerShell, showing you how to take full advantage of this scripting language for deploying, configuring, managing, and maintaining your Exchange environment.

    You'll first explore Windows PowerShell and the Exchange Server 2007 Management Shell. Next, you'll discover how to work with the new Exchange server roles as well as how to use the cmdlets and features that are specific to these roles. You'll then discover how to successfully bring PowerShell into your environment and work with users and groups. Numerous examples are integrated throughout the chapters so you'll be able to quickly apply the information to enhance your Exchange experience.

    What you will learn from this book

    • All of the PowerShell for Exchange fundamentals so you can quickly get started

    • Methods for working with Exchange User and Group Objects

    • Ways to configure the Client Access Server, Hub Transport, Mailbox Server and Unified Messaging Server roles

    • Best practices for utilizing PowerShell in a production environment

    • How to work with routing in Exchange 2007, continuous replication, and single copy clusters

    • Techniques for automating administration to ensure optimal performance

    Scripting SQL Management Objects in Windows PowerShell



    This book, by Willis Johnson, shows how to communicate with SQL Server using SQL Management Objects in Windows PowerShell scripts.

    Topics include how to create Windows PowerShell scripts that use SQL Management Objects (SMO) to manage and program SQL Server.   

    In addition, you will learn about areas of potential difficulty and see how to avoid them—for example, the use of '$' in instance name, quote nesting rules, connection pooling, and schemata.


    The scripts :

    • Load SMO
    • Create a server object; get a user’s credentials from the UI into a safestring
    • Connect to SQL Server using SQL Server authentication
    • Connect to SQL Server using Windows authentication
    • Profile a server instance by examining its properties
    • Use WMI to examine and configure a server’s Windows service
    • Use PowerShell cmdlets to start, stop, and restart a service; check for the existence of a database
    • Verify a file path
    • Save data in a csv file
    • Retrieve data from a csv file
    • Create a database, a schema or a table
    • Insert data in a table
    • Execute ad hoc T-SQL queries
    • Retrieve information about views
    • Create reports in HTML format
    • Display HTML reports in a browser window
    • Launch a Windows process
    • Tweak data format

      A downloadable ZIP archive is included which contains all the example scripts, as well as additional scripts.

    The electronic version of the book is available for only US $6.99.

    Wednesday, January 16, 2008

    Exchange 2007 in Depth - Webcasts series

    blogstrocity is delivering Part 1 of an 8 part series on Exchange 2007. Today is the Intro to the Exchange session. It reviews Exchange roles, why Exchange is 64 bit only, and demos on the new features in OWA, AutoDiscover, and Transport Rules.

    There's a chance that by the time this post will publish you won't be able to register the first webcast cause its already broadcasting? If so, here is the link for the second webcast.

    Monday, January 14, 2008

    Convert VB.NET code to C#

    This free utility from Developer Fusion converts code from VB.NET to C# and vice versa.


    Saturday, January 12, 2008

    Get without a verb

    Did you know that you can call any "Get" verb cmdlet without specifying it? (via Guy's Ezine)


    # Get-Process
    PS > process Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName ------- ------ ----- ----- ----- ------ -- ----------- 15 2 21532 4092 29 3.92 2404 _IISCHAgent 65 3 1144 1468 33 3.25 1988 Agent 40 3 1052 1432 30 2.91 3548 AGRSMMSG


    PS > service
    Status   Name               DisplayName
    ------   ----               -----------
    Stopped  Alerter            Alerter
    Running  ALG                Application Layer Gateway Service
    Stopped  AppMgmt            Application Management

    Friday, January 4, 2008

    TelePresence - the future of video conferencing


    Got to see this to believe, the guy on the right is a three-dimensional holographic figure, live'n kicking. Future is already here!

    You can download the movie here (31.5MB)

    Thursday, January 3, 2008

    New PowerShell TechNet event

    The two sessions event will be delivered by Richard Siddaway.

    Windows Powershell will ship as part all future major Microsoft products including Windows 2008. These two sessions will show you how to manage Windows Server 2008 and your Windows environment with Windows PowerShell as well as covering some of the features of PowerShell V2. Starting with an overview of Windows PowerShell and WMI we will show how local and remote systems can be managed by WMI and the new remoting features in Windows PowerShell V2. We will look at some of the new features in Windows Server 2008, including Server Core, Active Directory and IIS 7, and show how Windows PowerShell is the ideal management tool for automating your administrative experience.


    Wednesday, January 2, 2008

    PowerShell LUHN validation


    I came across an interesting security post on Detecting Credit Card Numbers in Network Traffic. Section 2.3 caught my eye and 2 seconds later I was on WIKI's Luhn algorithm page. Soon enough I found myself converting the code to PowerShell. So, pull out your credit card and check its number.


    ## Returns true if the given array of digits represents
    ## a valid Luhn number, and false otherwise. function Test-LuhnNumber([int[]]$digits){ [int]$sum=0 [bool]$alt=$false for($i = $digits.length - 1; $i -ge 0; $i--){ if($alt){ $digits[$i] *= 2 if($digits[$i] -gt 9) { $digits[$i] -= 9 } } $sum += $digits[$i] $alt = !$alt } return ($sum % 10) -eq 0 }
    ####################################################### ## Generates a number that passes the Luhn algorithm function New-LuhnNumber([int]$length){ $random = new-object random $digits = new-object int[] $length for($i = 0; $i -lt $length - 1; $i++){ $digits[$i] = $ } [int]$sum = 0; [bool]$alt = $true for($i = $length - 2; $i -ge 0; $i--){ if($alt){ [int]$temp = $digits[$i] $temp *= 2 if($temp -gt 9){ $temp -= 9 } $sum += $temp } else { $sum += $digits[$i] } $alt = !$alt } [int]$modulo = $sum % 10 if($modulo -gt 0) { $digits[$length-1] = (10 - $modulo) } return $digits }

    ## testing...
    PS > Test-LuhnNumber (0..9) False
    PS > Test-LuhnNumber (New-LuhnNumber 10)
    PS > Test-LuhnNumber (New-LuhnNumber 15)
    PS > Test-LuhnNumber (4,4,6,6,6,7,6,5,1)
    PS > Test-LuhnNumber @(2,8,6,3,7,7,1,1,2)
    PS > Test-LuhnNumber @(0,6,6,2,4,9,1,8,9,2,3)
    PS > Test-LuhnNumber "0","6","6","2","4","9","1","8","9","2","3"
    PS > Test-LuhnNumber ([string[]][char[]]"67276171468")

    Tuesday, January 1, 2008

    Creating and managing processes in PowerShell



    PowerShell's get-process cmdlet gets the processes that are running on the local computer, and is restricted to the local computer only, you can't interact with processes that runs on remote computers nor create ones locally or remotely.

    You can use WMI (see below), but I want to show another way of doing it, less documented one - static methods.

    Static methods give you the option to break loose of the cmdlet 'wrapper' and work directly on the underlying NET class. To find which static methods you can use on processes we'll use PowerShell Get-Process cmdlet, we'll pipe it to Get-Member to reveal the underlying NET type that get-process is using: 


    PS:55 >Get-Process | Get-Member
       TypeName: System.Diagnostics.Process
    Name                       MemberType     Definition
    ----                       ----------     ----------
    Handles                    AliasProperty  Handles = Handlecount
    Name                       AliasProperty  Name = ProcessName



    Managing processes with static methods

    As you can see, below the surface, Get-Process is using the [System.Diagnostics.Process] NET type to retrieve a process object for each process. From now on, you can work with the static methods of this type to interact with process objects. To find the static methods (surround the type name with square brackets), type:

    PS > [System.Diagnostics.Process] | Get-Member -Static -MemberType method

    TypeName: System.Diagnostics.Process
    Name               MemberType Definition
    ----               ---------- ----------(...)
    EnterDebugMode     Method     static System.Void EnterDebugMode()...
    Equals             Method     static System.Boolean Equals(Object...
    GetCurrentProcess  Method     static System.Diagnostics.Process G...
    GetProcessById     Method     static System.Diagnostics.Process G...
    GetProcesses       Method     static System.Diagnostics.Process[]...
    GetProcessesByName Method     static System.Diagnostics.Process[]...
    LeaveDebugMode     Method     static System.Void LeaveDebugMode()...
    ReferenceEquals    Method     static System.Boolean ReferenceEqua...
    Start              Method     static System.Diagnostics.Process S...


    The Definition column shows all the available overloads for each method. The notation for calling a static method is:
    PS > [System.Diagnostics.Process]::StaticMethodName(<args>)

    Lets find the overloads for the GetProcesses method, (each overload is delimited with a comma):

    PS > ([System.Diagnostics.Process] | gm -s GetProcesses).Definition

    static System.Diagnostics.Process[] GetProcesses(),
    static System.Diagnostics.Process[] GetProcesses(String machineName)

    The output shows two ways to call the method. You can call it with no arguments and get all running processes on the local computer or use the later to get processes from a remote computer. We are interested in the second one since it accept a string argument for a computer name. To save typing space we'll assign the type name to a variable:

    PS > $process = [System.Diagnostics.Process]

    # examples
    $process = [System.Diagnostics.Process]

    # get all running processes on the remote server
    PS > $process::GetProcesses($server)

    Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
    -------  ------    -----      ----- -----   ------     -- -----------
        165       7    15364      21684    56            2992 vmserverdWin32
        196       6     2764       5132    54            3740 LVComSX
         73       4     1100       3392    30            2452 ctfmon

    As you can see the output is the same output produced by the get-process. To find which methods you can invoke on a process, pipe it to get-member:

    PS > $process::GetProcessById(2992,$server) | gm -member method

       TypeName: System.Diagnostics.Process

    Name                      MemberType Definition
    ----                      ---------- ----------
    Close                     Method     System.Void Close()
    CloseMainWindow           Method     System.Boolean CloseMainWindow()
    CreateObjRef              Method     System.Runtime.Remoting.ObjRef Cr
    Dispose                   Method     System.Void Dispose()
    Kill                      Method     System.Void Kill()
    Refresh                   Method     System.Void Refresh()
    Start                     Method     System.Boolean Start()
    ToString                  Method     System.String ToString()
    WaitForExit               Method     System.Boolean WaitForExit(...


    This are the same methods you'll get if you run get-process | gm -member method. To call a static method simply append it to the command:

    PS > $process::GetProcessById(2992,$server).Kill()

    In the same manner you can get a list all properties of a process.

    PS > $process::GetProcessById(2992,$server) | gm -member property

    # get remote process by its process id
    PS > $process::GetProcessById(2992,$server)

    Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
    -------  ------    -----      ----- -----   ------     -- -----------
        165       7    15364      21684    56            2992 vmserverdWin32

    # get remote process by its name
    PS > $process::GetProcessesByName("vmserverdWin32",$server)

    Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
    -------  ------    -----      ----- -----   ------     -- -----------
        165       7    15364      21684    56            2992 vmserverdWin32

    # get PowerShell's process, locally
    PS > [System.Diagnostics.Process]::GetCurrentProcess()

    Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
    -------  ------    -----      ----- -----   ------     -- -----------
        512       9    39340      33148   163     4.06  11952 powershell


    Creating local processes

    To create processes, locally, you need to use the static Start() method. To find what overloads this method takes:

    PS > $process = [System.Diagnostics.Process]
    PS > (($process | gm -static start).definition).replace("static","`nstatic")
    static System.Diagnostics.Process Start(String fileName, String userName, SecureString password, String domain),

    System.Diagnostics.Process Start(String fileName, String arguments, String userName, SecureString password, String domain),

    System.Diagnostics.Process Start(String fileName)

    static System.Diagnostics.Process Start(String fileName, String arguments),

    static System.Diagnostics.Process Start(ProcessStartInfo startInfo)


    There are five different ways to call it, each overload accepts different set of arguments:

    1. Run a file (executable) with alternate credentials and a secure password.
    2. Adds an option to add arguments for the file name.
    3. Gets only file name.
    4. File name and arguments, no alternate credentials.
    5. Gets a ProcessStartInfo object.


    # Use the third overload to run notepad

    PS > [System.Diagnostics.Process]::Start("notepad")
    Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
    -------  ------    -----      ----- -----   ------     -- -----------
          0       1      136         84     1     0.00  13720 notepad
    # Use the fourth to run notepad with arguments, in this case make notepad load the system.ini file.
    PS > [System.Diagnostics.Process]::Start("notepad","$env:windir\system.ini")
    Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
    -------  ------    -----      ----- -----   ------     -- -----------
          5       1      340        840     8     0.03  23728 notepad

    BTW, if you want to avoid the default output, assign the command to a variable or cast it to [void], as in:
    PS > [void][System.Diagnostics.Process]::Start("notepad","$env:windir\system.ini")
    PS >

    The fifth option is the one I want to use since it is using another type to specify what starting info to assign to the new process, including alternate credentials (though in plain text and not secure as the first and second overloads which uses the SecureString parameter). Here's a partial property list, you can find the full list here:

    - Arguments
    - FileName
    - Password
    - UserName
    - WorkingDirectory


    Using the New-Object cmdlet

    In this example I'll use the New-Object cmdlet to instantiate a new System.Diagnostics.ProcessStartInfo object to specify a set of values to be used when the process start:

    # Specifies a set of values that are used when you start a process.
    $si = new-object System.Diagnostics.ProcessStartInfo
    $si.fileName = "notepad.exe"
    $si.Arguments= "$env:windir\system.ini"
    $si.WorkingDirectory = $pwd
    # this will launch the process in the background (hidden)
    # $si.windowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden
    # run process under alternate credentials
    # $si.UserName="username"
    # $si.Password="Password"

    # start the process
    $process = New-Object System.Diagnostics.Process

    # this is also valid
    # $process = [System.Diagnostics.Process]::Start($si)

    # close notepad and watch the output
    if($process.start()) { $process.waitForExit(); "existed"} 


    Note: The WaitForExit() method is available only for processes that are running on the local computer. If you need to track a process on a remote system construct a loop to check if the remote process exists.
    Want to know how to list all name/value pairs of the [System.Diagnostics.ProcessWindowStyle] type or any other [enum] type, see my post on Listing enumeration type values.



    Creating remote processes

    So far so good. But how about creating new processes on remote computers? Well, that's another story (Class). None of the above, Get-Process nor its underlying type, let you do that. The only way to do it is by using WMI.

    You can access WMI with the Get-WmiObject cmdlet or with PowerShell's Type accelerators (shortcuts). Type accelerators were developed by the Windows PowerShell team to make WMI scripts more easy to write for system administrators:

    [WMI] - type accelerator for ManagementObject.
    [WMICLASS] - type accelerator for ManagementClass.
    [WMISEARCHER] - type accelerator for a ManagementObjectSearcher.

    See the second resource link below for more information on this. 


    Here's a one-liner to create new process(es) on local/remote computers:

    PS > ([WMICLASS]"\\$computer\ROOT\CIMV2:win32_process").Create("notepad")
    __GENUS          : 2
    __CLASS          : __PARAMETERS
    __SUPERCLASS     :
    __DYNASTY        : __PARAMETERS
    __RELPATH        :
    __DERIVATION     : {}
    __SERVER         :
    __NAMESPACE      :
    __PATH           :
    ProcessId        : 7380
    ReturnValue      : 0

    If the ReturnValue property is set to 0 then you've successfully created the process on the remote computer, the ProcessId property shows the process id for the new process on the remote computer.

    Note: For security reasons the WMI Win32_Process.Create method cannot be used to start an interactive process remotely (it runs hidden, in the background).



    The above technique on static methods, opens a whole new world of discovering PowerShell and NET classes. You can apply it to any cmdlet and work your way up or down, depending on your point of view :-). Soon enough you'll find your way to MSDN, where you can get more information and code examples on each class.

    This post only scratches the surface and there's a lot more to write on processes... but now comes your part. Check out what Get-Service has to offer and what can you get by applying all of this to it.

    Last but not least, I'd like to thank Hal Rottenberg from TechProsaic and the PowerScripting Podcast for his help with editing and prompting me to write this article.

    Happy New Year!


    Additional Resources:

    Managing Processes in PowerShell
    Improved Support for WMI
    Getting Services associated with a Process via PowerShell
    Process Class
    ProcessStartInfo Class
    Create Method of the Win32_Process Class
    Casts and Get-WmiObject