ラベル ネットワーク の投稿を表示しています。 すべての投稿を表示
ラベル ネットワーク の投稿を表示しています。 すべての投稿を表示

2021年2月24日水曜日

◆SSHでファイル存在確認

SCPでLinuxサーバーからファイルをコピーしていたのだが、まれにファイルが無い時があることが判明。

存在確認をした上でコピーしたいのだが(もしくは存在しなくてもエラーを出さない)SCPのオプションでは無さそう・・・。

SFTPとかを使った方が良いのだろうか。

何分ここら辺の事は素人でよく判らない。

とりあえずSCPの前にSSHコマンドで確認することとした。

$fileExist = ssh $user@${hostName} "if [ -f /tmp/bkup.tar ]; then echo 'exist'; else echo 'not exist'; fi"

2019年11月5日火曜日

◆PowerShellからSSHを使う

1.OpenSSHクライアントを追加

Windows10 でSSHを使うには「Windowsキー  + I」で「Windowsの設定」を開く。
「アプリ」を選んで「アプリと機能」を開く。
「アプリと機能」から「オプション機能」を開く。
「オプション機能」が一覧表示されるので「OpenSSHクライアント」が表示されない場合は「機能の追加」から追加する。
(最近は最初から追加されているように思う)

2.公開鍵・暗号鍵のペアを作成

 (1)"C:\Windows\System32\OpenSSH\ssh-keygen.exe"を実行
 (2)「Enter file in which to save the key」と言ってくるので保存場所
    を指定する。(デフォルトで良ければそのままEnter)
    (デフォルトはログオンユーザー配下の「.ssh」)
 (3)「Enter passphrase」と表示されるのでパスフレーズを使う場合は指定

3.公開鍵ファイルをサーバーに送る

 手段は何でも良いが、差し当たってSCPで送る場合は
 scp  送信ファイル  ユーザー@接続先サーバー:パス
 といった感じで
 scp  $home\.ssh\id_rsa.pub  root@172.18.53.148:/etc/wk

4.公開鍵を配置

 (1)ログインユーザーのホームディレクトリに「.ssh」フォルダを作る
    mkdir  ~/.ssh
 (2)パーミッションを変更
    chmod  700  ~/.ssh
 (3)authorized_keysファイルを作成
    touch ~/.ssh/authorized_keys
 (4)パーミッションを変更
     chmod 600 ~/.ssh/authorized_keys
 (5)公開鍵をauthorized_keysに追加
    cat ~/id_rsa.pub >> .ssh/authorized_keys

5.PowerShellからSCPしてみる

  秘密鍵は「$home\.ssh」をデフォルトで参照してくれるらしい。
  別な場所に置く場合は「i」オプションでパスを指定する
  (次からはオプションなしでもそこを参照してくれるっぽい)

  scp  hoge.txt  root@172.18.53.148:/etc/wk

2016年11月7日月曜日

◆IPアドレスのロケーションを表示

http://community.idera.com/powershell/powertips/b/tips/posts/finding-location-of-ip-address

 

001
002
003
004
005
006
007
008
009
010

#requires -Version 3.0

function Get-IPLocation([Parameter(Mandatory)]$IPAddress
)
{

    $geoip = "http://geoip.nekudo.com/api/$IPAddress"
    Invoke-RestMethod -Method Get -Uri $geoip |
      Select-Object -ExpandProperty Country -Property City, IP, Location
 
}


Get-IPLocation -IPAddress 8.8.8.8

image

Restが簡単に使えますってサンプルかな。
個人的には、ロケーションを調べることは無いと思うがこのメソッドは覚えておきたい。

あと、以前はExpandPropertyとPropertyは共存できなかったと記憶しているが、できるようになってるんですね。

3.0から?

◆DHCPで設定されたアドレスを取得する

>Get-NetIPAddress | ? PrefixOrigin –eq DHCP | % IPAddress

2014年5月19日月曜日

◆メーラーを使ってメール送信

ウィルス対策ソフトによって「Send-MailMessage」がブロックされる場合、仕方が無いのでメールソフト経由で送信する。

もしかするとOUTLOOKあたりならCOMでも用意されているかも知れないが、今回はSendKeyを使った力技で。

こんなものでも使える局面はあるかもしれない。

001
002
003
004
005
006
007
008
009
010

