Centrum skryptów - Systemy Operacyjne

Jak za pomocą transakcji zapisywać w rejestrze?

Udostępnij na: Facebook

Skrypciarze odpowiadają na Wasze pytania

Cześć Skrypciarze!

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 stronyDo początku strony

Centrum skryptów - Systemy Operacyjne