2011年7月29日金曜日

◆Write-HostとWrite-Output

PowerShell: ◆ActiveDirectoryグループごとのメンバー一覧を表示するで作った以下のようなスクリプト。
image

結果をちょっとテキストに落としておきましょうと、7行目にリダイレクトを追加した。

} > D:\Desktop\PCList.txt

てな感じ。

すると、結果はだいぶ悲しい事になる。
グループタイトルとメンバー一覧が画面とテキストに泣き別れ。

ん~、そうだよね。Write-Hostだもんね。
という事でこれまであまり気にせずに使っていたWrite-Hostだが、なるべくWrite-Outputを使うべきなのだろうと反省。

ちなみに、6行目はWrite-Hostだと空行を表示してくれるがWrite-Outputだと引数が必須なので、
Write-Output “”
としておく。

2011年7月28日木曜日

◆ActiveDirectory、名前で検索してユーザーアカウントを無効にする

こんな感じで良いみたい。

Get-ADUser -Filter 'name -eq "原 辰則"' | Set-ADUser -Enabled $false

あとは以下のあたりをインプットにして定期的に整理してあげればよいかな・・・。

PowerShell: ◆ActiveDirectory過去2年間ログオンしていないユーザーを検索

2011年7月27日水曜日

◆Webページをダウンロードする2

以前、Webページをファイルにダウンロードしてみたが、ダウンロードした内容を整形してファイルに落としたかったので、一旦文字列に取得してみた。

DownloadFileの代りにDownloadStringを使うだけ。
と思っていたのだが、結果を見てみると日本語が文字化けしている。
Webページのソースを見るとUTF8のようなのでUnicode(UTF16)に変換してあげれば良いのだろうと思い、一生懸命取得した文字列に対してコードを変換を試みたが、なんともかんともうまくいかない。

変換の仕方がおかしいのか・・・。
何か勘違いをしているような・・・。

あちこち彷徨い、やっとWebClientにはEncodingプロパティがあり、こいつにUTF8を指定してやると上手くいくことが判った。
(DownloadStringの引数にも用意してくれれば良いのに・・・)

このプロパティのデフォルトは「Default」なので基本的にはS-JIS。
なので、UTF8をS-JISとして読み込んだ文字列をUTF8だと思って変換しようとしていたので上手くいかなかったのだろう。

001
002
003
004
005

$source = "http://www.yahoo.co.jp/"
$wc = New-Object System.Net.WebClient 
$wc.Encoding = [System.Text.Encoding]::UTF8
$txt = $wc.DownloadString($source)
$txt

◆ActiveDirectory、コンピュータ一覧を取得する

Get-ADComputerコマンドレットでActiveDirectoryのコンピュータ一覧を取得してみた。

デスクトップにCSVで出力するサンプル。

001
002
003
004
005
006
007
008
009
010

$oPath = [environment]::GetFolderPath("desktop")
$outFile = Join-Path $oPath "コンピュータ一覧.csv"

Get-ADComputer -Filter *  -Properties description,lastlogon |
 
 
select name,description,
 @{
   name
="lastLogon"
expression={[DateTime]::FromFileTime([Int64]::Parse($_.
lastLogon))}
  } 
|
 
 
sort lastLogon | ConvertTo-Csv -NoTypeInformation |
 
 
Out-File $outFile -Encoding default

未使用のPCを調べたかったのでlastlogonプロパティを取得してみたが、lastlogon日付はFileTime型のようで変換が必要。

1601 年 1 月 1 日以降の 100 ナノ秒間隔の数を表します。この構造体は 64 ビット値です。

との事なので、[DateTime]::FromFileTime([Int64]::Parse($_.lastLogon))を使って変換してあげると良いみたいです。

2011年7月22日金曜日

◆ActiveDirectory、Search-ADAccountで追加のプロパティを取得する

Search-ADAccountで取得されるのは名前のとおりADAccountオブジェクト。
なので、必要なユーザー情報が全部揃っているとは限らない。

足りないときはどうするか?
とりあえずGet-ADUserで取ってきてみた。

過去2年間ログオンしていないユーザーの名前とメールアドレスを表示するサンプル。

001
002
003
004
005

[string]$span = (365 * 2)  #過去2年間
$target = "OU=OU-Root,DC=xx,DC=xxx,DC=co,DC=jp"