add-type -AssemblyName System.Windows.Forms
$subject = 'メール送信のテストです'
$body = '本文です'
$to = 'minminnana@hoge.co.jp'
$mail = "mailto:$to&subject=$subject&body=$body"
Start-Process -FilePath $mail 
Start-Sleep -Seconds 2

#outlookの送信キー
[System.Windows.Forms.SendKeys]::SendWait("%S")

2013年2月5日火曜日

◆ネットワークカードの速度を表示

001
002
003

[System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() | 
 
ft Description,OperationalStatus,
    @{n="Speed(M)";e={($_.speed/1000000).tostring("0.0").padleft(8)}} -auto

image

2012年8月30日木曜日

◆NICの設定(NetAdapter関数)V3

ネットワークカード設定用の関数が色々と追加になっているようだ。(Windows8環境で確認している)

image

ネットワーク関係は素人なので私自身はあまり使うことは無いと思うが、GUIで出来ることはPowerShellでも出来るというのが現実の物となっているのだろうか。

ちょっとだけ試してみると、
「Get-NetAdapter」
image

「Rename-NetAdapter」
image

「Restart-NetAdapter」
image

Windows8をインストールしたときにNICの調子が悪くリンクスピードをオートネゴから100Mの全2重に設定したのだが、そんな設定も簡単にできてしまう。
image

「Set-NetAdapterAdvanceProperty」

image

本当に何でもできそうな感じだ。

2012年8月18日土曜日

◆ネットワークアダプター(NIC)をリセットする

古いPCにWindows8を入れたら、スリープからの復帰時にNICが有効にならなくなってしまったのでリセットするコマンドを作った。

001
002
003
004
005
006
007
008
009
010
011
012
013

function Reset-NetworkAdapter {
 
param
(
 
$name
  )

 
$nc = Get-WmiObject Win32_NetworkAdapter -Filter "NetConnectionID='$name'"
 
 
if($nc.Disable().ReturnValue){"Error in Disable"
}
 
if($nc.Enable().ReturnValue){"Error in Enable"
}
}


$netName = "イーサネット"

Reset-NetworkAdapter $netName

Windows8は、7の後継としては若干使いづらい印象。
特に、一般ユーザーは7の後継ではなく、タブレット用のOSと捉えたほうが良さそう。
Heper-Vは超嬉しいが、今のHDでは動かない(><)

ビジネスユーザーは7のままが幸せ。
開発者とタブレットユーザーは8が良いと思われる。

9あたりで7ユーザーに少し歩み寄ってくれるのではなかろうか・・・。

2011年7月27日水曜日

◆Webページをダウンロードする2

以前、Webページをファイルにダウンロードしてみたが、ダウンロードした内容を整形してファイルに落としたかったので、一旦文字列に取得してみた。

DownloadFileの代りにDownloadStringを使うだけ。
と思っていたのだが、結果を見てみると日本語が文字化けしている。
Webページのソースを見るとUTF8のようなのでUnicode(UTF16)に変換してあげれば良いのだろうと思い、一生懸命取得した文字列に対してコードを変換を試みたが、なんともかんともうまくいかない。

変換の仕方がおかしいのか・・・。
何か勘違いをしているような・・・。

あちこち彷徨い、やっとWebClientにはEncodingプロパティがあり、こいつにUTF8を指定してやると上手くいくことが判った。
(DownloadStringの引数にも用意してくれれば良いのに・・・)

このプロパティのデフォルトは「Default」なので基本的にはS-JIS。
なので、UTF8をS-JISとして読み込んだ文字列をUTF8だと思って変換しようとしていたので上手くいかなかったのだろう。

001
002
003
004
005

$source = "http://www.yahoo.co.jp/"
$wc = New-Object System.Net.WebClient 
$wc.Encoding = [System.Text.Encoding]::UTF8
$txt = $wc.DownloadString($source)
$txt

2011年6月6日月曜日

◆IPアドレスを取得する

やり方はいくつかありそうだが、普通にやるとこんな感じだろうか。

001
002

[system.net.dns]::GetHostAddresses((hostname))  | 
 
?{$_.AddressFamily -eq "InterNetwork"} | %{$_.IPAddressToString}

hostnameコマンドでホスト名を取得し、そこからIPアドレスを求めている。
とりあえず、IPv4のみを拾ってみた。

文字列ベースで取得するのであれば定番のipconfigでも良さそうだ。

001
ipconfig | grep ipv4 | %{($_ -split ": ")[-1]}

grepはPowerShell: ◆文字列で抽出するFilterを作るで作ったものを使った。
抽出された行を「: 」で分割し、添字[-1]で参照することによって最後のものを抽出している。

2011年5月16日月曜日

◆IISを管理する

IISがインストールされている環境でWebAdministrationモジュールをインポートする。
Get-Commandでコマンドの一覧を見ると*-Web*という名前でコマンドが用意されていることが判る。

PS>ipmo WebAdministration
PS>gcm -Module webadministration

CommandType     Name
-----------     ----
Cmdlet          Add-WebConfiguration
Cmdlet          Add-WebConfigurationLock
Cmdlet          Add-WebConfigurationProperty
Cmdlet          Backup-WebConfiguration
Alias           Begin-WebCommitDelay
Cmdlet          Clear-WebConfiguration
Cmdlet          Clear-WebRequestTracingSettings
Cmdlet          ConvertTo-WebApplication
Cmdlet          Disable-WebGlobalModule
Cmdlet          Disable-WebRequestTracing
Cmdlet          Enable-WebGlobalModule
Cmdlet          Enable-WebRequestTracing
Alias           End-WebCommitDelay
Cmdlet          Get-WebAppDomain
Cmdlet          Get-WebApplication
Cmdlet          Get-WebAppPoolState
Cmdlet          Get-WebBinding
Cmdlet          Get-WebConfigFile
 ・
 ・


IISドライブが用意されているのでアプリケーションプールやサイトを簡単に確認することができる。
image

アプリケーションプールの再起動もこんな感じ。
image

私自身はIISの管理とかはしないのであまり使い道は無いが、管理者の方は便利に使えるのではないしょうか。

2011年2月8日火曜日

◆インターネットに繋がっているか調べる(メモ)

インターネットに繋がっているかどうかを調べる方法として以下のようなサンプルがあった。

リフレクションを使わないとインスタンシングできないクラスってどんなクラス?っと思ったが、メソッドとかで検索しても見つからなかったので詳細は不明。
とりあえずメモしておく。

以下の2パターンがあったが後者の方が簡単そうなので前者は特に必要ないかのかな。

 

$networkListManager = [Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]"{DCB00C01-570F-4A9B-8D69-199FDBA5723B}"))
$connections = $networkListManager.GetNetworkConnections()
$connections | ForEach-Object {$_.isConnectedToInternet}

