Welcome to MSDN Blogs Sign in | Join | Help

Windows 7 の Troubleshooting Pack を作ってみよう (2)

スクリプト編です。

(PowerShell スクリプトのスペシャリストではないので、スクリプトの記述に関しては平凡だと思いますので、あらかじめご了承お願いします。)

最初の [Edit Troubleshooter Script] をクリックします。 Windows 7 にはデフォルトで Power Shell 2.0 用のエディタがありますので、これが起動します。

image

一番上の部分にスクリプトを記述して、F5 を押すか、ツールバーの実行ボタンを押すと、真ん中にその結果が表示されます。

一番下の Window は直接コマンドをいれてその様子を見たいときに使います。 結果は同様に真ん中に表示されます。

Troubleshooter Script

ここでのポイントは、

1. Windows.old\Windows フォルダが存在する

2. USMT が使える状態にある

をチェックします。 この条件に合致した場合には、 Root Cause を見つけたことになるので、update-diagrootcause を呼び出して $true を設定するというものです。

今回は WAIK をインストールしているだけではなく、USMT をあらかじめコピーしてから troubleshooting pack を実行する事も考慮して、2 箇所に USMT のフォルダがあるかどうかを調べています。

 

# TroubleshooterScript - This script checks for the presence of a root cause
# Key Cmdlets:
# -- update-diagrootcause flags the status of a root cause and can be used to pass parameters
# -- get-diaginput invokes an interactions and returns the response
# -- write-diagprogress displays a progress string to the user

$RootCauseID = "DataFromXP"

# Your detection Logic Here
$WinOldPath = $env:SystemDrive + "\Windows.old\Windows"
$USMTDir = $env:ProgramFiles + "\Windows AIK\Tools\USMT\" + $env:PROCESSOR_ARCHITECTURE
$USMTDir2 = $env:LOCALAPPDATA + "\Microsoft\Windows AIK\Tools\USMT\" + $env:PROCESSOR_ARCHITECTURE
$WinOld = Get-Item $WinOldPath
$USMT = Get-Item $USMTDir
$USMT2 = Get-Item $USMTDir2

if (!$WinOld) {
    Write-DiagProgress "Windows.old is not found"
    $RootCauseDetected = $false
    update-diagrootcause -id $RootCauseId -detected $RootCauseDetected
    return
} else {
    Write-DiagProgress "Windows.old is found"
}

if (!$USMT -and !$USMT2) {
    Write-DiagProgress "Windows Automated Installation Kit is not instelled. Please, install from http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=696dd665-9f76-4177-a811-39c26d3b3b34"
    $RootCauseDetected = $false
    update-diagrootcause -id $RootCauseId -detected $RootCauseDetected
    return
} else {
    Write-DiagProgress "Windows Automated Installation Kit is instelled or USMT is found."
}

Write-DiagProgress "There is Windows.old folder and Windows AIK is installed. Done for checking"
$RootCauseDetected = $true #Replace "$true" with the result of your detection logic

#The following line notifies Windows Troubleshooting Platform of the status of this root cause
update-diagrootcause -id $RootCauseId -detected $RootCauseDetected

 

Resolver Script

[Edit Resolver Script] をクリックすると、実際に問題を修正するスクリプトの記述となります。

ここでは特に、何かの値を返す必要があるという事はありません。 少し複雑なので、途中に日本語コメントを入れながら色を変えて記述します。

 

# Resolver Script - This script fixes the root cause. It only runs if the Troubleshooter detects the root cause.
# Key cmdlets:
# -- get-diaginput invokes an interactions and returns the response
# -- write-diagprogress displays a progress string to the user

# Your logic to fix the root cause here
$USMTDir = $env:ProgramFiles + "\Windows AIK\Tools\USMT\" + $env:PROCESSOR_ARCHITECTURE
$USMTDir2 = $env:LOCALAPPDATA + "\Microsoft\Windows AIK\Tools\USMT\" + $env:PROCESSOR_ARCHITECTURE
$USMT = Get-Item $USMTDir
$USMT2 = Get-Item $USMTDir2

#ここでは USMT のディレクトリのうち見つかったほうをディレクトリを使うようにしています。

if (!$USMT) {
    $USMTDir = $USMTDir2
}

if(!$USMT -and !$USMT2) {
    return $false
}

#次の Veryfier で Fix ができたかどうかを確認したいのですが、Global 変数でも値の保存ができなかったので、レジストリ上にキーを作ってその存在で判断しています

Remove-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion -Name "GetDataFromWindowsOld"

Write-DiagProgress "Prepartion was done.  Start scanscate for gathering information"

