2014年12月25日木曜日

◆サイズの大きなファイルを作る

テストとかで使う局面はありそうなのでパスをメモしておく。 
Creating Huge Dummy Files - Power Tips - PowerShell.com – PowerShell Scripts, Tips, Forums, and Resources
$Path = "$env:temp\hugefile.txt"
$Size = 200MB
$stream = New-Object System.IO.FileStream($Path, [System.IO.FileMode]::CreateNew)
$stream.Seek($Size, [System.IO.SeekOrigin]::Begin)
$stream.WriteByte(0)
$Stream.Close()
explorer.exe "/select,$Path"

2014年12月17日水曜日

◆プロンプトの色を変える(Change the color of the prompt)

連続してコマンド入力と結果表示を繰り返すと、前回の結果がどこからか判りづらくなる。

そこで、プロンプトの色を変えてみることにした。

プロンプト自体はPrompt関数の戻り値なので直接的に色は指定できそうにない。
そこで、Write-Hostで俺々プロンプトを表示させつつ、本物のプロンプトを消してやるって感じにすると、それっぽくなった。

本物のプロンプトはもう少しスマートに消せるのかもしれないが、とりあえずスペースとバックスペースを合わせてリターンすることによって結果的に何も表示させず場所も取らない形にしている。

>function Prompt{Write-Host "PS>" -fore Yellow -nonewline;return " `b"}

結果はこんな感じに。

image

◆WindowsキーをSendする

以前以下の様なIEを表示するスクリプトを作った。
PowerShell: ◆IE画面をアクティブにして最大化

色々と事情があって最近はChromeを半分以上の割合で使っている。

そこで、Chromeも最大化したくなった。
幸い、ChromeはIEと違って、単純に「Win + 1」とかで前回表示していたタブのまま復帰してくれるので、これをSendできれば簡単だ。

WindowsキーのSendは前回調べて挫折したのだが、もう一度探してみてや~っと見つけました。
PowerShell/WinKeys.ps1 at master · stefanstranger/PowerShell · GitHub

結局のところは、PowerShellでは難しいのでC#で作っているのね。
しかも.NETFrameworkでもないのね。

Windows8ではそのまま動いたが、Widnows7ではLinqとTasksのusingを消したほうがよさそうだ。

WindowsキーがSendできるのは、結構嬉しい。

2014年12月16日火曜日

◆HotFix(Windows Update)の適用確認

この間のWindowsUpadateは規模も大きかったせいか幾つか不具合が出ているようだ。

自分のPCに適用されているか確認するにはコントロールパネルの「プログラムと機能」から目視で確認できるが、探すのがちょっと大変。

PowerShellでは「Get-HotFix」というそのものずばりのコマンドが用意されているので簡単に確認できる。

PS>Get-HotFix "KB3004394","KB3002339","KB3011970","KB2553154"

権限があってFireWallが通れば一括での確認もできそう。

PS>"sv1","sv2" | %{Get-HotFix "kb982018","KB976932" -comp $_}

特に意味は無いが、WMIクエリーでもやってみたので一応メモしておく。

PS>gwmi -Query "select * from win32_quickfixengineering where hotfixid='KB982018'or hotfix id='KB976932'"

2014年11月28日金曜日

◆検索文字列の前後の行を表示する2

以下で表示したサンプルを最近見直したところ非常に見づらい。
PowerShell: ◆検索文字列の前後の行を表示する(Select-String)

マッチした塊ごとに区切りが欲しいところ。

Select-Stringの機能自体では難しそうなので、区切りを追加するロジックを入れてみた。

001
002
003
004
005
006
007
008
009
010

filter SelStrDlim{
 
$_.context.
precontext
 
">" + $_.
line
 
$_.context.
postcontext
 
"-" * 10
}
Get-Help Get-ChildItem -Full |
 
 
Out-String -Stream  |
  Select-String パイプライン -Context 7,1 |
  SelStrDlim

image

2014年11月11日火曜日

◆more関数のレスポンスタイムを改善する

以下のブログで「more」関数を使うより、「Out-Host  -Paging」を使ったほうが良いよ。
って話が出ている。
Use Out-Host instead of More - Power Tips - PowerShell.com – PowerShell Scripts, Tips, Forums, and Resources

「more」はパイプライン入力の結果が全て出力されてから処理されるので時間が掛かる。