---
[Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]'{DCB00C01-570F-4A9B-8D69-199FDBA5723B}')).IsConnectedToInternet

2011年2月3日木曜日

◆IPアドレスをソートする

IPアドレスを含んだCSVファイルなどを読み込んでIPアドレス順にソートする。

IPAddressクラスなんかにキャストしたら簡単にできるのかと思ったのだがそうも行かないようだ。(気づかないだけかもしれないが)

とりあえず力技でやって見る。
それぞれのオクテットをプロパティとして持つオブジェクトを作ってそれでソートしてやれば良いだろう。
分割するのはSplitでも良いと思うのだが、ここでは正規表現を使ってみた。
(IPAddressクラスのGetAddressBytes()なんかでも出来る)

001
002
003
004
005
006

$addrs = "10.2.10.2","10.30.10.3","10.30.10.130","10.210.1.1","10.1.244.2"
$addrs | %{$_ -match '(\d+).(\d+).(\d+).(\d+)' | Out-Null
          1..4 | %{$matches[$_] = [int]$matches[$_]
}
          
New-Object PsObject -Property $matches} |
 
          
sort {$_."1",$_."2",$_."3",$_."4"
          } | select @{name="IPAddress";expression={$_."0"}}

こんな感じで良いのかと思ったのだが結果を見るとうまくいっていない。プロパティが文字列として扱われている。$matchesを直接プロパティに設定したのではダメっぽい(理由は今ひとつ分かっていないが)

仕方が無いのでプロパティを一つずつ設定することにした。

001
002
003
004
005
006
007

$addrs = "10.2.10.2","10.30.10.3","10.30.10.130","10.210.1.1","10.1.244.2"
$addrs | %{$_ -match '(\d+).(\d+).(\d+).(\d+)' | Out-Null
            1..4 | %{$matches[$_] = [int]$matches[$_]
}
           
0..4 | %{$props=@{}}{$props."p$($_)" = $Matches[$_]
}
            
New-Object PsObject -Property $props
          } |
 
          
