Помощь Powershell

#powershell

#powershell

Вопрос:

В настоящее время я использую приведенный ниже сценарий PS, чтобы проверить, установлены ли в системе исправления MS за последние месяцы. Сценарий настроен на проверку $env:COMPUTERNAME.mbsa и Patch_NA.txt файла и отправку результата в $env:COMPUTERNAME.csv файл.

Теперь мне нужно изменить этот скрипт, чтобы также извлекать информацию с других POS устройств в том же месте ( C:UsersCambridgeSecurityScans ) и отправлять результаты в $env:COMPUTERNAME.csv file .
POS Устройства перечислены следующим образом:

 172.26.210.1.mbsa  
172.26.210.2.mbsa  
172.26.210.3.mbsa
  

и так далее.
IP Диапазон во всех наших местоположениях (последний октет) равен 1 - 60 . Есть идеи о том, как я могу это настроить?

Сценарий:

 $logname = "C:tempPatchVerify$env:COMPUTERNAME.csv"
[xml]$x=type "C:UsersCambridgeSecurityScans$env:COMPUTERNAME.mbsa"

#This list is created based on a text file that is provided.
$montlyPatches = type "C:TempPatchVerifyPatches_NA.txt"|
foreach{if ($_ -mat"-KB(?   <KB>d )"){$matches.KB}}

 $patchesNotInstalled=$x.SecScan.check | where {$_.id -eq 500} |foreach{`
 $_.detail.updatedata|where {$_.isinstalled -eq "false"}}|Select -expandProperty KBID

 $patchesInstalled =$x.SecScan.check | where {$_.id -eq 500} |foreach{`
$_.detail.updatedata|where {$_.isinstalled -eq "true"}}|Select -expandProperty KBID

"Store,Patch,Present"> $logname

$store = "$env:COMPUTERNAME"


foreach ($patch in $montlyPatches)
{
$result = "Unknown"
if ( $patchesInstalled -contains $patch)
{
  $result = "YES"
}
if ( $patchesNotInstalled -contains $patch)
{
  $result = "NO"
}

"$store,KB$($patch),$result" >>$logname
 }  
  

Комментарии:

1. Значит, вам просто нужно выполнить ту же процедуру для файлов, названных в честь IP-адреса каждого устройства, с расширением .mbsa? Вы уже пробовали что-нибудь с этой целью? Какие проблемы у вас возникли с тем, что вы пробовали?

2. Да, это примерно так. Я еще ничего не пробовал, просто начал смотреть на это.

3. Я бы посоветовал вам преобразовать эту часть в функцию, указав в качестве параметра либо полный путь, либо имя файла. Затем вы могли бы запустить цикл ForEach, чтобы довольно легко управлять POS-устройствами. Почему бы вам не попробовать и не сообщить нам, если у вас возникнут проблемы.

4. Спасибо. Я все еще новичок в PS, возможно, вы можете привести мне и пример?

Ответ №1:

В Интернете можно найти много информации о создании функций, но простым примером может быть:

 Function Check-Patches{
Param($FileName)
    $logname = "C:tempPatchVerify$FileName.csv"
    [xml]$x=type "C:UsersCambridgeSecurityScans$FileName.mbsa"
    The rest of your existing code goes here...

}

Check-Patches "$env:ComputerName"
For($i=1;$i -le 60;$i  ){
    Check-Patches "172.26.210.$i"
}
  

Если вам нужно, чтобы я что-то в этом разбил, дайте мне знать, и я перейду к дальнейшим объяснениям, но из того, что у вас уже есть, похоже, что вы неплохо разбираетесь в теории PowerShell и вам просто нужно знать, какие ресурсы доступны.

Редактировать: я обновил свой пример, чтобы лучше соответствовать вашему сценарию, заставив его принять имя файла, а затем применить это имя файла к переменным $logname и $ x внутри функции.

Сбой…

Сначала мы объявляем, что создаем функцию, используя Function ключевое слово. Далее следует имя функции, которую вы будете использовать позже для ее вызова, и открывающая фигурная скобка для запуска scriptblock, который составляет фактическую функцию.

