Memo/Windows/PowerShell

https://dexlab.net:443/pukiwiki/index.php?Memo/Windows/PowerShell
 

PowerShell

Windows_PowerShell - wikipedia
Windows PowerShell は、マイクロソフトが開発した拡張可能なコマンドラインインターフェース (CLI) シェルおよびスクリプト言語である。オブジェクト指向に基づいて設計されており、.NET Framework 2.0 を基盤としている。

長い行の改行


PowerShellでtcp疎通確認

  • Test-NetConnectionを使う場合。ICMPを使ってるため、ICMPを閉じている場合少し待たされる。
    • 「-InformationLevel Quiet」を付けると、True/Falseだけ得られる
      Test-NetConnection www.example.com -Port 443
      
      ComputerName     : www.example.com
      RemoteAddress    : 93.184.216.34
      RemotePort       : 443
      InterfaceAlias   : イーサネット 2
      SourceAddress    : ***.***.***.***
      TcpTestSucceeded : True
      
      Test-NetConnection www.example.com -Port 443 -InformationLevel Quiet
      True

Windowsのバージョン取得

  • $PSVersionTable を参照する方法
    $PSVersionTable.BuildVersion
    
    Major  Minor  Build  Revision
    -----  -----  -----  --------
    10     0      19041  1
  • Get-WmiObjectを使う方法。Revisionが表示されない
    Get-WmiObject Win32_OperatingSystem | ft BuildNumber,Version
    
    # Win10 1909の場合
    BuildNumber Version
    ----------- -------
    18363       10.0.18363

stdout, stderrのリダイレクト

  • About Redirection
    • shell scriptのように「2>&1」のような指定はできるが、2より上の値があり、Write-Hostを含むログをファイルに出すためには「*>」を指定する
    • 追記は「*>>」
  • stdout, stderr含む全ストリームをファイルへ出力
    .\script.ps1 *> script.log
  • タスクスケジューラにAnsibleで登録する場合。毎日実行するが、最新の実行分だけログに保存。
    - name: Create task to run a PS script as NETWORK service on boot
      win_scheduled_task:
        name: TaskName2
        description: Run a PowerShell script
        actions:
        - path: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
          arguments: -Command "c:\tmp\script.ps1 *> c:\tmp\script.log"
        triggers:
        - type: daily
          start_boundary: '2017-10-09T09:00:00'
        username: SYSTEM
        state: present
        enabled: yes

returnの罠

  • 普通のプログラミング言語では"func2"だけ出力されるはずが、期待が違う
    • 関数の呼び出し時に必ず変数で受取るようにすると、望んだ結果になる
  • functionのreturnは、現在の制御を抜けるだけ。returnはあってもなくても良い。
    return "func1"
    # は以下と同じ
    "func1"
    return
  • classのreturnは必須。
  • ret1.ps1
    function func1 {
        return "func1"
    }
    
    function func2 {
        func1
        return "func2"
    }
    
    func2
    • 実行結果
      func1
      func2
  • ret2.ps1
    function func1 {
        return "func1"
    }
    
    function func2 {
        $ret = func1
        return "func2"
    }
    
    func2
    • 実行結果
      func2

変数のダンプ

  • jsonで出力
    $var1 | ConvertTo-Json

try catch中の行番号の表示

try{
}
catch {
    $e = $_.Exception
    $line = $_.InvocationInfo.ScriptLineNumber
    Write-Host -ForegroundColor Red "caught exception: $e at $line"
}

相対パスを絶対パスへ変換 

echo (Convert-Path ".\example.log")
C:\tmp\example.log

設定ファイルや関数を別ファイルにして読み込む

  • example-conf.ps1
    $config_var1="hoge"
  • example.ps1
    # Include config
    . (Join-Path $PSScriptRoot "example-conf.ps1")
    
    echo $config_var1

Get-Date: 日付と時刻

# localtime
Get-Date
20204216:45:32

