ラベル PowerShell の投稿を表示しています。 すべての投稿を表示
ラベル PowerShell の投稿を表示しています。 すべての投稿を表示

2018年10月25日木曜日

【PowerShell】1ファイルずつzip圧縮【Compress-Archive】

●拡張子指定
dir *.txt | % { compress-archive $_ ($_.basename + ".zip")}

●全ファイル
dir | % { compress-archive $_ ($_.basename + ".zip")}

●パス指定
 dir c:\wk\tmp\ | % { compress-archive $_ ($_.basename + ".zip")}

●解説
%はforeachのエイリアス(別名)
compress-archiveは圧縮コマンド
$_はforeachで取り出される変数
basenameは拡張子を取り除いたファイル名

●拡張子指定した場合


●以下のようになる。



2018年9月1日土曜日

【PowerShell】カレントフォルダ(自フォルダ)取得

$pth = Split-Path -Parent $MyInvocation.MyCommand.Path
echo $pth
#上記を保存して実行した結果
PS C:\Users\root\Documents> .\test.ps1
C:\Users\root\Documents

2018年3月11日日曜日

【PowerShell】batから管理者権限で実行ポリシー(ExecutionPolicy)変更

Install.bat等から管理者権限でPowerShellを起動し、実行ポリシーを変更する。-waitを指定すると初回実行時(Execution Policyが変更されていない場合)にエラーが表示されるため、> nullでエラーを捨てている。
powershell "start-process powershell '-Command Set-ExecutionPolicy RemoteSigned -Confirm' -wait" -verb runas > nul 
ただし、ユーザアカウント制御のダイアログと以下のウインドウが表示される。

【PowerShell】PC起動時にメール送信

と言っても、タスクスケジューラーを使う。zip内のinstall.batを実行して メールやタスクスケジューラー登録を行う。使用しているのは、bat、PowerShell、タスクスケジューラーなので、動かない場合は適切に書き換える。
BootMail_v0.1.zip

■ソース(Bootメール送信.ps1)
# 設定ファイルのパス
$MyInvocation.MyCommand.Path | Split-Path -Parent | sv path
Join-Path $path setting.json | sv setting_path

# 設定ファイル読み込み
cat $setting_path | ConvertFrom-Json | sv conf

# 認証情報生成
ConvertTo-SecureString $conf.pass | sv pass
New-Object System.Management.Automation.PSCredential $conf.user, $pass | sv cred

# ホスト名取得
hostname | sv hst

# メール送信
Send-MailMessage `
    -To         $conf.to     `
    -From       $conf.from   `
    -SmtpServer $conf.server `
    -Port       $conf.port   `
    -Subject    "PC Boot"  `
    -Credential $cred        `
    -UseSsl                  `
    -Body       $hst
■ソース(設定ファイル作成.ps1)
# スクリプトのパスと設定ファイルのパス
$MyInvocation.MyCommand.Path | Split-Path -Parent | sv current_path
Join-Path $current_path setting.json | sv setting_path

Read-Host "送信先(to)メールアドレスを入力してください。"   | sv to
Read-Host "送信元(from)メールアドレスを入力してください。" | sv from
Read-Host "SMTPサーバアドレスを入力してください。"         | sv server
Read-Host "SMTPサーバポート番号を入力してください。"       | sv port

Get-Credential -m "【メールアカウント】と【パスワード】を入力して下さい。" | sv cred

# ユーザ入力情報から設定ファイルを作成。
@{
    to     = $to
    from   = $from
    server = $server
    port   = $port
    user   = $cred.UserName
    pass   = ConvertFrom-SecureString $cred.Password
} | sv setting
    
ConvertTo-Json $setting | Set-Content $setting_path