PS> dir c:\windows -Recurse -ErrorAction SilentlyContinue | more

こんなコマンドを打つとフリーズでもしたような感じになってしまう。

「Out-Host  -Paging」に変えて

PS> dir c:\windows -Recurse -ErrorAction SilentlyContinue | Out-Host  -Paging

で、めでたしめでたしなのだが、やはりここは関数にしてみたい。

単純に考えると、こんな感じ?

001
002
003
004
005
006

Function more2
{
  $input | Out-Host -Paging
}

dir c:\windows -Recurse -ea 0 | more2

と思うのだが、これだと通常の「more」と同じ動作に戻ってしまう。

しからば、こんなん?

001
002
003
004
005
006
007
008
009

Function more2
{
 
process
  {
   
$_ | Out-Host -Paging
  }
}


dir c:\windows -Recurse -ea 0 | more2

ん~、これだと1ファイルごとに表示されてしまい、Pigingも1ファイル毎の指定に解釈されて意味を成していない・・・。

あぁー、なんとなくこのパターンは見覚えがある。
すでに詳細は忘れてしまったが(笑)以下の技が使えそうな気がする。

PowerShell: ◆パイプライン入力・パラメータ入力対応のGridView出力関数を作る

自分で書いていおいて良く思い出せないのだが、適当にまねて作ってみた。

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028

function more2
{
  
begin
   {
     
$scriptCmd = {Out-Host  -Paging
 }
     
$steppablePipeline = $scriptCmd.
GetSteppablePipeline()
     
$steppablePipeline.Begin($true
)
   }

  
process
   {
     
try
      {
        
$steppablePipeline.Process($_
)
      }
     
catch
      {
       
break
;
      }
   }

  
end
   {
     
$steppablePipeline.
End()
   }
}


dir c:\windows -Recurse | more2

自信は無いがとりあえずは使い物になりそう。

2014年11月7日金曜日

◆コンピュータの説明を設定する

コンピュータの説明とは以下の部分。

image

 

>$op = gwmi Win32_OperatingSystem
>$op.Description = "仕事用コンピュータ"
>$op.Put()

 

Set-WmiInstanceを使ってもできる。

が、ヘルプを見ると以下のような感じで出来そうなのだが、旨くいかない。

>Set-WmiInstance -Class Win32_OperatingSystem -arguments @{Description="会社のコンピュータ"}

 

Set-WmiInstance : サポートされていないパラメーターです
発生場所 C:\Users\kumagai_mitsugu\AppData\Local\Temp\b67c3bf9-5b3d-4e70-bd99-d0ace79a285f.ps1:1 文字:16
+ Set-WmiInstance <<<<  -Class Win32_OperatingSystem -arguments @{Description="会社のコンピュータ"}
    + CategoryInfo          : InvalidOperation: (:) [Set-WmiInstance]、ManagementException
    + FullyQualifiedErrorId : SetWMIManagementException,Microsoft.PowerShell.Commands.SetWmiInstance

仕方が無いので、とりあえずこんな感じで。

>gwmi Win32_OperatingSystem | Set-WmiInstance -arguments @{Description="会社のコンピュータ"}

2014年10月30日木曜日

◆WPF(XAML)を使う

PowerShellからXAMLで作ったウインドウを扱ってみる。

XAML自体は直接作るのは面倒なのでVisualStudioからコピーする。
image

Windowのx:Classの指定はエラーになるようなので削除する(行削除)

後はXAMLの記述をヒア文字列で定義してWindows.Markup.XamlReaderクラスのParseメソッドで変換してあげるだけのようだ。

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024

$xaml = @"
<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Button Content="Button"
            HorizontalAlignment="Left" VerticalAlignment="Top"
   Width="75" Margin="230,138,0,0" Name="button1"/>
        <Label Content="Label" HorizontalAlignment="Left" Height="34"
   Margin="198,202,0,0" VerticalAlignment="Top"
   Width="171" Name="label1"/>

    </Grid>
</Window>
"@


Add-Type -AssemblyName PresentationFramework, PresentationCore, WindowsBase
$window = [Windows.Markup.XamlReader]::Parse($xaml)
$button = $window.FindName("button1")
$label = $window.FindName("label1")
$button.add_Click({$label.Content = "Hello World"})

