Как консолидировать вывод консоли в PowerShell и отправлять в формате электронной почты в формате HTML - PullRequest
0 голосов
/ 10 февраля 2019

Доброго времени суток,

Я пытаюсь адаптировать этот сценарий (, первоначально созданный Ситарам Пармати ), для основногоцель автоматизации рутинной административной задачи по управлению паролями локального администратора в системах Windows, которые находятся под моим контролем.Пока что скрипт работает - я могу сменить пароль и получить вывод по электронной почте ( хотя и в текстовом формате ) - но он еще не совсем там.

Это отрывок из моего сценария:

Полный сценарий доступен здесь для полного контекста.

$Computers = Get-Content -Path $InputFile

#Now let's loop through each computer and change the specified account password.
ForEach ($Computer in $Computers) {

    $Computer   =   $Computer.ToUpper()
    $IsOnline   =   "OFFLINE"
    $Status     =   "SUCCESS"

    Write-Verbose "Working on $Computer"
    If((Test-Connection -ComputerName $Computer -count 1 -ErrorAction 0)) {
        $IsOnline = "ONLINE"
        Write-Verbose "`t$Computer is Online"
    } Else { Write-Verbose "`t$Computer is OFFLINE" }

    Try {
        $Account = [ADSI]("WinNT://$Computer/$TargetAccount,user")
        $Account.psbase.invoke("setpassword",$Pwd1_Text)
        Write-Verbose "`tPassword Change completed successfully"
    }
    Catch {
        $Status = "FAILED"
        Write-Verbose "`tFailed to Change the password for $TargetAccount on $Computer. Error: $_"
        $StatsError = "$_"
    }

    $Obj = New-Object -TypeName PSObject -Property @{
        Date = "$(Get-Date)"
        ComputerName = $Computer
        IsOnline = $IsOnline
        PasswordChangeStatus = $Status
        DetailedStatus = $StatsError
    }

    $Obj | Format-Table ComputerName, Date, IsOnline, PasswordChangeStatus, DetailedStatus -AutoSize
    $Obj | Select-Object "ComputerName", "Date", "IsOnline", "PasswordChangeStatus", "DetailedStatus" | Export-Csv -Append -Path ".\output.csv" -NoTypeInformation

    If($Status -eq "FAILED" -or $IsOnline -eq "OFFLINE") {
        $Stream.Writeline("$Computer `t $IsOnline `t $Status")
    }
}

#Finally, let's close the Stream Writer, write the stream to the text file
#and notify the user of the location of the FailedComputers log file
$Stream.Close()
Write-Host "`n`nFailed computers list is saved to $FailedComputers"
$ScriptEndDate = $(Get-Date)

#Send an email log of what was done
$MsgBody = @"

Dear IT Admins,

Please be advised that the local admin account password for [ $TargetAccount ] has been changed
successfully on the following hosts:

Action Initiated by:  `t$([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)
Script Started:  `t$ScriptStartDate
Script Ended:  `t$ScriptEndDate

"@
Send-MailMessage -Body $MsgBody -Verbose

# Finally, let's clear the default parameters we set earlier
$PSDefaultParameterValues.Clear()

#END SCRIPT

В настоящее время сценарий выводится на консоль PowerShell какследующим образом:

ComputerName Date                IsOnline PasswordChangeStatus DetailedStatus
------------ ----                -------- -------------------- --------------
HOME2        02/10/2019 06:18:20 ONLINE   FAILED               Exception calling "Invoke" with "2" argument(s): "Access is denied....



ComputerName Date                IsOnline PasswordChangeStatus DetailedStatus
------------ ----                -------- -------------------- --------------
HOME3        02/10/2019 06:18:22 ONLINE   FAILED               Exception calling "Invoke" with "2" argument(s): "Access is denied....



ComputerName Date                IsOnline PasswordChangeStatus DetailedStatus
------------ ----                -------- -------------------- --------------
HOME4        02/10/2019 06:18:29 OFFLINE  FAILED               Exception calling "Invoke" with "2" argument(s): "The network path was not found....

ТАК МОЙ ВОПРОС - Как я могу заставить мой скрипт консолидировать вывод следующим образом (с одной строкой заголовка для хостов ONLINE и OFFLINE), чтобы я могвключить его в тело письма?

ComputerName Date                IsOnline PasswordChangeStatus DetailedStatus
------------ ----                -------- -------------------- --------------
HOME2        02/10/2019 06:18:20 ONLINE   FAILED               Exception calling "Invoke" with "2" argument(s): "Access is denied....
HOME3        02/10/2019 06:18:22 ONLINE   FAILED               Exception calling "Invoke" with "2" argument(s): "Access is denied....
HOME4        02/10/2019 06:18:29 OFFLINE  FAILED               Exception calling "Invoke" with "2" argument(s): "The network path was not found....

Я полагаю, что мне, возможно, придется каким-то образом преобразовать вывод консоли в таблицу, а затем включить CSS в переменную заголовка, которую можно передать в командлет Send-MailMessage вЧтобы применить некоторые стили к сообщению электронной почты.Но мне еще предстоит выяснить, как этого добиться, поэтому любая помощь с этой платформы будет очень признательна.

Спасибо всем!

1 Ответ

0 голосов
/ 11 февраля 2019

Немного опоздал к игре, но я бы сказал, что вы должны собрать / сохранить все свои PSObjects в ArrayList, а затем применить Format-Table.Этот пример работает, как и ожидалось - я просто проверяю, подключен ли компьютер к сети, и прокомментировал ваш код смены пароля.

$Computers = @('SERVERA', 'SERVERB')

[System.Collections.ArrayList] $res = New-Object -TypeName "System.Collections.ArrayList"

#Now let's loop through each computer and change the specified account password.
ForEach ($Computer in $Computers) {

    $Computer   =   $Computer.ToUpper()
    $IsOnline   =   "OFFLINE"
    $Status     =   "SUCCESS"

    Write-Verbose "Working on $Computer"
    If((Test-Connection -ComputerName $Computer -count 1 -ErrorAction 0)) {
        $IsOnline = "ONLINE"
        Write-Verbose "`t$Computer is Online"
    } Else { Write-Verbose "`t$Computer is OFFLINE" }

    <#
    Try {
        $Account = [ADSI]("WinNT://$Computer/$TargetAccount,user")
        $Account.psbase.invoke("setpassword",$Pwd1_Text)
        Write-Verbose "`tPassword Change completed successfully"
    }
    Catch {
        $Status = "FAILED"
        Write-Verbose "`tFailed to Change the password for $TargetAccount on $Computer. Error: $_"
        $StatsError = "$_"
    }
    #>

    $Obj = New-Object -TypeName PSObject -Property @{
        Date = "$(Get-Date)"
        ComputerName = $Computer
        IsOnline = $IsOnline
        PasswordChangeStatus = $Status
        DetailedStatus = $StatsError
    }

    $res.Add($Obj)

    #$Obj | Format-Table ComputerName, Date, IsOnline, PasswordChangeStatus, DetailedStatus -AutoSize
    #$Obj | Select-Object "ComputerName", "Date", "IsOnline", "PasswordChangeStatus", "DetailedStatus" | Export-Csv -Append -Path ".\output.csv" -NoTypeInformation

    If($Status -eq "FAILED" -or $IsOnline -eq "OFFLINE") {
        $Stream.Writeline("$Computer `t $IsOnline `t $Status")
    }
}

$res.ToArray() | Format-Table ComputerName, Date, IsOnline, PasswordChangeStatus, DetailedStatus -AutoSize

#This will output 1 file, with all the computers in it, with only 1 set of headers.
$res.ToArray() | Select-Object "ComputerName", "Date", "IsOnline", "PasswordChangeStatus", "DetailedStatus" | Export-Csv -Append -Path ".\output.csv" -NoTypeInformation

Он дает такой результат

ComputerName Date                IsOnline PasswordChangeStatus DetailedStatus
------------ ----                -------- -------------------- --------------
SERVERA      02/11/2019 11:05:57 ONLINE   SUCCESS
SERVERB      02/11/2019 11:05:57 ONLINE   SUCCESS

Я предполагаю, чтопоскольку вы продолжаете выполнять командлет Format-Table, консоль не знает, что вы хотите вывести объект того же типа.Так как вы вызываете его несколько раз, он должен убедиться, что выходная таблица явно анализируется для консоли.Хотя, когда у вас есть вещи в массиве, а затем только один раз вызывается Format-Table - вы получите ожидаемый результат, как показано.

Обратите внимание, что я также удалил Export-Csv из вашего foreach, и это также работаеткак и ожидалось.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...