# UTC
(Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:sszzz")
2020-04-02T08:03:27+09:00

# iso-8601
Get-Date -Format "o"
2020-04-02T16:56:30.9156570+09:00

# 文字列へ
(Get-Date).ToString()
2020/04/02 16:50:00

# 任意の書式へ
 (Get-Date).ToString("yyyy-MM-ddTHH:mm:sszzz")
2020-04-02T17:01:17+09:00

Test-Path: ファイル、ディレクトリ、レジストリの存在チェック


Write系コマンドレット

  • Write系コマンドレット一覧
    Get-Command -Module Microsoft.PowerShell.Utility -Verb Write
    
    CommandType     Name                                               Version    Source
    -----------     ----                                               -------    ------
    Cmdlet          Write-Debug                                        3.1.0.0    Microsoft.PowerShell.Utility
    Cmdlet          Write-Error                                        3.1.0.0    Microsoft.PowerShell.Utility
    Cmdlet          Write-Host                                         3.1.0.0    Microsoft.PowerShell.Utility
    Cmdlet          Write-Information                                  3.1.0.0    Microsoft.PowerShell.Utility
    Cmdlet          Write-Output                                       3.1.0.0    Microsoft.PowerShell.Utility
    Cmdlet          Write-Progress                                     3.1.0.0    Microsoft.PowerShell.Utility
    Cmdlet          Write-Verbose                                      3.1.0.0    Microsoft.PowerShell.Utility
    Cmdlet          Write-Warning                                      3.1.0.0    Microsoft.PowerShell.Utility
  • システム変数でOn/Offの切り替えができる
    # 出力On
    $VerbosePreference = 'Continue'
    
    # 出力Off
    $VerbosePreference = 'SilentlyContinue'
  • Write-Host "message"
    • ホスト画面へ出力。リダイレクトできない
    • -NoNewline : 改行なし
  • Write-Warning "message"
    • ホスト画面へ「WARNING: message」と出力
    • $WarningPreference で制御。デフォルト: Continue
  • Write-Verbose "message"
    • -Verbose 指定時だけ出力
    • $VerbosePreference で制御。デフォルト: SilentlyContinue
  • Write-Debug "message"
    • -Debug 指定時だけ出力して、一時停止。入力受付状態になる。
    • $DebugPreference で制御。デフォルト: SilentlyContinue
  • Write-Error "message"
    • 赤文字で出力
    • $ErrorActionPreference で制御。デフォルト: SilentlyContinue

ファイルサイズ、ディレクトリのファイル数

# ファイルの場合は、ファイルサイズ
(Get-ChildItem .\example.ps1).Length
987

# ディレクトリの場合は、ファイル数
(Get-ChildItem c:\tmp).Length
6

UTF8 BOMなしへ変換

  • 以下のコードはNG。ファイルサイズが大きいと遅い&メモリを大量に使用する
    • 入力がBOM付きの空ファイル(3byte)だと、$OutPathが作成されないので、New-Itemで作っている。
      function Utf8NoBom {
          param (
              [string] $InPath,
              [string] $OutPath
          )
      
          Get-Content -Path $InPath -Raw -Encoding Default `
          | % { [Text.Encoding]::UTF8.GetBytes($_) } `
          | Set-Content -Path $OutPath -Encoding Byte
      
          if (! (Test-Path -Path $OutPath)) {
              New-Item -Type File $OutPath
          }
      }
      
      
      Utf8NoBom ".\in.csv" ".\out.csv"

エラーの無視

  • $ErrorActionPreference
    • "Stop" : try{}catch{} したい場合
    • "continue" : エラーを表示する
    • "silentlycontinue" : エラーを表示しない
$ErrorActionPreference = "silentlycontinue"
# エラーを無視したいコマンド
$ErrorActionPreference = "continue"
  • エラーが出る部分を別関数にする
    function myfunc{
    
        try{
    # エラーが出る処理
    $ErrorActionPreference = "silentlycontinue"
        }catch{
        }
    }

圧縮/展開


入門


イベントログをcsv形式で出力

似たような関数があるが、使えるオプションが違う

  • Get-WinEvent
  • Get-EventLog
  • Export-CSV
    • -Encoding
      • UTF8
      • default (SJIS)
    • -NoTypeInformation
      • 型情報を出力しない
  • $LogNames=@("Application","Security","System")
    $LogName="Application"
    $AfterDate="2020-04-02"
    $CSVpath=$LogName + ".csv"
    Get-WinEvent -FilterHashtable @{LogName=$LogName;level=1,2;starttime=((Get-Date).AddDays(-1))} | Select timeCreated,levelDisplayName,providerName,id,@{name="message";expression={$_.message.Replace("`n",";")}} | Export-CSV $CSVpath -Encoding UTF8 -NoTypeInformation
    
    $AfterDate="2020-04-02"
    $CSVpath=$LogName + "." + $AfterDate + ".csv"
    Get-EventLog -LogName $LogName -After $AfterDate | Select timeCreated,levelDisplayName,providerName,id,@{name="message";expression={$_.message.Replace("`n",";")}}| Export-CSV $CSVpath -Encoding UTF8 -NoTypeInformation

PowerShellバージョンの確認

  • psver.ps1
    #!powershell
    $PSVersionTable.PSVersion
  • PowerShell から実行
    $PSVersionTable.PSVersion
  • cmd から実行
    powershell -Command ".\ver.ps1"
    
    Major  Minor  Build  Revision
    -----  -----  -----  --------
    5      1      18362  628
  • タスクスケジューラでのps1スクリプト実行時は、フルパスのpowershell.exe 経由で行う。ただし、v1.0指定でも最新のpowershellが使われるようだ
    %SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -Command ".\ver.ps1"
    
    Major  Minor  Build  Revision
    -----  -----  -----  --------
    5      1      18362  628

7


WSL(linux)のコマンドの呼び出し

wsl.exe経由で呼び出せる。


テレメトリ(利用者の情報を収集)の無効化:


Out-GridView: コマンド結果をテーブル形式の別ウィンドウで表示

Get-Process | Out-GridView

環境変数

  • 一覧
    Get-ChildItem env:
    
    Name                           Value
    ----                           -----
    ALLUSERSPROFILE                C:\ProgramData
    APPDATA                        C:\Users\user01\AppData\Roaming
    ChocolateyPath                 C:\Chocolatey
    CommonProgramFiles             C:\Program Files\Common Files
    ...
  • 一部だけ表示。echoは省略できる
    echo $env:LOCALAPPDATA
    C:\Users\user01\AppData\Local
    
    echo $env:APPDATA
    C:\Users\user01\AppData\Roaming
  • 設定
    $env:MYENV1 = "Hello"
    
    $env:MYENV1
    Hello

ヘルプの表示

  • 初回最新のヘルプがダウンロードされる
    Get-Help

find風の結果を得る

  • find -ls:
    gci -r

サービス一覧を取得

  • スタートアップの種類は紛らわしい
    • 自動:OS起動時に起動
    • 手動:ポートに要求があれば自動起動
    • 無効:起動を禁止
  • スタートアップ種類が手動(ポートにリクエストがあったら自動起動)で、起動しているサービス一覧
    powershell
    Get-Service | where StartType -eq Manual | where Status -eq Running
    
    Status   Name               DisplayName
    ------   ----               -----------
    Running  Appinfo            Application Information
    Running  AppMgmt            Application Management
    ...

zipファイルを展開せずにファイル名やファイルサイズで検索

  • 7z.exe を利用
  • hoge.jpg を検索
    powershell
    > get-childitem . -include *.zip -recurse | foreach ($_) { .\7z.exe l $_.name | Select-String "hoge.jpg" }

WMIからHDD SMART情報を取得

  • fileget-smart.ps1
    powershell ./get-smart.ps1
    
    ########
    Active: True
    InstanceName: IDE\DiskWDC_WD10EALX-759BA1_____________________19.01H19\4&1d873d54&0&0.0.0_0
    Length: 512
    bAttrID wStatusFlags bAttrValue bWorstValue bRawValue[6]
       1  47   0 200 200   0   0   0   0   0   0
       3  39   0 177 174  54  16   0   0   0   0
       4  50   0 100 100 239   1   0   0   0   0
       5  51   0 200 200   0   0   0   0   0   0
       7  46   0 200 200   0   0   0   0   0   0
       9  50   0  95  95 154  16   0   0   0   0
      10  50   0 100 100   0   0   0   0   0   0
      11  50   0 100 100   0   0   0   0   0   0
      12  50   0 100 100 237   1   0   0   0   0
     192  50   0 200 200  19   0   0   0   0   0
     193  50   0 200 200 219   1   0   0   0   0
     194  34   0 108 103  39   0   0   0   0   0
     196  50   0 200 200   0   0   0   0   0   0
     197  50   0 200 200   0   0   0   0   0   0
     198  48   0 100 253   0   0   0   0   0   0
     199  50   0 200 200   0   0   0   0   0   0
     200   8   0 100 253   0   0   0   0   0   0
     240  50   0  95  95  13  16   0   0   0   0
     241  50   0 200 200  92 134 168  41   2   0
     242  50   0 200 200   4 174  82 249   1   0

PowerShellの終了コードをcmd.exeに渡す

PowerShell内で「exit 2」としても、「echo %ERRORLEVEL%」は全て"1"になる。
以下のようにすれば取得できるようだ

powershell -NoProfile -command ".\test.ps1;exit $LASTEXITCODE"
echo %ERRORLEVEL%

PowerShellを実行可能にする

デフォルトでは実行不可になっている。

  • ローカルに保存されているスクリプトは実行可能、インターネット上のスクリプトは実行不可
    powershell Set-ExecutionPolicy RemoteSigned

添付ファイル: fileget-smart.ps1 976件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2020-10-28 (水) 15:49:37 (13h)