$window.ShowDialog() | Out-Null

実行すると以下のウインドウが表示されて、

image

ボタンをクリックすると「Hello World」が表示される。

image

Windowsフォームより使いやすいかも。

2014年10月29日水曜日

◆「Format-List *」をプロパティ順に表示する

以下のプロパティをPS3.0で表示する。

image

image

できればプロパティの名前順に表示したい。

Format-Listは基本的にパイプラインの最後なので簡単にソートすることは出来ない。

とりあえず以下のような感じだろうか。

>(Get-NetAdapter イーサーネット1 | tee -var net) | fl -Prop ($net | gm | sort name).name

2014年10月10日金曜日

◆CRをCRLFに変換する

以下のTipsの内容をメモしておく。

Normalizing Line Endings - Power Tips - PowerShell.com – PowerShell Scripts, Tips, Forums, and Resources

 

たまに、どこかから取ってきたファイルなどで改行コードがCRだけの場合があり、メモ帳で開くと残念な結果になる。

少し高機能なエディターとかであればCRだけでも旨く表示してくれるし、CRLFに変換して保存したりも出来る。

上記Tipsによると、PowerShellでも簡単に変換が可能だ。
特に、Replaceとか使わずとも「Get-Content」で読んでそのまま「Set-Content」で出力するだけで良いのだそうだ。

---

以下の説明が詳しい
http://www.atmarkit.co.jp/ait/articles/1605/16/news023.html

2014年10月8日水曜日

◆パラメータ名の一部省略の不思議

コマンドレットのパラメータは他のパラメータと区別可能ならば途中までの文字で指定が可能だ。

image

dir –p と入力してタブを押すと「Path」しか出てこないので「p」だけでも良さそうだが、なぜか以下のようなエラーとなる。

PS>dir -p c:\
Get-ChildItem : パラメーター名 'p' があいまいなため、パラメーターを処理できません。一致する名前の候補は次のとおりです:
-Path -LiteralPath。
発生場所 行:1 文字:4
+ dir <<<<  -p c:\
    + CategoryInfo          : InvalidArgument: (:) [Get-ChildItem]、ParameterBindingException
    + FullyQualifiedErrorId : AmbiguousParameter,Microsoft.PowerShell.Commands.GetChildItemCommand

なぜ「LiteralPath」も対象になるのだろう。

2014年10月6日月曜日

◆IF文での判定条件の書き方

今更ながら基本の基本を確認しておく。

IF文での判定条件は普通に考えると、

if($a –eq 1){hogehoge}

てな感じに書くのが一般的な気がする。
ただし、これは一般的な他の言語と同様な書き方で一見何の問題も無いように見えるが、PowerShellの場合はちょっと事情が異なる。

例えば以前PowerShell: ◆配列をフィルターするで書いたように、配列などではイコール演算子が感覚とはちょっと違った動作をする。

この間、PowerShell: ◆閾値以下の空き容量のHDドライブがあったら警告するで使った抽出判定も、

if(Get-PSDrive | ?{$_.USED –ne “”}){hogehoge}

ってな感じでは旨くいかない。(余計なものが幾つか残ってしまう)
image

では、どうすればよいのか。
昔からなんとなく使っている以下の書き方が実は正しい書き方なのではと最近思っている。

if($a){hogehoge}

こう書いた場合、どう判定されるかというと(経験的に)、その変数のデータ型の初期値であればFalse、初期値以外がTrueになる。

数値であれば、0がFalse、文字列であれば””がFalse、オブジェクトであればNullがFalseといった具合。
配列がちょっと厄介だが、要素が複数の場合はTrue、ひとつの場合はその変数の属性に応じて上記と同様に判定される。

この機能はおそらく、PowerShellが$aをbool型に自動変換しているのだろう。
即ち、

if([bool]$a){hogehoge}

と書くのと同じではないかと思う。

image

 

先に書いた、

if(Get-PSDrive | ?{$_.USED –ne “”}){hogehoge}

のパターンでは、USEDプロパティがスクリプトプロパティなので、ドライブによってUSEDのデータ型が違ってきている。

なので、演算子を直接使って判定しようとすると

image

てな感じになってしまう。

これはやはり普段から

if($a){hogehoge}

の書き方を使うのが良いのだろうと思う。