sort p1,p2,p3,p4 | select @{name="IPAddress";expression={$_.p0}}

20110203190630

今度は良さそうだ。

次は考え方を変えて文字列のままソートしてみる。
文字列の場合はそれぞれのオクテットの桁数を3桁に揃えてやれば良いだろう。

001
002
003
004

$addrs = "10.2.10.2","10.30.10.3","10.30.10.130","10.210.1.1","10.1.244.2"
$addrs |  %{"{0:000}.{1:000}.{2:000}.{3:000}" -f
@([int[]]$_.split('.'))} |
sort | %{"{0}.{1}.{2}.{3}" -f @([int[]]$_.split('.'))}

こっちのほうがいくらかスマートかな?

調べていたら、もっと簡単な方法もあった。
若干裏技的な気もするが、Versionクラスにキャストしてソートすると簡単だ。

001
002

$addrs = "10.2.10.2","10.30.10.3","10.30.10.130","10.210.1.1","10.1.244.2"
$addrs | % { [Version] $_ } | Sort | % { $_.toString() }

だいぶスマートになった。

2010年12月10日金曜日

◆IPアドレスとホスト名の相互変換を行う

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037

<#
.SYNOPSIS
  IPアドレスとホスト名の相互変換を行う。
.DESCRIPTION
  IPアドレスが引数に渡された場合はホスト名を、ホスト名が渡された場合は
  IPアドレスを返す。
.LINK
  $link$
.EXAMPLE
  mTrans-IP 172.16.65.29
.EXAMPLE
  mTrans-IP vista3
#>
 
param
( 
 
[string]$hostaddr
 
) 

function main
{ 
 
trap
{ 
   
Write-Warning ホスト又はアドレスが見つかりません;exit
 
  } 
 
if(isIpAddress($hostaddr
)){ 
    (
[Net.Dns]::GetHostByAddress($hostaddr)).
hostname 
  }
else
{ 
    (
[Net.Dns]::GetHostByName($hostaddr) |
 
     
select -ExpandProperty AddressList).
IpAddressToString 
     
  } 
}


function isIPAddress($IPHost) { 
#if($object){$object}else{"Null"}
  ($IPHost -as [System.Net.IPAddress]).IPAddressToString -eq $IPHost -and
 
  (
$IPHost -ne $null
) 
  #
Write-Host

}


. main

2010年12月9日木曜日

◆Pingでサーバーの死活確認(Test-Connection)

Test-Connectionコマンドレットを使うとPingコマンドを直接使うよりも簡単に結果を確認することが出来る(文字列解析が不要)

Quietスイッチを指定すると単純にPingが成功したか失敗したかの結果だけを返してくれる。
以下の例では直接Server名を指定するパターンと、Server名の入ったテキストファイルを用意するパターンに対応してみた。

結果はそのままテキストで表示してもよいが、ここではHTML形式にして表示させている。
(HTML化が本題ではないのでごく簡単な表示で済ませている)
また、場合によってはこのHTMLテキストをPowerShell: ◆メールを送る(Send-MailMessage)を使って管理者にメールするなんてのも良いだろう。

PowerShell: ◆コメントベースのヘルプを記述するで書いたコメントも先頭に付けてみた。

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035

<#
.SYNOPSIS
サーバーの死活確認を行う
.DESCRIPTION
Serversに指定したServerまたはinputpathで指定したテキストファイル中のServerに
対してPingを送信しその死活を確認する。
結果は指定されたパスにHTML形式で出力する。
.NOTES
inputpath、serversともに指定しないとエラーとなる。
.LINK
http://www.powershell.com
.EXAMPLE
Ping.ps1 -inputpath w:\pcname.txt
.EXAMPLE
Ping.ps1 -servers vista3,goemon
#>

param
(
 
[string]$inputpath,
  [string[]]$Servers,
  [string]$outputpath="W:\servers.htm"
)
if($inputpath
){
 
$pcname = Get-Content $inputpath
}elseif($Servers
){
 
$pcname = $servers
}else
{
 
Write-Warning "Please Specify Params"
  exit
}
$isalive = @(Test-Connection -ComputerName $pcname -Quiet)
$result = 0..($pcname.Count - 1) | %{$pcname[$_] + "," + $isalive[$_]}
$head = (Get-Date).ToString() + " サーバー死活確認"
$html =  $result | ConvertFrom-Csv -Header "PC名","IsAlive" |
 
 
ConvertTo-Html -Head $head -Title "Servers" 
$html | 
Out-File $outputpath