Search-ADAccount -AccountInactive -TimeSpan $span -UsersOnly `
-SearchBase $target | Get-ADUser -Properties mail | select name,mail

◆ActiveDirectory過去2年間ログオンしていないユーザーを検索

001
002
003
004
005

[string]$span = (365 * 2)  #過去2年間
$target = "OU=OU-Root,DC=xx,DC=xxx,DC=co,DC=jp"

Search-ADAccount -AccountInactive -TimeSpan $span -UsersOnly `
-SearchBase $target | select name,enabled,DistinguishedName,LastLogonDate

◆ActiveDirectoryグループごとのメンバー一覧を表示する2

前回、信頼関係を結んだ先のユーザーが上手く表示できなかったのでこれを対策すべく調べてみた。

さしあたって、PowerGUIをだしているQUESTがActiveDirectoryモジュールの拡張版みたいなやつをだしていて、それを使うと解決できそうだ。

普通であればサードパーティモジュールは使いたくない所だが、今回は所詮限られたサーバーに対して限られたクライアントから使うスクリプトなので良しとした。
(どのみちサーバーに追加サービスを入れているし、クライアントにもAD用の管理モジュールを追加しているし。)

モジュールは以下からダウンロード出来る。

気付きづらいが、真ん中辺りにあるチェックボックスをクリックするとダウンロードの一覧が表示される。

インストールしたら、以下のスナップインを追加してあげると、XXX-QADXXXXコマンドレットが使えるようになる。
Add-PSSnapin quest.activeroles.admanagement

後は単純に対応するコマンドレットに置き換えれば良いのかと思ったが、若干パラメータの指定も違うようだ。
詳しくは調べていないのだがとりあえず以下の様にして目的は達成できた。

001
002
003
004
005
006
007
008

#Add-PSSnapin quest.activeroles.admanagement
$target = "OU=OU-Root,DC=xx,DC=xxx,DC=co,DC=jp"
Get-QADGroup -SearchRoot $target -IncludedProperties description | sort name | 
%{
Write-Host ("■■ {0}({1}) ■■" -f $_.name,$_.
description)
    
Get-QADGroupMember -Identity $_ | %{$_.name}
Write-Host
}

◆ActiveDirectoryグループごとのメンバー一覧を表示する

グループの一覧を取得して、そのそれぞれに所属するユーザーを表示してみる。

001
002
003
004
005
006
007

$target = "OU=OU-Root,DC=XX,DC=XXX,DC=co,DC=jp"
Get-ADGroup -SearchBase $target -Properties description | sort name |
 
   
%
{
       
Write-Host ("■■ {0}({1}) ■■" -f $_.name,$_.
description)
       
Get-ADGroupMember -Identity $_ | %{$_.
name}
       
Write-Host
    }

対象のユーザーグループをフィルターしたいときは、
Get-ADGroup –Filter {name -like "A*"}
の様にFilterパラメータを追加してあげれば良い。

基本的にはこれでOKなのだが、ユーザーの中に信頼関係を結んだ先のユーザーが含まれていると上手く表示できないようだ。
「ActiveDirectory管理センター」でも表示できていないのでPowershellのActiveDirectoryモジュールでは対応していない気がする。

2011年7月21日木曜日

◆ActiveDirectoryグループを表示する(Get-ADGroup)

ビルトインユーザーグループを表示した例。

Get-ADGroup -Filter * -SearchBase "CN=Builtin,DC=hoge,DC=hoge,DC=co,DC=jp" -Properties description |
    select name,groupscope,description,DistinguishedName | sort name | ogv

結果はこんな感じになる。
image

 

OUを指定して配下のグループ一覧を表示してみる。
以下はOU-Rootという名前のOU配下のグループを表示した例。

Get-ADGroup -Filter * -SearchBase "OU=OU-Root,DC=hoge,DC=hoge,DC=co,DC=jp" -Properties description |
    select name,groupscope,description,DistinguishedName | sort name | ogv

◆Windows2008ServerR2より前のサーバーをPowershellで管理する

ActiveDirectoryモジュールを使ってR2より前のサーバーを管理するためには「ActiveDirectory管理ゲートウエイサービス」をサーバーにインストールする必要がある。

今回は2008Serverのドメインコントローラにインストールしてみた。
前提条件として、

  1. .NET Framework 3.5 Service Pack 1 (SP1)
  2. マイクロソフト サポート技術情報 969166 のパッチ
  3. マイクロソフト サポート技術情報 967574 (SP1の場合)のパッチ
    (SP2の場合は不要)

969166 のパッチを読み落として半日ほどハマってしまった。

