PSSession через обратный SSH туннель. Часть 2 - Графический интерфейс для управления файлами
01 Nov 2018
local_offer
powershell
В продолжение к посту «PSSession через обратный SSH туннель», написал два варианта скрипта для управления файлами и папками на удаленном хосте с графическим интерфейсом. Скрипт так же можно использовать и с обычной удаленной сессией Powershell.
Для работы скрипта предварительно необходимо создать сессию с удаленным хостом, затем запустить скрипт. Который в свою очередь проверит сессии, выберет открытую и отобразить форму. Что-то похожее есть в TeamViewer - «Передача файлов».
Вариант 1. Используется System.Windows.Forms
Этот вариант не стал доделывать, так как неудобно проектировать форму (фактический на ощупь) и сложную форму будет сделать очень тяжело.
PowerCommander.ps1:
```powershell
<#
.SYNOPSIS
Remote session file copy with GUI
.DESCRIPTION
.EXAMPLE
.LINK
https://webnote.satin-pl.com/
.NOTES
Version: 0.1
Author: Pavel Satin
Email: plsatin@yandex.ru
Creation Date: 31.10.2018
Purpose/Change: Initial script development
#>
$RemoteSession = (Get-PSSession | Where-Object State -eq "Opened").Name
$global:RemotePath = "C:\Users\"
$global:RemotePathPrev = "C:\"
$global:LocalPath = "C:\Temp\Downloads\"
$global:RemoteCopyPath = ""
$global:LocalCopyPath = ""
Add-Type -assembly System.Windows.Forms
function Copy-FromRemoteSession {
param (
[string]$RemoteSession,
[string]$RemotePath,
[string]$LocalPath
)
$RemoteSessionObj = Get-PSSession | Where-Object Name -eq $RemoteSession
Copy-Item -FromSession $RemoteSessionObj -Path $RemotePath -Destination $LocalPath -Recurse
}
function Copy-ToRemoteSession {
param (
[string]$RemoteSession,
[string]$LocalPath,
[string]$RemotePath
)
$RemoteSessionObj = Get-PSSession | Where-Object Name -eq $RemoteSession
Copy-Item -ToSession $RemoteSessionObj -Path $LocalPath -Destination $RemotePath -Recurse
}
function Update-RemoteListView {
param (
[string]$RemoteSession,
[string]$RemotePath
)
$RemoteSessionObj = Get-PSSession | Where-Object Name -eq $RemoteSession
$arrayFolders = @(Invoke-Command -Session $RemoteSessionObj -ScriptBlock { Get-ChildItem -Path $using:RemotePath | ?{ $_.PSIsContainer }})
$arrayFiles = @(Invoke-Command -Session $RemoteSessionObj -ScriptBlock { Get-ChildItem -Path $using:RemotePath | ?{ ! $_.PSIsContainer }})
$RemoteFilesListView.Items.Clear()
$RemoteFilesListView.Items.Add("..", -1)
foreach ( $obj in $arrayFolders ) {
$ListViewItem = New-Object System.Windows.Forms.ListViewItem($obj.ToString())
$ListViewItem.ImageIndex = 0
$ListViewItem.Subitems.Add("0")
$RemoteFilesListView.Items.Add($ListViewItem)
}
foreach ( $obj in $arrayFiles ) {
$ListViewItem = New-Object System.Windows.Forms.ListViewItem($obj.ToString())
$ListViewItem.ImageIndex = 1
$ListViewItem.Subitems.Add($obj.Length)
$RemoteFilesListView.Items.Add($ListViewItem)
}
}
function Update-LocalListView {
param (
[string]$LocalPath
)
$arrayFolders = Get-ChildItem -Path $global:LocalPath | ?{ $_.PSIsContainer }
$arrayFiles = Get-ChildItem -Path $global:LocalPath | ?{ ! $_.PSIsContainer }
$LocalFilesListView.Items.Clear()
$LocalFilesListView.Items.Add("..", -1)
foreach ( $obj in $arrayFolders ) {
$ListViewItem = New-Object System.Windows.Forms.ListViewItem($obj.ToString())
$ListViewItem.ImageIndex = 0
$ListViewItem.Subitems.Add("0")
$LocalFilesListView.Items.Add($ListViewItem)
}
foreach ( $obj in $arrayFiles ) {
$ListViewItem = New-Object System.Windows.Forms.ListViewItem($obj.ToString())
$ListViewItem.ImageIndex = 1
$ListViewItem.Subitems.Add($obj.Length)
$LocalFilesListView.Items.Add($ListViewItem)
}
}
$MainWindow = New-Object System.Windows.Forms.Form
$DownloadButton = New-Object System.Windows.Forms.Button
$UploadButton = New-Object System.Windows.Forms.Button
$RefreshRemoteFiles = New-Object System.Windows.Forms.Button
$RemoteSessionTextBox = New-Object System.Windows.Forms.TextBox
$RemotePathTextBox = New-Object System.Windows.Forms.TextBox
$LocalPathTextBox = New-Object System.Windows.Forms.TextBox
$RemoteFilesListView = New-Object System.Windows.Forms.ListView
$LocalFilesListView = New-Object System.Windows.Forms.ListView
#region ImageList for nodes
$global:imageList = new-Object System.Windows.Forms.ImageList
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 16
$System_Drawing_Size.Height = 16
$global:imageList.ImageSize = $System_Drawing_Size
$imageFolder = [System.Drawing.Image]::FromFile("C:\ProgramData\icinga2\scripts\icinga2\img\folder.ico")
$imageFile = [System.Drawing.Image]::FromFile("C:\ProgramData\icinga2\scripts\icinga2\img\file.ico")
$global:imageList.Images.Add("folder", $imageFolder)
$global:imageList.Images.Add("file", $imageFile)
$RemoteFilesListView_MouseDoubleClick = {
$SelItem = $RemoteFilesListView.SelectedItems[0].SubItems[0].Text
if ($SelItem -eq "..") {
$global:RemotePath = Split-Path -Path $global:RemotePath
Write-Host $global:RemotePath
$RemotePathTextBox.Text = $global:RemotePath
Update-RemoteListView $RemoteSession $global:RemotePath
} else {
$global:RemotePath = Join-Path -Path $RemotePath -ChildPath $SelItem
Write-Host $global:RemotePath
$RemotePathTextBox.Text = $global:RemotePath
Update-RemoteListView $RemoteSession $global:RemotePath
}
}
$RemoteFilesListView_MouseClick = {
$SelItem = $RemoteFilesListView.SelectedItems[0].SubItems[0].Text
if ($SelItem -eq "..") {
} else {
$global:RemoteCopyPath = Join-Path -Path $RemotePath -ChildPath $SelItem
}
}
$LocalFilesListView_MouseDoubleClick = {
$SelItem = $LocalFilesListView.SelectedItems[0].SubItems[0].Text
if ($SelItem -eq "..") {
$global:LocalPath = Split-Path -Path $global:LocalPath
Write-Host $global:LocalPath
$LocalPathTextBox.Text = $global:LocalPath
Update-LocalListView $global:LocalPath
} else {
$global:LocalPath = Join-Path -Path $global:LocalPath -ChildPath $SelItem
Write-Host $global:LocalPath
$LocalPathTextBox.Text = $global:LocalPath
Update-LocalListView $global:LocalPath
}
}
$LocalFilesListView_MouseClick = {
$SelItem = $LocalFilesListView.SelectedItems[0].SubItems[0].Text
if ($SelItem -eq "..") {
} else {
$global:LocalCopyPath = Join-Path -Path $global:LocalPath -ChildPath $SelItem
}
}
$MainWindow.StartPosition = "CenterScreen"
$MainWindow.Text = "PowerCommander"
$MainWindow.Width = 648
$MainWindow.Height = 560
$RemoteSessionTextBox.Location = New-Object System.Drawing.Point(10,10)
$RemoteSessionTextBox.Text = $RemoteSession
$RemoteSessionTextBox.Width = 180
$RemoteSessionTextBox.add_TextChanged({ $RemoteSession = $RemoteSessionTextBox.Text })
$RemoteSessionTextBox.TabIndex = 1
$RemotePathTextBox.Location = New-Object System.Drawing.Point(10,40)
$RemotePathTextBox.Text = $global:RemotePath
$RemotePathTextBox.Width = 300
$RemotePathTextBox.add_TextChanged({ $global:RemotePath = $RemotePathTextBox.Text })
$RemotePathTextBox.TabIndex = 2
$LocalPathTextBox.Location = New-Object System.Drawing.Point(320,40)
$LocalPathTextBox.Text = $global:LocalPath
$LocalPathTextBox.Width = 300
$LocalPathTextBox.add_TextChanged({ $global:LocalPath = $LocalPathTextBox.Text })
$LocalPathTextBox.TabIndex = 3
$RemoteFilesListView.Location = New-Object System.Drawing.Size(10,70)
$RemoteFilesListView.Size = New-Object System.Drawing.Size(300,20)
$RemoteFilesListView.Height = 380
$RemoteFilesListView.SmallImageList = $global:imageList
$RemoteFilesListView.View = "Details"
$RemoteFilesListView.Columns.Add("Name", -2) | Out-Null
$RemoteFilesListView.Columns.Add("Size") | Out-Null
$RemoteFilesListView.add_MouseDoubleClick($RemoteFilesListView_MouseDoubleClick)
$RemoteFilesListView.add_MouseClick($RemoteFilesListView_MouseClick)
$LocalFilesListView.Location = New-Object System.Drawing.Size(320,70)
$LocalFilesListView.Size = New-Object System.Drawing.Size(300,20)
$LocalFilesListView.Height = 380
$LocalFilesListView.SmallImageList = $global:imageList
$LocalFilesListView.View = "Details"
$LocalFilesListView.Columns.Add("Name", -2) | Out-Null
$LocalFilesListView.Columns.Add("Size") | Out-Null
$LocalFilesListView.add_MouseDoubleClick($LocalFilesListView_MouseDoubleClick)
$LocalFilesListView.add_MouseClick($LocalFilesListView_MouseClick)
$DownloadButton.add_click({ $RemoteSession = $RemoteSessionTextBox.Text; $global:LocalPath = $LocalPathTextBox.Text; Copy-FromRemoteSession $RemoteSession $global:RemoteCopyPath $global:LocalPath} )
$DownloadButton.Location = New-Object System.Drawing.Point(10,470)
$DownloadButton.Autosize = 1
$DownloadButton.TabIndex = 4
$DownloadButton.Text = "Download"
$UploadButton.add_click({ $RemoteSession = $RemoteSessionTextBox.Text; Copy-ToRemoteSession $RemoteSession $global:LocalCopyPath $global:RemotePath} )
$UploadButton.Location = New-Object System.Drawing.Point(320,470)
$UploadButton.Autosize = 1
$UploadButton.TabIndex = 4
$UploadButton.Text = "Upload"
$RefreshRemoteFiles.add_click({ $RemoteSession = $RemoteSessionTextBox.Text; $global:RemotePath = $RemotePathTextBox.Text; Update-RemoteListView $RemoteSession $global:RemotePath })
$RefreshRemoteFiles.Location = New-Object System.Drawing.Point(196,10)
$RefreshRemoteFiles.Autosize = 1
$RefreshRemoteFiles.TabIndex = 5
$RefreshRemoteFiles.Text = "Update remote files"
$MainWindow.Controls.Add($RemoteSessionTextBox)
$MainWindow.Controls.Add($RemotePathTextBox)
$MainWindow.Controls.Add($LocalPathTextBox)
$MainWindow.Controls.Add($DownloadButton)
$MainWindow.Controls.Add($UploadButton)
$MainWindow.Controls.Add($RefreshRemoteFiles)
$MainWindow.Controls.Add($RemoteFilesListView)
$MainWindow.Controls.Add($LocalFilesListView)
Update-LocalListView $global:LocalPath | Out-Null
$MainWindow.ShowDialog() | Out-Null
```
Вариант 2. Используется Windows Presentation Foundation
В этом варианте для проектрованиия формы используется Visual Studio, после чего готовый XAML копируется в скрипт.
PowerCommanderXAML.ps1:
```powershell
<#
.SYNOPSIS
Remote session file copy with GUI (WPF)
.DESCRIPTION
.EXAMPLE
.LINK
https://webnote.satin-pl.com/2018/11/01/posh_over_ssh_tunnel_part2/
.NOTES
Version: 0.3
Author: Pavel Satin
Email: plsatin@yandex.ru
Creation Date: 06.11.2018
Purpose/Change: Initial script development
#>
param (
[Parameter(Mandatory = $false)]
[string]$RemoteSession0 = ""
)
## Значения по умолчанию
$RemoteSession = (Get-PSSession | Where-Object State -eq "Opened").Name
$global:RemotePath = "C:\Users\"
$global:RemotePathPrev = "C:\"
$global:LocalPath = "C:\Temp\Downloads\"
$global:RemoteCopyPath = ""
$global:LocalCopyPath = ""
$global:computerOS = $null
$imageFolder = "C:\ProgramData\icinga2\scripts\icinga2\img\folder-16_office.png"
$imageFile = "C:\ProgramData\icinga2\scripts\icinga2\img\document-16_office.png"
$inputXML = @"
<Window x:Class="PowerCommander.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PowerCommander"
mc:Ignorable="d"
Title="PowerCommander" Height="482.863" Width="796.285" ResizeMode="NoResize">
<Grid HorizontalAlignment="Left" Width="789">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="396*"/>
<ColumnDefinition Width="396*"/>
</Grid.ColumnDefinitions>
<ListView x:Name="RemoteFilesListView" HorizontalAlignment="Left" Height="270" Margin="10,123,0,0" VerticalAlignment="Top" Width="376" SelectionMode="Single">
<ListView.View>
<GridView>
<GridViewColumn Header=" ">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<Image Width="16" Height="16" Source="{Binding Image}" />
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Name" Width="260" DisplayMemberBinding ="{Binding 'Name'}"/>
<GridViewColumn Header="Size" DisplayMemberBinding ="{Binding 'Size'}"/>
</GridView>
</ListView.View>
</ListView>
<Button x:Name="DownloadButton" Content="Download >>" HorizontalAlignment="Left" Margin="280,398,0,0" VerticalAlignment="Top" Width="106" Height="23"/>
<ListView x:Name="LocalFilesListView" HorizontalAlignment="Left" Height="270" Margin="0,123,0,0" VerticalAlignment="Top" Width="376" Grid.Column="1">
<ListView.View>
<GridView>
<GridViewColumn Header=" ">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<Image Width="16" Height="16" Source="{Binding Image}" />
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Name" Width="260" DisplayMemberBinding ="{Binding 'Name'}"/>
<GridViewColumn Header="Size" DisplayMemberBinding ="{Binding 'Size'}"/>
</GridView>
</ListView.View>
</ListView>
<Button x:Name="UploadButton" Content="<< Upload" HorizontalAlignment="Left" Margin="0,398,0,0" VerticalAlignment="Top" Width="106" RenderTransformOrigin="-3.079,0.131" Grid.Column="1" Height="23"/>
<TextBox x:Name="RemoteSessionTextBox" HorizontalAlignment="Left" Height="23" Margin="69,9,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="146"/>
<Button x:Name="RefreshRemoteFilesButton" Content="" HorizontalAlignment="Left" Margin="362,91,0,0" VerticalAlignment="Top" Width="23" Height="23">
<Button.Background>
<ImageBrush ImageSource="C:\ProgramData\icinga2\scripts\icinga2\img\restart.png"/>
</Button.Background>
</Button>
<TextBox x:Name="RemotePathTextBox" HorizontalAlignment="Left" Height="23" Margin="10,91,0,0" TextWrapping="Wrap" Text=" " VerticalAlignment="Top" Width="347"/>
<TextBox x:Name="LocalPathTextBox" HorizontalAlignment="Left" Height="23" Margin="0,91,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="347" Grid.Column="1"/>
<Label x:Name="RemoteHostLabel" Content="Remote host" HorizontalAlignment="Left" Margin="51,60,0,0" VerticalAlignment="Top" Height="26" Width="334"/>
<Label x:Name="LocalHostLabel" Content="Local host" HorizontalAlignment="Left" Margin="39,60,0,0" VerticalAlignment="Top" Grid.Column="1" Height="26" Width="337"/>
<Image x:Name="LocalHostImage" HorizontalAlignment="Left" Height="26" Margin="0,60,0,0" VerticalAlignment="Top" Width="34" Source="C:\ProgramData\icinga2\scripts\icinga2\img\workstation_32_gray.png" Grid.Column="1"/>
<Image x:Name="RemoteHostImage" HorizontalAlignment="Left" Height="26" Margin="12,60,0,0" VerticalAlignment="Top" Width="34" Source="C:\ProgramData\icinga2\scripts\icinga2\img\workstation_32.png"/>
<Label x:Name="SessionLabel" Content="Session:" HorizontalAlignment="Left" Margin="12,8,0,0" VerticalAlignment="Top" Height="26" Width="52"/>
<Button x:Name="RemoteHostAddFolderButton" Content="" HorizontalAlignment="Left" Margin="12,398,0,0" VerticalAlignment="Top" Width="23" Height="23">
<Button.Background>
<ImageBrush ImageSource="C:\ProgramData\icinga2\scripts\icinga2\img\add-folder-32.png"/>
</Button.Background>
</Button>
<Button x:Name="RemoteHostDeleteButton" Content="" HorizontalAlignment="Left" Margin="41,398,0,0" VerticalAlignment="Top" Width="23" Height="23">
<Button.Background>
<ImageBrush ImageSource="C:\ProgramData\icinga2\scripts\icinga2\img\delete-32.png"/>
</Button.Background>
</Button>
<Button x:Name="RefreshLocalFilesButton" Content="" HorizontalAlignment="Left" Margin="353,91,0,0" VerticalAlignment="Top" Width="23" Height="23" Grid.Column="1">
<Button.Background>
<ImageBrush ImageSource="C:\ProgramData\icinga2\scripts\icinga2\img\restart.png"/>
</Button.Background>
</Button>
<Button x:Name="LocalHostAddFolderButton" Content="" HorizontalAlignment="Left" Margin="324,398,0,0" VerticalAlignment="Top" Width="23" Height="23" Grid.Column="1">
<Button.Background>
<ImageBrush ImageSource="C:\ProgramData\icinga2\scripts\icinga2\img\add-folder-32.png"/>
</Button.Background>
</Button>
<Button x:Name="LocalHostDeleteButton" Content="" HorizontalAlignment="Left" Margin="353,398,0,0" VerticalAlignment="Top" Width="23" Height="23" Grid.Column="1">
<Button.Background>
<ImageBrush ImageSource="C:\ProgramData\icinga2\scripts\icinga2\img\delete-32.png"/>
</Button.Background>
</Button>
</Grid>
</Window>
"@
$inputXML = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N' -replace '^<Win.*', '<Window'
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
[xml]$XAML = $inputXML
# Читаем XAML
$reader = (New-Object System.Xml.XmlNodeReader $xaml)
try {
$Form = [Windows.Markup.XamlReader]::Load( $reader )
} catch {
Write-Warning "Unable to parse XML, with error: $($Error[0])`n Ensure that there are NO SelectionChanged or TextChanged properties (PowerShell cannot process them)"
throw
}
# Загружаем XAML объекты в PowerShell
$xaml.SelectNodes("//*[@Name]") | ForEach-Object {
Write-Verbose "trying item $($_.Name)"
try {
Set-Variable -Name "WPF$($_.Name)" -Value $Form.FindName($_.Name) -ErrorAction Stop
} catch {
throw
}
}
Function Get-FormVariables {
if ($global:ReadmeDisplay -ne $true) {
Write-Verbose "If you need to reference this display again, run Get-FormVariables"
$global:ReadmeDisplay=$true
}
Write-Verbose "Found the following interactable elements from our form"
get-variable WPF*
}
$FormVariables = Get-FormVariables | Out-String
Write-Verbose $FormVariables
## ===========================================================================
## Пишем логику
function Get-RemoteHostEnv {
param (
[string]$RemoteSession
)
$RemoteSessionObj = Get-PSSession | Where-Object Name -eq $RemoteSession
$envComputerName = @(Invoke-Command -Session $RemoteSessionObj -ScriptBlock { get-childitem -path env:computername })
$global:computerOS = @(Invoke-Command -Session $RemoteSessionObj -ScriptBlock { Get-WmiObject Win32_OperatingSystem -ErrorAction SilentlyContinue })
Write-Verbose "Connected to host: $($envComputerName.Value)"
$WPFRemoteHostLabel.Content = "Remote host: " + $envComputerName.Value
$WPFRemoteHostImage.ToolTip = "$($global:computerOS.Caption) ($($global:computerOS.OSArchitecture)) $($global:computerOS.Version)"
}
function Copy-FromRemoteSession {
param (
[string]$RemoteSession,
[string]$RemotePath,
[string]$LocalPath
)
$RemoteSessionObj = Get-PSSession | Where-Object Name -eq $RemoteSession
Copy-Item -FromSession $RemoteSessionObj -Path $RemotePath -Destination $LocalPath -Recurse
## Обновляем список локальных фалов после даунлоада
Update-LocalListView $global:LocalPath
}
function Copy-ToRemoteSession {
param (
[string]$RemoteSession,
[string]$LocalPath,
[string]$RemotePath
)
$RemoteSessionObj = Get-PSSession | Where-Object Name -eq $RemoteSession
Copy-Item -ToSession $RemoteSessionObj -Path $LocalPath -Destination $RemotePath -Recurse
## Обновляем список файлов на удаленном хосте после аплоада
Update-RemoteListView $RemoteSession $global:RemotePath
}
function Update-RemoteListView {
param (
[string]$RemoteSession,
[string]$RemotePath
)
$RemoteSessionObj = Get-PSSession | Where-Object Name -eq $RemoteSession
## Передать локальный параметр в ScriptBlock можно с помощью дерективы ($using:)
$arrayFolders = @(Invoke-Command -Session $RemoteSessionObj -ScriptBlock { Get-ChildItem -Path $using:RemotePath | Where-Object{ $_.PSIsContainer } | Select-Object Name })
$arrayFiles = @(Invoke-Command -Session $RemoteSessionObj -ScriptBlock { Get-ChildItem -Path $using:RemotePath | Where-Object{ ! $_.PSIsContainer } | Select-Object Name, Length })
$WPFRemoteFilesListView.Items.Clear()
$WPFRemoteFilesListView.Items.Add([pscustomobject]@{Name = ".."; Size = ""})
foreach ( $obj in $arrayFolders ) {
$WPFRemoteFilesListView.Items.Add([pscustomobject]@{Image = $imageFolder; Name = $obj.Name; Size = "0"})
}
foreach ( $obj in $arrayFiles ) {
$WPFRemoteFilesListView.Items.Add([pscustomobject]@{Image = $imageFile; Name = $obj.Name; Size = $obj.Length})
}
# $WPFRemotePathTextBox.Text = $global:RemotePath
$WPFRemotePathTextBox.ToolTip = $global:RemotePath
}
function Update-LocalListView {
param (
[string]$LocalPath
)
$arrayFolders = Get-ChildItem -Path $global:LocalPath | Where-Object{ $_.PSIsContainer } | Select-Object Name
$arrayFiles = Get-ChildItem -Path $global:LocalPath | Where-Object{ ! $_.PSIsContainer } | Select-Object Name, Length
$WPFLocalFilesListView.Items.Clear()
$WPFLocalFilesListView.Items.Add([pscustomobject]@{Name = ".."; Size = ""})
foreach ( $obj in $arrayFolders ) {
$WPFLocalFilesListView.Items.Add([pscustomobject]@{Image = $imageFolder; Name = $obj.Name; Size = "0"})
}
foreach ( $obj in $arrayFiles ) {
$WPFLocalFilesListView.Items.Add([pscustomobject]@{Image = $imageFile; Name = $obj.Name; Size = $obj.Length})
}
# $WPFLocalPathTextBox.Text = $global:LocalPath
$WPFLocalPathTextBox.ToolTip = $global:LocalPath
}
function Remove-RemoteFile {
param (
[string]$RemoteSession,
[string]$RemotePath
)
$SelItem = $WPFRemoteFilesListView.SelectedItems.Name
$global:RemoteCopyPath = Join-Path -Path $RemotePath -ChildPath $SelItem
Write-Verbose "Remove [$RemoteSession]$global:RemoteCopyPath"
Add-Type -Assembly PresentationFramework
$msgBoxInput = [System.Windows.MessageBox]::Show('Would you like delete item?','Confirm','YesNoCancel','Warning')
switch ($msgBoxInput) {
'Yes' {
$RemoteSessionObj = Get-PSSession | Where-Object Name -eq $RemoteSession
$removeItem = @(Invoke-Command -Session $RemoteSessionObj -ScriptBlock { Remove-Item -Path $using:RemoteCopyPath -Force -Recurse })
Update-RemoteListView $RemoteSession $global:RemotePath
}
'No' {
## Do something
}
'Cancel' {
## Do something
}
}
}
function New-RemoteFolder {
param (
[string]$RemoteSession,
[string]$RemotePath
)
Write-Verbose "New folder in [$RemoteSession]$global:RemotePath"
Add-Type -AssemblyName Microsoft.VisualBasic
$newRemoteFolder = [Microsoft.VisualBasic.Interaction]::InputBox('Enter a new folder name', 'New folder', "New folder")
$global:RemoteCopyPath = Join-Path -Path $RemotePath -ChildPath $newRemoteFolder
$RemoteSessionObj = Get-PSSession | Where-Object Name -eq $RemoteSession
$newItem = @(Invoke-Command -Session $RemoteSessionObj -ScriptBlock { New-Item -ItemType directory -Path $using:RemoteCopyPath })
Update-RemoteListView $RemoteSession $global:RemotePath
}
function Remove-LocalFile {
param (
[string]$LocalPath
)
$SelItem = $WPFLocalFilesListView.SelectedItems.Name
$global:LocalCopyPath = Join-Path -Path $LocalPath -ChildPath $SelItem
Write-Verbose "Remove $global:LocalCopyPath"
Add-Type -Assembly PresentationFramework
$msgBoxInput = [System.Windows.MessageBox]::Show('Would you like delete item?','Confirm','YesNoCancel','Warning')
switch ($msgBoxInput) {
'Yes' {
Remove-Item -Path $global:LocalCopyPath -Force -Recurse
Update-LocalListView $global:LocalPath
}
'No' {
## Do something
}
'Cancel' {
## Do something
}
}
}
function New-LocalFolder {
param (
[string]$LocalPath
)
Write-Verbose "New folder in $global:LocalPath"
Add-Type -AssemblyName Microsoft.VisualBasic
$newLocalFolder = [Microsoft.VisualBasic.Interaction]::InputBox('Enter a new folder name', 'New folder', "New folder")
$global:LocalCopyPath = Join-Path -Path $LocalPath -ChildPath $newLocalFolder
$newItem = New-Item -ItemType directory -Path $global:LocalCopyPath
Update-LocalListView $global:LocalPath
}
## Добавляем события контролам
$RemoteFilesListView_MouseDoubleClick = {
$SelItem = $WPFRemoteFilesListView.SelectedItems.Name
if ($SelItem -eq "..") {
$global:RemotePath = Split-Path -Path $global:RemotePath
Write-Verbose $global:RemotePath
$WPFRemotePathTextBox.Text = $global:RemotePath
Update-RemoteListView $RemoteSession $global:RemotePath
} else {
$global:RemotePath = Join-Path -Path $RemotePath -ChildPath $SelItem
Write-Verbose $global:RemotePath
$WPFRemotePathTextBox.Text = $global:RemotePath
Update-RemoteListView $RemoteSession $global:RemotePath
}
}
$LocalFilesListView_MouseDoubleClick = {
$SelItem = $WPFLocalFilesListView.SelectedItems.Name
if ($SelItem -eq "..") {
$global:LocalPath = Split-Path -Path $global:LocalPath
Write-Verbose $global:LocalPath
$WPFLocalPathTextBox.Text = $global:LocalPath
Update-LocalListView $global:LocalPath
} else {
$global:LocalPath = Join-Path -Path $global:LocalPath -ChildPath $SelItem
Write-Verbose $global:LocalPath
$WPFLocalPathTextBox.Text = $global:LocalPath
Update-LocalListView $global:LocalPath
}
}
$DownloadButton_Click = {
Write-Verbose "Download start ..."
$SelItem = $WPFRemoteFilesListView.SelectedItems.Name
if ($SelItem -eq "..") {
} else {
$global:RemoteCopyPath = Join-Path -Path $RemotePath -ChildPath $SelItem
Write-Verbose "Download [$RemoteSession]$global:RemoteCopyPath to $global:LocalPath"
Copy-FromRemoteSession $RemoteSession $global:RemoteCopyPath $global:LocalPath
Update-LocalListView $global:LocalPath | Out-Null
}
}
$UploadButton_Click = {
Write-Verbose "Upload start ..."
$SelItem = $WPFLocalFilesListView.SelectedItems.Name
if ($SelItem -eq "..") {
} else {
$global:LocalCopyPath = Join-Path -Path $global:LocalPath -ChildPath $SelItem
Write-Verbose "Upload $global:LocalCopyPath to [$RemoteSession]$global:RemotePath"
Copy-ToRemoteSession $RemoteSession $global:LocalCopyPath $global:RemotePath
Update-RemoteListView $RemoteSession $global:RemotePath
}
}
$RemotePathTextBox_KeyDown = {
param
(
[Parameter(Mandatory)][Object]$sender,
[Parameter(Mandatory)][Windows.Input.KeyEventArgs]$e
)
if($e.Key -eq "Enter") {
Write-Verbose $global:RemotePath
$WPFRemotePathTextBox.Text = $global:RemotePath
Update-RemoteListView $RemoteSession $global:RemotePath
}
}
$LocalPathTextBox_KeyDown = {
param
(
[Parameter(Mandatory)][Object]$sender,
[Parameter(Mandatory)][Windows.Input.KeyEventArgs]$e
)
if($e.Key -eq "Enter") {
Write-Verbose $global:LocalPath
$WPFLocalPathTextBox.Text = $global:LocalPath
Update-LocalListView $global:LocalPath
}
}
$WPFRemoteFilesListView.Add_MouseDoubleClick($RemoteFilesListView_MouseDoubleClick)
$WPFLocalFilesListView.Add_MouseDoubleClick($LocalFilesListView_MouseDoubleClick)
$WPFRefreshRemoteFilesButton.Add_Click({ Update-RemoteListView $RemoteSession $global:RemotePath })
$WPFDownloadButton.Add_Click($DownloadButton_Click)
$WPFUploadButton.Add_Click($UploadButton_Click)
$WPFRemotePathTextBox.Add_TextChanged({ $global:RemotePath = $WPFRemotePathTextBox.Text })
$WPFLocalPathTextBox.Add_TextChanged({ $global:LocalPath = $WPFLocalPathTextBox.Text })
$WPFRemoteHostDeleteButton.Add_Click({ Remove-RemoteFile $RemoteSession $global:RemotePath })
$WPFRemoteHostAddFolderButton.Add_Click({ New-RemoteFolder $RemoteSession $global:RemotePath })
$WPFRemotePathTextBox.Add_KeyDown($RemotePathTextBox_KeyDown)
$WPFLocalPathTextBox.Add_KeyDown($LocalPathTextBox_KeyDown)
$WPFRefreshLocalFilesButton.Add_Click({ Update-LocalListView $global:LocalPath })
$WPFLocalHostDeleteButton.Add_Click({ Remove-LocalFile $global:LocalPath })
$WPFLocalHostAddFolderButton.Add_Click({ New-LocalFolder $global:LocalPath })
## Заполняем поля ввода данными по умолчанию
$WPFRemoteSessionTextBox.Text = $RemoteSession
$WPFLocalPathTextBox.Text = $global:LocalPath
$WPFRemotePathTextBox.Text = $global:RemotePath
## Обновляем список локальных файлов
Update-LocalListView $global:LocalPath | Out-Null
Get-RemoteHostEnv $RemoteSession
Write-Verbose "To show the form, run the following"
Write-Verbose '$Form.ShowDialog() | out-null'
## Показываем форму
$Form.ShowDialog() | out-null
```