TEMTECOMAI ORTHOSTATIC HYPOTENSION

元ダメプログラマで現ダメ中間管理職の駄文

カテゴリ: PowerShell

警察です、ここの事業所に Aさんという方はいますか?

お調べしますね。 ここの事業所には W1 と W2 と W3 の 3つ事業本部が所属しています。
どの事業本部をお調べしますか? W1 ですね。
お調べしますね。 W1 事業本部には 4つの部がありますね。
・・・
・・・
・・・
・・・
Aさんはここの事業所ので所属はなく、ここの事業所の W3事業本部の  X5部の Y2課の Z1係の所属ですね。
これが Z1係の従業員リストです。 どうぞ。

警察です、ここの事業所の全従業員のリストをください

はいどうぞ、全従業員です。

たらい回しもイヤだ。 かといって全部から調べるのもイヤだ。 というかハッキリと答えてほしい

Get-ADGroupMember -Identity <グループ名>
これで取れるのは指定したグループに直接参加しているユーザーやグループの一覧なので、参加しているグループのメンバーの名前はでてこない。
Get-ADGroupMember -Identity <グループ名> -Recursive
これで指定したグループに参加しているグループに参加しているグループに参加しているメンバーのように間接的に参加しているメンバー全員をリストアップできる。
でも  YES か NO で答えが知りたい。

Get-ADGroupMember は Microsoft.ActiveDirectory.Management.ADPrincipal 型のオブジェクトか、その配列を返すので DistinguishedName とか SamAccountName とか SID とか持っているようです。
比較側のユーザーは普通に Get-ADUser で取得。 これももちろん同じプロパティを持ってる。
(Get-ADGroupMember -Identity <グループ名> -Recursive | Select-Object -ExpandProperty DistinguishedName) -Contains (Get-ADUser -Identity <ユーザー名>).DistinguishedName
これで Get-ADGroupMember から返ってきた DistinguishedName の配列と Get-ADUser から返っていた DistinguishedName を比較でき、含まれているかどうかを True / False で調べられるようになった。
本質を理解していないのでイロイロ遊んでみたら、Get-AdUser 側は DsitinguishedName を引き合いに出さなくても行けました。
(Get-ADGroupMember -Identity <グループ名> -Recursive | Select-Object -ExpandProperty DistinguishedName) -Contains (Get-ADUser -Identity <ユーザー名>)
そういうものなのかと理解したつもりになって、ついでに引数名 -Identity も省略してみたけど、これでも行けますね。 -Identity はデフォルトの引数だったかね。
(Get-ADGroupMember <グループ名> -Recursive | Select-Object -ExpandProperty DistinguishedName) -Contains (Get-ADUser <ユーザー名>)
さらに冒険してみた。
Select-Object でプロパティ展開する部分は -ExpandProperty を使うのだけれど、文字が長いとか -ExcludeProperty と間違うとか、意外に嫌われているようで、Select-Object の替わりに ForEach-Object を使う事もできるんだそうな。
(Get-ADGroupMember <グループ名> -Recursive | ForEach-Object DistinguishedName) -Contains (Get-ADUser <ユーザー名>)
奥が深いというか、、、

ようやく再リリース

Windows Management Framework (WMF) 5.0 RTM packages has been republished

ダウンロードはここから。
ダウンロード センター : Windows Management Framework 5.0

リリースノートはこれ。
Windows Management Framework (WMF) 5.0 RTM Release Notes Overview

PowerShell ってもんは、横に横にと、ものすごく長くなってしまう宿命なのかしらね。
世界で一番嫌いなのが横スクロールだ。
Param
(
    [ValidateSet("Phonetic", "EmployeeNumber", "AccountName")]
    [string]
    $conditionType,
    [string]$value
)

switch ($conditionType)
{
    "Phonetic" { $condition = "msds-PhoneticDisplayName -like '*$value*'"; break }
    "EmployeeNumber" { $condition = "employeeNumber -eq '$value'"; break }
    "AccountName" { $condition = "samaccountName -eq '$value'"; break }
    default { $condition = "*" }
}

Get-ADUser -Filter $condition -Properties * | Select-Object Enabled, LockedOut, Description, UserPrincipalName, Surname, Givenname, msDS-PhoneticDisplayName, EmployeeNumber, Department, EMailAddress, DistinguishedName

