2014年7月14日月曜日

[Powershell] Hyper-Vにて仮想マシンの稼働日時の情報を設定する

Hyper-Vで仮想マシンをたくさん作ったりサーバを共有して使っていると、どの仮想マシンをいつまで実行させていたのかが分からなくなります。

ハードディスクの容量が足りなくなった場合など仮想マシンの整理が必要な状況では、動かしていない仮想マシンであればアーカイブしたり削除したりする対象になります。でも、既定の設定ではいつ動かしていたかの情報を取ることができません。

下記のスクリプトをタスクスケジューラ等で定期的に実行すれば、実行中の仮想マシンのメモ欄にスクリプト実行時の日時を書き込みます。


# 
# Hyper-v にて実行中の仮想マシンのメモ情報に処理実行時の日時を書き込むスクリプト
# 


# 実行中の仮想マシンの一覧を取得します。
$RuningVms = (Get-VM | ? {$_.State -eq "Running"}).Name

# 実行中の仮想マシンに対して処理を行います。
foreach ($VmName in $RuningVms){

    # 仮想マシンのメモの情報を取得します。
    $VmNote = (Get-VM -Name $VmName).Notes

    # メモの情報を1行ずつ取得できるように加工します。
    $VmNote = $VmNote -split "`n"

    # メモ情報の行数を取得します。
    $VmNoteLineCount = $VmNote.Length

    # 処理にて使用する変数に初期値を設定します。
    $VmNoteRevised = $null
    $i = 0
    $RunningFlag = 0

    # メモ欄の最終稼働確認日を更新します。
    # 最終稼働確認日が記載された行を削除し、現在の日時が記載された行を追加します。
    while ($i -lt $VmNoteLineCount){
        if($VmNote[$i] -like "最終稼働確認日*"){
            $VmNoteRevised += "最終稼働確認日:" + (Get-Date).DateTime
            $RunningFlag = 1}
        else{
            $VmNoteRevised += $VmNote[$i]}
        $i ++
        if($i -lt $VmNoteLineCount){$VmNoteRevised += "`n"}
        }

    # 最終稼働確認日が記載された行を追加します。
    if($RunningFlag -eq 0){
        $VmNoteRevised += "`n"
        $VmNoteRevised += "最終稼働確認日:" + (Get-Date).DateTime}


    # 仮想マシンのメモ情報を更新します。
    Set-VM -Name $VmName -Notes $VmNoteRevised

}
  
  



2014年7月13日日曜日

[Powershell] ヒア文字列を分割し行ごとに処理できるようにする

Powershellでは複数行の長さの文字列をヒア文字列をして定義できます。
しかし、1行ずつ処理しようとしてもそのままではうまくいきませんでした。
Measure-Objectで調べたら1行の文字列として扱われている様です。


処理を行うためにはこれを分割し文字列の配列に変換する必要があります。
$HereString = $HereString -split "`n"
このようなコマンドで配列にすることができます。

サンプルスクリプト
# 
# ヒア文字列の行数を取得します。

# ヒア文字列を作成します。
# 改行も含めて12文字とカウントされます。

$HereString =@"
ほげほげ1
ほげほげ2
"@ 

""
"ヒア文字列に対してGetTypeメソッドを呼び出します。"
$HereString.GetType()
""
""
"ヒア文字列を1文字づつ呼び出します。"
""
$HereString[0]
$HereString[1]
$HereString[2]
$HereString[3]
$HereString[4]
$HereString[5]
$HereString[6]
$HereString[7]
$HereString[8]
$HereString[9]
$HereString[10]
$HereString[11]

""
"改行は3文字として扱われます。"
"どういう文字コードが当てられているかは分かりません。"
""
"ヒア文字列の行数(Measure-ObjectのCount)"
($HereString | Measure-Object).Count 
""
"ヒア文字列の長さ(Length)"
$HereString.Length
""
""
""
"【ヒア文字列の分割】"
"ヒア文字列を改行文字で分割し、元の変数に格納します。"
$HereString = $HereString -split "`n"
""
"分割したヒア文字列に対してGetTypeメソッドを呼び出します。"
$HereString.GetType()
""
""
"分割したヒア文字列を1行づつ呼び出します。"
"1文字ごとに取り出すことはできないようです。"
""
$HereString[0]
$HereString[1]
""
"分割したヒア文字列の行数(Measure-ObjectのCount)"
($HereString | Measure-Object).Count
""
"分割したヒア文字列の長さ(Length)"
$HereString.Length
  
  



実行すると以下のようになります。


ヒア文字列を1文字づつ呼び出します。















改行は3文字として扱われます。
どういう文字コードが当てられているかは分かりません。

ヒア文字列の行数(Measure-ObjectのCount)
1