結果はこんな感じになる。
20101209194217

2010年11月30日火曜日

◆纏めてnslookup

ホスト名をテキストファイルにいれておき、nslookupを纏めて実行する。

001
002
003
004
005

$hosts = gc d:\desktop\hostname.txt 
"■■■以下のホストのアドレスを照会します■■■" | tee -Variable msg 
$hosts 
"■" * $msg.length 
$hosts | nslookup

結果。
image

◆ネットワークアダプターを無効にする

001
002
003
004
005

Get-WmiObject Win32_NetworkAdapter -Filter "NetConnectionID='Mylocal'" | %{ 
 
$retrn = $_.Disable().
ReturnValue 
 
if(!$return){ $_.NetConnectionID + " を無効にしました。" }else
 
  { 
$_.NetConnectionID +  " を無効にできませんでした。"} 
}

有効にする時はEnableメソッドで。
汎用的に作るならNetConnectionIDの存在チェックもしたほうが良いかも。

結果はこうなる。
20101130101727

2010年11月24日水曜日

◆URLエンコード・デコードする

 
001
002
003
004
005

$esc = "[System.Uri]::EscapeDataString"
[System.Uri]::EscapeDataString("Powershellのブログ") | tee -Variable e1
[System.Uri]::EscapeDataString("<h1>Hello World</h1>") | tee -Variable e2
[System.Uri]::UnescapeDataString($e1)
[System.Uri]::UnescapeDataString($e2)

結果

20101124000853

2010年11月23日火曜日

◆IPアドレスを検証する

有効なIPアドレスを検証する。
正規表現などを使って検証する例も見かけるが、こんな方法もある。
-as演算子で型変換すると変換できない場合はエラーにならずにNullになる。.NETと同じだ。
なので変換してみてOKなら正しいと判断する。

また、if($object)という使い方、ここではさしあたってNulの時にFalseになる。
(厳密にいうと以下の使い方には若干バグがある)

001
002
003
004
005
006
007
008
009
010
011
012

function isIPAddress($object) {
if($object){$object}else{"Null"
}
  (
$object -as [System.Net.IPAddress]).IPAddressToString -eq $object –and
 
  (
$object -ne $null)
  Write-Host
}

isIPAddress "10.256.0.1"
isIPAddress "127.0.0.1"
IsIPAddress "hello"
IsIPAddress "192.168.0.1.1"
isIPAddress $null

結果はこんな感じになる。
20101123170544

メールアドレスの検証も同様に、こんな感じで。
[System.Net.Mail.MailAddress]).Address

2010年10月27日水曜日

◆Bits転送4 GUIクライアント版

これまで調べてきたBits転送機能を使ってGUI版のクライアントを作ってみた。
画面はこんな感じ。
image

ソースはこんな感じ。(Bits.ps1)

Set-PSDebug -Strict
$host.UI.RawUI.WindowTitle = "Bits転送ホスト"

Import-Module BitsTransfer
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName Microsoft.VisualBasic
$bindingSource = [System.Windows.Forms.BindingSource]
$bindingSource1 = New-Object $bindingSource
$bindingSource2 = New-Object $bindingSource
$path = Split-Path $myInvocation.MyCommand.path
$MessageBox = [System.WIndows.Forms.MessageBox]
$StartedEndMark,$endedEndMark = "☆","★"
 