ちなみに、「-ne」の場合は「!」を使って(!$a)とする。

 

あくまでも、経験則で考えたものですが・・・・。

2014年10月1日水曜日

◆閾値以下の空き容量のHDドライブがあったら警告する

>if(Get-PSDrive | ?{$_.used} | %{$_.Free / ($_.used + $_.free)} | ?{$_ -lt 0.6}){"HD容量不足発生";Read-Host}

image

ここでは閾値として0.6(60%)を指定している。

後はこれをスタートアップで実行しても良いし、サーバーなどを巡回しても良いしって感じだろうか。

---

質問があったので補足

各ドライブの空き容量を表示するにはとりあえずこんな感じで

>Get-PSDrive | ?{$_.used} | select name , @{name="残容量(%)";expression={[int](($_.Free / ($_.used + $_.free))*100)}}

image

2014年9月26日金曜日

◆Foreach-Objectのパラメータへの疑問

今更の感じはするが、Foreach-Objectの動作。

PS>1..3 | ForEach-Object{"開始"}{"ループ"}{"終了"}
開始
ループ
ループ
ループ
終了

本来、ヘルプを見ると位置オペランドは(-Process)だけなので、なぜこれで動くのだろうとちょっと疑問に思う。

ちなみに、以下は良いが、

PS>1..3 | ForEach-Object{"開始"}{"ループ"}

当然、以下は上と同じ書式なので「ループ」が初期処理とみなされる。

PS>1..3 | ForEach-Object{"ループ"}{"終了"}

なので、

PS>1..3 | ForEach-Object{"ループ"}  -end{"終了"}

とする必要が有りそう。

2014年9月11日木曜日

◆Get-Helpの怪

なぜか以下のようなエラーが発生する。

PS>get-help  演算子
Get-Help : 型 [Microsoft.ActiveDirectory.Management.ADUser] が見つかりません。この型を含むアセンブリが読み
ことを確認してください。
発生場所 行:1 文字:9
+ get-help <<<<  演算子
    + CategoryInfo          : InvalidOperation: (Microsoft.Activ...nagement.ADUser:String) [Get-Help]、Ru
    + FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.GetHelpCommand

普通は「演算子」という文字列が含まれるヘルプが一覧表示される。

image

さ~、なんとしたものか・・・。

自分だけがおかしいということは「Profile」・・・。

案の定、プロファイル無しで起動したらエラーは発生しなかった。

さぁ、ではプロファイルの何が悪いのか・・・。

なんだかんだ使わない物やテスト的に入っているものもありプロファイルは結構な量になっている。

と嘆いても仕方が無いので2分割方?で探していく・・・・・・・・・・・・・・・・・・・。

やっと見つけた、これだ!!

$env:path += ";D:\svndoc\PS\;.\"

ん~、スクリプトの入ったフォルダをPath環境変数に追加しているだけだ。

もしかして、このスクリプトの中もヘルプで探しに行ってしまうのか?

Version3で同じ環境にして試した見たが再現しなかった。

という事は「バグ」か。(><)

2014年8月26日火曜日

◆検索文字列をハイライト表示する

環境変数に目的のパスが含まれているか確認したいことは良くあるが、結構なが~いのが普通なので年寄が目視で確認するのはちと辛い。

メモ帳に貼り付けて検索すれば事足りるのだが、やっぱりここはPowerShellでやってみたい。

幸いファイル群から文字列を検索してハイライト表示するスクリプトが以下で公開されていた。
Wes' Puzzling Blog - Powershell script to find strings and highlight them in the output

(通常はこちらのほうが使いでがあると思われる。)

とりあえずこれをそのまま利用させていただいて単純な文字列からのパターン検索に変更した。
やっつけで変更したので中身はほとんど理解していない・・・。

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034

function Write-HostAndHighlightPattern(
  
[string] $pattern = ""
  , [string] $inputtext = ""
  , [switch] $caseSensitive = $false
)
{

 
if ($pattern -eq $null -or $pattern -eq ""
) { 
   
Write-Error "Please provide a search pattern!" ; return
 }

 
$regexPattern = $pattern
  if($caseSensitive -eq $false) { $regexPattern = "(?i)$regexPattern"
 }
 
$regex = New-Object System.Text.RegularExpressions.Regex $regexPattern

  $index = 0
  while($index -lt $inputText.
Length)
  {
   
$match = $regex.Match($inputText, $index
)
   
if($match.Success -and $match.Length -gt 0
)
    {
     
Write-Host $inputText.
SubString(
       
$index, $match.Index - $index) -nonewline
      Write-Host $match.Value.ToString() -Foreground Red -nonewline
      $index = $match.Index + $match.
Length
    }
   
else
    {
     
Write-Host $inputText.SubString($index) -nonewline
      $index = $inputText.
Length
    }
  }
}


