none
Format-Table not displaying a columns data

    Question

  • I am using the powershell command below to read a csv file and match the computer name to the employee name where the last login date is 181 days old. For some reason the Employee_Name column in the output is only displaying {} on each row. Any idea why its not returning the employee name?

    Import-Module ActiveDirectory
        $Days = (Get-Date).AddDays(-181) 
    
    
        $Computers = @{}
        Import-CSV -Path c:\PS\ComputerNames.CSV | % { $Computers[$_.Computer_Name] = $_.Employee_Name }
        Get-ADComputer -Property Name,lastLogonDate -Filter  {lastLogonDate -lt $Days} -Server servername -Searchbase "OU=US,DC=Domain,DC=net" | ? { $Computers.Keys -contains $_.Computer_Name } | select Name,lastLogonDate,@{n='Employee_Name';e={$Computers[$_.Computer_Name]}} | ft

    Friday, August 23, 2013 2:52 PM

Answers

  • Thanks for helping me so I take it I need to declare $csv? Since there is not import in this code? Add-Member : Cannot bind argument to parameter 'InputObject' because it is null. Format-Table : A positional parameter cannot be found that accepts argument 'EmployeeName'.

    That makes twice today where I have reposted an edit and it has disappeared.

    This is what was supposed to be in that post.

    $results=@()
    foreach($computer in $computers){
           $employeeName=$csv|?{$computer.Name -eq $_.computer_name} |%{$_.employee_name}
           $results+=$computer | 
                ForEach-Object{
                    $props=@{
                            Name=$computer.Name
                            EmployeeName=$employeeName
                          }
                    New-Object PsObject -Property $props
                }
    }
    $results | Format-Table Name, EmployeeName 
    

    I deleted the tested copy so this is a recreation. It shows you how to create a customobject that contains all of the info you want. Just build on it from there.

    $csv is the imported file.


    ¯\_(ツ)_/¯

    • Marked as answer by mkozz28 Friday, August 23, 2013 7:38 PM
    Friday, August 23, 2013 7:35 PM