function Main{
   
    #Formソースの読み込み
    Write-Host "Bits転送起動中・・・"
    $source1 = "Form1.cs"
    $source2 = "Form1.Designer.cs"
    $source3 = "CommonClasses.cs"
    $source = gc (Join-Path $path $source1)
    $source += gc (Join-Path $path $source2)
    $source += gc (Join-Path $path $source3)
    Add-Type -TypeDefinition ($source | out-string) -ReferencedAssemblies System.Windows.Forms,
                                                                          System.Drawing,
                                                                          System.Data,
                                                                          System.Core
    #Form表示
    $form = New-Object Bits.Form1
    $iconPath =  Join-Path $path "prodicon.ico"
    if(Test-Path $iconPath){
        $icon = New-Object System.Drawing.Icon (Join-Path $path "prodicon.ico")
        $form.icon = $icon
    }

    #イベント登録
    $form.Add_Load({formLoad})                      #フォームLoad処理
    $form.Add_FormClosing({formClosing})            #フォームクローズ処理
   
    $form.btnSync.Add_Click({btnSyncClick})         #同期実行処理
   
    $form.btnSerial.Add_Click({btnSerialClick})     #直列キュー投入処理
    $form.btnSuspend.Add_Click({btnSuspendClick})   #サスペンド処理
    $form.btnResume.Add_Click({btnResumeClick})     #Resume処理
    $form.btnDelete.Add_Click({btnDeleteClick})     #削除処理
   
    $form.btnParallel.Add_Click({btnParallelClick}) #並列キュー投入処理
    $form.btnSuspend2.Add_Click({btnSuspend2Click}) #サスペンド処理
    $form.btnResume2.Add_Click({btnResume2Click})   #Resume処理
    $form.btnDelete2.Add_Click({btnDelete2Click})   #削除処理
   
    $form.foreground.Add_Click({contextGridPriorityClick("foreground")})  #コンテキストメニュー
    $form.High.Add_Click({contextGridPriorityClick("High")})  #コンテキストメニュー
    $form.Normal.Add_Click({contextGridPriorityClick("Normal")})  #コンテキストメニュー
    $form.Low.Add_Click({contextGridPriorityClick("Low")})  #コンテキストメニュー
   
    #データソース設定
    $form.DataGridView1.DataSource = $bindingSource1
    $form.DataGridView2.DataSource = $bindingSource2
   
    fncRegistTimer
   
    cls
    [Windows.Forms.Application]::Run($form)
}

#フォームLoad処理
function formLoad{
    #投入済みで未完了のJOBを回復
    Get-BitsTransfer | %{
        $job = New-Object Bits.Job
        $_.FileList | Set file
        $job.FileName = Split-Path $file.RemoteName -Leaf
        $job.FromText = $file.RemoteName
        $job.ToText = $file.LocalName
        $job.Status = $_.JobState
        $job.JobID = $_.JobId
        $job.EndMark = $StartedEndMark
        if($_.DisplayName -eq "Serial"){
            $bindingSource1.Add($job)
        }else{
            $bindingSource2.Add($job)
        }
    }
   
    #直列キューの未投入分を回復
    $xmlpath = Join-Path $path "bindingsource1.xml"
    if(Test-Path $xmlpath){
        Import-Clixml $xmlpath | %{
            $job = New-Object Bits.Job
            $job.FileName = $_.FileName
            $job.FromText = $_.FromText
            $job.ToText = $_.ToText
            $job.Status = ""
            $job.EndMark = $StartedEndMark
            $bindingSource1.Add($job)
        }
    }
   
    #GridViewを選択解除&表示行調整
    if($bindingSource1.Count -gt 0){
        $form.DataGridView1.FirstDisplayedScrollingRowIndex = $bindingSource1.Count - 1
        $form.DataGridView1.ClearSelection()
    }
    if($bindingSource2.Count -gt 0){
        $form.DataGridView2.FirstDisplayedScrollingRowIndex = $bindingSource2.Count - 1
        $form.DataGridView2.ClearSelection()
    }
}

#フォームClosing処理
function formClosing{
    #$_.Cancel = $true
    $message1 = @"
キューに未終了のJOBが存在します。
JOBはそのまま継続されますが、
再度アプリケーションを実行するまで転送は完了しません。
"@
   
    #直列キュー未投入分を退避
    $bindingSource1 | ?{$_.Status -eq ""} | Export-Clixml -Path (Join-Path $path "bindingsource1.xml")
   
    foreach($job in $bindingSource1){
        if($job.EndMark -eq $StartedEndMark){
            $MessageBox::Show($message1)
            return
        }
    }
   
    foreach($job in $bindingSource2){
        if($job.EndMark -eq $StartedEndMark){
            $MessageBox::Show($message1)
            return
        }
    }
}

#同期実行処理
function btnSyncClick{
    if(fncCheckPath){
        [Microsoft.VisualBasic.Interaction]::AppActivate("Bits転送ホスト")
        Start-BitsTransfer $form.txtFrom.text $form.txtTo.text
        [Microsoft.VisualBasic.Interaction]::AppActivate("Bits転送")
    }else{
        $MessageBox::Show("転送元と転送先に正しいパスを指定してください")
        Return
    }
}