Write-HostAndHighlightPattern "system32" $env:path

結果

image

2014年8月22日金曜日

◆Measure-Objectで日付型のMAXは取得できない

WindowsUpadateの最終更新日を取得する。

Get-HotFix | Measure -Maximum -Property InstalledOn

てな感じで取得できそうな気がする。(実際、Windows8では取得できる)

しかし、Windows7では以下のようなエラーが・・・。

image

えぇー、数値しか駄目なの(><)

仕方がないので力技(一旦数値に変換してから戻す)

PS>[datetime][long]((Get-HotFix | select {($_.installedon).ticks} | measure -Maximum -Property '($_.installedon).ticks').Maximum)

まだ、以下のほうが良いか

PS>(Get-HotFix | sort installedon -Des | select -First 1).InstalledOn

ちゃんとやっている方もいらっしゃる
Measure-Latest: finding latest date/time | Dmitry's Blog: Cloud, PowerShell and beyond

 

Windows8が大コケしたおかげで、PowerShellも2.0がまだまだ幅を利かせてしまうので、ちょっと悩ましい。

2014年8月20日水曜日

◆変数の値解決?

ネットで見かけた質問で以下のようなものがあった。

$drive = ""
$cmd = "dir $drive"
$drives = "c:","d:"

foreach($drive in $drives)
{
    Invoke-Expression $cmd
}

なんとなく眺めるとうまくいくような気もする。

Invoke-Expressionをやめて単純に$cmdを表示させると、

PS>$drive = ""
$cmd = "dir $drive"
$drives = "c:","d:"

foreach($drive in $drives)
{
    $cmd
}

-- 以下、結果--

dir
dir

 

これまた意外と嵌れば嵌るのかもね・・・っと思ったり。

要は2行目の、
$cmd = "dir $drive"

のときに、$driveは値解決されちゃうので$cmdの中身は”dir”になっちゃう。

どうすれば良いんですかね・・・。

こんな感じ?

$drive = ""
$cmd = "dir {0}"
$drives = "c:","d:"

foreach($drive in $drives)
{
    Invoke-Expression ($cmd -f $drive)
}


もしかして、こんなのがスマートか?

$drive = ""
$cmd = {dir $drive}
$drives = "c:","d:"

foreach($drive in $drives)
{
   
   & $cmd
}

2014年8月13日水曜日

◆嵌る

ここ数ヶ月、火を噴いている突発的な仕事のお手伝いで忙しく、PowerShellともご無沙汰。

だいぶ老化が進んでいるのでちょっと使っていないとすぐに忘れる。
なんとか過去の投稿を見たりして思い出していかないと・・・。


以下のような何の変哲もないコマンドを打ったところ、
image

結果がこんな感じに表示された。
image

?、なんで?

これは、
image

ちゃんと表示される。
image

scriptpropertyだから?なんて思って「types.ps1xml」なんかを見てみても特に「CPU」が特別という事は無い。

しば~らく考えたが、全く持って検討も付かない。

ふと、こんな感じに入力してみたら、
image

あれ、表示された。
image

あ~、そう。
いや~、素人丸出し?

こいつの結果って、
image

こうなっちゃってるのね・・・。
image

あ~、もう、ヘッダーが見えない時点で気づこうよ(笑)

全く持って余計なところで時間をくってしまったが、やりたかったのは以下のようなスクリプト。
image

むか~し、以下で書いたことはあるのだが、どうも今まで有効に使ってこなかった気がする。
PowerShell: ◆カスタマイズした条件を使ってグルーピングする(Group-Object)

ハッシュテーブル化する方法は便利そうなので、忘れないようにしたい。
っと言っても忘れるのだが・・・。(笑)

----

ちなみに、そもそも今回の嵌りは画面の表示サイズとバッファサイズをずらしたのがいけないのだと思います。

