読者です 読者をやめる 読者になる 読者になる

雑記+備忘録

OS中心の技術情報と趣味について(最近は主に将棋)。備忘録なのでここに書かれたことを試すのは自己責任でお願いします。

PowerShellでADのグループメンバーを追加、削除

(2017/3/15追記)もっとシンプルにできました。
 コメントいただいた「素敵なおひげ」さんありがとうございました。

$user = Get-ADUser -Filter {(Name -like "*山田*") -And (Name -like "*太郎*")}

Remove-ADGroupMember "千葉支店_課長" -Members $user.DistinguishedName -Confirm:$false

Add-ADGroupMember "千葉支店_部長" -Members $user.DistinguishedName -Confirm:$false

最初うまくいかなかったのは「-Members」の引数に「Select-Object」で抽出したオブジェクトをもってきていたのが良くなくて、
「素敵なおひげ」さんのアドバイス通り、Get-ADUserで得たオブジェクトの「DistinguishedName」プロパティをもってきたらうまくいきました。
(追記ここまで)

基本的には「Add-ADGroupMember」「Remove-ADGroupMember」を使えばよいのですが、
メンバーの指定方法で苦戦したのでメモ。

これも要点だけ先に記載すると「-Members」の引数としては以下の4種類が指定可能とのことです。
MicrosoftTechNetコマンドリファレンスによる)
・識別名
  例:CN=山田 太郎,OU=東京本社,OU=スーパーさ部,DC=test,DC=local
・GUID(ObjectGUID)
・セキュリティ識別子(するObjectSID)
・セキュリティアカウントマネージャ(SAM)アカウント名(sAMAccountName)

で、SamAccountNameを指定してコマンドを実行すると、
ドメイン下にユーザーが存在しない」といった意味のメッセージが表示されます。

間にOUが挟まっているせいか、と識別名で指定することにします。
識別名を呼び出すために、

Get-ADUser -Filter {(Name -like "*山田*") -And (Name -like "*太郎*")} | Select DistinguishedName

フィルターの条件は「Name -eq “山田 太郎"」でも良かったのですが、
今回のシステムでユーザーを作る際に姓と名の間のスペースが半角か全角か統一されていない可能性があったので、
少しひねってみました。(こういうAnd条件が使えるということも見たかった)
→ただこれだと「小山田 太郎」さんとかいたらひっかかるか。要再考。
で、普通にこれを実行すると、「DistinguishName」が「オブジェクトとして」出力されるので、
「-Members」の引数に指定すると「型が変換できません」とエラーメッセージが表示されます。

で、文字列変換するために、

Get-ADUser -Filter {(Name -like "*山田*") -And (Name -like "*太郎*")} | Select DistinguishedName | Out-String

今度は「ゼロ文字列行」「DistinguishedName」「—————–」「CN=~」の4行の文字列として認識され、
そんなメンバーいないとエラーメッセージ。

