PowerShell Remoting Project Home

Thursday, June 29, 2006

PowerShell Remoting version 0.2.7.1




Download here

Uninstall old version of PowerShell Remoting before install newer version.
  1. New GUI client manager: Save/delete server information & connection option, generate connection script automatically, launch powershell remoting client directly.

  2. Add option to reject connection if user found invalid remote X509 certificate.

  3. Bug fix: Null login credential (press Cancel in CredUI window) cause server crash and client throw Null reference exception.

  4. Bug fix: other minor bugs
Check out the help.chm in release package for details.

Have Fun

Tags:       



Thursday, June 22, 2006

Enter Nested Prompt function

In windows PowerShell, $Host object provides direct access to some important APIs. One of the interesting functions is $Host.EnterNestedPrompt(). Frankly speaking, it did not appeal to me at all when I first tried it. But I discovered this beauty after I implemented my own PSHost  in PowerShell Remoting,

What did it do?
  1. Suspend & Save current execution context state.
  2. Create a new nested execution context.(Nested pipline, new prompt execution helper and new script excution helper)
  3. Push the new nested execution context to stack. (PowerShell use a static stack. In my PowerShell Remoting, it is more complicate. Every client has its own host; every host has its own stack for nested prompt.)
  4. Increase $NESTEDPROMPTLEVEL
That is to say:
  1. Your current pipeline is suspended. All variables and errors state were saved.
  2. In the meantime, you still have access to monad engine. You can have new prompt, run new script or other interactive command.
  3. When you are done with the new scope, you can call invoke $Host.ExitNestedPrompt()  or "exit" (which will call $Host.ExitNestedPrompt())  to return to previous pipeline.
What can I do with it?
  1. First, Let's see how "Suspend" works when using -confirm option or "Set-PSDebug -Step"
  2. > kill 2804 -Confirm

    Confirm
    Are you sure you want to perform this action?
    Performing operation "Stop-Process" on Target "Notepad (2804)".
    [Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help
    (default is "Y"):

    > Set-PSDebug -Step
    > D:\ps1\special.ps1

    Continue with this operation?
       1+ D:\ps1\special.ps1
    [Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help
    (default is "Y"):
    When you choose [S]Suspend, you actually called $Host.EnterNestedPrompt() which break current script and provide you an nested prompt.
  3. Secondly, $Host.EnterNestedPrompt() can be used as break point when debugging your script.
  4. To make a break point, you can add $Host.EnterNestedPrompt() at anywhere in your script. When your script execute to it, you will have a nested prompt to explore variables and errors at this break point.
    > 1..10 | %{if($_ -eq 5) {$host.EnterNestedPrompt()};$_}
    1
    2
    3
    4
    >>> $_
    5
    >>> exit
    5
    6
    7
    8
    9
    10
Be careful
  1. Nested prompt and original prompt share same variables provider. So when you change a variable in nested prompt, the change will remain effective in original prompt.
  2. Comannd will be written in history when it is completed. So a suspended command will not be found in history.
  3. The maximum depth of nested prompt level ($NESTEDPROMPTLEVEL) is 128. So always check $NESTEDPROMPTLEVEL for current nested prompt level. You can write it into your prompt function.
  4. Do not try to make a nested function using $Host.EnterNestedPrompt(). But you can always do this.
  5. function factorial
    {
        param ([int]$n = 1)
        if ($n -le 0)
        {
            "Invalid parameter."
             return
        }
        if ($n -eq 1)
        {
            return 1
        }
        return $n * (factorial ($n-1))
    }
Reference: Start-NewScope

Tags:       



Monday, June 12, 2006

What Access Rights Do You Have?

A PowerShell script to check User/Group access rights on FileSystem and Registry.

Yesterday, I was reading post on Mark's Sysinternals Blog: The Power in Power Users. It says "a user that belongs to the Power Users group can easily elevate themselves to fully-privileged administrators". He used a tool called AccessChk to find out what access rights does "Power User" group have.

If you read my serise posts on access control list in monad.  you will find out that we can get/set access rule in PowerShell directly without using extra tools. So I wrote a PowerShell script (Check-AccessRights.ps1) to get similar function as AccessChk. It is pretty dirty, but dose the job. You may want to try
D:\ps1\Check-AccessRights.ps1 .\
# Check your access rights on current path (could be filesystem or registry)
or
D:\ps1\Check-AccessRights.ps1 HKLM:\sytem\CurrentControlSet\Services $true "Power Users"
# HKLM:\sytem\CurrentControlSet\Services is Path to check
# $true is to get child object ACL recursively
# "Power Users" is user/group
Be prepared if you use -Recurse option ($true), you may want to redirect results to a file.
#################################################################
#
# File: Check-AccessRights.ps1
# Author: Tony (http://MSHForFun.blogspot.com/)
# Parameters:
#    $Path:  PowerShell Path (for example, c:\ or HKLM:\)
#    $Recurse: Check child object recursively
#    $Account: User name / Group (for example, "domain\alice",
#               "Power Users")
#
################################################################
param([string] $Path = {throw "Please specify a path"}, [bool] $Recurse = $false, [string] $Account)
if (-not (test-path $Path))
{
    $Path + " not exists!"
    return
}
if ([string]::ISNullOrEmpty($Account))
{
    $SID = ([System.Security.Principal.WindowsIdentity]::GetCurrent()).Owner
}
else
{
    $SID = (new-object System.Security.Principal.NTAccount($Account)).Translate([System.Security.Principal.SecurityIdentifier])
    if ($SID -eq $null) {return}
}
"Account: " + $SID.ToString()
"Path: " + $Path
$AccessRules = (get-acl $Path).Access
if ($AccessRules -eq $null)
{
    "Can't get access rules!"
    return
}
$AccessRules|foreach-object {
    $CurrentSID = $_.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier])
    if ($CurrentSID.ToString() -eq $SID.ToString())
    {
        $_
    }
}
if ($Recurse)
{
    Get-ChildItem $Path -Recurse| foreach {
        "========================================"
        "Child Path: " + $_.ToString()
        $AccessRules = (get-acl $Path).Access
        if ($AccessRules -eq $null)
        {
            "Can't get access rules!"
            return
        }
        $AccessRules|foreach-object {
            $CurrentSID = $_.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier])
            if ($CurrentSID.ToString() -eq $SID.ToString())
            {
              $_
            }
        }
    }
}