image

2014年8月7日木曜日

◆Windows Automation Snapin for PowerShell(メモ)

WASPなんてのが有ったのでメモしておく。

以下のようなWindow操作関連のコマンドレットを提供してくれるようです。

Get-WindowPosition
Remove-Window
Select-ChildWindow
Select-Control
Select-Window
Send-Click
Send-Keys
Set-WindowActive
Set-WindowPosition

一応インストーラも付いてくるのですが、Windows7環境ではなぜか旨くいかなかったので(3.0が必要?)、展開された「WASP.dll」をマイドキュメントにある「WindowsPowerShell」フォルダに「Module\WASP」フォルダを作ってあげてその中に入れてあげると良さそう。

使うときは「ipmo WASP」とやってあげればOK。

2014年7月4日金曜日

◆拡張子毎にファイルをフォルダに振り分ける

  PowerShellの紹介とかサンプルでよく出てきそうなやつ。

以下のようなごちゃごちゃのファイルを拡張子毎にフォルダを作って振り分けてコピーする。

image

001
002
003
004
005
006

$outDir = "d:\Desktop\out1"
dir "d:\Desktop\imp1" | group extension | %
{
 
$outDirEx = Join-Path $outDir $_.Name.Substring(1
)
 
if(!(Test-Path $outDirEx)){mkdir $outDirEx
} 
 
$_.Group | %{copy $_.FullName $outDirEx }
}

結果

image

2014年7月1日火曜日

◆演算子を連結して実行する

PowerShellの演算子は連結して実行できたりする。

PS>"a,b,c,d,e" -split ','
a
b
c
d
e
PS>"a,b,c,d,e" -split ',' -notlike 'c'
a
b
d
e
PS>"a,b,c,d,e" -split ',' -notlike 'c'-replace 'b','{0}'
a
{0}
d
e
PS>"a,b,c,d,e" -split ',' -notlike 'c'-replace 'b','{0}'-join '-'
a-{0}-d-e
PS>("a,b,c,d,e" -split ',' -notlike 'c'-replace 'b','{0}'-join '-') -f 'bbb'
a-bbb-d-e

最後のフォーマット演算子(-f)はなぜか括弧が必要だった。
(優先順位が違うのだろうか)

2014年6月30日月曜日

◆Profileのスクリプト実行をバイパスする

Profileに記述したスクリプトを実行したくないときが稀にある。

そんなときは、起動パラメータを指定すると良い。

>PowerShell –NoProfile

頻繁に使う場合は、スクリプトの先頭に以下を追加しておく。

>Add-Type -AssemblyName PresentationFramework
>if([System.Windows.Input.Keyboard]::IsKeyDown('Ctrl')) { return }

Profile以外でも使えそうな機能なので覚えておくと良さそう。

ただし、この機能はSTAを要求するようなのでPowerShell3.0以降で使うのが良いかも。

2014年5月19日月曜日

◆メーラーを使ってメール送信

ウィルス対策ソフトによって「Send-MailMessage」がブロックされる場合、仕方が無いのでメールソフト経由で送信する。

もしかするとOUTLOOKあたりならCOMでも用意されているかも知れないが、今回はSendKeyを使った力技で。

こんなものでも使える局面はあるかもしれない。

001
002
003
004
005
006
007
008
009
010

add-type -AssemblyName System.Windows.Forms
$subject = 'メール送信のテストです'
$body = '本文です'
$to = 'minminnana@hoge.co.jp'
$mail = "mailto:$to&subject=$subject&body=$body"
Start-Process -FilePath $mail 
Start-Sleep -Seconds 2

#outlookの送信キー
[System.Windows.Forms.SendKeys]::SendWait("%S")

2014年5月2日金曜日

◆EFSでファイル暗号化

日々のPC利用において頭の痛いことの一つにパスワードの管理がある。
クラウドの普及に伴って、管理すべきパスワードの数は増加の一途。
大体は共通のパスワードを使いまわしたりするのだが、怪しげなサイトにも使ったりすると非常に危険。

私も以前、GmailのIDをのっとられた事があるので、それからは個別のパスワードを使用している。

ただし、当然いくつものパスワードを記憶できるわけも無く・・・。
結局メモする事になる。

素のまま置いておくのはさすがに気がひけるので暗号化を試してみる。