#直列キュー投入処理
function btnSerialClick{
    if(fncCheckPath){
        $job = New-Object Bits.Job
        $job.FileName = Split-Path $form.txtFrom.text -Leaf
        $job.FromText = $form.txtFrom.text
        $job.ToText = $form.txtTo.text
        $job.Status = ""
        $job.EndMark = $StartedEndMark
        $bindingSource1.Add($job)
        $form.DataGridView1.ClearSelection()
        $form.DataGridView1.FirstDisplayedScrollingRowIndex = $bindingSource1.Count - 1
    }else{
        $MessageBox::Show("転送元と転送先に正しいパスを指定してください")
        Return
    }
   
}

#コンテキストメニュー処理(プライオリティ変更処理)
function contextGridPriorityClick($priority){
    $arrJobIds = @()
    foreach ($row in $form.dataGridView2.SelectedRows)
    {
        if($bindingSource2[$row.Index].EndMark -eq $StartedEndmark){
            $arrJobIds += $bindingSource2[$row.Index].JobID
        }
    }
   
    if($arrJobIds.Count){
        Get-BitsTransfer -JobId $arrJobIds | Set-BitsTransfer -Priority $priority
    }
}

#パス中の不要文字削除&空白チェック
function fncCheckPath{
    $form.txtFrom.text = $form.txtFrom.text -replace '"',""
    $form.txtTo.text = $form.txtTo.text -replace '"',""
    try{
        if($form.txtFrom.text.StartsWith("http")){
            $result = Test-Path $form.txtTo.text -ea Stop
            if($result){
                $form.txtTo.text = Resolve-Path $form.txtTo.text
            }
            return $result
        }else{
            $result =  (Test-Path $form.txtFrom.text -ea Stop) -and (Test-Path $form.txtTo.text -ea Stop)
            if($result){
                $form.txtFrom.text = Resolve-Path $form.txtFrom.text
                $form.txtTo.text = Resolve-Path $form.txtTo.text
            }
            return $result
        }
    }Catch{
        Write-Warning $error[0]
        return $false
    }
}

#サスペンド処理
function btnSuspendClick{
    fncSuspend $form.DataGridView1 $bindingSource1
}
function btnSuspend2Click{
    fncSuspend $form.DataGridView2 $bindingSource2
}
function fncSuspend($grid,$bindingSource){
    $selectedRows = $grid.SelectedRows
    if($selectedRows.Count){
        $selectedRows | %{
            $job = $bindingSource[$_.index] #選択行に対応するJOBオブジェクト
            if($job.EndMark -eq $StartedEndMark -and $job.JobId){
                Get-BitsTransfer -JobId $job.JobId | Suspend-BitsTransfer
            }
        }
    }else{
        $MessageBox::Show("対象の行(JOB)を選択してください")
    }
}

#Resume処理
function btnResumeClick{
    foreach($job in $bindingSource1){
        if(("Transferring","Connecting") -contains $job.Status){
            $MessageBox::Show("他のJOBが実行中です")
            return
        }
    }
   
    fncResume $form.DataGridView1 $bindingSource1 {break}
    
}
function btnResume2Click{  
    fncResume $form.DataGridView2 $bindingSource2 {continue}
}
function fncResume($grid,$bindingSource,$script){
    $selectedRows = $grid.SelectedRows
    if($selectedRows.Count){
        foreach($selectedRow in $selectedRows){
            $job = $bindingSource[$selectedRow.index]
            if($job.Status -eq "Suspended"){
                Get-BitsTransfer -JobId $job.JobId | Resume-BitsTransfer -Asynchronous
                Invoke-Command $script #直列キューの時はResumeはひとつだけ
            }
        }
    }else{
        $MessageBox::Show("対象の行(JOB)を選択してください")
    }
}

#削除処理
function btnDeleteClick{
    fncDelete $form.DataGridView1 $bindingSource1
}
function btnDelete2Click{
    fncDelete $form.DataGridView2 $bindingSource2
}
function fncDelete($grid,$bindingSource){
    $selectedRows = $grid.SelectedRows
    if($selectedRows.Count){
        $selectedRows | %{
            $job = $bindingSource[$_.index] #選択行に対応するJOBオブジェクト
            #TransferredはComplete-Transferで既に消えている
            if($job.EndMark -eq $StartedEndMark -and $job.JobId){ 
                Get-BitsTransfer -JobId $job.JobId | Remove-BitsTransfer
            }
            $bindingSource.RemoveAt($_.index)
            $grid.Refresh()
        }
    }else{
        $MessageBox::Show("対象の行(JOB)を選択してください")
    }
}