管理する側はWindows7かR2Serverになるようだ。
Windows7から管理する場合は管理用のモジュールを入れておく必要がある。
MTG Blog: ◆ActiveDirectoryをWindows7から管理する(ユーザ管理)

ちなみに、この環境を作るとR2から追加された機能である「ActiveDirectory管理センター」も使えるようになる。

image

ドメインコントローラが複数台あるときも、どれか1台で管理ゲートウエイサービスが動いていれば使えるようだ。

2011年7月19日火曜日

◆XMLファイルを扱う3(Select-Xml)

PowerShell: ◆XMLファイルを扱うではXML型にキャストしたが、Select-Xmlコマンドレットを使っても良さそうだ。

Types.ps1xml

<Types>
    <Type>
        <Name>System.Array</Name>
        <Members>
            <AliasProperty>
                <Name>Count</Name>
                <ReferencedMemberName>Length</ReferencedMemberName>
            </AliasProperty>
        </Members>
    </Type>
    <Type>
        <Name>System.Xml.XmlNode</Name>
        <Members>
            <CodeMethod>
                <Name>ToString</Name>
                <CodeReference>
                    <TypeName>Microsoft.PowerShell.ToStringCodeMethods</TypeName>
                    <MethodName>XmlNode</MethodName>
                </CodeReference>
            </CodeMethod>
        </Members>
    </Type>
         .
         .
         .


001
002

select-xml -path $path -xpath "/Types/Type/Members/AliasProperty" | 
 
select {$_.node.Name} , {$_.node.ReferencedMemberName}

image

 

001
002

select-xml -path $path -xpath "/Types/Type/Members/AliasProperty/Name" | 
   
select {$_.node."#text"}

image

ノードのそれぞれのプロパティを参照すると以上の様な感じになると思うのだが、実際にはExpandPropertyを使って以下のように書くと簡単そうである。

001
002

select-xml -path $path -xpath "/Types/Type/Members/AliasProperty" | 
 
select -ExpandProperty node

2011年7月7日木曜日

◆変数とパイプラインの両方にオブジェクトを送る(Tee-Object)

変数やファイルに出力しつつ画面にも表示させたいなんて時にはTee-Objectコマンドレットを使う。

PS>ps | tee p

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
     95       9     5836      13664    90     2.29   4884 conhost
     34       5     1308       3472    43     0.00   4916 conhost
    522      12     2048       5380    64     0.36    492 csrss
    698      23    15100      29272   204     2.07    580 csrss

ここで、Tee-Objectは変数pにプロセスオブジェクトを突っ込みつつパイプラインにそのままおくっている。ただし、後続のしょりが無いので画面に表示されているといった感じだ。

なので以下の様にするとプロセスオブジェクトは画面に表示されなくなる。

PS>ps | tee p | measure


Count    : 67
Average  :
Sum      :
Maximum  :
Minimum  :
Property :

2011年7月1日金曜日

◆サービスのログオンアカウントを取得、抽出

Get-Serviceコマンドレットではログオンアカウントが拾えないっぽい。
そこで、WMIオブジェクト(Win32_Service)を使って取得する。

PS>gwmi win32_service | select name,startname | group startname

Count Name                      Group
----- ----                      -----
   94 localSystem               {@{name=AeLookupSvc; startname=
   52 NT AUTHORITY\LocalService {@{name=ALG; startname=NT AUTHO
   28 NT AUTHORITY\NetworkSe... {@{name=aspnet_state; startname


PS>

 

抽出するにはFilterを掛けてあげれば良い。

PS>gwmi Win32_Service -Filter "startname='LocalSystem'" | select -First 3


ExitCode  : 0
Name      : AeLookupSvc
ProcessId : 364
StartMode : Manual
State     : Running
Status    : OK

ExitCode  : 0
Name      : AppHostSvc
ProcessId : 1364
StartMode : Auto
State     : Running
Status    : OK

ExitCode  : 1077
Name      : Appinfo
ProcessId : 0
StartMode : Manual
State     : Stopped
Status    : OK

抽出文字列に\がある場合はエスケープが必要なようなので注意が必要だ。

PS>gwmi Win32_Service -Filter "startname='NT AUTHORITY\\LocalService'"


ExitCode  : 1077
Name      : ALG
ProcessId : 0
StartMode : Manual
State     : Stopped
Status    : OK

ExitCode  : 1077
Name      : AppIDSvc
ProcessId : 0
StartMode : Manual
State     : Stopped
Status    : OK