G
G
genbachae2020-05-08 05:22:22
PowerShell
genbachae, 2020-05-08 05:22:22

How to work with Start-Job in Power Shell?

In the written script:

[xml]$inputs = New-Object system.Xml.XmlDocument
$inputs.Load('.\inputs.xml') 

[string]$result = ''
[string]$adresses = ''

foreach ($server in $inputs.SelectNodes('//server'))
{
  $hostname = $server.host                                    #   получаем DNS имя сервера
    Start-Job {                                                 #   стартуем задание
      if (Test-Connection $hostname -Quiet)
      {
        $result += "Ping to " + $hostname + " success`r`n"      #   формируем содержимое файла report.txt
        $port = $server.port
        $sock = new-object System.Net.Sockets.Socket -ArgumentList $([System.Net.Sockets.AddressFamily]::InterNetwork),$([System.Net.Sockets.SocketType]::Stream),$([System.Net.Sockets.ProtocolType]::Tcp)
          try {
            $sock.Connect($hostname,$Port) | Out-Null       #   попытка соединения
            $result += "port " + $port + " connect success`r`n"
            $result += "`r`n"
            $sock.Close()
            }
          catch {
          $result += "port " + $port + " connect fail`r`n"
          $result += "`r`n"
          } 
    
      }
      else
      {
        $result += "Ping to " + $hostname + " fail`r`n"         #   формируем содержимое файла report.txt
      }
    }                                                           #   конец задания
}
$result += "`r`n"

foreach ($process in $inputs.SelectNodes('//process'))          #   определяет какие процессы запущены
{
  if (Get-Process -Name $process.InnerText -ErrorAction SilentlyContinue)
  {
    $result += "Process " + $process.InnerText + " exists`r`n"
  }
  else
  {
    $result += "Process " + $process.InnerText + " not exists`r`n"
  }
}
$result += "`r`n"

foreach ($service in $inputs.SelectNodes('//service'))
{
  if (Get-service -Name $service.InnerText -ErrorAction SilentlyContinue)
  {  # 
    $Servicestatus = Get-service $service.InnerText | select status, DisplayName      # получение списка служб в Powershell
    $result += "Service " + $service.InnerText + " " + $Servicestatus.status + "`r`n"
  }
  else
  {
    $result += "Service " + $service.InnerText + " " + "not exists`r`n"
  }
  
}

Start-Sleep -Sec 99                                                 #   задержка чтобы пинги отработали

Out-File -FilePath .\report.txt -InputObject $result -Encoding Default
foreach ($adress in $inputs.SelectNodes('//email'))
{
  $adresses += $adress.InnerText + "; "
}
if ($adresses -ne '')
{
  Add-Type -AssemblyName Microsoft.Office.Interop.Outlook         #   ошибка если нет Outlook на компе
  $Outlook = New-Object -ComObject Outlook.Application
  $Mail = $Outlook.CreateItem(0)
  
  $Mail.To = $adresses
  $Computer = Get-WmiObject  -Class win32_ComputerSystem
  
  $Mail.Subject = "Testing report on "+ $Computer.Name
  $Mail.Body =$result
  $Mail.Send()
}

the first foreach loop is supposed to ping the hosts and put the results of those pings into the $result variable, but that doesn't happen. The rest of the code works without problems!

Question: tell me what I'm doing wrong in the first foreach loop?

Answer the question

In order to leave comments, you need to log in

3 answer(s)
G
genbachae, 2020-05-12
@genbachae

Managed to solve it like this:

[xml]$inputs = New-Object system.Xml.XmlDocument
$inputs.Load('.\inputs.xml') 

[string]$result = ''
[string]$adresses = ''
$matrix = New-Object System.Collections.ArrayList

$Get_Ping={                                                      #   функция будет выполняться в задании
    param($server)
    $hostname = $server.host

    if (Test-Connection $hostname -Quiet -count 1){
        $resPing += "Ping to " + $hostname + " success`r`n"      #   формируем содержимое файла report.txt
        $port = $server.port
        $sock = new-object System.Net.Sockets.Socket -ArgumentList ( 
                    $([System.Net.Sockets.AddressFamily]::InterNetwork),
                    $([System.Net.Sockets.SocketType]::Stream),
                    $([System.Net.Sockets.ProtocolType]::Tcp) )
        try {
            $sock.Connect($hostname,$Port) | Out-Null            #   попытка соединения
            $resPing += "Port " + $port + " connect success`r`n`r`n"
            $sock.Close()
        }
        catch {
            $resPing += "Port " + $port + " connect fail`r`n`r`n"
        } 
    }
    else {
        $resPing += "Ping to " + $hostname + " fail`r`n"         #   формируем содержимое файла report.txt
    }
    return $resPing
}

foreach ($server in $inputs.SelectNodes('//server'))
{
    $jb = Start-Job $Get_Ping -Args $server                      #   запускаем задание для каждого хоста
  $matrix.Add($jb)
}

foreach ($process in $inputs.SelectNodes('//process'))           #   определяет какие процессы запущены
{
  if (Get-Process -Name $process.InnerText -ErrorAction SilentlyContinue)
  {
    $result += "Process " + $process.InnerText + " exists`r`n"
  }
  else
  {
    $result += "Process " + $process.InnerText + " not exists`r`n"
  }
}
$result += "`r`n"

foreach ($service in $inputs.SelectNodes('//service'))
{
  if (Get-service -Name $service.InnerText -ErrorAction SilentlyContinue)
  {  # 
    $Servicestatus = Get-service $service.InnerText | select status, DisplayName      # получение списка служб в Powershell
    $result += "Service " + $service.InnerText + " " + $Servicestatus.status + "`r`n"
  }
  else
  {
    $result += "Service " + $service.InnerText + " " + "not exists`r`n"
  }
  
}
$result += "`r`n"

foreach($jb in $matrix)                                          #   собираем результаты выполнения пингов
{
    $rez = $jb|Wait-Job|Receive-Job
    $result += $rez
}

Out-File -FilePath .\report.txt -InputObject $result -Encoding Default
foreach ($adress in $inputs.SelectNodes('//email'))
{
  $adresses += $adress.InnerText + "; "
}
if ($adresses -ne '')
{
  Add-Type -AssemblyName Microsoft.Office.Interop.Outlook
  $Outlook = New-Object -ComObject Outlook.Application
  $Mail = $Outlook.CreateItem(0)
  
  $Mail.To = $adresses
  $Computer = Get-WmiObject  -Class win32_ComputerSystem
  
  $Mail.Subject = "Testing report on "+ $Computer.Name
  $Mail.Body =$result
  $Mail.Send()
}

R
Roman Bezrukov, 2020-05-08
@NortheR73

Here , it seems, your case is described ...

M
MaxKozlov, 2020-05-08
@MaxKozlov

firstly, there is no Wait-Job anywhere
; secondly, the Job itself cannot write anything to the result, you just need to give everything to the output
; thirdly, external variables cannot be used inside the job script - they are not available there, you must pass everything through arguments or $ using:
fourthly, what is issued in output, after wait-job, you need to receive it through receive-job
fifthly, it is better to send mail via Send-MailMessage
finally, sixthly, instead of Job, it is better to use ThreadJob or PoshRSJob - they load the computer less
, that is, the scheme is something like this:

$sourcedata = get-content in_file
$jobs = 
foreach ($data in $sourcedata) {
   Start-Job { somescript $using:data }
}
$result = $jobs | wait-Job | receive-Job
$jobs | remove-Job
$result | set-content out_file
send-mailmessage ...

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question