会社内とかの使用に限定するのであれば、OSの機能で暗号化するのが簡単だ。

暗号化したいファイルのプロパティから指定するだけ。
image

暗号化すると以下のように緑色で表示される。
image

ファイルサーバーに置いたファイルも、ドメイン内ならば暗号化したときと同じユーザーでログインすればどのクライアントからも使用できる。

PowerShellからも以下のように簡単に暗号化できる。

PS>(Get-Item  d:\Desktop\test.txt).Encrypt()

2014年4月30日水曜日

◆UNCパスをTest-Pathで確認する

Testing UNC Paths - Power Tips - PowerShell.com – PowerShell Scripts, Tips, Forums, and Resources

Set-Location HKCU:\

とかやった後に、Test-Path \\Server\myfolder

とかでUNCパスを確認しようとするとうまくいかないってお話。

\\Server というレジストリーを探しに行っちゃうって事でしょうか。

コンテキストの影響を受けずに確認するには、

Test-Path  FileSystem::\\Server\myfolder

とやると良いとの事。

2014年4月22日火曜日

◆レジストリへのアクセス

レジストリへのアクセスは専用のプロバイダーが用意されていて、通常のファイルシステムのようにアクセスできる。
 特に難しいわけではないのでこれまでも適当に使ってきたが、それほど頻繁に使うわけでもないので、結局毎回試行錯誤しながら使うことになる。

そこで、いまさらの感はあるが使い方を自分用にメモしておく。

基本的には「Get-Item」と「Get-ItemProperty」を使ってアクセスする。(と思う)

以下のレジストリにアクセスしてみる。

image

Get-Item」で「TortoiseSVN」キーにアクセスするとこんな感じになる。

PS>Get-Item hkcu:software\TortoiseSVN


    Hive: HKEY_CURRENT_USER\software