ヒア文字列の長さ(Length)
12



【ヒア文字列の分割】
ヒア文字列を改行文字で分割し、元の変数に格納します。

分割したヒア文字列に対してGetTypeメソッドを呼び出します。
True     True     String[]                                 System.Array                                                                                                                                    


分割したヒア文字列を1行づつ呼び出します。
1文字ごとに取り出すことはできないようです。

ほげほげ1
ほげほげ2

分割したヒア文字列の行数(Measure-ObjectのCount)
2

分割したヒア文字列の長さ(Length)
2


[Powershell] 共有フォルダを作成する

共有フォルダを作成するときに使用するPowershellスクリプトを作ってみました。

このサンプルスクリプトではC:\SharedフォルダをSharedという名前の共有フォルダにします。
その共有フォルダにEveryone、フルコントロールの共有権限を設定します。
(NTFS権限の設定はこのスクリプトでは行いません)


# 共有フォルダを作成するスクリプト
#
# 1.フォルダを作成します。
# 2.そのフォルダを共有フォルダにします。
# 3.そのフォルダに共有権限設定を行います。

# 1.
# 共有フォルダにするフォルダのパスを指定します。
# フォルダがない場合は新規にフォルダを作成し、
# 既存のフォルダがある場合はそれを共有フォルダにします。
$SharedFolderPath = "C:\Shared"

# 2.
# 共有フォルダ名を指定します。
# すでに共有フォルダがある場合は処理を中止します。
# 処理中止時には共有権限設定も行いません。
$SharedFolderName = "Shared"

# 3.
# 設定する共有権限を指定します。
$AccoutName = "Everyone"
$FolderPermission = "FULL"


# 1.フォルダの作成
if (-not (Test-Path $SharedFolderPath)){
    New-Item $SharedFolderPath -Type Directory}

# 2.共有フォルダの作成
if (Get-SmbShare –Name $SharedFolderName -ErrorAction SilentlyContinue){
    "すでに共有 $SharedFolderName が存在します。処理を中止します。";Exit}  #処理中止
else{
    New-SmbShare –Name $SharedFolderName –Path $SharedFolderPath}

# 3.共有権限の設定
Grant-SmbShareAccess -Name $SharedFolderName -AccountName $AccoutName -AccessRight $FolderPermission -Force
   
   

参考サイト
PowerShell で smb コマンドレットで 共有 フォルダを作成する
Set-SmbShare

あと、Powershell DSCでの共有フォルダの設定は下のサイトが参考になります。
xSmbShare PowerShell Module (DSC Resource Kit)
Configure SMB Shares with PowerShell DSC

2014年6月22日日曜日

[Powershell] プロセスを停止してからシャットダウンする

コンピュータをシャットダウンする前に、iTuneなどを停止していないとシャットダウン中に「プログラムが動いている」と警告がでてシャットダウン処理がそこで一時停止してしまいます。

なので、Powershellで止めたいプロセスを先に止めてからシャットダウンを行うスクリプトを作りました。


# シャットダウン前に停止したいプロセスを列挙する
$RunningProcesses = ("iTunes","LINE","LYNC","OUTLOOK","EXCEL","WINWORD")

# 列挙したプロセスを停止する
foreach ($Process in $RunningProcesses){
    if (Get-Process | Where-Object {$_.ProcessName -eq $Process})
        {Stop-Process -Name $Process}
 }

# コンピュータをシャットダウンする 
Stop-Computer -Force


スクリプトを以下のようなバッチファイルで動かせば途中で止まらずにシャットダウンができます。

echo off
echo これからコンピュータをシャットダウンします。
echo Enterを3回押してください。
echo on
pause
pause
pause
Powershell -Command "C:\PowershellScripts\Shutdown.ps1"

2014年6月20日金曜日

[Powershell DSC] Windows 8.1でPowershell Desired State Configurationをとりあえず動かしてみた

Powershell DSC (Desired State Configuration)をWindows 8.1でとりあえず、何でもいいから動かしたかった。

サイトによくあるサンプルはIISのインストール・設定が多いがクライアントPCにIISを入れても全然うれしくないので他のサンプルを当たることに。以下はそのメモになります。

やってみたこと


① とりあえず以下のサンプルコードを作ってみたった

以下のスクリプトを"C:\PowershellScripts\PSS_DSC_zip.ps1"に保存。実行すると、"C:\PowershellScripts\test.zip"を解凍して"C:\Temp2"に展開します。
正直、まだ十分勉強していないので以下のスクリプトが正しい自信は無いです。

Configuration Filecopy
{
   Node "localhost"
   {

        Archive ArchiveExample {
            Ensure = "Present"  # You can also set Ensure to "Absent"
            Path = "C:\PowershellScripts\test.zip"
            Destination = "C:\Temp2"
        } 

    }

}

