Zarządzanie PS poprzez port szeregowy

Ciekawostka: czy da się zarządzać PowerShellem poprzez post szeregowy? Domyślnie nie jest to wspierane rozwiązanie niemniej jest to wykonalne.

Do tego celu przyda się nam klasa System.IO.Ports.SerialPort oraz klasyczny cmdlet do wykonywania Invoke-Expression.

Aby zacząć pracę z portami szeregowymi przydatne jest sprawdzenie dostępnych portów COM na danej maszynie. Do tego celu możemy wykorzystać metodę getportnames().

[System.IO.Ports.SerialPort]::getportnames()

Pierwszym etapem jaki zaprezentuję będzie moduł do wysyłania poleceń do zdalnej maszyny. Gdy już  znamy jakie porty możemy wykorzystać musimy utworzyć nowy obiekt na podstawie klasy SerialPort.

$port = new-Object System.IO.Ports.SerialPort $portName,$baudRate,$parity,$dataBits,$stopBits

Przy czym:
$portName – wskazanie portu jaki chcemy wykorzystać
$baudRate – Szybkość wykorzystywanej transmisji
$parity – parzystość
$dataBits – Bity danych
$stopBits – Bity stopu

Kolejnym krokiem jest już otwarcie portu oraz wysłanie polecenia poprzez port szeregowy przy wykorzystaniu metody WriteLine(). Natomiast po wysłaniu można zamknąć port by go zbędnie nie blokować.

$port.open()
$port.WriteLine($command)
$port.Close()

Gdzie w naszym przypadku $command to zmienna z naszym poleceniem.

Całość wygląda następująco:

function Write-PSSerialPort
{
  param
  (
    [parameter(Position=0, Mandatory = $true, ValueFromPipeline = $true)]
    [String]$portName,
    [Int]$baudRate=9600,
    [ValidateSet("None","Odd", "Even", "Mark", "Space")]
       [String]$parity="None",
    [Int]$dataBits=8,
    [ValidateSet("None","One", "Even", "Two", "OnePointFive")]
    [String]$stopBits="One",
    [String]$command,
    [Switch]$waitForRespond,
    [Switch]$close
  )
 
  $port = new-Object System.IO.Ports.SerialPort $portName,$baudRate,$parity,$dataBits,$stopBits
  $port.open()
  $port.WriteLine($command)
    
  if($waitForRespond)
  {
    $result = $port.ReadLine()
    $result.Replace("#^#","`n") 
  }      $port.Close()
}

Etapem drugim jest utworzenie modułu odbierania danych. Wygląda to wręcz identycznie jednakże jedyną różnicą jest wykorzystanie metody ReadLine() zamiast WriteLine() oraz następnie wykonanie komendy przy pomocy Invoke-Expression.

$port = new-Object System.IO.Ports.SerialPort $portName,$baudRate,$parity,$dataBits,$stopBits 
$port.open() 
$command = $port.ReadLine() 
Invoke-Expression -Command ($command)
$port.Close()

Całość modułu nasłuchiwania wygląda następująco.

function Read-PSSerialPort
{
  param
  (
    [parameter(Position=0, Mandatory = $true, ValueFromPipeline = $true)]
    [String]$portName,
    [Int]$baudRate=9600,
    [ValidateSet("None","Odd", "Even", "Mark", "Space")]
       [String]$parity="None",
    [Int]$dataBits=8,
    [ValidateSet("None","One", "Even", "Two", "OnePointFive")]
    [String]$stopBits="One",
    [Switch]$ListeningMode,
    [Switch]$onScreen
  )
 
  $port = new-Object System.IO.Ports.SerialPort $portName,$baudRate,$parity,$dataBits,$stopBits
  $port.open()
  $command = $port.ReadLine()
    
  $result = Invoke-Expression -Command ($command) | Out-String
  $send = $result.Trim()
  if($onScreen)
  {
    $result 
  }
  
  $port.WriteLine($send.Replace("`n","#^#"))
  $port.Close()
     
  if($ListeningMode)
  {
    Read-SerialPort -portName $portName -baudRate $baudRate -parity $parity -dataBits $dataBits -stopBits $stopBits -ListeningMode  
  }
}

Skrypt ten niestety pozwala tylko i wyłącznie na odbieraniu rezultatu komend w formie tekstowej, lecz przy prostym zarządzaniu systemem nie powinno to sprawiać problemów. W przypadku bardziej zaawansowanych przedsięwzięć i tak zalecałbym zdalną administrację poprzez sieć.

Źródła:
http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.aspx
http://gallery.technet.microsoft.com/scriptcenter/39c25f4e-b5da-490f-abfd-6a341f70cddc

Advertisements

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Log Out / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Log Out / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Log Out / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Log Out / Zmień )

Connecting to %s