# Sunday, November 01, 2009

One of the things that never quite fit well with me with the remoting feature in PowerShell 2.0 is that while you can “telnet” to remote systems with Enter-PSSession and import commands and do all sorts of cool tricks, there is no way to send or retrieve files from the console. It seems like such a waste that you configure WinRM up with SSL and Kerberos and get this nice encrypted channel up, but if you want to transfer files you have to revert to file shares, remote desktop or classic ftp.

Back in the “good ole’ days” of BBSs and FidoNet, people used to use simple protocols like XModem (advancing to YModem and then ZModem) or Kermit that worked by streaming character data directly to your terminal. It wasn’t fast or particularly efficient, but it got the job done. I thought I’d take a crack at building something similar for PowerShell, and this first 0.5 release is the fruits of this weekend’s tinkering. At the moment it only can “pull” a file to the local system from a remote session, but the next release will allow “pushing” a file from a local system to a remote session.

image

The reason I named it after XModem is because it works in a similar way: files are not “pulled” from the remote server, but instead are “pushed.” X[YZ]Modem file transfer was initiated by the remote end. I’ll not spoil the fun by explaining how it works, but I think you’ll enjoy pulling it apart. It’s in a module format and is implemented in pure script.

Requirements

  • PowerShell 2.0 installed on both client and server with remoting enabled to the location of the file being transferred.

E.g. if you want to grab a file using Get-RemoteFile from a remote server, you must be able to create a valid PSSession to it with the New-PSSession cmdlet. When Send-LocalFile is implemented, you’ll need remoting enabled in the other direction too.

  • The PMODEM module must be findable on both the client and server via import-module and must be the same version.

Here’s the Get-RemoteFile function help (via –?):

NAME
    Get-RemoteFile

SYNOPSIS
    Retrieves a file from a remote computer via a supplied PSession.


SYNTAX
    Get-RemoteFile [-Session] <pssession> [-RemoteFile] <string> [[-LocalPath] <string>] [[-PacketSize] <int32>]
	[-PassThru] [-AsJob] [<commonparameters>]


DESCRIPTION
    Retrieves a remote file from a server via a supplied PSSession. All communication
    is performed out-of-band, yet inside the secure WinRM channel.

    No other ports, file shares or any other special configuration is needed. However,
    the PMODEM module must be on the remote computer and findable in its $ENV:PSModulePath;
    the protocol versions must also match on both ends. You will be warned of any
    misconfiguration(s).

    When not running asynchronously, progress records are generated.


RELATED LINKS

REMARKS
    To see the examples, type: "get-help Get-RemoteFile -examples".
    For more information, type: "get-help Get-RemoteFile -detailed".
    For technical information, type: "get-help Get-RemoteFile -full".

Things coming in later releases: wildcards/multiple file support, compression and integration via proxy functions (copy-item/move-item/remove-item/rename-item etc).

Download PModem

Grab pmodem-0.5.zip and unzip it into a folder in your $ENV:PSModulePath on the client and server computers you want to use PMODEM on.

Have fun!

posted on Sunday, November 01, 2009 8:57:10 PM (Eastern Standard Time, UTC-05:00)  #    Comments [1] Trackback
# Friday, October 30, 2009

UPDATE: Some general information on remoting: Hey, Scripting Guy! Tell Me About Remoting in Windows PowerShell 2.0
UPDATE 2:
This also applies to machines not attached to a domain (thanks @alexandair)

