Desktops.ps1
<# .Synopsis Returns the desktops for this Windows Station. .DESCRIPTION Returns the desktops for this Windows Station. .EXAMPLE Get-Desktop .EXAMPLE Get-Desktop -Name Default #> function Get-Desktop { param( # The name of the desktop to return [Parameter(Position=0)] [String]$Name = "*" ) $windowStation = [PoshInternals.User32]::GetProcessWindowStation() if ($windowStation -eq [IntPtr]::Zero) { throw (New-Object System.ComponentModel.Win32Exception) } $global:desktops = @() if (-not [PoshInternals.User32]::EnumDesktops($windowStation, {$global:desktops += $args[0]; $true }, [IntPtr]::Zero)) { Write-Error "Failed to enumerate desktops!" return } $desktops | Where { $_ -Like $Name } | ForEach-Object { $Handle = [PoshInternals.User32]::OpenDesktop($_, 0, $true, [PoshInternals.ACCESS_MASK]::DESKTOP_ALL) [PSCustomObject]@{ Handle=$Handle;Name=$_} } } <# .Synopsis Creates a new desktop in the current process's win station. .DESCRIPTION Creates a new desktop in the current process's win station. .EXAMPLE New-Desktop -Name Desktop2 #> function New-Desktop { [CmdletBinding()] param( [Parameter(Mandatory, Position=0)] [String]$Name, [Switch]$NoExplorer ) $DesktopHandle = [PoshInternals.User32]::CreateDesktop($Name, [IntPtr]::Zero, [IntPtr]::Zero, 0, [PoshInternals.ACCESS_MASK]::DESKTOP_ALL, [IntPtr]::Zero) if ($DesktopHandle -eq [IntPtr]::Zero) { $ex = New-Object System.ComponentModel.Win32Exception Write-Error "Failed to create desktop! $($ex.Message)" } else { if (-not $NoExplorer) { Start-Process explorer.exe -Desktop $Name } $Desktop = [PSCustomObject]@{ Handle=$DesktopHandle;Name=$Name} $Desktop | Add-Member -MemberType ScriptMethod -Name Close -Value { [PoshInternals.User32]::CloseDesktop($this) } -PassThru } } <# .Synopsis Shows the specified desktop. .DESCRIPTION This cmdlet will change the current input desktop to the one specified. If the NoExplorer switch was specified on New-Desktop, then there will be nothing running in the newly created desktop. Use Start-Process with the Desktop parameter, before changing desktops, to start a proces in the target desktop. .EXAMPLE Show-Desktop -Name Desktop2 #> function Show-Desktop { [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeLine=$true, ParameterSetName="Desktop")] [PSObject]$Desktop, [Parameter(Mandatory, ValueFromPipeLine=$true, ParameterSetName="Name", Position=0)] [string]$Name ) Process { if ($Desktop -eq $null) { $Desktop = Get-Desktop -Name $Name } if ($Desktop -eq $null) { Write-Error "Failed to find desktop" return } if (-not [PoshInternals.User32]::SwitchDesktop($Desktop.Handle)) { throw (New-Object System.ComponentModel.Win32Exception) } } } function Start-Process { [CmdletBinding(DefaultParameterSetName='Default', HelpUri='http://go.microsoft.com/fwlink/?LinkID=135261')] param( [Parameter(Mandatory=$true, Position=0)] [Alias('PSPath')] [ValidateNotNullOrEmpty()] [string] ${FilePath}, [Parameter(Position=1)] [Alias('Args')] [ValidateNotNullOrEmpty()] [string[]] ${ArgumentList}, [Parameter(ParameterSetName='Default')] [Alias('RunAs')] [ValidateNotNullOrEmpty()] [pscredential] ${Credential}, [ValidateNotNullOrEmpty()] [string] ${WorkingDirectory}, [Parameter(ParameterSetName='Default')] [Alias('Lup')] [switch] ${LoadUserProfile}, [Parameter(ParameterSetName='Default')] [Alias('nnw')] [switch] ${NoNewWindow}, [switch] ${PassThru}, [Parameter(ParameterSetName='Default')] [Alias('RSE')] [ValidateNotNullOrEmpty()] [string] ${RedirectStandardError}, [Parameter(ParameterSetName='Default')] [Alias('RSI')] [ValidateNotNullOrEmpty()] [string] ${RedirectStandardInput}, [Parameter(ParameterSetName='Default')] [Alias('RSO')] [ValidateNotNullOrEmpty()] [string] ${RedirectStandardOutput}, [Parameter(ParameterSetName='UseShellExecute')] [ValidateNotNullOrEmpty()] [string] ${Verb}, [switch] ${Wait}, [ValidateNotNullOrEmpty()] [System.Diagnostics.ProcessWindowStyle] ${WindowStyle}, [Parameter(ParameterSetName='Default')] [switch] ${UseNewEnvironment}, [Parameter(ParameterSetName='AltDesktop')] [string] ${Desktop}) begin { try { if (-not $PSBoundParameters['Desktop']) { $outBuffer = $null if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) { $PSBoundParameters['OutBuffer'] = 1 } $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Start-Process', [System.Management.Automation.CommandTypes]::Cmdlet) $scriptCmd = {& $wrappedCmd @PSBoundParameters } $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin) $steppablePipeline.Begin($PSCmdlet) } } catch { throw } } process { try { if ($PSBoundParameters['Desktop']) { $CommandLine = "$FilePath $ArgumentList" $Process = [PoshInternals.CreateProcessHelper]::CreateProcess($CommandLine, $Desktop) if ($PassThru) { $Process } if ($Wait) { $Process.WaitForExit() } } else { $steppablePipeline.Process($_) } } catch { throw } } end { if (-not $PSBoundParameters['Desktop']) { try { $steppablePipeline.End() } catch { throw } } } <# .ForwardHelpTargetName Start-Process .ForwardHelpCategory Cmdlet #> } |