Filecopy -OutputPath . 
Start-DscConfiguration -Path .\Filecopy -Wait -Verbose

② Powershell DSC を使うためには一度"Enable-PSRemoting"を実行しないといけないらしい。

早速、実行したらエラーになりました。



PS C:\PowershellScripts> C:\PowershellScripts\PSS_DSC_zip.ps1


    ディレクトリ: C:\PowershellScripts\Filecopy



Mode                LastWriteTime     Length Name                                                                                                                             


----                -------------     ------ ----                                                                                                                             

-a---        2014/06/19     22:17       1280 localhost.mof                                                                                                                    
詳細: パラメーター ''methodName' = SendConfigurationApply,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microsoft/Windows/DesiredStateConfiguration' を使用して操作 'CimMethod の呼び出し' を実行します。
クライアントは、要求で指定された接続先に接続できません。 接続先のサービスが実行されていて、要求を受け付けられる状態であることを確認してください。 接続先で実行されている WS-Management サービス (通常は IIS または WinRM) に関するログとドキュメントを参照してください。 接続先が WinRM サービスの場合は、リモート 
ホスト上で次のコマンドを実行して、WinRM サービスを分析および構成してください: "winrm quickconfig"
    + CategoryInfo          : 接続エラー: (root/Microsoft/...gurationManager: String) []、CimException
    + FullyQualifiedErrorId : HRESULT 0x80338012
    + PSComputerName        : localhost

詳細: 操作 'CimMethod の呼び出し' が完了しました。
詳細: 構成ジョブが完了するまでにかかった時間は 6.058 秒です


ここで"Enable-PSRemoting -Force"を実行



PS C:\PowershellScripts> Enable-PSRemoting -Force
WinRM は要求を受信するように更新されました。
WinRM サービスの種類を正しく変更できました。 
WinRM サービスが開始されました。 

WinRM はリモート管理用に更新されました。

このコンピューター上のあらゆる IP への WS-Man 要求を受け付けるため、HTTP://* 上に WinRM リスナーを作成しました。 
WinRM ファイアウォールの例外を有効にしました。 
ローカル ユーザーにリモートで管理権限を付与するよう LocalAccountTokenFilterPolicy を構成しました。 


これを実行したらうまくいくようになりました。


PS C:\PowershellScripts> C:\PowershellScripts\PSS_DSC_zip.ps1


    ディレクトリ: C:\PowershellScripts\Filecopy



Mode                LastWriteTime     Length Name                                                                                                                             

----                -------------     ------ ----                                                                                                                             
-a---        2014/06/19     22:19       1280 localhost.mof                                                                                                                    
詳細: パラメーター ''methodName' = SendConfigurationApply,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microsoft/Windows/DesiredStateConfiguration' を使用して操作 '
CimMethod の呼び出し' を実行します。
詳細: コンピューター URANUX-WIN8、ユーザー SID S-1-5-21-4205703447-7355389-1786604373-1001 から LCM メソッドが呼び出されました。
詳細: [URANUX-WIN8]: LCM:  [ 開始     設定       ]
詳細: [URANUX-WIN8]: LCM:  [ 開始     リソース     ]  [[Archive]ArchiveExample]
詳細: [URANUX-WIN8]: LCM:  [ 開始     テスト      ]  [[Archive]ArchiveExample]
詳細: [URANUX-WIN8]:                            [[Archive]ArchiveExample] The destination file C:\Temp2\PowershellScripts\CompareAcl.ps1 was missing or was not a file
詳細: [URANUX-WIN8]:                            [[Archive]ArchiveExample] The destination file 
詳細: [URANUX-WIN8]: LCM:  [ 終了     テスト      ]  [[Archive]ArchiveExample]  5.7380 秒かかりました。
詳細: [URANUX-WIN8]: LCM:  [ 開始     設定       ]  [[Archive]ArchiveExample]
詳細: [URANUX-WIN8]:                            [[Archive]ArchiveExample] The configuration of MSFT_ArchiveResource is starting
詳細: [URANUX-WIN8]:                            [[Archive]ArchiveExample] The archive at C:\PowershellScripts\test.zip was unpacked to destination C:\Temp2
詳細: [URANUX-WIN8]:                            [[Archive]ArchiveExample] The configuration of MSFT_ArchiveResource has completed
詳細: [URANUX-WIN8]: LCM:  [ 終了     設定       ]  [[Archive]ArchiveExample]  0.2520 秒かかりました。
詳細: [URANUX-WIN8]: LCM:  [ 終了     リソース     ]  [[Archive]ArchiveExample]
詳細: [URANUX-WIN8]: LCM:  [ 終了     設定       ]
詳細: [URANUX-WIN8]: LCM:  [ 終了     設定       ]    (6.3300 秒)。
詳細: 操作 'CimMethod の呼び出し' が完了しました。
詳細: 構成ジョブが完了するまでにかかった時間は 6.393 秒です