Далее идет строка параметров, которая в данном случае очень проста, объявляя только одну переменную в качестве входных данных. В качестве альтернативы это можно было бы сделать как Function Check-Patches ($FileName){ , но когда вы начинаете знакомиться с более продвинутыми функциями, это только сбивает с толку, поэтому я рекомендую придерживаться размещения параметров внутри scriptblock функции. Это первое, что вам нужно внутри вашей функции в большинстве случаев, исключая любую справку, которую вы бы написали для функции.

Затем мы обновили строки для $logname и [xml]$x , которые используют $FileName, который функция получает в качестве входных данных.

После этого появляется весь ваш код, который анализирует журналы исправлений и выводит данные в ваш CSV, а также закрывающая фигурная скобка, которая завершает блок сценариев, и функция.

Затем мы вызываем его для имени компьютера и запускаем цикл For . Цикл For выполняет все значения от 1 до 60, и для каждого цикла он использует это число в качестве последнего октета имени файла для ввода в функцию и проверки этих файлов.

Несколько комментариев к остальной части вашего кода. $monthlypatches = может быть изменено на = type | ?{$_ -match "-KB(? <KB>d )"}|%{$matches.KB} так, чтобы результаты фильтровались перед циклом ForEach, что может сократить время.

В строках $patchesInstalled и $patchesNotInstalled вам не нужна обратная метка в конце этой строки. Естественно, у вас может быть разрыв строки после начала скриптового блока для цикла ForEach. Наличие его там может быть трудно увидеть позже, если сценарий сломается, и если после него что-то есть (включая пробел), сценарий может сломаться и выдать ошибки, которые трудно отследить.

Наконец, вы дважды перебираете $ x, а затем $monthlyPatches один раз и выполняете множество отдельных записей в файл журнала. Я бы предложил создать массив, заполнить его пользовательскими объектами, которые имеют 3 свойства (сохранить, исправить и представить), а затем вывести это в конце функции. Это немного меняет ситуацию, но затем ваша функция выводит объект, который вы могли бы передать в Export-CSV, или, возможно, позже вы могли бы захотеть, чтобы он делал что-то еще, но, по крайней мере, тогда у вас это было бы. Чтобы сделать это, я бы запустил $ x через коммутатор, чтобы проверить, установлены ли вещи, затем я бы очистил массив, установив для всех monthlypatches, которых еще нет в этом массиве, значение Unknown. Это было бы что-то вроде:

 Function Check-Patches{
Param($FileName)
    $logname = "C:tempPatchVerify$FileName.csv"
    [xml]$x=type "C:UsersCambridgeSecurityScans$FileName.mbsa"
    $PatchStatus = @()

    #This list is created based on a text file that is provided.
    $monthlyPatches = GC "C:TempPatchVerifyPatches_NA.txt"|?{$_ -match "-KB(?   <KB>d )"} | %{$matches.KB}

    #Create objects for all the patches in the updatelog that were in the monthly list.
    Switch($x.SecScan.Check|?{$_.KBID -in $monthlyPatches -and $_.id -eq 500}){
        {$_.detail.updatedata.isinstalled -eq "true"}{$PatchStatus =[PSCustomObject][Ordered]@{Store=$FileName;Patch=$_.KBID;Present="YES"};Continue}
        {$_.detail.updatedata.isinstalled -eq "false"}{$PatchStatus =[PSCustomObject][Ordered]@{Store=$FileName;Patch=$_.KBID;Present="NO"};Continue}
    }

    #Populate all of the monthly patches that weren't found on the machine as installed or failed
    $monthlyPatches | ?{$_ -notin $PatchStatus.Patch} | %{$PatchStatus  = [PSCustomObject][Ordered]@{Store=$FileName;Patch=$_;Present="Unknown"}}

    #Output results
    $PatchStatus
}

#Check patches on current computer
Check-Patches "$env:ComputerName"|Export-Csv "C:tempPatchVerify$env:ComputerName.csv" -NoTypeInformation

#Check patches on POS Devices
For($i=1;$i -le 60;$i  ){
    Check-Patches "172.26.210.$i"|Export-Csv "C:tempPatchVerify172.26.210.$i.csv" -NoTypeInformation
}
  

Комментарии:

1. Спасибо, я настрою это и попробую.

2. Когда у вас будет секунда, можете ли вы прерваться:

3. Я его настроил, но он не записывает информацию в файл журнала.

4. Обновленный ответ, объяснение и предложение альтернативы.

5. Доброе утро и спасибо за разбивку. Я просто попытался запустить то, что у вас есть выше, и это не удается.