PowerShell関連まとめ

# はじめに
最初に実装したい機能のコマンド調べて
helpやmicrosoftのサイトを見て実装

# 開発環境
## VSCode
◆Visual Studio Code May 2020
　https://code.visualstudio.com/updates/v1_46
　　※過去バージョンダウンロードしたいときとか便利なので...
◆PowerShell - Visual Studio Marketplace
　https://marketplace.visualstudio.com/items?itemName=ms-vscode.PowerShell
　　※最新バージョン(2020.6.0)
◆PowerShell拡張
　https://marketplace.visualstudio.com/_apis/public/gallery/publishers/ms-vscode/vsextensions/PowerShell/2020.1.0/vspackage
　　※URLを貼り付けて実行するとダウンロードが始まります。
　　※このバージョンは、PowerShell 3.0/4.0等のレガシーバージョンもサポート
◆PowerShell のサポート ライフサイクル
　https://docs.microsoft.com/ja-jp/powershell/scripting/powershell-support-lifecycle

### [参考サイト]
◆PowerShell入門（コマンドレット一覧）
　http://omoisan.hatenablog.com/entry/2018/03/04/221930
　　※簡単に調べたい場合のサイトを押さえておいて
◆PowerShell モジュール ブラウザー
　https://docs.microsoft.com/ja-jp/powershell/module/?view=powershell-6
　　※本家のサイト
◆Windows PowerShell のヘルプ
　https://forsenergy.com/ja-jp/windowspowershellhelp/
　　※日本語の解説サイト

# フォルダ/ファイル操作

## ソート
```powershell:Sort.ps1
# 昇順
Get-Content -Encoding UTF8 -Path "./input.txt" | Sort-Object | Set-Content  -Encoding UTF8 "./output.txt"
# 降順
Get-Content -Encoding UTF8 -Path "./input.txt" | Sort-Object -Descending | Set-Content  -Encoding UTF8 "./output.txt" 
```

## コピー
```powershell:Copy.ps1
Copy-Item .\test.ps1 -destination \\192.168.100.24\C$\work
```

## ファイルRead/Write
```powershell:FileOperation.ps1
# usage 
#  PowerShell -ExecutionPolicy RemoteSigned .\fileOperation.ps1

# 環境変数
# 対象ファイル
$InputFilePath = ".\Surfaceねた.txt"
$OutputFilePath = ".\Surfaceねた2.txt"

# String(SJIS),UTF8
$Lines = Get-Content $InputFilePath -Encoding String

Add-Content -Path $OutputFilePath -Value $Lines[13] -Encoding String


# PowershellはUTF8で出力するとBOM有で保存されるため、BOM無に変換する方法

#(1)テンプレートのパス指定
$PATH1="template.xml"
#(2)結果ファイルのパス指定
$PATH2="output.xml"
#(3)テンプレートの読込
$TEMP1=GET-CONTENT $PATH1
#(4)リプレースしたいパラメータと値を定義
$PARAMS=@{"{0}"="00123"; "{1}"="M001"; "{2}"="010538"} 
#(5)テンプレートの内容をリプレース
foreach($P in $PARAMS.Keys){$F1=($F1.replace($P,$PARAMS[$P]));}
#(6)結果をファイル出力(BOMなしUTF-8)
$ENC=NEW-OBJECT System.Text.UTF8Encoding -ArgumentList @($false)
[System.IO.File]::WriteAllLines($PATH2,$F1,$ENC)
#(7)結果表示
GET-CONTENT $PATH2

# template.xml
#<?xml version="1.0" ?>
#<setting>
#    <machineid>{0}</machineid>
#    <macineid2>{0}</machineid2>
#    <machinespeed>{1}</machinespeed>
#    <machinelocation>{2}</machinelocation>
#</setting>

# output.xml
#<setting>
#    <machineid>00123</machineid>
#    <macineid2>00123</machineid2>
#    <machinespeed>M001</machinespeed>
#    <machinelocation>010538</machinelocation>
#</setting>
```
### 参考サイト
◆もりもりゲームブログ: PowerShellで、たとえば設定ファイルの内容を変更して保存したい時の簡単なやり方 (連想配列を使うよ)
　https://morimorigameblogg.blogspot.com/2019/03/powershell_17.html
◆PowerShellでBOM無しUTF8を簡単に扱う、デフォルト設定を簡単に変える方法 - しばたテックブログ
　https://blog.shibata.tech/entry/2016/10/02/154329
◆PowerShellで巨大なファイルをGet-Contentし、Export-Csvするのを省メモリで行う
　https://blog.osakana.net/archives/8062
◆テキストファイルの読み込み、書き込み
　http://suyamasoft.blue.coocan.jp/PowerShell/Tips/TextFile/Get-Content/index.html#GetContent
◆PowerShellでファイルのフルパスを取得する
　https://www.it-swarm.jp.net/ja/powershell/powershell%E3%81%A7%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E3%83%95%E3%83%AB%E3%83%91%E3%82%B9%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B/1068824591/


## CSVファイル操作
### 参考サイト
◆PowerShell で csv を扱う方法まとめ
　https://qiita.com/nimzo6689/items/4a6fcabc032f570de6f0
◆PowerShellでCSVファイルを操作する方法まとめ！
　https://bgt-48.blogspot.com/2019/04/powershellcsv.html


