Posts Tagged ‘PowerShell 2.0’
PowerShell からプログラムを管理者権限で起動する
PowerShell を起動する際、「管理者として実行」するのを忘れてしまい、管理者権限が必要なコマンドレットやプログラムを実行して気付いたときなどに。
PowerShell を操作している途中で、スタート画面やタスクバーにピン留めされたアイコンをマウスで右クリックして「管理者として実行」するのは面倒です。こんな時は、Start-Process のパラメータ -Verb に RunAs を指定すると、管理者権限で新しいプロセスを起動してくれます。(UAC のプロンプトが迂回できるわけではありません。)
PS C:\> Enable-PSRemoting Enable-PSRemoting : アクセスが拒否されました。このコマンドレットを実行するには、[管理者として実行] オプションを使用して Windows PowerShell を起動してください。 発生場所 行:1 文字:1 + Enable-PSRemoting + ~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [Enable-PSRemoting], InvalidOperationException + FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.PowerShell.Commands.EnablePSRemotingCommand PS C:\> PS C:\> Start-Process powershell.exe -Verb RunAs PS C:\>
新しい PowerShell は、新しいウィンドウで起動します。(もともとのウィンドウと異なる権限レベルなので当然ですが。)
ちなみに、-Verb の値として RunAs を指定できるのは、基本的に .bat や .exe などのみです。あるプログラム(やファイル)について、どのような Verb (動詞)を指定できるかは、以下のコマンドで確認できます。
PS C:\> $psinfo = New-Object System.Diagnostics.ProcessStartInfo -Args PowerShell.exe PS C:\> $psinfo.Verbs open runas runasuser
※利用可能な Verb は OS によって異なる場合があります。また、大文字小文字は区別されません。
バッチファイル(.bat)だと以下の様になります。
PS C:\> $psinfo = New-Object System.Diagnostics.ProcessStartInfo -Args "D:\Data\PowerShell\test.bat" PS C:\> $psinfo.Verbs edit open print runas runasuser
なお、RunAsUser を指定すると、「別のユーザーとして実行」プロンプトが開き、入力した資格情報でプロセスが開始されます。
PS C:\> Start-Process powershell.exe -Verb runasuser
Windows Update でエラーコード 80070003 が発生した場合の対処法
以前に、Windows Update でエラーコード 8024401C が発生した場合の対処法を投稿しましたが、今回はエラーコード 80070003 の場合の対処方法です。
※手順と同じ処理を行う PowerShell スクリプトは、本投稿の一番最後に記載しています。
Windows Update (Microsoft Update)を実行した際にエラーコード 80070003 (0x80070003)が発生し、更新が正常に行えないことがあります。
このエラーは、Windows Update のダウンロードキャッシュが破損していたり、内部データベースの不整合が原因で処理が行えない場合に発生します。Windows Update が使用する更新プログラム一時ファイルを削除することで、エラーを解消できます。
注意:
更新プログラム一時ファイルを削除すると、Windows Update の更新履歴がリセット(クリア)されます。更新履歴がクリアされるのみで、実際に適用された更新プログラムが削除されるわけではありません。また、既に適用済みの更新プログラムについて再適用が必要になるわけでもありません。
Windows Update の更新プログラム一時ファイルを削除する手順は、以下の通りです。
- Windows Update サービスを停止する。
- 以下のフォルダ内に存在する、全てのファイルとフォルダを削除する。
- %systemroot%\SoftwareDistribution\DataStore
- %systemroot%\SoftwareDistribution\Download
- Windows Update サービスを開始する。
注意:
手順を実行する際は十分注意して下さい。システムフォルダ内のファイルを不用意に削除すると、システムが破損したり起動しなくなる恐れがあります。
Windows Update サービスを停止する
サービスを停止する方法は色々とありますが、今回は「サービス」管理ツールを使用します。(PowerShell が使える方は、Stop-Service コマンドレットを使うと楽です。)
[Windows キー] + X を入力して「ファイル名を指定して実行」を選択するか、[Windows キー] + R を入力します。
「名前」に “services.msc” と入力して、OK をクリックします。
「サービス」管理ツールで、Windows Update サービスの状態が「実行中」となっていることを確認します。
Windows Update を右クリックし、コンテキストメニューから「停止」を選択します。
サービスの停止処理が実行されます。Windows Update サービスの状態欄に何も表示されていない(=サービスが停止している)ことを確認します。
「サービス」管理ツールは後で使うので、閉じないで最小化しておきます。
更新プログラム一時ファイルを削除する
エクスプローラーで %systemroot%\SoftwareDistribution\DataStore フォルダ(通常は、C:\Windows\SoftwareDistribution\DataStore)を開きます。フォルダ内の全てのファイルとフォルダを選択し、削除します。
管理者権限への昇格を求められますので、「すべての項目にこれを実行する」にチェックを入れて、「続行」をクリックします。なお、管理者権限を持たない(Administrators グループに所属していない)ユーザーでログインしている場合は、管理者権限を持つユーザー名と、そのパスワードが求められます。
同様に、エクスプローラーで %systemroot%\SoftwareDistribution\Download フォルダ(通常は、C:\Windows\SoftwareDistribution\Download)を開きます。フォルダ内の全てのファイルとフォルダを選択し、削除します。
管理者権限への昇格を求められますので、「すべての項目にこれを実行する」にチェックを入れて、「続行」をクリックします。
Windows Update サービスを開始する
「サービス」管理ツールで Windows Update サービスを右クリックし、コンテキストメニューから「開始」を選択します。
Windows Update (Microsoft Update)を開くと、エラー表示が消えている事が分かります。また、更新プログラムの最終確認日時や更新プログラムのインストール日時がクリア(初期化)されていることが分かります。
前述の通り、更新履歴についても削除されている事が分かります。
他に問題が発生していなければ、更新プログラムの確認とインストールが行えます。
おまけ
PowerShell で上記手順と同じ処理を行う場合は、以下のスクリプトを実行します。必ず、「管理者として実行」してください。
Stop-Service wuauserv Remove-Item -Recurse $env:SystemRoot\SoftwareDistribution\DataStore\* Remove-Item -Recurse $env:SystemRoot\SoftwareDistribution\Download\* Start-Service wuauserv
超簡単ですね。
参考
PowerShell で行数や文字数をカウントする
Linux ではログファイルやデータの簡単なチェックを行う際に、wc (Word Count)で行数をカウントすることが多々あります。PowerShell では以下の方法で行数や文字数をカウントする事が出来ます。
- Measure-Object コマンドレットを使用する
- Count プロパティ又は Length プロパティを使用する
Measure-Object はオブジェクトの個数をカウントしたり、数値型のプロパティについて最小値や最大値、合計、平均といった値を計算することが出来るコマンドレットですが、文字列型(String 型)のオブジェクトについては行数や単語数、文字数をカウントすることが出来ます。
Measure-Object
Calculates the numeric properties of objects, and the characters, words, and lines in string objects, such as files of text.
Parameter Set: GenericMeasure
Measure-Object [[-Property] <String[]>] [-Average] [-InputObject <PSObject>] [-Maximum] [-Minimum] [-Sum] [<CommonParameters>]
Parameter Set: TextMeasure
Measure-Object [[-Property] <String[]>] [-Character] [-IgnoreWhiteSpace] [-InputObject <PSObject>] [-Line] [-Word] [<CommonParameters>]
行数をカウントする場合は、下側の構文を使用します。例えば、”C:\Windows\WindowsUpdate.log” の行数、単語数、文字数をカウントする場合は、以下を実行します。
PS C:\Users\Administrator> $log = Get-Content C:\Windows\WindowsUpdate.log PS C:\Users\Administrator> $log | Measure-Object -Line -Character -Word | Format-List Lines,Words,Characters Lines : 10548 Words : 123639 Characters : 1132103
実は、Get-Content で取得したテキスト($log)は String 型の配列です。1 行分が 1 つの String オブジェクトとなっており、行数分の要素を持つ配列として保持されます。そのため、オブジェクト数のカウントにより行数を取得することもできます。
PS C:\Users\Administrator> $log.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array PS C:\Users\Administrator> $log | Measure-Object | Format-List Count Count : 10548
同様に、配列の要素数を返すプロパティ Count や Length からも行数を取得できます。
PS C:\Users\Administrator> $log.Count 10548 PS C:\Users\Administrator> $log.Length 10548
このように、様々な方法で行数を取得する事が出来ますが、カウント対象のテキストに空行が含まれる場合は注意が必要です。Measure-Object の Line スイッチでカウントする行数には、空白行は含まれません。(カウントされません。)
PS C:\Users\Administrator> $ipc = (ipconfig) PS C:\Users\Administrator> $ipc | Measure-Object -Line -Character -Word | Format-List Lines,Words,Characters Lines : 15 Words : 121 Characters : 590 PS C:\Users\Administrator> $ipc | Measure-Object | Format-List Count Count : 23 PS C:\Users\Administrator> $ipc.Count 23 PS C:\Users\Administrator> $ipc.Length 23
ipconfig の表示(出力)をカウントしてみると、Measure-Object でカウントした Line とそれ以外の値(Measure-Object の Count や、配列の要素数としての Count、Length)が異なっています。Linux の wc コマンドとは動作が異なりますので注意が必要です。空行(空白行)を含めた値が必要な場合は、Line ではなく Count の値を使用しましょう。
ちなみに、Measure-Object を使用した場合と Count プロパティ(Length プロパティ)へアクセスした場合の実行時間を計測してみたところ、以下のようになりました。
PS C:\Users\Administrator> Measure-Command { $log | Measure-Object | Format-List Count } | Format-List TotalMilliseconds TotalMilliseconds : 194.0421 PS C:\Users\Administrator> Measure-Command { $log | Measure-Object -Line -Character -Word | Format-List Lines,Words,Characters } | Format-List TotalMilliseconds TotalMilliseconds : 160.143 PS C:\Users\Administrator> Measure-Command { $log.Count } | Format-List TotalMilliseconds TotalMilliseconds : 0.303 PS C:\Users\Administrator> Measure-Command { $log.Length } | Format-List TotalMilliseconds TotalMilliseconds : 0.2631
Measure-Object の方が明らかに遅いですが、気にするほどの差ではありませんでした。(行数やファイルサイズが増えた場合にはもう少し顕著な差が出るかもしれませんが。)むしろ、Measure-Object を使用することで計測対象が $null であっても問題が発生する可能性が低くなりますので、Measure-Object を使用した方が良いかもしれません。
PowerShell で連続した値を生成する
特定範囲の IP アドレスの一覧を生成したい場合など、連続した値(整数値)を生成したい事があります。PowerShell で連続した値を生成する場合は .. 演算子が利用できます。
演算子に関するヘルプは、about_Operators にまとめられています。(Get-Help からも参照できます。)
.. Range operator
Represents the sequential integers in an integer array, given an upper and lower boundary.
初期値と終了値を指定すると、その間の整数を配列として返します。
PS C:\Users\Administrator> (1..10).GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array PS C:\Users\Administrator> 1..10 1 2 3 4 5 6 7 8 9 10
初期値と終了値には小数や負数も記述できます。また、初期値が終了値よりも大きい場合は、逆順で値が生成されます。
PS C:\Users\Administrator> 1.1..5.3 1 2 3 4 5 PS C:\Users\Administrator> -5..3 -5 -4 -3 -2 -1 0 1 2 3 PS C:\Users\Administrator> 2..-2 2 1 0 -1 -2
小数の場合は、整数に丸められた後で連続値が生成されます。
# 1.1 は 1、2.8 は 3 に丸めらえる PS C:\Users\Administrator> [int]1.1 1 PS C:\Users\Administrator> [int]2.8 3 PS C:\Users\Administrator> [int]1.1..[int]2.8 1 2 3 PS C:\Users\Administrator> 1.1..2.8 1 2 3
PowerShell で小数(浮動小数点型の値)を整数(32bit 符号付整数値)へキャストすると、四捨五入が行われます。もう少し正確には、四捨六入で 0.5 は原則として偶数側へ丸められます。
PS C:\Users\Administrator> [int]0.5 0 PS C:\Users\Administrator> [int]1.5 2 PS C:\Users\Administrator> [int]2.5 2 PS C:\Users\Administrator> [int]3.5 4 PS C:\Users\Administrator> [int]4.5 4 PS C:\Users\Administrator> [int]10.5 10 PS C:\Users\Administrator> [int]11.5 12
一定の間隔で値を生成したい場合は、.. 演算子と四則演算を組み合わせます。1 から順に +10 ずつ 101 までの値を生成したい場合は以下のようになります。(数学の問題ですね。)
PS C:\Users\Administrator> 0..10 | % { $_ * 10 + 1 } 1 11 21 31 41 51 61 71 81 91 101
連続した値は色々なところで使えます。例えば、192.168.0.0/24 のネットワーク内へ ping を実行しホストが存在するかを確認したい場合は、以下のように実行します。
# -n は実行回数、-w はタイムアウト(ミリ秒) # -w を指定しないと、ホストが ICMP 応答しない場合に時間がかかる PS C:\Users\Administrator> 1..254 | % { ping -n 1 -w 100 192.168.0.$_ } | Out-Null PS C:\Users\Administrator> arp -a インターフェイス: 192.168.0.11 --- 0xa インターネット アドレス 物理アドレス 種類 (以下略)
たとえ相手先が ping をフィルターしていたとしても、arp 応答には答えますので、一通り ping を実行した後の arp テーブルを参照すれば、どの IP アドレスが現在使用されているか(オンラインか)分かります。(ついでに MAC アドレスも分かります。)
PowerShell でファイルのハッシュ値を計算する
Windows には md5sum や sha1sum といったコマンドが標準では用意されていません。では、MD5 や SHA1 ハッシュを計算することができないかというと、そんな事はありません。PowerShell を使用すれば割と簡単にハッシュ値を得ることができます。
PowerShell のコマンドレットを使用して MD5 や SHA1 ハッシュを直接計算することはできませんが、.NET Framework のクラスにはハッシュ値を計算できるクラスがありますので、それを使います。具体的には、System.Security.Cryptography 名前空間の MD5 クラスや SHA1 クラスを使用します。
対象となるハッシュアルゴリズムのインスタンスを作成し、ComputeHash メソッドへファイルストリームを渡せばハッシュ値を計算できます。以下のスクリプトは $file に指定したファイルの SHA1 ハッシュ値を計算、表示します。
$file = "C:\Users\Administrator\Downloads\9200.16384.WIN8_RTM.120725-1247_X64FRE_SERVER_EVAL_JA-JP-HRM_SSS_X64FREE_JA-JP_DV5.ISO" $sha1 = [System.Security.Cryptography.SHA1]::Create() $stream = New-Object IO.StreamReader $file $hash = $sha1.ComputeHash($stream.BaseStream) $stream.Close() $hs = "" $hash | %{ $hs += $_.ToString("x2") } $hs # <表示例> # 722a306ac458ec7bdda19706977b749f2c49ebc6
ここでは、Administrator のダウンロードフォルダに保存した、Windows Server 2012 の体験版(ISO ファイル)の SHA1 ハッシュ値を計算しています。
ハッシュアルゴリズムのインスタンスは、Create メソッドで生成します。(Create は Static メソッドです。)ComputeHash メソッドはバイト配列か Stream からハッシュ値を計算します。今回はファイルストリームとして System.IO 名前空間の StreamReader クラスのインスタンスを作成し、それを ComputeHash へ渡しています。
ComputeHash で計算されたハッシュ値($hash)はバイト配列(byte[])を返します。配列の各要素を16進数へ変換し結合することで、ファイルのハッシュ値(ハッシュ文字列)を得ることができます。
日常的に使用するのであれば専用のアプリケーションを導入したほうが効率的ですが、ちょっとハッシュ値を確認したいときや追加でアプリケーションをインストールしたくないときには便利です。
PowerShell で touch する
Linux を使用していると touch コマンドを使用してファイルを新規作成したりタイムスタンプを変更したりしますが、Windows には touch コマンドがありません。(PowerShell のエイリアスとしても登録されていません。)PowerShell で同様の操作を行う場合は、New-Item コマンドレットまたは Get-Item コマンドレットを使用します。
ファイルの新規作成
ファイルを新規に作成する場合は、New-Item を使用します。エイリアスは ni です。
Parameter Set: pathSet New-Item [-Path] <String[]> [-Credential <PSCredential> ] [-Force][-ItemType <String> ] [-Value <Object> ] [-Confirm] [-WhatIf][-UseTransaction] [ <CommonParameters>] Parameter Set: nameSet New-Item [[-Path] <String[]> ] -Name <String> [-Credential <PSCredential> ] [-Force][-ItemType <String> ] [-Value <Object> ] [-Confirm] [-WhatIf][-UseTransaction] [ <CommonParameters>]
新規作成するファイルのパス(または名前)を指定します。名前指定でパスを省略した場合は、カレントフォルダに作成されます。また、New-Item コマンドレットはファイル以外のアイテムも作成できるため、ItemType スイッチで作成対象の種類(今回はファイル)を指定する必要があります。
PS C:\Users\kazu\Documents\PowerShell> Get-ChildItem ディレクトリ: C:\Users\kazu\Documents\PowerShell Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 2013/02/12 2:44 646 tmp-20130212-01.ps1 -a--- 2013/02/12 2:44 247 tmp-20130212-02.ps1 PS C:\Users\kazu\Documents\PowerShell> New-Item -ItemType file newfile ディレクトリ: C:\Users\kazu\Documents\PowerShell Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 2013/02/17 23:09 0 newfile PS C:\Users\kazu\Documents\PowerShell> Get-ChildItem ディレクトリ: C:\Users\kazu\Documents\PowerShell Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 2013/02/17 23:09 0 newfile -a--- 2013/02/12 2:44 646 tmp-20130212-01.ps1 -a--- 2013/02/12 2:44 247 tmp-20130212-02.ps1
ファイルのタイムスタンプ変更
ファイルのタイムスタンプを変更する場合は、対象のファイルを取得しプロパティを変更します。ファイル(アイテム)を取得するには、Get-Item を使用します。エイリアスは gi です。
Parameter Set: Path Get-Item [-Path] <String[]> [-Credential <PSCredential> ][-Exclude <String[]> ] [-Filter <String> ] [-Force] [-Include <String[]> ][-UseTransaction] [ <CommonParameters>] Parameter Set: LiteralPath Get-Item -LiteralPath <String[]> [-Credential <PSCredential> ][-Exclude <String[]> ] [-Filter <String> ] [-Force] [-Include <String[]> ][-UseTransaction] [ <CommonParameters>]
タイムスタンプを変更したいファイルをオブジェクトとして取得した後、LastAccessTime プロパティまたは LastWriteTime プロパティを変更します。LastAccessTime が最終アクセス日時、LastWriteTime が最終更新日時です。
例えば、ファイル newfile の最終更新日時を現在時刻へ変更する場合は、LastWriteTime プロパティへ現在時刻を表す DateTime 型のオブジェクト(Get-Date コマンドレットで取得できます)を設定します。
PS C:\Users\kazu\Documents\PowerShell> $a = Get-Item newfile PS C:\Users\kazu\Documents\PowerShell> $a ディレクトリ: C:\Users\kazu\Documents\PowerShell Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 2013/02/17 23:09 0 newfile PS C:\Users\kazu\Documents\PowerShell> $a.LastWriteTime = (Get-Date) PS C:\Users\kazu\Documents\PowerShell> $a ディレクトリ: C:\Users\kazu\Documents\PowerShell Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 2013/02/17 23:25 0 newfile PS C:\Users\kazu\Documents\PowerShell> Get-Item newfile ディレクトリ: C:\Users\kazu\Documents\PowerShell Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 2013/02/17 23:25 0 newfile
$a のプロパティだけでなく、ファイルのプロパティも変更されていることが分かります。
ファイルオブジェクトを変数へ格納せず、いきなりプロパティを変更することもできます。
PS C:\Users\kazu\Documents\PowerShell> Get-Item newfile ディレクトリ: C:\Users\kazu\Documents\PowerShell Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 2013/02/17 23:25 0 newfile PS C:\Users\kazu\Documents\PowerShell> (Get-Item newfile).LastWriteTime = (Get-Date -Date "2013/01/01 11:11:11") PS C:\Users\kazu\Documents\PowerShell> Get-Item newfile ディレクトリ: C:\Users\kazu\Documents\PowerShell Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 2013/01/01 11:11 0 newfile
PowerShell スクリプトのコマンドヘルプの書き方(簡易版)
leave a comment »
PowerShell では Get-Help コマンドレットでコマンドのヘルプを出力できます。自作したスクリプト(モジュール化などはしていない、単純な ps1 スクリプトファイル)であっても、ヘルプ情報を埋め込むことができます。
書き方
ヘルプ トピックの作成方法は、about_Comment_Based_Help に記載されています。
スクリプトファイルの先頭(Requires の直後)に、ブロックコメントで必要な情報を記載します。(ブロックコメントではなく 1 行ずつコメント化しても認識しますが、複数行に渡ることが多いため通常はブロックコメントを使用します。)
記述方法のサンプルは以下の通りです。
ヘルプ キーワード
ヘルプ キーワードはドット(.)で始まります。
関数またはスクリプトの簡単な説明。
関数またはスクリプトの詳細な説明。
パラメーターの説明。
関数またはスクリプトの使用方法(使用例)。
入力オブジェクトの .NET Framework 型。
出力オブジェクトの .NET Framework 型。
関数またはスクリプトに関する追加情報。
「関連リンク」セクションに表示される内容。
キーワードは他にもありますが、簡単なスクリプトであれば上記以外を使用するシーンは少ないと思います。
スクリプトの説明を、通常のコメントとしてスクリプト内に埋め込むのもよいですが、PowerShell として用意されている方法がありますので、なるべくスクリプトのヘルプ トピックを記述するくせをつけると良さそうです。
Written by kazu
2016/09/29 at 03:24
カテゴリー: PowerShell
Tagged with Comment Based Help, Help, PowerShell 2.0, PowerShell 3.0, PowerShell 4.0, PowerShell 5.0, PowerShell Core