とりあえず動いた。よかった。よかった。

解凍されるファイルの一覧が表示され、指定通りにファイルが解凍されたのが確認できました。


2014年4月19日土曜日

PowerShellを使って「内容を圧縮してディスク領域を節約する」設定を行う

ファイルのプロパティにある「内容を圧縮してディスク領域を節約する」にチェックを入れる事で、ファイルの容量を削減する事が可能です。 

<使用例> 

テスト用に976KB(1,000,000バイト)のテキストファイルを作成しました。

 ディスク上のサイズが980KBのファイルが・・・・
  

 64KBになりました。
  

 サーバで自動的に作成されるログファイルの「内容を圧縮してディスク領域を節約する」にPowerShellを使ってチェックを入れる事ができればディスク容量を節約できそうです。ZIPファイルにしてもいいですがこちらのほうが見る時に楽そうです。

 <設定用PowerShellスクリプト>

このスクリプトを使うことで「内容を圧縮してディスク領域を節約する」のチェックをつけたり、外したりができます。
Pathパラメータには設定を行うファイルのパス、
Modeパラメータにはチェックを外すときは"Uncompress"、チェックをつけて圧縮するときには"Compress"のパラメータを入れます。(デフォルトは"Compress")
 
Param(
[Parameter(Mandatory=$True)]
[String]$Path 
,
[Parameter(Mandatory=$False,
HelpMessage="""Compress""(圧縮),""Uncompress""(非圧縮)のどちらかを指定してください")]
[ValidateSet("Compress", "Uncompress")]  
[String]$Mode = "Compress"
)

# エラーメッセージを表示して処理を中止する関数
Function Set-FileError {
        $Message=@"
 
   
    Pathに記載されたファイルが存在しません。
   処理を中止します。 
  
"@
    Write-Error $Message
    Exit
}

# Pathに指定されたパスにオブジェクトがあるかどうかをテストします。
If(-not(Test-Path -Path $Path)){
    Set-FileError
    }
    
# Pathに指定されたオブジェクトがファイルかどうかをテストします。
If((Get-Item $Path).PsIsContainer){
    Set-FileError
    }

# WmiObjctの設定を行います。
$Path = $Path -replace "\\","\\"
$File = Get-WmiObject -Query "SELECT * FROM CIM_DataFile WHERE Name='$Path'"

# ModeパラメータがComressの場合は圧縮、Uncompressの場合は非圧縮します。
If($Mode -eq "Compress"){
    $File.Compress()
    }
ElseIF($Mode -eq "Uncompress"){
    $File.Uncompress()
    }
  
 

<参考サイト>

#PSTip Compress and uncompress files and folders using WMI
Hey, Scripting Guy! テキスト ファイルが存在するかどうかを確認する方法はありますか


2014年4月14日月曜日

PowerShellを使って電源オプションの取得・設定を行う

PowerShellを使ったWindowsの電源オプションの情報取得と設定方法を調べました。
以下のスクリプトを実行するすることで情報取得と設定が可能です。

<電源オプションの情報取得>

○スクリプト
Get-WmiObject -Namespace root\cimv2\power -Class win32_PowerPlan | Select-Object ElementName, IsActive | Format-Table -AutoSize
 

○結果(例)

ElementName IsActive
----------- --------
バランス           False
高パフォーマンス        True
省電力            False
画面を暗くする        False

<電源オプションの設定>

パラメータにbl, hp, psと入力し実行することで、電源オプションを「バランス」「高パフォーマンス」「省電力」に設定できます。
Param(
[Parameter(Mandatory=$True)]
[String]$PowerPlan
)

$bl =@("bl","Balanced","バランス")
$hp =@("hp","High performance","高パフォーマンス")
$ps =@("ps","Power Saver","省電力")

If ($bl -contains $PowerPlan){
    $en = 'バランス'
}
ElseIf ($hp -contains $PowerPlan){
    $en = '高パフォーマンス'
}
ElseIf ($ps -contains $PowerPlan){
    $en = '省電力'
}
else {
$Message=@"
 
   
 PowerPlanパラメータに以下の値を設定してください。
  
 バランス・・・・・・bl
 高パフォーマンス・・hp
 省電力・・・・・・・ps
  
"@
Write-Error $Message
Exit
}

$p = Get-CimInstance -Name root\cimv2\power -Class win32_PowerPlan -Filter "ElementName = '$en'"
Invoke-CimMethod -InputObject $p -MethodName Activate
 
 


参考サイト
Use PowerShell and WMI or CIM to View and to Set Power Plans