抽出した値だけを文字列にしたいんだ。
探すと、以下が使えるようです。
(参考(ありがとうございます):http://stknohg.hatenablog.jp/entry/2015/08/23/235304

Get-ADUser -Filter {(Name -like "*山田*") -And (Name -like "*太郎*")} | Select DistinguishedName | Out-String -Stream

画面上の出力は先ほどと同じですが、表示される4行が文字列の配列の形になっているので、
変数に格納した際に以下のように使えます。

$a = Get-ADUser -Filter {(Name -like "*山田*") -And (Name -like "*太郎*")} | Select DistinguishedName | Out-String -Stream

Remove-ADGroupMember "千葉支店_課長" -Members $a[3] -Confirm:$false

Add-ADGroupMember "千葉支店_部長" -Members $a[3] -Confirm:$false

「-Confirm:$false」は「-Confirm $false」ではないのでこれも注意するポイントです。

負荷テスト用ツール(メモリ)

負荷テストで使えるツールについてメモ。Microsoftで公開している「Windows Sysinternals」から入手できるものを中心に。

この記事にまとまっています。
https://blogs.msdn.microsoft.com/vijaysk/2012/10/26/tools-to-simulate-cpu-memory-disk-load/

○ TestLimit
上記サイトからダウンロードできます。本家Sysinternalsのサイトでは探し方が悪いのか見つけられず。
ダウンロード後、コマンドプロンプトから必要なオプションを指定してexeファイルを実行ます。
実行するファイルは32ビット環境では「Testlimit.exe」、64ビット環境では「Testlimit64.exe」です。
例えば以下では500MBの負荷をかけ続けます。
Testlimit64.exe -d -c 500
オプションの「-d」よりも後ろにMB単位で使いたいメモリのサイズを指定します。
「-c」についてはヘルプの説明では意味が分かりませんでしたが、
「-c」なしで実行してみたところ一定時間ごとに「使うメモリが500MBずつ増加」していき、マシンをフリーズさせたので、
「-c」は「占有するメモリサイズを指定した値に保つ」意味と思われます。

f:id:saborin-2002:20170311234259p:plain

CPUツールと異なり、ほとんどゆれ幅がありません。

f:id:saborin-2002:20170311234313p:plain

負荷の終了は、コマンドプロンプトで「Ctrl + c」でプログラムの実行を中断させます。

負荷テスト用ツール(CPU)

負荷テストで使えるツールについてメモ。Microsoftで公開している「Windows Sysinternals」から入手できるものを中心に。

この記事にまとまっています。
https://blogs.msdn.microsoft.com/vijaysk/2012/10/26/tools-to-simulate-cpu-memory-disk-load/

○ CPUSTRES.EXE
上記サイトからダウンロードできます。本家Sysinternalsのサイトでは探し方が悪いのか見つけられず。
ダウンロード後、exeファイルをダブルクリックで実行し、表示されるGUIベースで操作します。

f:id:saborin-2002:20170311234040p:plain


「Thread」が4つ表示され、複数スレッドで負荷をかけられます。複数コアに対して負荷をかける際に有用です。
使いたい「Thread」の「Active」にチェックを入れて有効にします。
Thread Priorityは、他のプログラムに対する優先度を設定するようです(適当)。普通は「Normal」で問題ないと思います。
Activityは、負荷のかけ度合を段階的に設定します。「Low」「Medium」「Busy」「Maximum」とあり、
それぞれ「約15%」「約25%」「約55%」「100%近く」の目安です。
あとはそれらを組み合わせて、テストで必要な負荷をかけ続けます。
パフォーマンスモニターで見ると、実行中多少のゆれ幅があります。

f:id:saborin-2002:20170311234105p:plain

PowerShellの関数(ファンクション)の考え方

(参考としてリンクさせていただいたURLの筆者の皆様ありがとうございます)

別ファイルに分けて関数化する方法
→ファイルを作って、「. “C:\fso\include.ps1"」のように「ドット、スペース、フルパス」で呼び出し元ファイルに記載(これを「スクリプトをドット ソース形式で使用」という)

以下を参考にしました。(いつものScripting Guy)
https://gallery.technet.microsoft.com/scriptcenter/b590021a-b311-47f9-8f48-3809658b7cbf

ところが、「戻り値はどうやって指定するんだろ」と疑問を持った途端に、
PowerShellの仕様の壁(基本らしい)にぶち当たりました。
「関数内で値が出力されると、returnキーワードがついてなくてもすべて呼び出し元に出力される」ということで、
作成したファンクション内の値出力が全て返ってきます。
(参考)
http://stknohg.hatenablog.jp/entry/2015/07/05/114903
http://winscript.jp/powershell/253

いや、純粋に計算結果で出た一つの値だけを返したいんだけど、と探した結果、以下のサイトにとても分かりやすく書いてありました。
http://tyru.hatenablog.com/entry/2015/11/08/004204

で、以下のサンプルソースを作ってみました。

Moto.ps1

# 引数1:文字列

# ファイルのパスを情報取得
$scriptPath = $MyInvocation.MyCommand.Path
$nofilePath = Split-Path -Parent $scriptPath

# Function取り込み
. ($nofilePath + "\Include.ps1")

# Functionにより値変換
$pTaro = fncAddTaro($args[0])

echo $pTaro



Include.ps1

# ファンクション
# 文字列が「ピコ」を含めば「ピコ太郎」を返す
# 文字列に「ウルトラ」を含めば「ウルトラマンタロウ」を返す
# それ以外は「たろー」を付加して返す
Function fncAddTaro($strMoji) {

  $rtnVal = ""
  .{
     if ($strMoji.Contains("ピコ")) {
       $rtnVal = "ピコ太郎"
       return # ここで「.{ }」ブロックを抜ける
     }

     if ($strMoji.Contains("ウルトラ")) {
       $rtnVal = "ウルトラマンタロウ"
       return
     }

   $rtnVal = $strMoji + "たろー"
   return
   } | Out-Null  # 「.{ }」ブロックの中の出力は戻り値に含めない

return $rtnVal

}



実行結果

PS > .\Moto.ps1 "パピコ"
ピコ太郎
PS > .\Moto.ps1 "ウルトラクイズ"
ウルトラマンタロウ
PS > .\Moto.ps1 "ワルトラ"
ワルトラたろー
PS > .\Moto.ps1 "山下"
山下たろー

指定したExcelファイルのシート名を全て取得するPowerShell

表題の件、スクリプトを作成しました。
業務をしていてあると便利だな、と。

# 指定したExcelのシート名を全て取得するPowerShell
# 引数1:ファイル名

# ファイルのパスを取得
$scriptPF = $MyInvocation.MyCommand.Path
$scriptPath = Split-Path -Parent $scriptPF

$filePF = $scriptPath + "\" + $args[0]

# ファイルが存在する場合に処理
if (Test-Path $filePF) {

  # Excelのオープン
  $objExcelAp = New-Object -ComObject Excel.Application
  $objExcelAp.Visible = $true

  $objExcelBook = $objExcelAp.Workbooks.Open($filePF)

  $objExcelBook.Sheets | ForEach-Object {
    $_.Name | Out-File ($scriptPath + "_AllSheetsName.txt") -Append -Encoding Default
  }

  # ファイルを閉じてExcelの終了
  $objExcelAp.Quit()

  # 各変数を解放(.ブロックでOut-Nullしているのは実行すると「0 0 0」と表示されるため)
  .{
     [System.Runtime.Interopservices.Marshal]::ReleaseComObject($objExcelBook)
     $objExcelBook = $null
     [System.Runtime.Interopservices.Marshal]::ReleaseComObject($objExcelAp)
     $objExcelAp = $null
  } | Out-Null

  # ガベージコレクトの明示実行
  [GC]::Collect()
  [GC]::WaitForPendingFinalizers()
  [GC]::Collect()

}

テキストファイルの各行頭もしくは行末に文字列を挿入

表題の件、スクリプトを作成しました。
業務をしていて、あると便利だな、と。

# テキストファイルを1行ずつ読んで書き込む【行頭に特定文字】
# 書き込むファイル名はc_+<読み込むファイル名>
# 引数1:ファイル名
# 引数2:挿入文字列

$file = ".\" + $args[0]

# ファイル存在する場合に処理
if (Test-Path $file) {

  # 読み込み挿入書き込み
  foreach ($line in Get-Content $file) {
    $args[1] + $line | Out-File (".\c_" + $args[0]) -Append -Encoding Default
  }

}

途中を少しだけ手を加えると、行末に挿入になります。

# テキストファイルを1行ずつ読んで書き込む【行末に特定文字】
# 書き込むファイル名はc_+<読み込むファイル名>
# 引数1:ファイル名
# 引数2:挿入文字列

$file = ".\" + $args[0]

# ファイル存在する場合に処理
if (Test-Path $file) {

  # 読み込み挿入書き込み
  foreach ($line in Get-Content $file) {
    $line + $args[1] | Out-File (".\c_" + $args[0]) -Append -Encoding Default
  }

}

「速効! 振り飛車の絶対手筋105」を解いていく

先日の「将棋基本手筋コレクション432」の次にやるべき次の一手本は何か…振り党としてはまずはこれでしょうか。

速効! 振り飛車の絶対手筋105 (マイナビ将棋BOOKS)

速効! 振り飛車の絶対手筋105 (マイナビ将棋BOOKS)

前回同様、正答率を記録しながら解くことにしました。
今度は、納得する正答率になるまで何周かやってみる予定です。
この本の構成として例題と問題集形式が混在していますが、例題も問題集の1問とみなして解いていくことにします。

で、1周目、知らない手筋ばかりで正答率はほぼゼロ。
いかに必修手筋を押さえていないかが浮き彫りになりました。
現在2周目。半分弱解いて、正答率3割ぐらい。一度じゃ覚えないもんだなあ。
マスターすれば、中盤の多くの場面で指針を得られる気がするので、
コツコツと繰り返し解いていこうと思います。