All replies

  • First of all I'd recommend to avoid such long one-liners. Variables for intermediate results are usually helpful.

    Wrong might be this:
    You use  $_.Computer_Name  in your long one-liner, but the object behind  $_  is the AD computer object, and here the name property is named "name".

    So it might work if you use   $_.Name  instead.

    Friday, August 23, 2013 3:42 PM
  • This is closer to what you are trying to do:

    Import-Module ActiveDirectory
    $Days = (Get-Date).AddDays(-181) 
    Import-CSV -Path c:\PS\ComputerNames.CSV |
         ForEach-Object{
              $employee_name=$_.Employee_name
              Get-ADComputer $_.computer_name -filter {$_.lastlogondate -lt $Days}| 
              select Name,lastLogonDate, @{n='Employee_Name';e={$employee_name}}
        } |
        Format-Table -AutoSize

    There is no need for the hash. The CSV is already a hash. You just need to capture the name before starting the embedded pipeline.


    ¯\_(ツ)_/¯

    Friday, August 23, 2013 3:55 PM
  • Here is another approach which can add more flexibility in some ways.

    Import-Module ActiveDirectory
    $Days = (Get-Date).AddDays(-181) 
    Import-CSV -Path c:\PS\ComputerNames.CSV |
         ForEach-Object{
              $computer=Get-ADComputer $_.computer_name
              New-Object PsObject -Property @{
                                              Name=$computer.Name
                                              LastLogonDate=$computer.LastLogonDate
                                              EmployeeName=$_.employee_name
                                              }
        } | 
        Where-Object{ $_.LastLogonDate -lt days } |
        Format-Table -AutoSize


    ¯\_(ツ)_/¯

    Friday, August 23, 2013 3:59 PM
  • If you want to stick with your own code, try the following:

    Import-Module ActiveDirectory
    $Days = (Get-Date).AddDays(-181)


    $Computers = @{}
    Import-CSV -Path c:\PS\ComputerNames.CSV | % { $Computers[$_.Computer_Name] = $_.Employee_Name }
    Get-ADComputer -Property Name,lastLogonDate -Filter  {lastLogonDate -lt $Days} -Server servername -Searchbase "OU=US,DC=Domain,DC=net" | ? {
        $Computers.Keys -contains $_.Name } | select Name,lastLogonDate,@{n='Employee_Name';e={$Computers[$_.Name]}} | ft

    wizend

    Friday, August 23, 2013 4:43 PM
  • Thanks, I am getting the error that Get-ADComputer : A positional parameter cannot be found that accepts argument 'CA1020L'. like for each computer object. Also where would I put my searchbase code? Thanks!
    Friday, August 23, 2013 4:44 PM
  • Thanks, I am getting the error that Get-ADComputer : A positional parameter cannot be found that accepts argument 'CA1020L'. like for each computer object. Also where would I put my searchbase code? Thanks!

    Use Get-ADComputer -Identity $_.computer_name.

    Look at the help for Get-ADComputer.  Note that the two parameter sets are exclusive.  You can search on a collection with 'filter' and 'searchbase' or you can retrieve a computer by name.  You cannot do both in the same command.  If you attempt to combine them you will get weird results.

    Get all computers by name. Filter on lastlogon.  Filter on "parent" if you need to.  By doing this as discrete steps you will start to see how this works and how PowerShell interacts with it.

    There are a dozen or more approaches to doing this kind of thing.  Pick the simplest until you understand how it works.

    What you are trying to do is not clear from the code and statements posted.


    ¯\_(ツ)_/¯

    Friday, August 23, 2013 4:59 PM
  • Sorry, what I am trying to do is I have a csv file "ComputerNames.csv" with 2 columns. Computer Name and Employee Name. I would like to first search Active Directory for the computers with a lastlogon 181 days ago and then that those computer names returned and match them to an employee name from the csv. Thanks for your assistance. This is my first attempt at powershell
    Friday, August 23, 2013 5:38 PM
  • Ok - that makes sense and was one of the possibilities I assumed.

    The lastlogin for the computer has nothing to do with an employee.  It tr4elss us when the computer was last booted or when it reauthorized on the domain which happens frequently.  The lastlogin will be old only for computers that have been turned of or not joined for that amount of time.

    Start by getting the computers of interest.

    $computers=Get-ADComputer -filter {LastLogin -lt $days}

    Now just tag them with the employee name

    $results=@()
    foreach($computer in $computers){
           $employeeName=$csv|?{$computer.Name -eq $_.computer_name} |%{$_.employee_name}
           $results+=$computer | Add-Member -MemberType NoteProperty -Name EmployeeName -Value $employeeName -PassThru
    }
    $results | Format-Table Name. EmployeeName 

    Doing it this way you can adjust each step until you get the behavior needed and you will learn how the bits work before trying to pipeline this. Pipelining makes the code simpler but is technically more complex and not as easy to debug.

    This will search the file for the computer name and add it to the computer object


    ¯\_(ツ)_/¯


    • Edited by jrv Friday, August 23, 2013 6:01 PM
    Friday, August 23, 2013 6:01 PM
  • Thanks for helping me so I take it I need to declare $csv? Since there is not import in this code? Add-Member : Cannot bind argument to parameter 'InputObject' because it is null. Format-Table : A positional parameter cannot be found that accepts argument 'EmployeeName'.
    Friday, August 23, 2013 7:23 PM
  • Thanks for helping me so I take it I need to declare $csv? Since there is not import in this code? Add-Member : Cannot bind argument to parameter 'InputObject' because it is null. Format-Table : A positional parameter cannot be found that accepts argument 'EmployeeName'.

    That makes twice today where I have reposted an edit and it has disappeared.

    This is what was supposed to be in that post.

    $results=@()
    foreach($computer in $computers){
           $employeeName=$csv|?{$computer.Name -eq $_.computer_name} |%{$_.employee_name}
           $results+=$computer | 
                ForEach-Object{
                    $props=@{
                            Name=$computer.Name
                            EmployeeName=$employeeName
                          }
                    New-Object PsObject -Property $props
                }
    }
    $results | Format-Table Name, EmployeeName 
    

    I deleted the tested copy so this is a recreation. It shows you how to create a customobject that contains all of the info you want. Just build on it from there.

    $csv is the imported file.


    ¯\_(ツ)_/¯

    • Marked as answer by mkozz28 Friday, August 23, 2013 7:38 PM
    Friday, August 23, 2013 7:35 PM
  • Thank you
    Friday, August 23, 2013 7:37 PM
  • If you want to see how to do it all in a single pipeline then it is very easy to convert htat to this:

    Get-AdComputer -filter * |
         ForEach-Object{
              $cname=$_.Name
              $props=@{
                       Name=$cname
                       EmployeeName=$csv|?{$cName -eq $_.computer_name}|%{$_.employee_name}
                     }
               New-Object PsObject -Property $props
         } | 
         Format-Table Name, EmployeeName 


    ¯\_(ツ)_/¯

    Friday, August 23, 2013 8:10 PM