If you’re running Windows 7 (and if not, why not?) you may have noticed that premium versions include a license for Virtual XP Mode. (read more at http://www.microsoft.com/windows/virtual-pc/download.aspx) Essentially it’s an integrated version of Virtual PC with a full copy of Windows XP SP2 running in it. It’s pretty nice – you can have programs from the virtualized XP instance in your Windows 7 Start Menu and they can even share your desktop.

Problem

First thing you might think as a PowerShell fan is to put PowerShell v2.0 on Virtual XP Mode so you can tinker around with PowerShell Remoting (don’t forget to install .NET Framework 3.5 SP1 first!) Unfortunately it’s not all plain sailing as a default security configuration in Virtual XP prevents the Enable-PSRemoting Cmdlet from succeeding:

PS C:\Documents and Settings\XPMUser> Enable-PSRemoting

WinRM Quick Configuration
Running command "Set-WSManQuickConfig" to enable this machine for remote management through WinRM service.
 This includes:
    1. Starting or restarting (if already started) the WinRM service
    2. Setting the WinRM service type to auto start
    3. Creating a listener to accept requests on any IP address
    4. Enabling firewall exception for WS-Management traffic (for http only).

Do you want to continue?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"):
WinRM has been updated to receive requests.
WinRM service type changed successfully.
WinRM service started.

Set-WSManQuickConfig : Access is denied. 
At line:50 char:33
+             Set-WSManQuickConfig <<<<  -force
    + CategoryInfo          : InvalidOperation: (:) [Set-WSManQuickConfig], InvalidOperationException
    + FullyQualifiedErrorId : WsManError,Microsoft.WSMan.Management.SetWSManQuickConfigCommand

Resolution

Thankfully, it’s a quick fix; log into VXP and perform Start > Run… “gpedit.msc” and navigate your way to:

Computer Configuration > Windows Settings > Security Settings > Local Policies > Security Options

…and change: Network access: Sharing and security model for local accounts

…to: Classic – local users authenticate as themselves.

Now run Enable-PSRemoting again and it should work. No need to reboot!

fix_gpo_security_network_access

posted on Friday, October 30, 2009 12:46:44 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0] Trackback
# Wednesday, October 28, 2009

( from: http://support.microsoft.com/default.aspx/kb/968929 – downloads at foot of page )

Windows PowerShell is a command-line shell and scripting language that is designed for system administration and Automation. Built on the Microsoft .NET Framework, Windows PowerShell enables IT professionals and developers to control and automate the administration of Windows and applications.

New features that are introduced in Windows PowerShell 2.0 include the following:

  • Remoting
    Windows PowerShell 2.0 lets you run commands on one or more remote computers from a single computer that is running Windows PowerShell. PowerShell remoting allows for multiple ways of connecting. These ways include interactive (1:1), fan-out (1:many), and fan-in (many:1 by using the IIS hosting model).
  • Integrated Scripting Environment
    PowerShell Integrated Scripting Environment (ISE) enables you to run interactive commands and edit and debug scripts in a graphical environment. The main features include color-coded syntax, selective execution, graphical debugging, Unicode support, and context-sensitive help.
  • Modules
    Modules allow for script developers and administrators to partition and organize their Windows PowerShell code in self-contained, reusable units. Code from a module executes in its own self-contained context and does not affect the state outside the module.
  • Advanced functions
    Advanced functions are functions that have the same capabilities and behavior as cmdlets. However, they are written completely in the Windows PowerShell language, instead of compiled C#.
  • Background jobs
    Windows PowerShell 2.0 allows for running a command or expression asynchronously and "in the background" without interacting with the console.
  • Eventing
    This feature adds support to the Windows PowerShell engine infrastructure for listening, forwarding, and acting on management and system events.
  • Script internationalization
    This new feature enables Windows PowerShell scripts to display messages in the spoken language that is specified by the UI culture setting on the user's computer.
  • Script debugging
    New debugging features were added to Windows PowerShell that let you set breakpoints on lines, columns, variables, and commands, and that let you specify the action that occurs when the breakpoint is hit.
  • New cmdlets
    Windows PowerShell 2.0 introduces over 100 built-in cmdlets. These cmdlets, excluding other tasks, enables you to do computer-related, event log, and performance counter management tasks.

WinRM 2.0

WinRM is the Microsoft implementation of WS-Management Protocol, a standard Simple Object Access Protocol (SOAP)–based, firewall-friendly protocol that allows for hardware and operating systems from different vendors to interoperate. The WS-Management Protocol specification provides a common way for systems to access and exchange management information across an IT infrastructure.

WinRM 2.0 includes the following new features:

  • The WinRM Client Shell API provides functionality to create and manage shells and shell operations, commands, and data streams on remote computers.
  • The WinRM Plug-in API provides functionality that enables a user to write plug-ins by implementing certain APIs for supported resources and operations.
  • WinRM 2.0 introduces a hosting framework. Two hosting models are supported. One is Internet Information Services (IIS)-based and the other is WinRM service-based.
  • Association traversal lets a user retrieve instances of Association classes by using a standard filtering mechanism.
  • WinRM 2.0 supports delegating user credentials across multiple remote computers.
  • Users of WinRM 2.0 can use Windows PowerShell cmdlets for system management.
  • WinRM has added a specific set of quotas that provide a better quality of service and allocate server resources to concurrent users. The WinRM quota set is based on the quota infrastructure that is implemented for the IIS service.

System requirements

WinRM 2.0 and PowerShell 2.0 can be installed on the following supported operating systems:

  • Windows Server 2008 with Service Pack 2
  • Windows Server 2003 with Service Pack 2
  • Windows Vista with Service Pack 2
  • Windows Vista with Service Pack 1
  • Windows XP with Service Pack 3
Windows PowerShell 2.0 requires the Microsoft .NET Framework 2.0 with Service Pack 1.

BITS 4.0

BITS 4.0 can be installed on the following supported operating systems:
  • Windows Server 2008 with Service Pack 2
  • Windows Vista with Service Pack 2
  • Windows Vista with Service Pack 1
posted on Wednesday, October 28, 2009 9:27:29 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0] Trackback
# Wednesday, October 21, 2009