Get-ADUser -Filter $condition | Get-ADPrincipalGroupMembership | Sort-Object GroupScope, Name | Format-Table GroupScope, Name -AutoSize
みたいな

ここ数日の成果物は PowerShell のスクリプト ファイル (*.ps1) と SQL Serve 用のスクリプト ファイル (*.sql) に分散してしまっている。
どうせなら PowerShell に一本化したいよね。
残念ながら Windows Server 2008 R2、WSUS 3.0、Windows Internal Database という我が WSUS 環境では PowerShell による管理が整備されきっていない時代の物らしく、WSUS はアセンブリを読み込んで .NET 的なアプローチをし、SQL Server は sqlcmd.exe に sql ファイルを流し込む事になるようです。
しかも sqlcmd.exe は Windows Internal Database ではインストールされないようなので別途無償版の SQL Server Management Studio Express とかをインストールしないとなりませんね。
Windows Server 2012 の WSUS 4.0 では PowerShell のコマンドレットが用意されているみたいですね。
Windows Internal Database はどうなんでしょうか。。。 SQL Server 2012 以降なら PowerShell 用の sqlps モジュールもありますが、WID ではダメなんでしょうか。。。 ダメかもわからんね。。。

WSUS 3.0 SP2 on Windows Server 2008 R2 (Windows Internal Database 使用)

WSUS のクリーンアップは時間がかかる。
ホントにかかる。
数日待たされる可能性もある。

その間ずっと管理者でログオンして管理ツールを開いていることになる。
リモート デスクトップから操作してたら作業用 PC の電源も切れなくなってしまうし、だからと言ってサーバーにログオンしっぱなしってのもよろしくない。
ならばタスクで自動実行すればいいんじゃないだろうか、と。


とか思っていたらマイクロソフトのスクリプト センターにありましたよ。 さすが Scriptyng Guys だ。
WSUS Cleanup
https://gallery.technet.microsoft.com/ScriptCenter/fd39c7d4-05bb-4c2d-8a99-f92ca8d08218/

[reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")` 
 | out-null 
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer(); 
$cleanupScope = new-object Microsoft.UpdateServices.Administration.CleanupScope; 
$cleanupScope.DeclineSupersededUpdates = $true        
$cleanupScope.DeclineExpiredUpdates         = $true 
$cleanupScope.CleanupObsoleteUpdates     = $true 
$cleanupScope.CompressUpdates                  = $true 
#$cleanupScope.CleanupObsoleteComputers = $true 
$cleanupScope.CleanupUnneededContentFiles = $true 
$cleanupManager = $wsus.GetCleanupManager(); 
$cleanupManager.PerformCleanup($cleanupScope);
こいつを ps1 ファイルにしてタスク スケジューラーに登録しろ、という話ですかね。
スクリプトをパッと見てすぐにわかりますが、[Refrection.assembly]::LoadWithPartialName() で Microsoft.UpdateServices.Administration を読み込んでいるので、PowerShell らしくない方法ですよね。
Windows Server 2012 の WSUS は PowerShell 用のモジュールがあるらしいのですが、WSUS 3.0 には存在しない。 だからアセンブリを読み込んで処理を行う、ということでしょう。

スクリプトのほとんどの部分はクリーンアップ ウィザードの UI にあるチェックボックスの項目っぽいですね。 これらのプロパティに $true または $false を設定して処理項目を決定するわけですね。
ちょっと UI に表示されている処理項目と数が合わないけれど、まぁクリーンアップの範囲でしょう。
CleanupObsoleteComputers がコメントアウトされてます。 しばらく (30日だっけ?) アクセスしていないコンピューターの情報を削除するって処理でしょうか。

タスクで無人実行するのだから try-catch を使って、エラーもイベントログに出力するようにしたらいいんじゃないかね。

最近 PowerShell のお勉強に力を入れています。
対象は主に Active Directory の管理。

それとは別に、Office 365 管理の文書を読んでいると Exchange の管理なんかにも PowerShell がバンバン搭乗してくる。
たしか Windows Server 2008 あたりから標準搭載されたんだっけ?
随分と不勉強な期間を過ごしてしまったものだ。。。

とりあえず Windows 8.1 の Active Directory 管理センターが生成するスクリプトを見て勉強中。
ユーザー アカウントを新規作成するだけでも 4つぐらいのスクリプトを流しているみたい。
  1. 基本的な項目を指定してアカウントを作成する。
  2. セキュリティ関連の設定をする。
  3. アカウントを有効にする。
  4. 次回ログオン時にパスワード変更を強制するようにする。

みたいな。
最初の New-ADUser コマンドレットにもう少し作業を集約できやしないかね。

あとは作成したスクリプトの中に値を指定していく方法を考えなくちゃね。
ユーザーを作成するケースは 3種類程度で、ケースごとに指定する項目が若干増減する。
ユーザーの情報を変更するケースも何種類かに限られる。
所属が変わる。
社内権限が変わる。
PC へのログオンを禁止する。 またはその逆。
メール アドレスが変わる。 (外部の POP3 なので連動しない)
削除のケースは一つだけ。 単純に削除するだけ。

この作業をするためのツールを自作するにしても、汎用的な作業に使えるようなものになってしまうと車輪の再発名になってしまうので、上に挙げたような実際に起こるケースを起点にすればいいのかな。

何らかの UI を作ったとして、入力したものを最終的に PowerShell に流すにはどうしたらいいのかな。
パイプを駆使すれば 1行のコマンドで済むだろう。それなら Shell で PowerShell を起動してコマンドを引数で与えれば大丈夫かもしれない。
コマンドが複数行になってしまう場合はどうだろう。 スクリプトファイルを生成してから渡せばいいのかな。

というか UI の言語から直接 PowerShell をコントロールすることはできるのかな。
UI は何で作ればいいんだろうか。
Windows フォーム? 今更だなぁ。。。
今の主流派 WPF なのかな?
Windows フォームの開発者たちは既に WPF を習得しちゃったのかな。 MVVM とか書籍を読んでも概念ばかりでよくわからないよ。

まだ英語版しか出ていなくて、バージョン 1.1では DHCP サーバー管理ツールの mcc コンソールなど一部は未搭載。(PowerShell でなら管理できるらしい)
今すぐ日本語の Windows 10 にインストールするにはちょっとだけ余分な手数が必要らしいので大人しく日本語版が出るのを待っている状況。

メイン機である Windows 7 (Windows Server 2008 / 2008 R2) 向けの Active Directory 管理センターで日常業務は問題なし。
ただ最近気がついたのだけれど Windows 8, Windows Server 2012 / 2012 R2 向けの管理センターでは後ろで生成されてる PowerShell のスクリプトを見ることができるって機能があるらしく、これが気になって仕方がない。

今更 Windows 8.1 に戻すのもアレだし、、、ってことで、MSDN サブスクリプションで落とした Windows 8 Pro の iso を使って仮想マシンを立てることにした。
アップデートが多すぎて 8.1 までの道のりは長い。

PowerShellPowerShell のコマンドプロンプトが開いてもウィンドウだけが表示されてプロンプトが表示されない。
いくら待っても表示されない。
この状態でもう一枚 PowerShell のコマンドプロンプトを開こうとすると、この 2枚目のウィンドウは正常に開いて操作可能な状態になる。
ただし依然として 1枚目のウィンドウにはプロンプトが表示されない。
1枚目のウィンドウがどうなっているかというと、背景はオイラが設定した青色になっていて、プロンプトが表示されていない状態でウィンドウの左上(0, 0 の位置)にカーソルが点滅。ウィンドウ内の任意の位置でマウスをドラッグさせると選択モードにもなる。でも文字は入力できない。
仕方がないので 1枚目のウィンドウ右上の [X] をクリック。しばらくすると <プログラムの終了 - Windows PowerShell> のダイアログが出る。迷わず [すぐに終了(E)] をクリック。
んで 2枚目のウィンドウで作業を始める。

だそうです。
http://blogs.technet.com/stanabe/archive/2006/05/07/427471.aspx
cmd.exe に替わる次世代のシェル、WSH + VBScript に替わる次世代のシステム管理用スクリプトとして期待しておるわけですが、ホントに Vista には間に合わないのかなぁ。
期待している範囲まで実装するのは間に合いそうにもないけれど、そこそこ使えるレベルはいけるんじゃないかと思うんだけど。

ダウンロード ページ
http://www.microsoft.com/downloads/details.aspx?familyid=2B0BBFCD-0797-4083-A817-5E6A054A85C9&displaylang=en
紹介ページ
http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

↑このページのトップヘ