#並列キュー投入処理
function btnParallelClick{
    if(fncCheckPath){
        $job = New-Object Bits.Job
        #JOB情報を取得しGridへ表示
        $job.FromText = $form.txtFrom.text
        $job.ToText = $form.txtTo.text
        $job.EndMark = $StartedEndMark

        #フォームからプライオリティ判定
        foreach($cntrl in $form.groupBox2.Controls){
            if($cntrl -is [System.Windows.Forms.RadioButton]){
                if($cntrl.Checked){
                    $priority = $cntrl.Text
                    break
                }
            }
        }
           
        #Tranfertype判定
        $type = fncSetTransfertype
        $job.FileName = Split-Path $form.txtFrom.text -Leaf
       
        #JOB投入
        $ret = Start-BitsTransfer $form.txtFrom.text $form.txtTo.text  `
                                    -Async -TransferType $type -Priority $priority
        Set-BitsTransfer -BitsJob $ret -DisplayName "Parallel"
       
        #JOBステータス更新処理
        fncSetJobInfo $job $ret   

        $bindingSource2.Add($job)
        $form.DataGridView2.ClearSelection()
        $form.DataGridView2.FirstDisplayedScrollingRowIndex = $bindingSource2.Count -1
    }else{
        $MessageBox::Show("転送元と転送先に正しいパスを指定してください")
        Return
    }
   
}

#タイマー処理
function fncRegistTimer{

    $form.timer1.Add_Tick({
        #直列キューJOBステータス更新処理
        fncUpdateJobStatus $bindingSource1
       
        #並列キューJOBステータス更新処理
        fncUpdateJobStatus $bindingSource2
       
        #直列キューJOB投入処理
        :outer foreach($job in $bindingSource1){
            switch($job.Status){
                "Transferring"{break outer}
                "Connecting" {break outer}
                "" {
                        $type = fncSetTransfertype
                        $ret = Start-BitsTransfer $job.FromText $job.ToText  `
                                    -Async -TransferType $type -Priority Foreground
                        Set-BitsTransfer -BitsJob $ret -DisplayName "Serial"
                        fncSetJobInfo $job $ret
                        break outer
                    }
                default{}
            }
        }
       
        #データグリッドリフレッシュ
        $form.DataGridView1.AutoResizeColumns()
        $form.DataGridView1.Refresh()
        $form.DataGridView2.AutoResizeColumns()
        $form.DataGridView2.Refresh()

       
    })
}

function fncSetTransfertype{
    if($form.txtFrom.text.StartsWith("http")){
        return "Download"
    }elseif($form.txtTo.text.StartsWith("\\")){
        return "Upload"
    }else{
        return "Download"
    }
}

#JOBステータス更新処理
function fncUpdateJobStatus($bindingSource){
    foreach($job in $bindingSource){
        if($job.EndMark -eq $endedEndMark){continue}
        if($job.JobID){
            $ret = Get-BitsTransfer -JobId $job.JobID
            fncSetJobInfo $job $ret
        }              
    }
}

#JOBステータス設定処理
function fncSetJobInfo($job,$bitsInfo){
    $job.Status = $bitsInfo.JobState
    $job.JobID = $bitsInfo.JobId
    $job.StartTime = $bitsInfo.CreationTime
    $job.Priority = $bitsInfo.Priority
    $job.Percent = [int](($bitsInfo.BytesTransferred/$bitsInfo.BytesTotal)*100)
    if($job.Status -eq "Transferred"){
        $job.EndTime = $bitsInfo.TransferCompletionTime
        $job.EndMark = $endedEndMark
        $job.Percent = 100
        Complete-BitsTransfer -BitsJob $bitsInfo.JobId
    }
}

Main

さすがに面倒なのでFormはVisualStudioで作ってAdd-Typeでソースを取り込んでいる。
起動用のバッチファイルとかと纏めて以下へ置いた。
http://cid-ddbd2fc6fc634eaa.office.live.com/self.aspx/.Public/BitsGUI.zip

そこそこ使い物になるように思うのですが、いかがなものでしょう。