Jak za pomocą transakcji zapisywać w rejestrze?
Skrypciarze odpowiadają na Wasze pytania
Witamy w rubryce TechNet, w której Skrypciarze z firmy Microsoft odpowiadają na częste pytania dotyczące używania skryptów w administracji systemu. Jeśli macie jakieś pytania z tej dziedziny, zachęcamy do wysłania e-maila na adres: scripter@microsoft.com. Nie możemy zagwarantować odpowiedzi na każde otrzymane pytanie, ale staramy się jak możemy. |
Jak za pomocą transakcji zapisywać w rejestrze?
Cześć, Skrypciarze! Chciałabym używać transakcji do zapisywania w rejestrze, ale chciałabym też, aby w sytuacji, gdy coś nie zadziała, następowało przerwanie działania całej transakcji. Nie wiem, co zrobić, aby uzyskać taki efekt w programie Windows PowerShell. Co robię nie tak?
-- TW
Cześć, TW! Czołem, tutaj skrypciarz Ed Wilson. Dzisiaj jest cudowny dzień — jak dotąd spędzam go głównie na konferencjach w programie Live Meeting dla specjalistów MVP. Jest bardzo ciekawie. Najciekawsze są jednak posty w serwisie Twitter na temat konferencji. Okazuje się, że do całodziennych konferencji najlepiej pasuje herbata Dragon Pearl i ciastka ANZAC.
Konferencje właśnie się kończą, bierzmy się więc do pracy nad transakcjami. Można by oczekiwać, że rozpoczęcie transakcji apletem polecenia Start-Transaction, wykonanie nieprawidłowej kwerendy WMI, a następnie użycie transakcji do utworzenia klucza rejestru spowoduje przerwanie transakcji. Jednak klucz rejestru zostanie utworzony, ponieważ w aplecie polecenia Get-WmiObject nie ma parametru –usetransaction. Denerwujący komunikat wyświetlany po użyciu apletu polecenia Start-Transaction informuje, że w transakcji uwzględniane są wyłącznie polecenia z parametrem –usetransaction. W poniższej sekwencji poleceń tworzony jest klucz rejestru test2.
PS C:\> Start-Transaction
Suggestion [1,Transactions]: Once a transaction is started, only commands that get called with the -UseTransaction flag become part of that transaction.
PS C:\> $a = gwmi win32_computerSystem -ComputerName localtoast
Get-WmiObject : Serwer RPC jest niedostępny. (Wyjątek od HRESULT: 0x800706BA)
At line:1 char:10
+ $a = gwmi <<<< win32_computerSystem -ComputerName localtoast
+ CategoryInfo : InvalidOperation: (:) [Get-WmiObject], COMException
+ FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
PS C:\> New-ItemProperty -Name memory -Value ($a.totalphysicalmemory).tostring() `
-Path HKCU:\Software\ScriptingGuys\test2
Nie można wywołać metody w wyrażeniu o wartości null.
At line:1 char:71
+ New-ItemProperty -Name memory -Value ($a.totalphysicalmemory).tostring <<<< () -Path HKCU:\Software\ScriptingGuys\test2
+ CategoryInfo : InvalidOperation: (tostring:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
PS C:\> New-ItemProperty -Name test -Value rolledback -Path HKCU:\Software\ScriptingGuys\test2 -UseTransaction
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software\ScriptingGuys\test2
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software\ScriptingGuys
PSChildName : test2
PSDrive : HKCU
PSProvider : Microsoft.PowerShell.Core\Registry
test : rolledback
PS C:\> Complete-Transaction
PS C:\>
Nowy klucz rejestru widać poniżej:
Aby wychwycić błędy z apletów polecenia, które nie uczestniczą bezpośrednio w transakcji, np. z apletu polecenia Get-WmiObject, można użyć sekwencji Try/Catch/Finally. Widać to w skrypcie TrapErrorInTransaction.ps1. Skrypt ten wymaga programu Windows PowerShell 2.0 nie tylko ze względu na użycie apletów poleceń w transakcjach, ale też z powodu zastosowania sekwencji Try/Catch/Finally.
TrapErrorInTransaction.ps1
#requires –version 2.0
Function New-MemoryRegKey ($computer)
{
$t = {Start-Transaction}
&($t)
Try
{
$a = Get-WmiObject -Class win32_operatingSystem -ComputerName $computer -ErrorAction silentlyContinue
Set-ItemProperty -Name FreeMemory -Path HKCU:\Software\ScriptingGuys\test2 `
-Value ($a.FreePhysicalMemory).ToString() -UseTransaction| out-null
Complete-Transaction
"zaktualizowano klucz rejestru"
}
Catch [System.Exception]
{
Undo-Transaction
"cofnięcie transakcji"
}
Finally { "done" }
} #end function New-MemoryRegKey
new-MemoryRegKey localhost
Mój znajomy Luis, specjalista z portugalskiego działu firmy Microsoft, pokazał mi sztuczkę pozwalającą zablokować wyświetlanie komunikatu po wywołaniu apletu polecenia Start-Transaction. Aby zablokować ten komunikat należy najpierw umieścić aplet polecenia Start-Transaction w bloku skryptu i przypisać wynik do zmiennej $t. Następnie możemy użyć operatora invocation do wykonania apletu polecenia Start-Transaction. Daje nam to dane wyjściowe bez żadnych dodatkowych komunikatów. Oto potrzebne dwa wiersze kodu:
$t = {Start-Transaction}
&($t)
Następnie wykonujemy kwerendę WMI i podejmujemy próbę utworzenia lub zaktualizowania klucza rejestru. W celu podjęcia próby wykonania jakiegoś zadania używamy polecenia Try. Aby zablokować wyświetlanie informacji o błędach w działaniu WMI, dodajemy parametr -erroraction do apletu polecenia SilentlyContinue. Jeśli działanie WMI zostanie ukończone, a rejestr zostanie zaktualizowany bez problemu, transakcja zostanie wykonana. Widać to poniżej:
Try
{
$a = Get-WmiObject -Class win32_operatingSystem -ComputerName $computer -ErrorAction silentlyContinue
Set-ItemProperty -Name FreeMemory -Path HKCU:\Software\ScriptingGuys\test2 `
-Value ($a.FreePhysicalMemory).ToString() -UseTransaction| out-null
Complete-Transaction
"zaktualizowano klucz rejestru"
}
Jeśli w bloku Try wystąpi błąd, będziemy chcieli cofnąć transakcję. Najczęstszym błędem jest system.exception. Jego wystąpienie spowoduje wywołanie bloku Catch. Widać to poniżej:
Catch [System.Exception]
{
Undo-Transaction
"cofnięcie transakcji"
}
Blok Finally jest wykonywany zawsze — niezależnie od tego, czy wystąpił błąd. W naszym przykładzie wyświetlamy po prostu wiadomość informującą, że wszystko gotowe:
Finally { "gotowe" }
Jeśli blok Try zostanie wykonany z powodzeniem, klucz rejestru zostanie zaktualizowany, jeśli już istniał. Jeśli klucz jeszcze nie istniał, zostanie utworzony. Widać to poniżej.
Jeśli po uruchomieniu skryptu wystąpi błąd, wiadomości zostaną wyświetlone w konsoli. Jeśli nie wystąpi żaden błąd, wyświetlone zostaną aktualizacje stanu. Są to proste ciągi znaków, które można z łatwością modyfikować lub usuwać. Widać to poniżej.
Skrypciarze Ed Wilson i Craig Liebendorfer
Do początku strony |