2010/12/20

PowerShellでTwitter


ということでPowerShellを使って Twitterチェックスクリプトを作っているのだけど
自分のやりたい挙動の八割はできたー。
こうやってTwitterを眺めているとなかなか面白い。
少しずつ作成した箇所を紹介できればいいなぁと思います。

とりあえず、こちら。
Twitter API の仕様書 日本語訳
http://watcher.moe-nifty.com/memo/docs/twitterAPI.txt

あと、TwitterAPI searchについてはこちらも参考になりました。

Twitter Search API の使い方
http://www.ibm.com/developerworks/jp/xml/library/x-twitsrchapi/

なにはともあれ、Twitter Search APIを使って情報をとってみる。
Function Get-TwitterSearch {

 Param($searchTerm)

 if ($WebClient -eq $null) {
  $Global:WebClient=new-object System.Net.WebClient
 }

 $results=[xml]($webClient.DownloadString("http://search.twitter.com/search.atom?lang=ja&q=$SearchTerm"))
 $Searchitems=$results.feed.entry

 $SearchItems
}

Get-TwitterSearch関数をつくって、引数に検索する文字を入れることで、
Twitter情報をxml形式でひっぱって返してくれます。

検索の仕様だとかは上記の参考リンクを参照してもらうとして・・。
データをとれればしめたもの。あとはいくらでもPowerShellで編集できちゃいます。
とりあえず、名前と時間、つぶやきを取得したいのであればこんな感じ。
PowerShellをつぶやいた人をとってみました。

$tdata= Get-TwitterSearch PowerShell
$tdata | %{ write-host $_.author.name "--" $([datetime]$_.published); write-host $_.title; write-host }


あとはこれを応用すれば 
好きなキーワードをストリーミングでずっと流し続けることができると。
任意のユーザーに対しても検索できるので、その紹介はまた機会あらば。

2010/11/15

ログの書き込みがあったら知らせるスクリプト

前回の続き。
http://win-enikki.blogspot.com/2010/11/usbpowershell.html

前回はUSBメモリ使用者にログオフ時にメッセージ出力するスクリプトを紹介しました。
今回は、出力ログを監視することで監視者に知らせるスクリプトを紹介します。
とりあえず、スクリプト例を以下に表示します。
$writeDir="\\buso-pcv\test"
$writeTxt="usblog.txt"
$tmpColor= @("Red", "Blue", "Green", "Magenta", "DarkCyan")