【PowerShell】タスクスケジューラー登録はWin7とWin8以降で別

  • Windows7
    • schtasks
  • Window8やWindow10は、以下が使用可能
    • New-ScheduledTaskPrincipal
    • New-JobTrigger
    • New-ScheduledTaskAction
    • Register-ScheduledTask

    schtasksよりRegister-ScheduledTaskの方が色々できそうだが、残念ながらWin7では使えない。

    2018年1月31日水曜日

    【PowerShell】グローバルIPアドレスをメール送信

    ◆目次
    1. セキュリティソフトでメール送信を除外。
    2. Google設定で安全でないアプリを許可するよう設定。※
    3. PowerShellでメール送信。
      ※Gmailの場合の手順。セキュリティレベルは下がるので注意。また、2段階認証の設定も必要とのこと。自分の場合は何故か不要だった。

    ◆ダウンロード
    GrobalIPMailv0.2.zip
    GrobalIPMailv0.1.zip

    ◆手順
    1. セキュリティソフトでメール送信を除外。(以下AVGの場合)
      1.  タスクバーのAVG(ver17.9.3040)をクリック。
      2. [メニュー]-[設定]-[コンポーネント]-[(メールシールドの)カスタマイズ]の順に選択。
      3. 送信メールをスキャン(SMTP)のチェックを外し、[OK]ボタン-[OK]ボタン。
         
    2. Google設定で安全でないアプリを許可するよう設定。
      1. Chromeを起動。
      2. アドレス欄にgoogle.comと入力。
      3. Chrome右上の:::ボタン(Googleアプリボタン)押下。
      4. [アカウント]を選択。
      5. [端末のアクティビティとセキュリティ イベント]を選択。
      6. [アカウントにアクセスできるアプリ]を選択。
      7. [安全性の低いアプリの許可]を無効から有効に変更。
         
    3. PowerShellでメール送信。
      (上述のzipを使う場合は、同梱のreadme.txtを参照のこと。下記のコードとは別で、タスクスケジューラによる定期処理を行う。)
      1. 後述の簡易コードをファイルに保存。ファイル名はgipmail.ps1。
        その際、[ユーザ名]と[ぱすわーど]は読み替えること。
      2. gipmail.ps1を右クリックし、[PowerShellで実行]を選択。
         
    ◆簡易コード(gipmail.ps1)
    $from = "ユーザ名@gmail.com"
    $to = "ユーザ名@gmail.com"
    $server = "smtp.gmail.com"
    $port = 587
    $user = "ユーザ名@gmail.com"
    $pass = "ぱすわーど"
    
    curl ipinfo.io | ConvertFrom-Json | sv ret
    $ret.ip
    
    $client = New-Object Net.Mail.SmtpClient($server, $port)
    $client.EnableSsl = $true
    $client.Credentials = New-Object Net.NetworkCredential($user, $pass)
    
    New-Object Net.Mail.MailMessage($from, $to,"Global IP", $ret.ip) | sv msg
    $client.Send($msg)
    

    ◆zip内のコード(GrobalIPメール送信.ps1:要setting.json)
    # 設定ファイルのパス・前回取得したグローバルIPアドレス記録ファイルのパス
    $MyInvocation.MyCommand.Path | Split-Path -Parent | sv path
    Join-Path $path setting.json | sv setting_path
    Join-Path $path latest_gip.txt | sv gip_path
    
    # 設定ファイル読み込み。
    cat $setting_path | ConvertFrom-Json | sv conf
    
    # 認証情報生成
    ConvertTo-SecureString $conf.pass | sv pass
    New-Object System.Management.Automation.PSCredential $conf.user, $pass | sv cred
    
    # 前回のIPをファイルから取得
    if (Test-Path $gip_path) {
        cat $gip_path | sv latestip
    }
    
    # グローバルIP取得サイトにアクセス。
    curl ipinfo.io | ConvertFrom-Json | sv ret
    
    # 前回のIPと今回取得したIPが不一致の場合のみ、ファイル書き込み&メール送信。
    if ($latestip -ne $ret.ip) {
        Send-MailMessage `
            -To         $conf.to     `
            -From       $conf.from   `
            -SmtpServer $conf.server `
            -Port       $conf.port   `
            -Subject    "Global IP"  `
            -Credential $cred        `
            -UseSsl                  `
            -Body       $ret.ip
    
        # メール送信に成功した場合のみ、グローバルIPアドレスを更新
        if ($? -eq $true) {
            $ret.ip | tee -f $gip_path
        }
    }
    

    2017年5月20日土曜日

    【ESXi】【PowerShell】ゲストOSの起動にWake On LAN(Magic Packet)を使用

    注意!!下記の手順は、ゲストOSが壊れる可能性があります!!

    スナップショットを取ってから実行すること。以下の記事に記載した通り、ゲストOSが壊れる可能性がある。

    【ESXi】E1001eからVMXNET3に変更したらWin10起動不可


    [仮想マシンへのWake ON LAN設定手順]
    1.  ブラウザを開く。
    2.  VMware Host Client(例:https://192.168.1.2/ui/#/host)のページへ移動。
    3.  [ナビゲータ]パネルの[仮想マシン]のツリーノードを展開。
    4.  win10x64(Wake On LAN対象のVM)を選択。
    5.  [パワーオン]ボタン押下。
    6.  ゲストOS起動後、プログラムの削除から、VMWare Toolsをアンインストール。
    7.  ゲストOSをシャットダウン。
    8.  win10x64(Wake On LAN対象のVM)を右クリック。
    9.  [設定の編集]を選択。
    10.  [ネットワークアダプタ1](Wake On Lan対象のNIC)のツリーノードを展開。
    11.  [アダプタ タイプ]を[E1000e]から[VMXNET3]に変更。
    12.  [保存]ボタン押下。
    13.  該当マシンの[パワーオン]ボタン押下。
    14. VMWare Tools をインストール。
    15. 下記のSendWakeupMsg.ps1の内容をテキストエディタに貼り付け。
    16. 設定値のMACアドレスとIPアドレスを変更。
    17. テキストをファイル保存。
    18. ゲストOSをスタンバイにする。
    19. 保存した.ps1ファイルを実行。


    SendWakeupMsg.ps1
    # 設定値============================================
    # 起動対象PCのMACアドレス
    $mac_addr = "11:22:33:44:55:66"
    
    # 起動対象PCのIPアドレス
    $ip_addr = "255.255.255.255" #ブロードキャストでも可能
    
    # 処理内容=========================================
    # magic packetの生成。FF×6の後に起動対象PCのMACアドレスが16回続く
    $mac_addr -split ':' | %{[Convert]::ToInt32($_, 16)} | sv data
    $packet = @(0xFF) * 6 + $data * 16 
    
    # UDPクライアント生成&パケット送信
    $udp_client = New-Object System.Net.Sockets.UdpClient 
    $udp_client.Send($packet, $packet.Length, $ip_addr, 2304) | Out-Null
    $udp_client.Close() 
    

    ●VMをスタンバイにした時のパフォーマンス
    VM状態CPU使用率メモリ使用量下記イメージの時間帯
    スタンバイ0.01~0.15%4GB00:46~01:20
    VM起動し、アイドル状態1~4%4GB01:25~01:44

    メモリ使用量は下がらない…。そりゃそうか、スタンバイだしなぁ。
    CPU消費もアイドルなら低いし、やる意味ないかなぁ。



    ◆環境
    • 仮想マシン
      • CPU core数:4
      • メモリ:4GB
      • OS:Windows10 Pro x64
      • 仮想マシン:VMWare vShpere ESXi6.5
    • ホストPCの性能(参考)
      • CPU:Intel Core i5-4250U(2Core 2HT)
      • メモリ:16GB
      • ドライブ:SSD(ウルトラ II mSATA SSD SDMSATA-512G-G25C)
      • 仮想マシン:VMWare ESXi6.0上の仮想マシン

    2016年12月23日金曜日

    【PowerShell】スクリーンショット2

    ■フリーソフトが使用できない職場なので、 WinShotも使用できない。仕方なく、 PowerShellでスクリーンキャプチャする。 
    少し改良したので再掲
    ##########################################################################################
    # 注意事項
    #  ・ドライブ直下のフォルダ(例えばc:\tmpなど)は権限が無いため、
    #    本スクリプトでは作成できないことがあります。事前に作成して下さい。
    #  ・実行ポリシーが変更されていない場合、(Set-ExecutionPolicy RemoteSigned等)が必要です。
    ##########################################################################################
    Add-Type -AssemblyName System.Windows.Forms
    Add-Type -AssemblyName System.Drawing
    
    # 出力先ファイルパス
    $filePath = "c:\tmp\evi\C{0:000}.png"
    #$filePath = "c:\tmp\evi\" + $(Get-Date).ToString("yyyyMMdd") + "\C{0:000}.png"
    
    # Jpeg,Gif,Bmp,Pngから選択する。
    $fileKind = [System.Drawing.Imaging.ImageFormat]::Png
    
    # スクリーンキャプチャして、Graphicsオブジェクトを生成
    $rect = [System.windows.forms.Screen]::PrimaryScreen.Bounds
    $bitmap = New-Object System.Drawing.Bitmap($rect.Width, $rect.Height)
    
    $graphics = [System.Drawing.Graphics]::FromImage($bitmap)
    $zero = New-Object System.Drawing.Point(0, 0)
    $graphics.CopyFromScreen($zero, $zero, $bitmap.Size)
    
    # フォルダ作成、フォルダがすでに存在するエラーは非表示。他のエラーも黙らせるので注意。
    $dirPath = Split-Path $filePath -parent
    New-Item -path $dirPath -type directory -ErrorAction SilentlyContinue
    
    # ファイル名を決定。順に、以下の処理を行う。
    # 1000までの数字を生成、ファイル名をフォーマットに従い決定、ファイルが存在するかチェック、最初の1件を取得、変数に格納を行う。
    1..1000 | % { $filePath -f $_ }  | Where { (Test-Path $_) -eq $false } | select -First 1 | sv resultFile
    
    # ファイル保存
    $bitmap.Save($resultFile, $fileKind)
    
    ##########################################################################################
    # ファイル作成後処理。フォルダやファイルを開く。必要に応じて、コメントアウトする。
    ##########################################################################################
    $shell = New-Object -ComObject Shell.Application # explorer ieの一覧を取得
    
    #============================================================================
    # 拡張子に対する既定のアプリケーションで開く。
    #============================================================================
    #ii $resultFile
    
    #============================================================================
    # ペイントで開く。
    #============================================================================
    #mspaint $resultFile
    
    #============================================================================
    # IEで開く。(毎回新しいウィンドウで開く。)
    #============================================================================
    #$ieCom = New-Object -ComObject InternetExplorer.Application  # IEで開く。
    #$ieCom.Navigate($resultFile)
    #$ieCom.Visible = $true
    
    #============================================================================
    # IEで開く。初回のみIEを1つ開き、2回目以降はウィンドウを更新する。
    #============================================================================
    # 対象のウィンドウのみ取得。
    $ie = $null
    $locationURL = "file:///" + $dirPath.Replace("\", "/")
    $shell.windows() | where {($_.LocationURL -like $locationURL + "*") -and ($_.Name -eq "Internet Explorer")} | select -First 1 | sv ie
    
    # オープン済みのIEが取得できなかった場合は、IEを開く。
    if ($ie -eq $null)
    {
        $ie = New-Object -ComObject InternetExplorer.Application
        $ie.Width = 700
        $ie.Height = 300
        $ie.Left = 1000
        $ie.top = 300
        $ie.AddressBar = $false
    }
    
    # IEで作成したファイルを開く。
    $ie.Navigate($resultFile)
    $ie.Visible = $true
    
    #============================================================================
    # エクスプローラを開く。
    #============================================================================
    $exp = $null
    $locationURL = "file:///" + $dirPath.Replace("\", "/")
    $shell.windows() | where {($_.LocationURL -like $locationURL) -and ($_.Name -eq "エクスプローラー")} | select -First 1 | sv exp
    if ($exp -eq $null)
    {
        Start "explorer " -Args $dirPath -Wait
        $shell.windows() | where {($_.LocationURL -like $locationURL) -and ($_.Name -eq "エクスプローラー")} | select -First 1 | sv exp
    
        $exp.Width = 700
        $exp.Height = 300
        $exp.Left = 1000
        $exp.top = 0
        $exp.AddressBar = $false
        $exp.Document.SortColumns = "prop:System.DateModified;"
        $exp.Document.CurrentViewMode = 5
        $exp.Document.IconSize = 150
    }
    
    $exp.Refresh2()
    

    2016年10月11日火曜日

    【PowerShell】Windows起動、終了時刻を表示

    ■Win10
    Get-EventLog -LN System |
        % EventID -in (7001, 7002) |
        select TimeWritten, EventID, Message -F 20
    Read-Host "Input Key"
    Read-Host "Input Key"

    ※高速スタートアップが有効だと、6005,6006は起動、終了時に記録されないとのこと。そのため、ログオン・ログオフ時刻を表示する。
    また、Read-Host×2は-Fが非同期になってしまう対策。

    ◆Windowsの起動・終了時刻を表示するスクリプト(正確にはイベントログ開始・終了時刻)。
    ①Win10 PowerShell5.1.1※1
    Get-EventLog -LogName System |
        where {($_.EventID -eq 6005) -or ($_.EventID -eq 6006)} |
        select -First 10 |
        foreach { Write-Host $_.TimeWritten, $_.Message }
    
    Read-Host "Enterキーを入力して下さい。"
    

    ②Win10 PowerShell5.1.1(別解)※1
    Get-EventLog -LogName System |
        where EventID -in (6005, 6006) |
        select -First 10 |
        foreach { Write-Host $_.TimeWritten, $_.Message }
    
    Read-Host "Enterキーを入力して下さい。"
    

    ③PowerShell3.0、4.0、5.0※2(①~④中で一番簡単な方法)
    Get-EventLog -LN System |
        where EventID -in (6005, 6006) |
        select TimeWritten, Message -F 10 
    
    Read-Host "Enterキーを入力して下さい。"
    

    ④PowerShell2.0
    Get-EventLog -LogName System |
        where {($_.EventID -eq 6005) -or ($_.EventID -eq 6006)} |
        select TimeWritten, Message -First 10 
    
    Read-Host "Enterキーを入力して下さい。"
    

    ◆①、②の実行結果


    ■③、④の実行結果


    ※1 select TimeWritten, Message -First 10は実行できるはずだが、実行すると何故かRead-Hostが先に実行され、その後イベントログが表示されてしまう。仕方無く、foreachとWrite-Hostを使っている。しかし、PowerShell3.0以下ではselect TimeWritten, Message -First 10が動作する。

    ※2 動作するバージョンと動作しないバージョンがある。Win10が駄目っぽい。

    • ×Win10(2016/10/18現在) PowerShell5.1.14393.206
    • ×Win10 PowerShell5.0.10240.16384
    • 〇Win8 PowerShell3.0
    • 〇Win7 PowerShell5.0.10586.117
    • 〇Win7 PowerShell4.0

    2016年9月12日月曜日

    【PowerShell】スクリーンショット(画面キャプチャ)

    ■Win10標準ショートカットキー
    Win10では画面キャプチャ&ファイル保存してくれる以下のショートカットキーがあるので、もはやこのページの内容は不要となってしまった。(❖:Windowsロゴキー)

    • アクティブ画面キャプチャ+ファイル保存:❖+Alt+PrtSc
    • 全画面キャプチャ+ファイル保存    :❖+PrtSc
    • 指定範囲キャプチャ(ファイル保存しない) :❖+Shift+S
    • クリップボード履歴          :❖+V

    ※これらのショートカットキーはWin10のバージョンによって使えないものがあるようです。

    話を戻して・・・
    ■PowerShellソース
    $path = "c:\tmp\"                     # 出力先
    $file = "Cap_{0:000}.png"             # {0:000} 0番目の引数を3桁の0埋め数字とする。
    
    Add-Type -A System.Windows.Forms      # このセッションに型を追加。
    
    [Windows.Forms.Screen]::PrimaryScreen.Bounds |                   # ディスプレイサイズを取得し、
        % {[Drawing.Bitmap]::New($_.Width, $_.Height)} |             # そのサイズのBitmapデータ生成。
        sv b                                                         # Set-Variable 変数への代入。bにBitmapオブジェクトを代入。
    
    [Drawing.Graphics]::FromImage($b).CopyFromScreen(0, 0, $b.Size)  # 描画オブジェクトで画面キャプチャして、Bitmapデータへ反映。
    
    md -f $path                           # フォルダ作成。-f:force 既に存在する場合エラーを抑止。
    
    1..1000 |                             # 1~1000まで
        % { $path + $file -f $_ }  |      # 繰り返し、フォーマット。c:\tmp\Cap_001.pngなどに変換。
        ? { (Test-Path $_) -eq $false } | # その内、ファイルが存在しないパスのみを取得。
        select -F 1 |                     # 最初の1件のみにフィルタして、
        % { $b.Save($_) }                 # そのパスにBitmapデータをファイル保存。
    

    Newスクリーンショット:上記に少し機能追加したもの。

    ■ショートカットキー
    Win7以降ならタスクバーにピン留めしてWindowsキー+1とか2とか(タスクバーの左からのピン留め位置。ピン留めした位置が1番左なら、Windowsキー+1)。

    ■フリーソフトが使用できない職場なので、 WinShotも使用できない。仕方なく PowerShellでスクリーンキャプチャ&ファイル(画像ファイル)保存する。ちなみに全画面で保存される。

    ■Win7でも動くはず。
    Download

    上記のリンクからダウンロードした場合は、ファイルを右クリックしてプロパティを選択し、「ブロックの解除」が必要な場合がある。
    上記のDownloadと下記のコードは同じもの。

    Add-Type -AssemblyName System.Windows.Forms
    Add-Type -AssemblyName System.Drawing
    
    $filePath = "c:\tmp\Cap_{0:000}.png"
    $fileKind = [System.Drawing.Imaging.ImageFormat]::Png
    #$fileKind = [System.Drawing.Imaging.ImageFormat]::Jpeg
    #$fileKind = [System.Drawing.Imaging.ImageFormat]::Gif
    #$fileKind = [System.Drawing.Imaging.ImageFormat]::Bmp
    
    # スクリーンキャプチャして、Graphicsオブジェクトを生成
    $rect = [System.windows.forms.Screen]::PrimaryScreen.Bounds
    $bitmap = New-Object System.Drawing.Bitmap($rect.Width, $rect.Height)
    
    $graphics = [System.Drawing.Graphics]::FromImage($bitmap)
    $zero = New-Object System.Drawing.Point(0, 0)
    $graphics.CopyFromScreen($zero, $zero, $bitmap.Size)
    
    # ファイル名を決定するために、存在しないファイルになるまでループ
    $i = 0
    do
    {
        $path = $filePath -F $i # 文字列フォーマット
        $i++
    } while (Test-Path $path);
    
    # ファイル保存
    $bitmap.Save($path, $fileKind)
    
    

    ■powershell画面を非表示にする。
    1. 該当のps1ファイルを右クリックし、ショートカットの作成。
    2. 作成したショートカットを右クリックし、プロパティ。

    3. リンク先に【powershell.exe -w Hidden -ep RemoteSigned -c "C:\Users\root\Desktop\cap\cap.ps1"】を入力し、【OK】ボタン押下。パスは読み替えること。-ep RemoteSignedを指定した場合、後述のpowershellの有効化は不要。
    4. ショートカットファイルをタスクバーにD&D。

    上記手順後、タスクバーのpowershellアイコンをクリックするとpowershell画面非表示の状態でキャプチャされる。

    ■powershell 有効化
    1. Winキー押下し、【powershell】と入力し、表示されたWindows PowerShellを右クリックし、「管理者として実行」を選択。

    2.  【Set-ExecutionPolicy RemoteSigned】を入力。(Set-Ex入力後Tabで補完、Re入力後、Tabで補完)

    ■ショートカットキーの登録。(制限事項有り※)
    1. 上記のコードを保存または、リンクからDownload。
       例)c:\bat\スクリーンキャプチャ.ps1
    2. 保存したファイルを右クリック-「ショートカットの作成」を選択。
    3. 作成したショートカットファイルを選択し、Alt + Enterキー。
    4. 「リンク先」欄の先頭にpowershell を追加。
       例1)powershell C:\bat\スクリーンキャプチャ.ps1
       例2)C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe C:\bat\スクリーンキャプチャ.ps1
    5. 「ショートカットキー」欄を選択。
    6. 使用したいショートカットキーを押下。
       例)Ctrl + Alt + P。
    7. 「実行時の大きさ」欄を「最小化」に変更。
    8. Winロゴキー + Rキー押下。
    9. shell:startupを入力し、Enterキーを押下。
    10. エクスプローラが開くので、上記のショートカットファイルを移動。
    11. OS再起動。
    ※このショートカットキーの登録の場合、アクティブウィンドウが変更されてしまうため、ツールチップなどの一部の表示がキャプチャできないことがある。

    2016年9月3日土曜日

    【PowerShell】フォルダ内の最新画像を表示

    ネット接続できない職場なので、基本的にスクリプトを自作する必要がある。
    エクスプローラで画像表示することも可能だが、カスタマイズできるように
    スクリプト化。

    Download

    #==================================================================
    # ツールの概要
    #==================================================================
    # 一定間隔で指定フォルダの最新の画像ファイルを表示する。
    # ウィンドウをクリックした場合も最新の画像ファイルを表示する。
    # ウィンドウをダブルクリックするとウィンドウが画像にフィットする。
    
    #==================================================================
    # 事前準備
    #==================================================================
    # 管理者権限でpowershellを開き、実行ポリシーを変更しておく。
    # Window 8の場合
    # 1. キーボードでWindowsキー押下。
    # 2. キーボードでpowershellと入力。
    # 3. Shift-Ctrlを押しながら、powershellアイコンをクリック。
    # 4. キーボードでSet-ExecutionPolicy RemoteSignedと入力。
    
    #==================================================================
    # 使用方法
    #==================================================================
    # このテキストをコピーしてファイルに保存。拡張子はps1とする。
    # 下記の「設定値」欄を変更し、powershellからps1ファイルを実行。
    # Windows8の場合はファイルを右クリックして「PowerShellで実行」を選択。
    
    #==================================================================
    # ライセンス
    #==================================================================
    # Copyright (c) 2015 Barracuda sh
    # This software is released under the MIT License.
    # http://opensource.org/licenses/mit-license.php
    
    #==================================================================
    # 設定値
    #==================================================================
    $pictDirPath = "C:\tmp"
    $fileExt = @("*.gif", "*.jpg", "*.jpeg", "*.png", "*.bmp")
    $interval = 2000
    $width = 480
    $height = 320
    #$DebugPreference = "Continue"
    
    #==================================================================
    # メイン処理
    #==================================================================
    # コンソールを非表示
    PowerShell -WindowStyle Hidden -Command Exit
    
    # アセンブリ読み込み
    Add-Type -Assembly System.Windows.Forms
    Add-Type -Assembly System.Drawing
    
    # Formサイズ(=画像サイズ)
    $size = New-Object System.Drawing.Point
    $size.X = $width
    $size.Y = $height
    
    # Form生成
    [System.Windows.Forms.Form]$mainForm = New-Object System.Windows.Forms.Form
    $mainForm.ClientSize = $size
    
    # PictureBoxを生成しFormへ追加
    [System.Windows.Forms.PictureBox]$pictBox = New-Object System.Windows.Forms.PictureBox
    $pictBox.Sizemode = [System.Windows.Forms.PictureBoxSizeMode]::Zoom
    $pictBox.AutoSize = $false
    $pictBox.Size = $size
    $pictBox.anchor = `
        [System.Windows.Forms.AnchorStyles]::Top -bor `
        [System.Windows.Forms.AnchorStyles]::Bottom -bor `
        [System.Windows.Forms.AnchorStyles]::Left -bor `
        [System.Windows.Forms.AnchorStyles]::Right 
    $mainForm.Controls.Add($pictBox)
    
    #タイマーイベントコールバック関数
    $tick = {
        Write-Debug "[イベント]タイマー"
        # 画像表示を行う
        updatePict $script:mainForm $script:pictBox $script:pictDirPath $script:fileExt $false
    }
    
    # ピクチャーボックスクリックイベントコールバック関数
    $click = {
        Write-Debug "[イベント]クリック"
        # 強制画像表示を行う
        updatePict $script:mainForm $script:pictBox $script:pictDirPath $script:fileExt $true
    }
    
    # ピクチャーボックスクリックイベントコールバック関数 
    $doubleClick = {
        Write-Debug "[イベント]ダブルクリック"
        $widthRatio  = $pictBox.Size.Width  / $pictBox.Image.Size.Width
        $heightRatio = $pictBox.Size.Height / $pictBox.Image.Size.Height
    
        Write-Debug ("width  ratio = " + $widthRatio)
        Write-Debug ("height ratio = " + $heightRatio)
    
        if ($widthRatio -le $heightRatio)
        {
            [int]$newWidth  = $script:mainForm.ClientSize.Width
            [int]$newHeight = $script:pictBox.Image.Height * $widthRatio + 1
        }
        else
        {
            [int]$newWidth  = $script:pictBox.Image.Width * $heightRatio + 1
            [int]$newHeight = $script:mainForm.ClientSize.Height
        }
        $script:mainForm.ClientSize = New-Object System.Drawing.Size($newWidth, $newHeight)
    }
    
    # 画像更新関数
    function updatePict ([System.Windows.Forms.Form]$form, [System.Windows.Forms.PictureBox]$pictBoxObj, [string]$path, [array]$ext, [bool]$force) {
        Write-Debug ("path = " + $path)
        Write-Debug ("ext = " + $ext)
        Write-Debug ("force = " + $force)
    
        # ファイル一覧を取得
        $path = $path + "\*.*"
        $sortFileAry = (Get-ChildItem $path -include $ext | sort CreationTime -Desc)
    
        # ファイル数が0なら終了
        if ($sortFileAry.Length -eq 0)
        {
            $pictBoxObj.ImageLocation = ""
            $form.Text = ""
            return
        }
    
        # 最新のファイルのパスを取得
        $latest = $sortFileAry[0].FullName
    
        # CPU・HDD負荷低減のため、前回と同じファイルパスの場合は画像表示をスキップ。
        if (!$force) {
            if ($pictBoxObj.ImageLocation -eq $latest)
            {
                Write-Debug "更新無"
                return
            }
        }
    
        # 前回と違うファイルパスの場合は、画像ファイルを表示する。 
        $pictBoxObj.ImageLocation = $latest
        $form.Text = $latest
        Write-Debug $latest
    }
    
    # PictureBoxのクリックイベント登録
    $pictBox.Add_Click($click)
    $pictBox.Add_DoubleClick($doubleClick)
    
    # タイマー生成
    $timer = New-Object Windows.Forms.Timer
    $timer.Interval = $interval
    $timer.Add_Tick($tick)
    $timer.Enabled = $true
    
    # 初回画像表示
    updatePict $script:mainForm $pictBox $pictDirPath $script:fileExt $true
    
    # メインフォームを表示
    $mainForm.ShowDialog()
    
    # タイマーを終了。
    $timer.Enabled = $false