こんな方法でもできそう。
001 002 | $script:n = 0 ps | sort id | ft @{n="number";e={($script:n++)}},id,name -auto |
スクリプト変数を使うとSelectやFormat出力の時に直接カウントアップできる。
また、カウントアップだけだと出力されないので括弧で囲むと良いようだ。
($script:n++)
これは
$script:n++;$script:nと同じ結果になる。
こんな方法でもできそう。
001 002 | $script:n = 0 ps | sort id | ft @{n="number";e={($script:n++)}},id,name -auto |
スクリプト変数を使うとSelectやFormat出力の時に直接カウントアップできる。
また、カウントアップだけだと出力されないので括弧で囲むと良いようだ。
($script:n++)
これは
$script:n++;$script:nと同じ結果になる。
サーバーにしかけてあるジョブが増えてきたのでバックアップしておこうかと思ったのだが、GUIでは1つずつしかエクスポートできなさそう。
3.0が使えればコマンドレットが用意されているようだが、3.0を追加できないサーバーなので他の方法を探してみた。
「schtasks」か「Win32_ScheduledJob」あたりを使うのかなっと思って探しているとCOMを使ったそのものずはりのサンプルがあったので基本的にそのまま使わせていただいた。
Powershell, and exporting Windows Scheduled Tasks – TheGeekery
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 | $outPath = "f:\desktop\wk" $outFileName = "{0}.xml" $sch = New-Object -ComObject("Schedule.Service") $sch.Connect("localhost") $tasks = $sch.GetFolder("\").GetTasks(0) $outfile_temp = Join-Path $outPath $outFileName $tasks | %{ $xml = $_.Xml $task_name = $_.Name $outfile = $outfile_temp -f $task_name $xml | Out-File $outfile } |
昔どこかで見かけたことはあるが、あまり使い道は無いのかと思っていた。
ふと思い立って、一応使い方を確認しておくことにした。
まずは、DLL(System.Management.Automation.dll)が必要なようなので参照を追加する。私のWindows8環境では以下の場所にあった。
"C:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShell\3.0\System.Management.Automation.dll"
Get-Processを使うにはこんな感じでOKだった。
namespace PowerShellTest { class Program { static void Main(string[] args) { PowerShell ps = PowerShell.Create(); ps.AddCommand("Get-Process"); var results = ps.Invoke(); results.ToList().ForEach( p => Console.WriteLine(p.Properties["ProcessName"].Value));
} } } |
Get-ProcessからPSObjectが返ってきてしまうので、プロパティが文字列参照になってしまうあたりが今1つな感じ・・・。
いままで全く気付いていなかったのだが、ISEでは複数の「タブ」を扱える。
ここで、「タブ」というのは以下
をクリックして追加される以下では無い。
以下のように追加される。
今まで「タブ」だと思っていたのは「ページ」とでも呼ぶのだろうか・・・。
どうやらこの「タブ」が1つのセッションとして扱われているらしい。
なので、「タブ」間では変数等が共有されない。
これまで、最終確認とかでISE自体を開きなおしていたのだが、実は新しいタブを追加すればよいだけだったのね・・・。(お恥ずかしい)
「Ctrl + N」 新しいページを開く
「Ctrl + T」 新しいタブを開く
最近ちょっとPowerShellから離れていたので良く判らないが、about系のヘルプはまだ日本語化されていないのだろうか。
Update-Helpでも入ってこないっポイ?
Onlineでも参照できない?
自分的には英語でもそんなに苦ではないのだが、人に教えるときに「ほら、こうやってヘルプを見ると簡単でしょ?」と言えないのがちょっと・・・。
特にコマンドレットのヘルプなら英語でも良いけど、about系は説明がメインだから余計厳しい。
クライアントではそれほど3.0のメリットも感じないので、7で2.0を使うのが幸せなのだろうか。
8はちょっと失敗感ただよっているしなぁ・・・。
スクリプトが「昇格した管理者権限」を要求するような場合、最初にチェックしたほうが親切かもしれない。
以下にそのサンプルがあったのでメモしておく。
Testing Administrator Privileges - Power Tips - PowerShell.com – PowerShell Scripts, Tips, Forums, and Resources
非常に短いコーディングでチェックできるので便利そう。
若干トリッキーなので仕掛けを解析しておくと、
まずネイティブなコマンドの「whoami /groups」を使って現在のユーザーが所属するグループを表示すると以下のような感じで返ってくる。
ここで、「昇格した管理者権限」に属する場合は以下のグループが存在するようだ。
これは、対話ログオンすると「INTERACTIVE」グループに動的に所属するのと同じパターンかな。
あとは「match」演算子を使って「昇格した管理者権限」の「SID」が含まれるか判定している。
配列に「match」演算子を使うとマッチした要素だけが抽出される。
PS>"ma","mb","mc" -match "b" |
あとはマッチしなければ何も返ってこない(null)しマッチすればマッチした文字列が返ってくるのを、「bool」にキャストしている。
PowerShell: ◆Invoke-WebRequestサンプル
Invoke-WebRequestで取ってきた後、ParsedHtmlプロパティを使うと自分でHTML解析せずに色々と使えそう。
私自身Web系のプログラミングはやらないので詳しくは判らないが、さしあたってタグとその順番を指定して切り出すには以下のような感じ。
001 002 003 004 005 006 007 008 009 | $URL = "http://weather.yahoo.co.jp/weather/jp/3/3310.html" $OutputFile = "$env:temp\weather.html" $data = Invoke-WebRequest -Uri $URL @($data.ParsedHtml.getElementsByTagName("h2"))[0].OuterHTML , @($data.ParsedHtml.getElementsByTagName("table"))[0].OuterHTML | Set-Content -Path $OutputFile & $OutputFile |
<切り出し前>
<切り出し後>
昔からあるし使い方も難しくない。
相対パスを絶対パスにしてくれたり、ワイルドカードを展開してくれたりする。
Officeのインストールパスを取得するサンプルが載っていたのでメモしておく。
バージョンが違ったり、64ビットだったりしても問題なく取得できる。
(あくまでもデフォルトパスにインストールした場合だと思うが)
001 002 003 004 005 006 007 | gwmi win32_desktop | ?{$_.name -eq "NT AUTHORITY\SYSTEM"} gwmi win32_desktop -filter "name='NT AUTHORITY\\SYSTEM'" gwmi win32_desktop -Filter "name='$env:userdomain\\$env:username'" [wmi]"win32_desktop='NT AUTHORITY\SYSTEM'" |
「¥」の扱いにちょっと注意が必要。
WMIの世界ではエスケープが必要で、PowerShellの世界ではエスケープが不要って事かな。
別セッションに変数を渡すサンプル。(V3からの機能だそうです)
001 002 003 004 005 | $class = 'Win32_LogicalDisk' $ComputerName = 'hogePC.sample.co.jp' Invoke-Command -ScriptBlock { Get-WmiObject -Class $using:class } -ComputerName $ComputerName |
バックグラウンドジョブを使うときなんかに重宝するかも。
参考までにV2でやるにはこんな感じでパラメータ渡ししてあげるらしいです。
001 002 003 004 005 006 | $class = 'Win32_LogicalDisk' $ComputerName = 'vista3.ad.ics.co.jp' Invoke-Command -ScriptBlock { param($class) Get-WmiObject -Class $class } -ComputerName $ComputerName -ArgumentList $class |
以前もちょっと取り上げたV3で追加になったコマンド。
実際に使う機会があったのでサンプルとして記載しておく。
かつてノーツで作られていた議事録をSharePointに移行したリストがあったのだが、移行ツールに不具合があるのか稀に添付文書のリンク切れが発生している。
そこで、リンク切れをチェックしてリストアップするスクリプトを書いた。
リスト形式(一覧)では添付の有無しか判らず、そのパスは明細を読む必要がある。
そこで、リストを一旦CSVに落として添付があるものについて「Invoke-WebRequest」で読み込んでみる。
そこから「href」に「Attachment」(すなわち添付)の文字があるものを抽出して存在チェックする。
とりあえず存在チェック自体も「Invoke-WebRequest」で読んでみてエラーになるかどうかで判断している。(これについては他にもっと良い方法が有るのかも・・・)
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 | $url = "http://server/sites/hoge/MEETING/Lists/List/DispForm.aspx?ID={0}" $csv = Import-Csv "F:\Desktop\打ち合わせ報告書.csv" -Encoding default $csv | %{ if($_.添付 -eq 1){ $_.整理番号 | Tee-Object -Variable number $urlString = $url -f $_.ID $web = Invoke-WebRequest -uri $urlString -UseDefaultCredentials $web.links | ?{$_.href -like "*attachment*"} | %{ $_.href | %{ Invoke-WebRequest -uri $_ -UseDefaultCredentials | Out-Null if($? -eq $false){$number >> "F:\Desktop\整理番号.txt"} } } } } |
昔、ほぼ同じことを以下でやっているが忘れていたのでメモ。
PowerShell: ◆カスタマイズした条件を使ってグルーピングする(Group-Object)
以下のようなCSVファイルを読み込んで、ハッシュテーブル化すると各項目をダイレクトに参照出来て便利だよってお話。
001 002 003 004 005 | $content = Import-Csv "F:\Desktop\Servers.csv" $hash = $content | Group-Object -AsHashTable -AsString -Property Name $hash["sv4"].OS $hash.sv3.SP |
タスクスケジューラに登録されたタスクの一覧を表示するスクリプトがあったので試してみた。
それ自体は特に問題はない。
複数サーバーのタスクをクライアントから覗けるとベターかと思うのだが、昇格した管理者権限が要求される。
以前PowerShell: ◆別の資格情報で管理者として実行するでちょっとやったのだが、もう一度ちゃんと調べてみたところPowerShellをネストして呼び出すというのが主流のようだ。(別の資格情報でPowerShellを起動し、その中でまたPowerShellを起動し昇格してコマンド実行)
コマンドを単独で実行するサンプルはあったのだが、スクリプトブロックを実行するサンプルが見当たらなかったため試行錯誤で作ってみた。
文字列の扱いが面倒で、都度エラーに対処しながら書いたのでスマートな書き方では無いかもしれない。(前回同様パスワードは予め保存しているものを使っている)
$password = ConvertTo-SecureString (gc f:\myPass) $cred = New-Object System.Management.Automation.PsCredential "ad\adm",$password
$cmd = { $computers = 'hoge-sv','v064' #★対象サーバー $service = New-Object -ComObject Schedule.Service $computers | %{ $service.Connect($_) $folder = $service.GetFolder('\') $tasks = $folder.GetTasks(1) Write-Host 'ComputerName = ' $_ -ForegroundColor Yellow $tasks | ft Name, Enabled, LastRunTime, LastTaskResult, NextRunTime -auto } }
$sc = "-command &{Start-Process PowerShell -ArgumentList {-noexit -command $cmd} -Verb runas }" Start-Process -Credential $cred -FilePath PowerShell.exe -ArgumentList $sc |
>([wmi]"Win32_userAccount.Domain='ad',Name='hogeUser'").GetRelated('Win32_Group') |
ローカルマシン上のグループにも属している場合は、ローカルグループも表示される。
何のはずみか、PowerGUIのメニューとツールバーが消えてしまった。
普通ならばどこかのコンテキストメニュで回復できそうなものだが、何も見当たらない・・・。
なんともはや・・・。
原因はさておき、以下にあるファイルにレイアウトが設定されるようなので、これを削除すると良さそうだ。
C:\Users\ユーザー名\AppData\Roaming\Quest Software\PowerGUI\BarManagerLayoutFile.xml
ふぅ~。
SharePoint2010の入ったサーバーにPowerShell3.0を入れた。
するとこれまで動いていたスクリプトが動かなくなってしまった。
「SharePoint は、バージョン 4.0.30319.296 の Microsoft .Net Runtime ではサポートされません」
まさか下位互換が無いなんてことは無いよねっと思い調べていると、そのまさかである。
Windows Server 2012 では SharePoint Server 2010 がサポートされない
つくづくSharePointという製品はいけてない。
3つも4つも前のバージョンならいざしらず、一つ前のバージョンが入らないって。
しかも、今回はWindowsServer2012に入れたわけでは無く、2008R2にSharePoint3.0を入れただけ。
ダメならダメでSharePointのインストーラでチェックしなきゃ。
SharePoint、信じがたい程使いづらいGUI、超低品質、バージョン間の互換性は皆無。
何十年もの間、いろんな製品を見たが、これは酷すぎ。(SharePontとコラボしているProjectServerも酷いが)
SharePoint2013などは互換性が無いわけだから名前を変えるべきでは無いのかなぁ・・・。
ここのところSharePoint2013をセットアップしていたのだが、結局その使用を断念することになった。
SharePoint2013ではデフォルトの認証方式が「クレームベース」に変更されている。(クレームベース自体はこれまでもあったのだが、デフォルトでは無かったのであまり使われていなかったのではなかろうか)
で、「クレームベース」とやら、具体的に何が違うのかは良く判らないのだが、とにかく色々と非互換がありそう。
さしあたって「InfoPath」がさっぱり動かない。
軒並みコーディング変更まで必要になりそうな気配。
ならばと、「クレームベース」を止めてこれまでのデフォルト(Classicだったかな)に戻すと、「WebApps」が動かなくなると脅される。
ん~、相変わらずSharePointはカオスだ。
結局ざっと眺めた感じでは2013に魅力的な機能は見当たらないので(イントラネット向けではないのかも)、苦労して2013にするメリットは無いと判断した。
そもそも「InfoPath」自体、印刷がさっぱりであまり使い物にならないので、いずれ撤退して、SharePoint2020あたりでの移行を目指すか(笑)
愚痴はさておき、SharePointサイトのテーマを設定する。
GUIでは「サイトの操作」「サイトの設定」「外観」「サイトのテーマ」から設定することができる。
これを見ると、親サイトのテーマを変えるとサブサイトのテーマも一気に変更してくれる。
っと思うのが普通だが、サブサイトのテーマは一向に変わってくれない。
サブサイト側の設定は確かに継承設定に変更されるのだが、
テーマ自体が反映されない。
なんともはや・・・。
仕方がないので、スクリプトで一律変更することにした。
あまり自信はないがこんな感じだろうか。
001 002 003 004 005 006 007 008 009 010 011 012 013 | Add-PSSnapin Microsoft.SharePoint.PowerShell $root = "http://svname/sites/root1" $themeFile = "_catalogs/theme/Vantage.thmx" #テーマ更新 $rootSite = Get-SPSite $root $web = Get-SPWeb "$root/sub1" $theme = [Microsoft.SharePoint.Utilities.ThmxTheme]::Open($rootSite,$themeFile) $theme.ApplyTo($web,$false) $web.Update() $web.Dispose() $rootSite.Dispose() |
対応する名前は以下のスクリプトで取得可能。
>[Microsoft.SharePoint.Utilities.ThmxTheme]::GetManagedThemes($rootsite) | select name |
これを設定するタイミングでテーマも変更してあげないといけないようだ。
なので今のテーマを一律子供に反映したいときは、一旦別のテーマにしてから戻してあげると良さそう。
SharePoint恐るべし。