You might not know it, but when you import a PowerShell module you can pass it one or more arguments by way of Import-Module's -ArgumentList (aliased to -Args) parameter. While it looks like passing parameters to a standard ps1 file, there are some limitations. Take this module for an example:

# -- begin foo.psm1 --
param()
 
. {
  param(
     [validateset("a","b","c")]
     $letter
 
     function Get-Letter {
        "You initialized the module with $letter"
     }
} @args
# -- end foo.psm1

ps> import-module foo -args b
ps> get-letter
"You initialized the module with b"

You might notice that I am dotting (dot-sourcing or dot-executing) the scriptblock. By doing this, you are ensuring that anything declared in the scriptblock is imported into the calling scope. You can also apply advanced-function style validation to the module initializer by splatting (@) the module arguments ($args). If the scriptblock was called instead (via & { ... } @args) then the nested scope created from the call (&) operator prevents the function Get-Letter from being exported from the module because it goes out of scope when the called scriptblock completes. So, why not put the param block at the top of the module where param() is now you might ask? Because that mechanism is broken and/or partially implemented in v2, and completely ignores [cmdletbinding()] directives and validators. Note also that there is no way to use switches in the traditional sense with module arguments; instead you can pass boolean literals like $true or $false which will be mapped positionally to any declared switches.

So where might you use this technique of module initializers? You could create a generalized custom module that works with your various development environments, or SQL clusters/servers. You pass the name of the environment (or server) to the module on import, and all of the functions exported then are "bound" to that cluster (or server) so you don't have to continually pass each function the cluster (or server) name as an argument.

Have fun!

posted on Wednesday, October 21, 2009 11:05:08 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [0] Trackback
# Wednesday, October 14, 2009

Updated: now use a temporary file to set text to avoid overflowing command-line buffer

The Windows Clipboard – accessible via System.Windows.Forms.Clipboard – requires an STA thread to read/write to it. By default, the console version of PowerShell 2.0 (i.e. not ISE) starts in MTA mode. This means that read/writing via this class is unreliable. Rather than always starting up console PowerShell in STA mode via the –STA flag, you can use this flag in a sneakier way to get what you want:

function Set-ClipboardText {
        param($text)

        # need to use temp file to avoid exceeding command-line length limit
        $temp = [io.path]::GetTempFileName()

        try {
            set-content -Path $temp -Value $text

            $command = {
                    add-type -an system.windows.forms
                    [System.Windows.Forms.Clipboard]::SetText((get-content $args))
            }
            
            powershell -sta -noprofile -command $command -args $temp

        } finally {
            if ((test-path $temp)) {
                remove-item $temp
            }
        }
}

function Get-ClipboardText {
        $command = {
                add-type -an system.windows.forms
                [System.Windows.Forms.Clipboard]::GetText()
        }
        powershell -sta -noprofile -command $command
}

Essentially we are running PowerShell as a child process temporarily in STA mode, skipping loading the profile and executing a scriptblock.

posted on Wednesday, October 14, 2009 11:53:35 AM (Eastern Daylight Time, UTC-04:00)  #    Comments [0] Trackback