[Void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

$i = 0 #終了フラグ
$cl = 0 #カラーバリエーション
$watcher = New-Object System.IO.FileSystemWatcher              # FileSystemWatcherの作成
$watcher.Path = $writeDir                                      # 監視対象のフォルダ指定
$watcher.Filter = $writeTxt                                        # フィルター
$watcher.NotifyFilter = [System.IO.NotifyFilters]::LastWrite 

$NotifyIcon = New-Object System.Windows.Forms.NotifyIcon
$powerShellExe = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
$icon = [System.Drawing.Icon]::ExtractAssociatedIcon($powerShellExe)
$notifyIcon.Icon = $icon
$notifyIcon.Visible = $true

Write-Host "チェック開始します。"

while ($i -ge 0)
{
    $result = $watcher.WaitForChanged([System.IO.WatcherChangeTypes]::ALL)
    $tmpVar = $(Get-Content "$writeDir\$writeTxt")[-1] -split ","
    
    Write-Host ""
    Write-Host "#########################################"
    Write-host "【コンピュータ】"  $tmpVar[0] -ForegroundColor $tmpColor[$cl]
    Write-host "【ユーザー】"  $tmpVar[1] -ForegroundColor $tmpColor[$cl]
    Write-host "【ログオフ時刻】"  $tmpVar[2] -ForegroundColor $tmpColor[$cl]
    Write-Host "#########################################"
    
    $notifyIcon.ShowBalloonTip("1", "USBチェック", "USBメモリがささっているユーザーがいます", "Info")

    $cl+=1
    if ($cl -eq $tmpColor.length) {
        $cl=0
    }
}

ここでのポイントはFileSystemWatcher クラスです。
FileSystemWatcher クラス
http://msdn.microsoft.com/ja-jp/library/system.io.filesystemwatcher%28VS.80%29.aspx

監視ログを対象に、書き込みが発生したらログの最終行を出力させる。
また、ログは変更した場合分かりやすいようtmpColorにある配列順に文字色を代えるようにしています。
ついでに、NotifyIconクラスを使用してバルーン表示もさせています。
NotifyIconクラス
http://msdn.microsoft.com/ja-jp/library/system.windows.forms.notifyicon%28VS.80%29.aspx

以上の結果でこのように表示されます。
出力ごとに色が変わり、バルーンも出力



















このスクリプトは、今回だけでなく他でもログに書き込みがあった場合の監視ができるので、
色々汎用性が高いかなーとおもってます。
いかがでしょうかー。

2010/11/10

USBメモリ抜き忘れ防止スクリプトをPowerShellでやってみる

久々にPowerShellを使う機会にめぐまれたので、投稿します。

USBメモリ、今では安価となりかなり利用率は増えましたが
それと同時にメモリの抜き忘れも増えているみたいです。
なんとかならんのかー、という要望があったので
折角なのでPowerShellでログオフ時にUSBメモリがささっているとダイアログを出すスクリプトを作ってみました。
ちなみに、色々ネット上にある参考スクリプトをツギハギしたりしています。
使用時は自己責任でお願いします ><


とりあえず、1つ目のポイントとして、USBメモリの有無確認ですが、
win32_usbhub クラスを利用することでみつけることができます。

Win32_USBHub クラス - WMI Fun !!
http://www.wmifun.net/library/win32_usbhub.html

USBメモリの場合、Nameが "USB 大容量記憶装置"であり、
Statusが"OK"であれば、ほぼちゃんと認識された状態のUSBメモリがささっているといえます。
Get-WmiObject -Class win32_usbhub | ? { $_.name -eq "USB 大容量記憶装置" } | ? { $_.status -eq  "OK" }
USBメモリをさしていた場合

あとは、ダイアログとして出すようにスクリプトを組めば完成です。
詳細は以下。
#USBログオフ時メッセージプロンプト処理
#メッセージ文
$messagePath="C:\temp\usbmessage.txt"
#ログ出力パス
$usbLOG="\\buso-pcv\test\usblog.txt"

#--------------------------------------
#メッセージボックス
#--------------------------------------
function MessageBox([string]$p_value = "")
{
    [Void][Windows.Forms.MessageBox]::Show($p_value,"お知らせ","OK", "Warning")
}


$crUSB = Get-WmiObject -Class win32_usbhub | ? { $_.name -eq "USB 大容量記憶装置" } | ? { $_.status -eq  "OK" }


if ($crUSB) {
    write-output "$env:computername,$env:username,$(get-date)" >> $usbLOG

    #Windowsフォームのロード
    [Void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms");

    MessageBox $([String]::Join("`r`n", (Get-Content $messagePath)))
   
}
 メッセージ文は、いろんな人が編集する場所でもあることから、
別テキストからの呼び出しに 。(ここでは "C:\temp\usbmessage.txt")
以下のようにusbmessage.txtに書いてみました。
USBがさしっぱなしだぞー( ゚Д゚)
誰かに盗まれても知らないぞ( ´∀`)
って、席にもういないッッΣΣ(゚Д゚;)
また、ダイヤログが出たときに、使用者のホスト名、ユーザー名、時刻を吐き出すようにしてみました。
このスクリプトをログオフスクリプトとして設置しておけば完了です。
実際に使用するとこんな感じ。
USB差しっぱなしでログオフした場合

usblogに記録されたログ

ちなみにGPOでPowershellのログオフスクリプトを管理する場合には、
スクリプト実行ポリシーを有効にすることと、PowerShell用のタブが別途あるので注意しましょう。
(あと、もちろん適用環境ではPowerShellがインストールされていることが前提です(笑))


GPOによるスクリプト実行ポリシーの許可

ログオフスクリプトのPowerShellタブ

また、「ハードウェアの安全な取り外し」を行わなくても大丈夫か?という点については
書き込み中でなければ、ほぼ問題ないとのこと。
ログオフ後なら なおのこと その後ぬいても問題ないでしょう。
どうしても怖いというのであれば、もう一度ログインして手順を踏んで抜いてもらうということで。

USBメモリやUSB HDDを安心して取り外す - ITmedia
http://bizmakoto.jp/bizid/articles/0710/03/news062.html


さて、これで使用者には注意を促しましたが、上記のメッセージにある通り
そもそも、使用者はログオフボタンを押した時点で皆 律儀に席に座っているとはかぎりません。

なので、USBメモリをさしてログオフした人を管理者へ知らせるスクリプトも作ってみました。

今回は長くなったので、スクリプトについてはまた次回。
ちなみに動作としてはこんな感じに出力させました。
USBメモリさし忘れ監視
ログを監視し続けて、書き込みがあったら出力、ついでにポップアップ表示もさせています。
では、また次回。(といって、またえらく時間あいたら嫌だな・・)

2010/08/18

ActiveDirectoryでの監査ポリシーを考えてみる

ADを運用していると、
オブジェクトの変更をしたりログイン・ログオフしたときの様々なログを取得したいーという要望があります。
そんな時は、ADによる 監査ポリシーを使用するという手段がありました。
しかし、監査ポリシーの使用は精度があまり高くない、使いにくいという話もちらほら聞こえたりしていて
結局積極的に使用を控えていました。
しかし、2008R2Serverも浸透している現在、少し立ち戻って本当に使えないのか少し検証してみたいと思います。

・監査ポリシーとは
Technet 監査ポリシー
http://technet.microsoft.com/ja-jp/library/cc730601%28WS.10%29.aspx
上記にあるように、GPOによる設定で様々な「監査」を実施することで、セキュリティログへ情報を書き出します。
設定できる監査項目は以下のとおり。
http://technet.microsoft.com/ja-jp/library/cc787176%28WS.10%29.aspx
---
http://technet.microsoft.com/ja-jp/library/cc787567%28WS.10%29.aspx

---
http://technet.microsoft.com/ja-jp/library/cc737542%28WS.10%29.aspx

---
http://technet.microsoft.com/ja-jp/library/cc776774%28WS.10%29.aspx
---
http://technet.microsoft.com/ja-jp/library/cc728087%28WS.10%29.aspx
---

残り4つの監査項目はまた次回。
監査ポリシーの問題点や、チューニングについてもおいおい調べていきたいと思ってます。

2010/08/09

DISMコマンド

DISMコマンドは7には標準搭載されているコマンドですが、色々できるようです。


WindowsTips
新しい DISM ツールを使用して Windows イメージを準備およびサービスする
http://technet.microsoft.com/ja-jp/windows/ee183884.aspx



COMPUTERWORLD BLOG
VHD のオフラインパッチ by DISM
http://blog.computerworld.jp/2010/08/09/offlinepatch-by-dism/

@IT
Windows 7/Windows Server 2008 R2のコンポーネントをdismコマンドで管理する
http://www.atmarkit.co.jp/fwin2k/win2ktips/1296dism/dism.html

な○の 屋
WinPE 3.0 ( Windows AIK for Windows 7 )
http://yuichi.tea-nifty.com/blog/2009/08/winpe-30-window.html

Windows 7 エンタープライズ ショート ビデオ
How Do I: Deployment Image Servicing and Management (DISM)?
http://technet.microsoft.com/ja-jp/windows/dd320284.aspx

---
Dism /? でヘルプが出ます。
上記記事にあるように、適用したパッチをオフラインからアンインストールしたり、
イメージを展開することなく、更新プログラムの確認などができるようです。

まだ、イメージ展開サービスやVHDファイルを運用レベルで使ってはいないのですが、
今後使用する機会もあるかもしれないですねー

2010/06/04

PowerShellにしゃべらせる

Windowsでしゃべらせるには色々な方法があるみたいですが、
.NET Framework 3.0 を入れているのであれば、Speech.Synthesis.SpeechSynthesizerクラスを使うのが楽っぽいです。
$null = [Reflection.Assembly]::LoadWithPartialName("System.Speech")
$SMSpeaker = new-object System.Speech.Synthesis.SpeechSynthesizer

あとは Speakメソッドでしゃべらせるだけ。
 $SMSpeaker.Speak("hello buso")
日本語はデフォでは対応していないらしく、Office2003についてくるLH Kenj なんかの音声合成エンジンを使わなければならないっぽい。
2010も出る今となってOffice2003といわれてもなぁ。
ちなみに、ツイッターと連動させて読み上げさせるスクリプトを作っている人もいました。
うーん、僕も日本語でも読み上げさせたいぞ。


まぁ、監視として、何かあったら読み上げるというのもこれで簡単にできそうですね。

2010/06/01

サーバのグループポリシーのリンク監視の方法を模索してみる その3

さらにグループポリシーリンク監視の模索の続き。
サーバのグループポリシーのリンク監視の方法を模索してみる その1
サーバのグループポリシーのリンク監視の方法を模索してみる その2

前回、前々回とポリシー編集とリンクの付与の比較を出力する方法を模索し、
スクリプトを作ってみました。処理内容はこんな感じ。


エラー時の動作などはまったく組み込んでないので参考程度でどぞ。
#CheckGPO

Import-Module activedirectory
Import-Module grouppolicy

#origpoファイルの場所
$workpath="C:\hogehoge\"

#メール配信先設定
$smtpHost = "SMTPサーバアドレス"
$mailfrom = "FROMのアドレス"
$mailto = "メール配信先"
$mailsubject = "GPOCheckログ"
$mailer = New-Object System.net.mail.smtpclient($smtpHost)

function comparegpo ($crlink, $orilink, $crgpo, $origpo) {
    
#gpo設定 変更された場合は新しいGPOのバックアップを行い oriファイルを更新
    compare-object $crgpo $origpo -property modificationtime,gpostatus,displayname | Set-Variable diffgpo
    if ($diffgpo) { 
        "$(get-date) :--GPO変更が発生しました"
        $diffgpo | sort displayname | ft -AutoSize
    $timename=$(Get-ItemProperty $workpath\origpo.xml).LastWriteTime -replace "[/,:, ]",""

    $diffgpo | ? { $_.sideindicator -eq "<=" } | % { "backup実施"; backup-gpo $_.displayname -path $workpath\gpbackup | fl }
    move-item $workpath\origpo.xml $workpath\log\$timename"gpo.xml" | Out-null
        $crgpo | Export-Clixml $workpath\origpo.xml
     }

#link設定  変更された場合は oriファイルを更新
    compare-object $crlink $orilink -Property target,displayname,enabled | Set-Variable diffgpl
    if ($diffgpl) { 
        "$(get-date) :--GPO Linkに増減が発生しました"
        $diffgpl | sort displayname | ft -AutoSize
    $timename=$(Get-ItemProperty $workpath\orilink.xml).LastWriteTime -replace "[/,:, ]",""
    move-item $workpath\orilink.xml $workpath\log\$timename"orilink.xml"
        $crlink | Export-Clixml $workpath\orilink.xml 
    }

}

#origpo存在チェック
if (test-path "$workpath\origpo.xml"){
    $origpo=Import-Clixml "$workpath\origpo.xml"
} else {
    "origpo.xml NotFound"
    get-gpo -all | Export-Clixml $workpath\origpo.xml
    return
}

if (test-path "$workpath\orilink.xml"){
    $orilink=Import-Clixml "$workpath\orilink.xml"
} else {
    "orilink.xml NotFound"
    Get-ADOrganizationalUnit -Filter 'Name -like "*"' | % { Get-GPInheritance -Target $_ } | ? { $_.gpolinks -ne "" } | % { $_.path; $_.gpolinks } | Export-Clixml $workpath\orilink.xml
    return
}


#現在のOU状態の取得
$crlink = Get-ADOrganizationalUnit -Filter 'Name -like "*"' | % { Get-GPInheritance -Target $_ } | ? { $_.gpolinks -ne "" } | % { $_.path; $_.gpolinks }
$crgpo = get-gpo -all


#比較対象を関数で渡し、戻り値が存在した場合にはメールを出す
$result=comparegpo $crlink $orilink $crgpo $origpo

if ($result) { 
    $mailbody=[string]::join("`r`n", ($result | out-string -width 200 ))
    $mailer.send($mailfrom, $mailto, $mailsubject, $mailbody )
    $result | out-string -width 200 > $workpath\recent.log
    $result
    "変更が発生し、メールを出しました"
}
$work フォルダの配下にlog フォルダと、 gpbackupフォルダを用意してください。
適当にGPOを変更かけて、リンクをつけたあとにスクリプトを実行してみました。


あとはこのスクリプトを一定時間のタスクで回しておけば、
多少の監視にはなるかなぁと。

結局、サイトのGPOは対応できなかったけどなッッ

2010/05/25

IPv6を勉強する

IPv6アドレス。
Vistaのころも多少は浸透していましたが、
7になってからもはや標準となりつつあり、v4の頃と勝手が違ってきているので少し勉強してみたいと思います。
(Windowsの電卓で 表示を「プログラマ」にすると値の計算なり色々やりやすいです)

IPv4と比較しつつ、違いをみてみる。

・アドレス表記
16進表記のほうが、10進より確かに把握しやすいやも。
とりあえず、16ビットずつ:で区切られ、1桁は4ビット分として16進表記で表されているというのを
覚えておこぉ

その他にもv4でいうところのプライベートアドレスやら、
v4との互換性も見ていかないといけないですね。 それはまた次回以降ということで。

2010/05/24

サーバのグループポリシーのリンク監視の方法を模索してみる その2

前回の続き
前回は、OUのリストを取得し、そこに貼られているGPOを出力するということをやりました。
で、OUに貼られているGPOはとれてもサイトに貼られたGPOはとれないね、というところまでやりました。

・・・まぁ、サイトに関するGPOはとりあえずおいとく(笑)
できるところを固め、そこから順次付け足すというのが 僕の今ままでの手法なので
とりあえずできそうなところからやってみます。
ということで、オリジナルGPOと変更したGPOを比較する手法を今回はやってみます。


前回はリンクに関することしか触れませんでしたが、
PowerShell v2 のgrouppolicy モジュールにはGet-GPO というGPO情報を取得できるコマンドがあります。

PS > Import-Module grouppolicy
PS > get-gpo -all

 -All オプションをつけることで、すべてのGPOの情報を取得できます。
情報としては、Statusや、変更時刻などが記されているので、この情報を保存します。
PowerShellだとオブジェクトはXMLファイルとして保存できるので、それを利用してみます。
PS > Get-GPO -All | Export-Clixml -Path .\origpo.xml
では、試しにGPOを変更して、比較してみましょう。
↓が現在のGPO

GPOtest1を内容変更、GPOtest2を「すべての状態を無効」 GPOtest4を削除してみます。

では、さっき保存したorigpo.xml と現在のGPOを比較してみます。
PS > $origpo=Import-Clixml .\origpo.xml
PS > $crgpo=Get-GPO -All

PS > Compare-Object $crgpo $origpo -Property displayname,modificationtime,GpoStatus | sort displayname


表示名、変更時刻、ステータスを比較対象として出力してみました。
ちゃんと、変更された、削除されたGPOが出力されていますねー。
これを定期的に実行、タスクに組み込むことで変更に対する監視ができるのではないでしょうか。
前回のOUリンクも同じ方法でオブジェクトを保存し、リンクの比較をしてみるとよいかもですね。

・・でも、サイトのやりかたはやっぱりわからんw

2010/05/19

サーバのグループポリシーのリンク監視の方法を模索してみる


さて、久々の更新です。
独りよがりで描かず、今後は定義を再確認しつつ
わかりやすく絵で表現していこうかなーと思っていたのですが、
少し作ってみたいPowerShellのスクリプトができたので、
やっぱり今回もPowerShellのメモ描きですw

その作ってみたいスクリプトとは・・


他に良い案があればみなさんに教えてもらうとして・・(笑)
とりあえず、泥臭い手段でPowerShellを使って模索してみます。

PowerShell v2 になってからADに関するモジュールが追加されたので、それを利用してみましょう。
とりあえず、ActiveDirectory と、GroupPolicy のモジュールを追加してみる。
PS > Import-Module activedirectory
PS > Import-Module grouppolicy
これにより、ADやグループポリシーに関するコマンドを使用することができます。
PS> Get-Command -module activedirectory


CommandType     Name                            Definition
-----------     ----                            ----------
Cmdlet          Add-ADComputerServiceAccount    Add-ADComputerServiceAccount...
Cmdlet          Add-ADDomainControllerPasswo... Add-ADDomainControllerPasswo...
Cmdlet          Add-ADFineGrainedPasswordPol... Add-ADFineGrainedPasswordPol...
Cmdlet          Add-ADGroupMember               Add-ADGroupMember [-Identity...
Cmdlet          Add-ADPrincipalGroupMembership  Add-ADPrincipalGroupMembersh...
PS > Get-Command -module grouppolicy


CommandType     Name                            Definition
-----------     ----                            ----------
Cmdlet          Backup-GPO                      Backup-GPO -Guid -Pat...
Cmdlet          Copy-GPO                        Copy-GPO -SourceGuid ...
Cmdlet          Get-GPInheritance               Get-GPInheritance [-Target] ...
Cmdlet          Get-GPO                         Get-GPO [-Guid] [[-Do...
Cmdlet          Get-GPOReport                   Get-GPOReport [-Guid] ...
 さて、では例として下記のようにGPOがリンクされていた場合。

GPOのリンクが何がついているかを見るには、 Get-GPInheritance コマンドレットを使います。
PS> Get-GPInheritance -target "OU=GroupA,OU=UserList,DC=furyu,DC=local"




Name                  : groupa
ContainerType         : OU
Path                  : ou=groupa,ou=userlist,dc=furyu,dc=local
GpoInheritanceBlocked : No
GpoLinks              : {GPOtest1, GPOtest2}
InheritedGpoLinks     : {GPOtest1, GPOtest2, Default Domain Policy}
 ちょっとこれだけだとわかりづらいから、 GpoLinks だけを取り出してみる。
PS > Get-GPInheritance -target "OU=GroupA,OU=UserList,DC=furyu,DC=local" | % { $_.gpolinks }


GpoId       : 09ecc96a-2d91-4594-8474-4404e82241d2
DisplayName : GPOtest1
Enabled     : True
Enforced    : False
Target      : ou=groupa,ou=userlist,dc=furyu,dc=local
Order       : 1


GpoId       : 72e4f0a0-7b01-4944-9fba-6ad14faefb49
DisplayName : GPOtest2
Enabled     : True
Enforced    : False
Target      : ou=groupa,ou=userlist,dc=furyu,dc=local
Order       : 2
これで、 OUが "OU=GroupA,OU=UserList,DC=furyu,DC=local" のかかっているリンクのGPOをとりだすことができました。
しかし、監視するとなると全OUのリンク状況を知らないといけないですよね。
というわけで、全OUを列挙してみましょう。
OUを出すには、ActiveDirectoryモジュールを追加してできた、Get-ADOrganizationalUnit コマンドレットを使います。
PS > Get-ADOrganizationalUnit -Filter 'Name -like "*"'


City                     :
Country                  :
DistinguishedName        : OU=Domain Controllers,DC=furyu,DC=local
LinkedGroupPolicyObjects : {CN={6AC1786C-016F-11D2-945F-00C04fB984F9},CN=Polici
                           es,CN=System,DC=furyu,DC=local}
ManagedBy                :
Name                     : Domain Controllers
ObjectClass              : organizationalUnit
ObjectGUID               : ee6dfe99-a1f5-4579-b810-d12d22fcdfff
PostalCode               :
State                    :
StreetAddress            :
 これで全OUを取り出せるので、このオブジェクト群を変数にいれてしまいます。
PS > $oulist=Get-ADOrganizationalUnit -Filter 'Name -like "*"'
 では、この変数を利用してリンクが貼られているOUとそのGPOを出してみましょう。
PS > $oulist | % { Get-GPInheritance -target $_ } | ? { $_.gpolinks -ne "" } | fl -Property path,gpolinks


Path     : ou=domain controllers,dc=furyu,dc=local
GpoLinks : {Default Domain Controllers Policy}


Path     : ou=groupa,ou=userlist,dc=furyu,dc=local
GpoLinks : {GPOtest1, GPOtest2}


Path     : ou=groupb,ou=userlist,dc=furyu,dc=local
GpoLinks : {GPOtest2, GPOtest3, GPOtest1, GPOtest4}

あとは、このオリジナルのリストと、取得したリストを比較するスクリプトを定期的にタスクで流して差異がでたら報告、みたいな作りをさせればなぁと思ったのですが。


そんなわけで、もう少しやり方考えなきゃなぁと思ってます。

2010/04/16

クラシック表示のシェルをオンにする


この時期はリプレースがあったりして、当然7も新たにドメインに参加することになったりしてます。
で、今回発覚したのがGPOの「クラッシック表示のシェルをオンにする」の機能変更。

このポリシー自体は、エクスプローラをクラッシック表示に切り替え、
エクスプローラーの処理の負担や消費メモリ量の軽減させ軽快な動作をはかることができるのですが。。

しかし、今までは「有効」にすることで強制的にダブルクリックになっていたのに
7からは「有効」にするとシングルクリックが適用されるという・・。ひどいッッ
混在している環境だったらどうやって統一させろというんだろう・・。

ちなみに、フォルダオプションを見ても見た目上は「ダブルクリックで開く」になってます。
とりあえず、現状適用されているかどうかを見る場合は、レジストリを見るとてっとり早いです。
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer
ClassicShell  DWORD値


クラッシック表示のシェルに関してはこちらのブログで詳しく紹介されていますので、どうぞ。
attosoft.info Blog
http://attosoft.info/blog/win-accel/item-useclassicshell/

2010/04/04

タスクスケジューラ設定

4月1日、エイプリルフール。
円谷プロでは毎年手のこんだサイトを作りあげるが、
今年はTwitterの模倣、円谷ッターをやっていた。
円谷ッター(跡地)
http://tsubutter.m-78.jp/



ウルトラ兄弟と怪獣達が円谷ッターを使って、
4月1日終日ずーっとつぶやいていた。
0時から23時までほぼずっと誰かがつぶやいていたけれど、
流石に社員がずっと張り付いていたわけではあるまい。
(ゴモたんは別だろうけれどもw)

先週ツギハギで作ったTwitterスクリプトを利用しつつ、
Twitterのタスクスケジュールつぶやきができないかなぁと考えたが・・

簡単にできると思ったが、思った以上に苦労

まず、Windowsのタスク処理を見なければなるまい。
Vista,2008Serverからタスクスケジューラの機能が大きく変わった。
IT Prp: 大幅に強化されたWindows Server 2008のタスク・スケジューラ
フォルダを作成し、タスクを管理するライブラリ機能もつき管理しやすくなったようだ。


それを踏まえた上で、この記事を参照してみよう。
Hey, Scripting Guy!: タスク スケジューラを使って効率的に作業する方法はありますか
PowerShellを利用したタスク管理のスクリプトである。
上記のスクリプトを使って、「Twitter」ライブラリを作ってみる。




デフォルトのタスクスケジューラ
 . .\taskps.ps1
New-TaskFolder -folder (New-TaskObject) -path "\twitter"

Name                                                             Path
----                                                             ----
twitter                                                          \twitter

Twitterフォルダが作成された。

続いて、タスクの登録に関しては以下の記事。
Hey, Scripting Guy!: スケジュールされたタスクを複数のコンピューター上に作成する方法はありますか

と、上記を参考にしながら昨日ガシガシ作ったのだけど、
特殊なことをせず、素直にATコマンドを使えば良かったような気がする・・。
あらかじめ未来のつぶやきを設定して「おえかき うぃる」とつぶやきたかったのです。。
完成したにはしたけれど、ちょっと微妙な感じなので今回はコード公開は見送り。

2010/03/28

PowerShellでTwitter投稿

こんな記事を見た。

twitter で大学のネットワークを監視 [これでも大学職員のブログ -情報センター勤務中-]
http://d.hatena.ne.jp/daigaku-syokuin/20100326/p1

と、いうわけで探してみました。
やはりPowerShell経由でTwitter投稿するスクリプトを作っている方がいました。

SAPIEN Technologies
http://blog.sapien.com/index.php/2008/06/23/out-twitter/

Mike Ormond's Blog
http://blogs.msdn.com/mikeormond/archive/2009/01/30/updated-twitter-powershell-script.aspx

素晴らしい。で、二つのスクリプトの良いとこ取りをしてくっつけてみた。
以下をFixtwit.ps1 として保存してください。
Function Out-Twitter {

    BEGIN {
            #check for global Twitter credential
            if (!$global:Twitter_Credential) {
                $global:Twitter_Credential=Get-Credential
            }
    }

    PROCESS {
  
        #turn off error pipeline
        $erroractionpreference="SilentlyContinue"
  
        [string]$tweet=$_
  
        ##Twitter投稿関数
        function SubmitWebRequest(  
            [string] $RequestUrl,
            [string] $RequestMethod,
            [string] $RequestContentType,
            [string] $PostString,
            [string] $Username,
            [string] $Password
            )
        {
          [System.Net.ServicePointManager]::Expect100Continue = $false

          $request = [System.Net.WebRequest]::Create($RequestUrl)
          
          if ($Username) {
            $request.Credentials = new-object System.Net.NetworkCredential($Username, $Password)
          }
          
          $request.Method = $RequestMethod
        
          if ($RequestMethod -ieq "POST") {
            $request.ContentType = $RequestContentType      

            $formdata = [System.Text.Encoding]::UTF8.GetBytes($PostString)
            $request.ContentLength = $formdata.Length
            $requestStream = $request.GetRequestStream()
            $requestStream.Write($formdata, 0, $formdata.Length)
            $requestStream.Close()
          }
        
          $response = $request.GetResponse()

          $reader = new-object System.IO.StreamReader($response.GetResponseStream())
          $returnvalue = $reader.ReadToEnd()
          $reader.Close()
        
          return $returnvalue
        } #end function
      
        #Short Url
        Function Get-Snurl {
            Param([string]$link="http://www.google.com")
      
            $tinyurlrequest = "http://tinyurl.com/api-create.php?url=$link"
                       

            write-progress "Tweeting" "Getting tiny URL" -cu $tinyurlrequest
            $tinyurl = SubmitWebRequest $tinyurlrequest "GET"
            write-debug "Tweeting - Received tiny URL Response: $($tinyurl)"
            write $tinyurl
  
        }
        #search for web links using Regex
        [regex]$regex="(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?"
  
         If ($tweet -match $regex) {
                  $link=$matches[0]
          }
       
         #if an embedded url was found, convert it to a snurl link
         if ($link) {
            $snurl=Get-Snurl $link
            $tweet=$tweet.Replace($link,$snurl)
         }


        if ($tweet.Length -gt 140) {
            Write-Warning ("Your message is " + (($tweet.length)-140)  + " characters too long.")
            $clear=$True
            return
        }
      
      
        $tweetstring = [String]::Format("status={0}", $tweet)
        $request = [Net.WebRequest]::Create($url)
        $twitusername=$global:Twitter_Credential.GetNetworkCredential().Username
        $twitpassword=$global:Twitter_Credential.GetNetworkCredential().Password
      
        $twitResponseText = SubmitWebRequest `
                                    "http://twitter.com/statuses/update.xml" `
                                    "POST" `
                                    "application/x-www-form-urlencoded" `
                                    $tweetstring `
                                    $twitusername `
                                    $twitpassword
        write-debug "Tweeting - Posted status update. Response: $($twitResponseText)"

   }
    
    END {
        #if there was an error, then don't keep the global Twitter
        #credential
        if ($clear) {
            Remove-Variable Twitter_Credential -scope Global
            }
        }
      
} #end Function
 じゃば、使ってみる。
PS 2010/03/28 12:23> . .\fixtwit.ps1
PS 2010/03/28 12:24> "もう昼・・お腹すいた・・" | Out-Twitter
fixtwit.ps1 をドット化して実行。
つぶやきたい言葉をはいて、パイプを通し Out-Twitter を実行。

実行すると資格情報を聞かれるので、
Twitterのアカウントとパスワードを入力する。


入力すると処理が走り、投稿完了。

投稿されていることが確認できた。
URL短縮もされるはずなんだけど、うまく行く時と行かないときがあるような。。
なんでだろう。
↑修正しました。

あくまでツギハギなので本家のスクリプトを見に行ってください。
これをPowerShellのバックグラウンド処理を使えば監視っぽいことはできるかもですね。

2010/03/25

チェックブログふえてきました。

ブログチェックにはRSSがとても便利。
MS社員の方も多くのブログを運営していて、とても参考になります。
技術共有が簡単にでき、いろんな可能性を秘めているこの業界がやっぱり好きです。

Windows Maniax の野良さんによってマイクロソフト株式会社の社員ブログ一覧が
まとめられています。

開発系のブログも紹介されているのでチェックしてはいかがでしょうかー。

2010/03/24

PowerShellの使い方


PowerShellがいくら普及してきた、といってもいきなり
1から10までPowerShellでやるには荷が重いし、
運用管理レベルでは、仰々しく作り込みをするではなく
はじめの内はバッチの中でちょこちょことコマンドレッドを使うというレベルでいいかと思う。
慣れてきたら色々趣向をこらしてやってみるってことで。
(いまだ.NETFrameWork よくわからないし。)

例えば、ここ最近のHotFix適用状況を調べるバッチだとこんな感じで。
 @echo off
:1
echo HotFixチェック
set /p kbmonth=何ヶ月分のFotFixを出力しますか?:

powershell -command "& { Get-HotFix | ? { $_.InstalledOn -ge $(get-date).addmonths(-%kbmonth%) } }"

pause
goto 1
 これをバッチとして用意して実行すれば、
コマンドプロンプトの中でPowerShellを呼び出し、Get-HotFixコマンドレッドを使って
HotFixの適用状況を得ることができます。
HotFixチェック
何ヶ月分のFotFixを出力しますか?:1


Source        Description      HotFixID      InstalledBy          InstalledOn
------        -----------      --------      -----------          -----------
BUSO-PC       Update           KB976264      NT AUTHORITY\SYSTEM  2010/03/10...
BUSO-PC       Update           KB980302      NT AUTHORITY\SYSTEM  2010/03/23...



続行するには何かキーを押してください . . .
HotFixチェック
何ヶ月分のFotFixを出力しますか?:2

Source        Description      HotFixID      InstalledBy          InstalledOn
------        -----------      --------      -----------          -----------
BUSO-PC       Security Update  KB971468      NT AUTHORITY\SYSTEM  2010/02/10...
BUSO-PC       Security Update  KB975560      NT AUTHORITY\SYSTEM  2010/02/10...
BUSO-PC       Update           KB976264      NT AUTHORITY\SYSTEM  2010/03/10...
BUSO-PC       Update           KB976662      NT AUTHORITY\SYSTEM  2010/02/24...
BUSO-PC       Update           KB976972      NT AUTHORITY\SYSTEM  2010/01/27...

:(略

まぁはじめはこんな感じで徐々にコマンドレッドを使っていく、という形で。
しかし、この使い方でもPowerShellのリモート機能を組み合わせると結構面白いことができます。
それはまぁ、機会あればまたいずれ。

2010/03/22

Select-String その他。

Select-Stringコマンドレッドは、
-Pattern にそって文字列やファイルからテキストを抜き出すことができる。
正規表現も利用できるので、今回は "=[02468]"
つまり、イコールのあとに偶数・奇数がくるものをパターンとしてオブジェクトを作り出した。
とりあえず、小難しいことは置いといて、Select-Stringはgrepやfindstrの代わりになり、
正規表現も使用可能だということを覚えとく。

PowerShellを扱う場合、その出力されたオブジェクトはなにかを把握しておくことも重要。
オブジェクトがなんなのかを調べるには、Get-Member(エイリアスはgm)を使うといい。

PS .\sample> Select-String -Pattern "=[02468]" .\userlist.txt | gm


   TypeName: Microsoft.PowerShell.Commands.MatchInfo

Name         MemberType Definition
----         ---------- ----------
Equals       Method     bool Equals(System.Object obj)
GetHashCode  Method     int GetHashCode()
GetType      Method     type GetType()
RelativePath Method     string RelativePath(string directory)
ToString     Method     string ToString(), string ToString(string directory)
Context      Property   Microsoft.PowerShell.Commands.MatchInfoContext Conte...
Filename     Property   System.String Filename {get;}
IgnoreCase   Property   System.Boolean IgnoreCase {get;set;}
Line         Property   System.String Line {get;set;}
LineNumber   Property   System.Int32 LineNumber {get;set;}
Matches      Property   System.Text.RegularExpressions.Match[] Matches {get;...
Path         Property   System.String Path {get;set;}
Pattern      Property   System.String Pattern {get;set;}
今回はSelect-Stringコマンドレッドを使ったことで
Microsoft.PowerShell.Commands.MatchInfo オブジェクトができたわけだ。
要素を指定してオブジェクトプロパティを見てみよう。

PS .\sample> $(Select-String -Pattern "=[02468]" .\userlist.txt)[0].line
CN=2,ou=Tokyo,dc=ad-domain,dc=company,dc=local

PS .\sample> $(Select-String -Pattern "=[02468]" .\userlist.txt)[0].linenumber
2
Foreach-Object コマンドはエイリアスで Foreach または % として割り当てられている。
ちなみに、パイプで渡された各オブジェクトは $_  としてわたされる。
同じくプロパティを見てみる。
PS .\sample> Select-String -Pattern "=[02468]" .\userlist.txt | % { $_.line }
CN=2,ou=Tokyo,dc=ad-domain,dc=company,dc=local
CN=4,ou=Tokyo,dc=ad-domain,dc=company,dc=local
CN=6,ou=Tokyo,dc=ad-domain,dc=company,dc=local
CN=8,ou=Tokyo,dc=ad-domain,dc=company,dc=local

PS .\sample> Select-String -Pattern "=[02468]" .\userlist.txt | % { $_.linenumber }
2
4
6
8
 2行目の整形前を出力する。
PS .\sample> Select-String -Pattern "=[02468]" .\userlist.txt | % { $_ }

userlist.txt:2:CN=2,ou=Tokyo,dc=ad-domain,dc=company,dc=local
userlist.txt:4:CN=4,ou=Tokyo,dc=ad-domain,dc=company,dc=local
userlist.txt:6:CN=6,ou=Tokyo,dc=ad-domain,dc=company,dc=local
userlist.txt:8:CN=8,ou=Tokyo,dc=ad-domain,dc=company,dc=local
 文字列オブジェクトには -split で区切ることができるので分解。
PS .\sample> Select-String -Pattern "=[02468]" .\userlist.txt | % { $_ -split "," }
E:\sample\userlist.txt:2:CN=2
ou=Tokyo
dc=ad-domain
: (略
 分解した文字列は配列に格納されているため、1番目のものだけ取り出す。
PS .\sample> Select-String -Pattern "=[02468]" .\userlist.txt | % { $($_ -split",")[0] }
E:\sample\userlist.txt:2:CN=2
E:\sample\userlist.txt:4:CN=4
E:\sample\userlist.txt:6:CN=6
E:\sample\userlist.txt:8:CN=8
 同様の手順で"="で区切り、2番目の要素を取り出し、目的のアカウントの部分を取得する・・と。
PS .\sample> Select-String -Pattern "=[02468]" .\userlist.txt | % { $($_ -split",")[0] } | % { $($_ -split "=")[1] }
2
4
6
8
 ----------------------------------------------------------
・・・すいません、詳しく説明しようとしたら、逆にわかりにくくなったですね
ここらへんに絵での説明に限界を感じる(笑)
とりあえずForeach-Objectの使い方とGet-Memberを覚えておこうってことで。

2010/03/21

データ整形


この時期は、新年度を控えていてデータ整理だとかをしなきゃいけなかったりする。
Dsquery user コマンドを使うことで、ADのユーザーオブジェクトを取得することができる。
サンプルとして下記ユーザーデータ userlist.txtを取得できたとする。

CN=1,ou=Tokyo,dc=ad-domain,dc=company,dc=local
CN=2,ou=Tokyo,dc=ad-domain,dc=company,dc=local
CN=3,ou=Tokyo,dc=ad-domain,dc=company,dc=local
CN=4,ou=Tokyo,dc=ad-domain,dc=company,dc=local
CN=5,ou=Tokyo,dc=ad-domain,dc=company,dc=local
CN=6,ou=Tokyo,dc=ad-domain,dc=company,dc=local
CN=7,ou=Tokyo,dc=ad-domain,dc=company,dc=local
CN=8,ou=Tokyo,dc=ad-domain,dc=company,dc=local
CN=9,ou=Tokyo,dc=ad-domain,dc=company,dc=local
CN=10,ou=Tokyo,dc=ad-domain,dc=company,dc=local

このアカウント(CN)の1文字目の数字から偶数・奇数 へと分ける。
さらにアカウント以外の余分なパスを削って、という指示。
PowerShellが出たことで、
Windows管理者といえどスクリプトをある程度は使いこなさないといけない時代がきてますよね。
僕はスクリプト書くのは好きなほうなんですが
いかんせん普段から使っているわけでないので発想に乏しいというかなんというか・・。

ちなみに、新人の子がとった手法はこちら。

grep =0 userlist.txt | cut -d , -f 1 | cut -d = -f 2 | cat >> Even
grep =1 userlist.txt | cut -d , -f 1 | cut -d = -f 2 | cat >> Odd
grep =2 userlist.txt | cut -d , -f 1 | cut -d = -f 2 | cat >> Even
grep =3 userlist.txt | cut -d , -f 1 | cut -d = -f 2 | cat >> Odd
 grepの検索を10回分 手動でかえてあげる必要はあるものの、あとはうまく切り取ってる。
早く結果を出力するのがなんぼなので力技でやったにせよ、よく考えたなぁと。
そして僕はというと・・。
PS .\sample> $regex1 = "^.*=([13579].*)(,OU=Tokyo)"
PS .\sample> gc .\userlist.txt | Select-String -Pattern $regex1 -AllMatches `
>> | foreach { $_.matches[0].groups[1].value }
>>
1
3
5
7
9
10
正規表現での抽出にばかり目が行って、出力されるはされたけれどわかりづらい・・。
新人の子と僕のを組み合わせた方式がてっとりばやくてわかりよいか。
PS .\sample> Select-String -Pattern "=[02468]" .\userlist.txt | `
>> foreach { $($_ -split ",")[0] } | foreach { $($_ -split "=")[1] } | sort
>>
2
4
6
8
積極的に実務にPowerShell使っていきたいー。

2010/03/15

ループバック処理


最後は、駆け足ですが。
動作としては、マシン起動したあとにコンピュータにつけられたコンピュター構成のGPOが適用され
その後、ユーザーログインした時に、ユーザーにかけられたGPOが適用、
最後にループバック処理を実施している場合はコンピュータにかけられたユーザー構成GPOが適用されます。

設定手順は下記の通り。
ユーザー構成をコンピュータごとに設定するには、次の手順を実行します。
  1. グループ ポリシー Microsoft 管理コンソール (MMC) で [コンピュータの構成] を展開します。
  2. [管理用テンプレート]、[システム] を順に展開し、[グループ ポリシー] をクリックし、[ユーザー グループ ポリシー ループバックの処理モード] を有効にします。
 3回に分けて描きましたが、いずれにせよ、どうGPOを管理するかがポイントだと思います。
グループポリシーオブジェクトの置き場所はツリー構造じゃないので、
数が増えていくにつれて管理が困難になっていくので困る。
他にも何かGPOの管理手順で良い方法とかあれば教えて頂ければ嬉しいです。