SKC  VC Name                           Property
---  -- ----                           --------
  7  12 TortoiseSVN                    {SoundUtils KeyPath, TortoiseSVN,

「SKC」というのは「SubKeyCount」の略で、以下の部分の個数を表す。
image

「VC」は「ValueCount」の略で、以下の部分の個数を表す。
image

「プロパティ」は以下を指すようだ。
image

 

「Get-Item」を「Get-ChildItem」に変えると以下のようにサブキー毎に同様の情報が表示される。

PS>Get-ChildItem hkcu:software\TortoiseSVN


    Hive: HKEY_CURRENT_USER\software\TortoiseSVN


SKC  VC Name                           Property
---  -- ----                           --------
  0  17 DiffTools                      {.dll, .exe, .doc, .docm...}
  1   1 History                        {lastCheckoutPath}
  0   4 LastUsedUUIDsForGrouping       {0, 1, 2, 3}
  0   1 LogCache                       {Version}
  0   6 MergeTools                     {.doc, .docm, .docx, .ods...}
  0   6 StatusColumns                  {CommitDlgVersion, CommitDlg,
  1   0 TortoiseProc                   {}

プロパティの一覧は以下のように取得

PS>(Get-item hkcu:software\TortoiseSVN).property
SoundUtils KeyPath
TortoiseSVN
TortoiseMerge
TortoiseIDiff
DiffProps
CurrentVersion
CheckNewerWeek
RepoBrowserColumnWidth
ErrorOccurred
NewVersionLink
NewVersionText
NewVersion

これでも同じっぽい

PS>(Get-item hkcu:software\TortoiseSVN).getvaluenames()

ただし、どちらも取得できるのは文字列の情報。

以下の一行の情報をオブジェクトで取得できるのかと思ったのだが、どうにも見当たらない。
image

とりあえずダイレクトにバリューを取得するには、

PS>(Get-item hkcu:software\TortoiseSVN).GetValue("CheckNewerWeek")
16

ここで、「Get-ItemProperty」を試してみると、こちらは以下のオブジェクトを返してくる。(1つのオブジェクト)
「Get-Item」と違ってサブキーの情報は取得できない。
名前の通り、自身のプロパティに特化した情報といった感じ。
image

左側の「名前」(プロパティ)をその名の通りプロパティとして持っているオブジェクトなので、ダイレクトにバリューを取得するには、

PS>(Get-ItemProperty hkcu:software\TortoiseSVN).CheckNewerWeek
16

となる。

これを踏まえて「Get-Item」を使って一覧表示するには、プロパティ(ValueName)を纏めて取得し、その一つずつに対して「GetValue()」でバリュー、「GetValueKind()」で種類を取得する。
image

image

種類が不要であれば「Get-ItemProperty」だけで事足りる。(が、こちらは余計なプロパティも含まれる)

PS>Get-ItemProperty hkcu:software\TortoiseSVN


PSPath                 : Microsoft.PowerShell.Core\Reg
PSParentPath           : Microsoft.PowerShell.Core\Reg
PSChildName            : TortoiseSVN
PSDrive                : HKCU
PSProvider             : Microsoft.PowerShell.Core\Reg
SoundUtils KeyPath     : keypath
TortoiseSVN            : TortoiseSVN
TortoiseMerge          : TortoiseMerge
TortoiseIDiff          : TortoiseIDiff
DiffProps              :
CurrentVersion         : 1.8.4.24972
CheckNewerWeek         : 16
RepoBrowserColumnWidth : 00000000000000000000000000000
ErrorOccurred          : 0
NewVersionLink         :
http://tortoisesvn.net
NewVersionText         : A new version of TortoiseSVN
NewVersion             : 1.8.6.25419

2014年3月11日火曜日

◆PowerShellスクリプトをExeに変換する2

PowerShell: ◆PowerShellスクリプトをExeに変換する

ちょっと使う機会があったのだが、パラメータ指定で躓いたのでメモしておく。

EXEで実行する時はスクリプト実行時と同じ指定ではパラメータが取ってこれない。

調べてみると以下の様に「arguments」指定が必要らしい。

>hoge.exe –arguments –param テストパラメータ

◆WindowsUpdate情報、McAfee情報

McAfeeのDatバージョンとWindowsUpdateの最終更新日を毎月報告せよ、と会社からのありがたーいお達し。

いまどき、「力技でやるんかい」って突っ込みはうちの会社には通用しない。

これまでは某H社の馬鹿高いツールを使っていたのだが、よっぽど評判が悪いのか待てど暮らせどWindows8には対応してこない。

ActiveDirectoryでも入れてちょっとしたツールでも作って情報収集すれば一発なのだが、何があっても(目先の)節約至上主義の会社なので力技をこよなく好む。

とりあえず自分だけは楽をしようとスクリプトを書いてみた。

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030

param(
  $mailFrom,
  $mailTo
)
$path = 
"hklm:SOFTWARE\Network Associates\ePolicy Orchestrator\Application Plugins\VIRUSCAN8800"

$prop = Get-ItemProperty -Path $path
#-----
$Session = New-Object -ComObject Microsoft.Update.Session 
$Searcher = $Session.CreateUpdateSearcher() 
$current = $Searcher.QueryHistory(1,1) | select -ExpandProperty date

#-----
$mess1 = "McAfee Datバージョンは 【{0}】 です。" -f $prop.DATVersion
$mess2 = "WindowsUpdate最終適用日は 【{0}】 です。" -f $current

#-----
if($mailFrom -and $mailTo){
  Send-MailMessage    -To $mailTo
                                    `
                     
-From $mailFrom
                                `
                     
-Subject "報告レポート"
                          `
                     
-SmtpServer "hoge.ccc.co.jp"
                  `
                     
-Body "`r`n$mess1`r`n$mess2"
                   `
                     
-Encoding  ([System.Text.Encoding]::
Default)
}

else{
  Add-Type -AssemblyName System.Windows.Forms
  [WIndows.Forms.MessageBox]::Show("$mess1`r`n$mess2") | Out-Null
}

McAfeeのDatバージョンについてはレジストリに持っている値を使ってみました。(確実かどうかは判りません)

WindowsUpdateについては、きっとやり方が色々あるのでしょうが、今回は以下のサイトを参考にしました。
Hey, Scripting Guy! コンピューターに追加されたすべての更新プログラムの一覧を取得する方法はありますか

12行目の「QueryHistory」メソッドで履歴の開始位置と件数を指定する様なので最新の1件を取得してみました。

そのまま実行すると結果をメッセージボックス表示、パラメータを指定するとメール送信としてみました。

------

WindowsUpdateの日付については「Get-HotFix」なんてコマンドレットがあるので、そちらのほうがきっと簡単ですよね・・・。