#カレントディレクトリを USMT のディレクトリに変更し、scanstate をパラメータつきで呼び出します。このとき –Wait を指定してプロセスが終了するまで待つ設定です。
Set-Location $USMTDir
Start-Process "scanstate.exe" -Wait -ArgumentList ($env:SystemDrive + "\migs /auto /offlineWinOld:" + $env:SystemDrive + "\windows.old\Windows /hardlink /nocompress /efs:hardlink /c")

#プロセスが終わると、ログファイル scanstate.log が作られるので、これを読み出してエラーが記録されていないかどうかを確認します。 エラーが記録されている場合には処理を中止して戻ります。

$ErrorCheck=""
$ErrorCheck = select-string -path scanstate.log -pattern "Failed.\[gle=0x"
if($ErrorCheck) {
    Write-DiagProgress ("Error has occured :" + (Get-Content scanstate.log))
    return $false
}

#scanstate が正常終了すると、マイグレーションストアが %SystemDrive%\migs に作成されていますので、loadstate をパラメータつきで呼び出して、そこからデータを吸い上げて、動作中の Windows 7 に適用します。 同様に –wait をつけています。

Write-DiagProgress "Start loadstate for applying information in Windows 7"
Start-Process "loadstate.exe" -Wait -ArgumentList ($env:SystemDrive + "\migs /auto /hardlink /nocompress /lae /lac /c")

#同様に loadstate.log を読みこんでエラーチェックを行いますが、ここではすでにマイグレーションストアが作られているので、ストアの削除を行う必要があるので、エラーになったという記録だけを行って、処理を続行します。

$ErrorCheck=""
$ErrorCheck = select-string -path loadstate.log -pattern "Failed.\[gle=0x"
$NoError = $true
if($ErrorCheck) {
    Write-DiagProgress ("Error has occured :" + (Get-Content loadstate.log))
    $NoError = $false
}

#マイグレーション ストア の削除を usmtutils を使って行います。 ここではどうしても、Yes か No の選択がコマンドプロンプトで求められるので、ユーザーに Y を押してもらう必要があります。

Write-DiagProgress "Start usmtutils for deleting migration store. Please, input ""Y"" in command window"
Start-Process "usmtutils.exe" -Wait -ArgumentList ("/rd " + $env:SystemDrive + "\migs")

#次は再起動のための shutdown の呼び出しですが、loadstate でエラーになっていた場合は再起動を行いません。 loadstate まで成功した場合には、レジストリにキーを作成して、shutdown を呼び出して 1分後 に再起動を行います。

if($NoError) {
    Write-DiagProgress "Done and Restart the computer within 60 second"
    New-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion -Name "GetDataFromWindowsOld" -PropertyType Binary -Value 1
    Start-Process "Shutdown.exe" -ArgumentList "/r /t 60"
    return $true
} else {
    return $false
}

 

Verifier Script

[Edit Verifier Script]をクリックすると、問題が修正されたかどうかのチェックを行うスクリプトの編集となります。

このスクリプトでは、先の Resolver で最後まで正常にスクリプトが走った場合に作成される、レジストリの値を調べて、存在する場合には、$RootCauseDetected = $false  ということで、update-diagrootcause を呼び出します。

 

# Verifier Script - This script confirms that a root cause has been resolved correctly
# Key Cmdlets:
# -- update-diagrootcause flags the status of a root cause and can be used to pass parameters
# -- get-diaginput invokes an interactions and returns the response
# -- write-diagprogress displays a progress string to the user

$RootCauseID = "DataFromXP"

# Your detection Logic Here
$Flag = Get-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion -Name "GetDataFromWindowsOld" | Select-Object GetDataFromWindowsOld

if(!$Flag) {
    $RootCauseDetected = $true #$false #Replace "$false" with the result of your detection logic
} else {
    $RootCauseDetected = $false #$false #Replace "$false" with the result of your detection logic
}

#The following line notifies Windows Troubleshooting Platform of the status of this root cause
update-diagrootcause -id $RootCauseId -detected $RootCauseDetected

 

ここで気がつかれた方もいらっしゃると思いますが、troubuleshooter で update-diagrootcause に True を設定して、 Verifier で false を設定する事で、Fix が行われたという認識となります。

つまり、troubleshooter では update-diagrootcause が false の場合には Resolver には進みませんし、Verifier で True のままだと問題が修正されていないという認識となります。

 

次はテストとパッケージの作成を行っていきます。

Published Thursday, October 15, 2009 9:29 PM by Yukinori_Kashima

Comments

Anonymous comments are disabled
 
Page view tracker