## リモート操作
```powershell:RemoteOperation.ps1
$user   = "{ユーザ名}"
$pass   = ConvertTo-SecureString "{パスワード}" -AsPlainText -Force
$remote = "{IPアドレス}"

$credential = New-Object System.Management.Automation.PSCredential $user, $pass

$session = New-PSSession $remote -Credential $credential 
Invoke-Command -Session $session -ScriptBlock { New-Item -Path "{リモートPC上のパス}\YYYYMMDD" -ItemType "Directory" -Force }
Copy-Item -Path "{ローカルPC上のパス}" -Destination "{リモートPC上のパス}\YYYYMMDD" -ToSession $session -Recurse
Remove-PSSession $session
---------------------------------------------------------------------

PS C:\> $hostname = "masao-pc"       # 接続先ホスト（環境に合わせて変更する）
PS C:\> $username = "masao-pc\masao" # 接続ユーザー（環境に合わせて変更する）
PS C:\> $passwd   = "masao"          # パスワード （環境に合わせて変更する）
PS C:\> 
PS C:\> # セキュアストリングの作成（パスワードの暗号化）
PS C:\> $sec_str = ConvertTo-SecureString $passwd -AsPlainText -Force
PS C:\> 
PS C:\> # Credential オプションに指定するオブジェクトのインスタンス生成
PS C:\> $psc = New-Object System.Management.Automation.PsCredential($username, $sec_str)
PS C:\> 
PS C:\> # New-PSSession コマンドによるセッションの生成
PS C:\> $sess = New-PSSession -ComputerName $hostname -Credential $psc
PS C:\> Get-PSSession # セッションの確認
 
 Id Name ComputerName State ConfigurationName Availability
 -- ---- ------------ ----- ----------------- ------------
 1 Session1 masao-pc Opened Microsoft.PowerShell Available
 
PS C:\> # コマンドをリモートホスト上で実行する
PS C:\> Invoke-Command -Session $sess -ScriptBlock {Get-ExecutionPolicy;}
 
PSComputerName RunspaceId PSShowComputerName Value
-------------- ---------- ------------------ -----
masao-pc 7e14da16-066c-4289-811d-af... True Restricted
 
PS C:\> Remove-PSSession -Session $sess # セッションを削除
PS C:\> Get-PSSession # セッションの確認
```
### [参考サイト]
◆PowerShell でリモート接続する ( Enter-PSSession )
　http://hensa40.cutegirl.jp/archives/677

## ファイル検索
※参考サイトにまさに欲しかったものがあった...今度試してみる

### [参考サイト]
◆Excel の複数ファイル一括検索・置換
　https://qiita.com/earthdiver1/items/f4280d161a96e20489e2
◆POWERSHELL　文字列エスケープ＆置換
　http://goldyrain.blogspot.com/2011/12/powershell.html


```powershell:excel_find_customize.ps1
# フォルダ内にショートカットファイルがあると失敗するので事前に削除
#   ※ファイル名をキーに処理実行判断すればよいが、一旦Pending...

# デバッグ用
Write-Host "【処理ファイル】$filename"

# 読み取り専用でファイルを開く(開く際に読み取り専用で開くかどうかのダイアログが表示される問題の対応＆検索なので編集リスクを低減したい)
# $workbook = $excel.Workbooks.Open($filename)
$workbook = $excel.Workbooks.Open($filename, $default, $true)

# なぜか下記で例外発生するファイルがあるので、try～catchで囲む
$result = $range1.Find($string,             # What

# ファイルを保存しないで閉じる
# $workbook.Close()
$workbook.Close($false, $default, $default)

```

# その他

## Oracle
```powershell:selectCount.ps1
# usage 
#  PowerShell -ExecutionPolicy RemoteSigned .\selectCount.ps1

$sql=@"
SELECT TRIM(COUNT(*)) FROM "TEST"."Students";
"@
$result = $sql | sqlplus system/manager@XE
$result | Out-File "result.txt" -Encoding utf8
Write-Host $result[12]
```

## Windowsサービス
```powershell:WindowsService.ps1
# usage WindowsService.ps1 -ServiceName <String> -Operation <start or stop>

# 引数定義
Param(
    [ValidateScript( { if ($_ -ne "") { $true } else { $false } })][String]$ServiceName,
    [ValidateSet("start", "stop")][String]$Operation
)

If ($Operation -eq "start") {
    # Windowsサービス起動
}
Elseif ($Operation -eq "stop") {
    # サービス状態取得
    $ServiceStasus = Get-Service | Where-Object { $_.name -match $ServiceName } | ForEach-Object { $_.Status }
    # サービス状態判定
    switch ($ServiceStasus) {
        "Stopped" { return 0 }  # サービス停止済のため何もせず終了
        "Running" { return 0 }  # Windowsサービス停止 
        # default { if ($cnt -eq $Upto) { return 1 } } # チェック回数の上限に達した場合、1を返す   
    }
}

# ◆Powershell サービスの実行状態を確認する関数
#   https://qiita.com/yamazon/items/d74f40ab600fc90bf0b2
```