Have Fun

Tags:       



Wednesday, June 07, 2006

PowerShellIDE: the Good, the Bad and the Ugly

PowerShellIDE? Yes, an IDE for PowerShell! Oh, boy! That's a whole lot fun. If you like PowerShell, you should try this out.

The good:
It is advertised (it is free at this moment) as "The World's First PowerShell Editor" (what is "PowerShell Analyzer" then?) and wrapped in a dazzling GUI (you should really checkout its Mac style chooser).

You got intellisense functionality, a debugger, variable explorer and properties window.

You can set up a breakpoint in your script and checkout pipline in a GUI environment.

It is the first GUI Monad hosting application I have seen which can handle legacy console application (like ping.exe or netshe.exe)

The bad:
1. Not yet implemented.
You'd better forgot about following API:
Read-host -AsSecureString (ReadLineAsSecureString)
PromptForCredential
SetBufferContents
Getbuffercontents

2. It is not the same!
Don't expect same user experience with
Write-progress
$host.UI.ReadLine() (Oops, Popup window)
$host.UI.RawUI.ReadKey()

The ugly:
PowerShellIDE has to be run under Administrator account. This is killing me. Come on, men! Why it has to read prefetch?
PowerShellIDE.E:3300    OPEN    C:\WINDOWS\Prefetch\POWERSHELLIDE.EXE-3628D30E.pf    ACCESS DENIED
Some other thoughts:
I came across someone's post (I forgot where) talking about PowerShell: "This thing is for Programmer." Now, we have an IDE for PowerShell. It again prove "This thing is for Programmer." Remember the famous joke about Microsoft Visual Studio:" The IDE is so good and you were having so much fun with it. Eventually you forgot what you were doing." This is exactly what happened here:

Despite of intellisense, the entire "breakpoint, pipline reader and properties" thing can be done in PowerShell.exe command line directly. Just add "$host.EnterNestedPrompt()" in my script, I can get current pipline status, explore properties as I wish. But in the windows world, everyone indulged themselves to the IDE thing. People always try to find an IDE desperately even there is no need for that. I bet those guys from "slash dot" will laugh at us again.

Tags:       



Tuesday, June 06, 2006

PowerShell Remoting version 0.2.6.0

Download here

Uninstall old version of PowerShell Remoting before install newer version.
  1. Write Server Information & Error to EventLog (Source: PowerShellRemoting). Log file will no longer be used by newer version.

  2. SSL support using SSLStream.

  3. Warning: SSL is for advanced user.
    If you want to provide SSL support to server, you should

    • Get X509 certificate for server. For testing purpose, you can use makecert.exe (included in .NET framework SDK)
    • Install X509 certificate at StoreLocation: LocalMachine, StoreName: My (personal).
    • Grand "NetworkService" account read access to X509 certificate associated private key file.
    • Set [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PowerShellRemoting\Parameters\ X509] to thumbprint of X509 Certificate.

      There is pretty good walkthrough at John Howard's blog.

  4. X509 Option

  5. [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PowerShellRemoting\Parameters]
    "X509"="0"

  6. DebugHost Option (Default 0: false)

  7. [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PowerShellRemoting\Parameters]
    "DebugHost"=dword:00000000

  8. Bug fix: Write-Progress throw null object Exception.
Check out the help.chm in release package for details.

Have Fun

Tags: