Экспорт данных на основе логина foreach [Powershell]

У меня есть простой CSV-файл со столбцом "логины"

logins
john
mark
maria
...

Используйте сценарий PowerShell для проверки их последнего входа в систему:

Import-Module ActiveDirectory
function Get-ADUserLastLogon([string]$userName)
{
    $time = 0
    $user = Get-ADUser $userName | Get-ADObject -Properties lastLogon
    if($user.LastLogon -gt $time)
    {
        $time = $user.LastLogon
    }
    $dt = [DateTime]::FromFileTime($time)
    Write-Host $username $dt }

import-csv -Encoding UTF8 -path C:\scripts\loginy.csv | foreach {
    Get-ADUserLastLogon -UserName  $_.logins
}

Это отлично работает с выводом

john 2018-05-10 14:11:28
mark 2018-11-29 14:26:58
maria 2018-11-02 11:14:17
...

Когда я пытаюсь экспортировать результаты в файл csv по коду

$users = import-csv -Encoding UTF8 -path C:\scripts\loginy.csv
$results = @()
foreach ($_.logins in $users) {
    $results += Get-ADUserLastLogon -UserName  $_.logins
}
$results | Export-CSV C:\scripts\Eksporty\logowania.csv -Append -encoding "utf8"

получение ошибки

At C:\scripts\OstatnieLogowanie.ps1:19 char:12
+ foreach ($_.logins in $users) {
    +            ~
    Missing 'in' after variable in foreach loop.
    At C:\scripts\OstatnieLogowanie.ps1:19 char:29
    + foreach ($_.logins in $users)

}

Я не могу заставить его работать более 2 часов: /


person Curl User    schedule 18.12.2018    source источник


Ответы (2)


Изменить: я перепутал LastLogon и LastLogonTimestamp. LastLogonDate основан на LastLogonTimestamp. Различия между этими свойствами объясняются здесь и здесь. Я вернусь и обновлю свой ответ.


Вы используете Write-Host для вывода данных:

Write-Host $username $dt

Это не сработает. Write-Host означает «писать на экран консоли, а не на стандартный вывод». Это будет работать нормально, если вы пытаетесь отобразить данные, но при вызове $x = Get-ADUserLastLogon -UserName $login результаты будут выведены на экран консоли, и переменной $x ничего не будет присвоено. Например:

PS C:\> $x = Write-Host 0
0
PS C:\> $x
PS C:\>

Видите, как Write-Host по-прежнему пишет в консоль, а $x не имеет значения?

Ваша функция должна выглядеть примерно так: $username, $dt, Write-Output $username, $dt или return $username, $dt.

Хотя это все равно не сработает так, как вы хотите. Я бы, вероятно, использовал специальный объект (см. Get-Help about_Object_Creation -ShowWindow), например:

Import-Module ActiveDirectory
function Get-ADUserLastLogon([string]$userName) {
    $user = Get-ADUser $userName -Properties LastLogonDate 
    [PSCustomObject]@{'Logins' = $username; 'LastLogonDate' = $user.LastLogonDate}
}

$users = import-csv -Encoding UTF8 -path C:\scripts\loginy.csv
$results = foreach ($user in $users) {
    Get-ADUserLastLogon -UserName  $user.logins
}
$results | Export-CSV C:\scripts\Eksporty\logowania.csv -Append -encoding "utf8"

Честно говоря, однако, если бы я делал то, что вы пытаетесь сделать здесь, мой реальный код выглядел бы так:

Import-Csv -Encoding -Path C:\scripts\loginy.csv |
    Select-Object -ExpandProperty logins |
    Get-ADUser -Properties LastLogonDate |
    Select-Object @{n = 'Logins'; e = {$_.SamAccountName}}, LastLogonDate |
    Export-Csv -Path C:\scripts\Eksporty\logowania.csv -Encoding UTF8 -NoTypeInformation

Select-Object -ExpandProperty logins передаст только голое значение столбца логинов. Get-ADUser принимает идентификаторы из конвейера и выбирает LastLogonDate для каждого пользователя, если SamAccountName (свойство по умолчанию) является именем входа в систему.

В следующей строке Select-Object @{n = 'Logins'; e = {$_.SamAccountName}}, LastLogonDate вычисляемое свойство (см. Примеры в Get-Help Select-Object -ShowWindow) используется для переименования свойства SamAccountName в столбце с именем Logins. Вы можете использовать Select-Object SamAccountName, LastLogonDate, если вас не волнует имя столбца. А параметр -NoTypeInformation в Export-Csv просто не дает ему добавлять эту раздражающую чушь "#TYPE System.Management.Automation.PSCustomObject" в первую строку.

person Bacon Bits    schedule 18.12.2018
comment
Спасибо за подробную информацию. Ваши коды работают, но дата входа в систему отличается от моей функции. Я проверил, какая дата правильная, с помощью cmd: net user% login% / domain, и у вашего скрипта неправильная дата .... - person Curl User; 18.12.2018
comment
@CurlUser А, ты прав. Я путаю LastLogon и LastLogonTimestamp. LastLogonDate основан на LastLogonTImestamp. Различия объясняются здесь. Я обновлю свой ответ. - person Bacon Bits; 18.12.2018

$ _ - это переменная для текущего значения в конвейере. Во второй части кода, поскольку у вас нет конвейера, $_ пуст и не имеет никакого свойства / метода, связанного с ним.

Что вы можете сделать, это -

$users = import-csv -Encoding UTF8 -path C:\scripts\loginy.csv
foreach ($user in $users) {
Get-ADUserLastLogon -UserName  $user.logins | Export-CSV C:\scripts\Eksporty\logowania.csv -Append -encoding "utf8"
} 

ИЛИ

$users = import-csv -Encoding UTF8 -path C:\scripts\loginy.csv
foreach ($_ in $users) {
Get-ADUserLastLogon -UserName  $_.logins | Export-CSV C:\scripts\Eksporty\logowania.csv -Append -encoding "utf8"
} 

Хотя я бы рекомендовал не использовать последнее, поскольку $_ - это автоматическая переменная $PSItem, и у вас может быть много других имен для переменной, которые не являются ключевыми словами, функциями и т. Д.

Использование += для расширения массива требует создания нового экземпляра за кулисами на каждой итерации.

person Vivek Kumar Singh    schedule 18.12.2018
comment
Восстановление массива с помощью + = на каждой итерации неэффективно, лучше назначить вывод foreach непосредственно переменной $results = foreach ( - person ; 18.12.2018
comment
Не совсем так, при прямом экспорте вам вообще не нужна переменная $results. - person ; 18.12.2018
comment
не работает ... На C: \ scripts \ OstatnieLogowanie.ps1: 19 char: 3 +} | Export-CSV C: \ scripts \ Eksporty \ logowania.csv -Append -encoding u ... + ~ Пустой элемент трубы не допускается. + CategoryInfo: ParserError: (:) [], ParentContainsErrorRecordException + FullyQualifiedErrorId: EmptyPipeElement - person Curl User; 18.12.2018
comment
@CurlUser - Попробуйте прямо сейчас. - person Vivek Kumar Singh; 18.12.2018