Script to featch lastlogon userid and date, time from the list of servers.

Hello All,
i need a script where i can featch lastlogon userid and date , time from the list of servers. and export it to csv.

i have one which works as function.
if i pipe it to export to csv. it will stop running.

#>

[CmdletBinding()]
param(
[Parameter(Position=0,ValueFromPipeline=$true)]
[Alias(“CN”,“Computer”)]
[String[]]$ComputerName="$env:COMPUTERNAME",
[String]$FilterSID,
[String]$WQLFilter=“NOT SID = ‘S-1-5-18’ AND NOT SID = ‘S-1-5-19’ AND NOT SID = ‘S-1-5-20’”
)

Begin
{
#Adjusting ErrorActionPreference to stop on all errors
$TempErrAct = $ErrorActionPreference
$ErrorActionPreference = “Stop”
#Exclude Local System, Local Service & Network Service
}#End Begin Script Block

Process
{
Foreach ($Computer in $ComputerName)
{
$Computer = $Computer.ToUpper().Trim()
Try
{
#Querying Windows version to determine how to proceed.
$Win32OS = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $Computer
$Build = $Win32OS.BuildNumber

        #Win32_UserProfile exist on Windows Vista and above
        If ($Build -ge 6001)
          {
            If ($FilterSID)
              {
                $WQLFilter = $WQLFilter + " AND NOT SID = `'$FilterSID`'"
              }#End If ($FilterSID)
            $Win32User = Get-WmiObject -Class Win32_UserProfile -Filter $WQLFilter -ComputerName $Computer
            $LastUser = $Win32User | Sort-Object -Property LastUseTime -Descending | Select-Object -First 1
            $Loaded = $LastUser.Loaded
            $Script:Time = ([WMI]'').ConvertToDateTime($LastUser.LastUseTime)
            
            #Convert SID to Account for friendly display
            $Script:UserSID = New-Object System.Security.Principal.SecurityIdentifier($LastUser.SID)
            $User = $Script:UserSID.Translate([System.Security.Principal.NTAccount])
          }#End If ($Build -ge 6001)
          
        If ($Build -le 6000)
          {
            If ($Build -eq 2195)
              {
                $SysDrv = $Win32OS.SystemDirectory.ToCharArray()[0] + ":"
              }#End If ($Build -eq 2195)
            Else
              {
                $SysDrv = $Win32OS.SystemDrive
              }#End Else
            $SysDrv = $SysDrv.Replace(":","$")
            $Script:ProfLoc = "\\$Computer\$SysDrv\Documents and Settings"
            $Profiles = Get-ChildItem -Path $Script:ProfLoc
            $Script:NTUserDatLog = $Profiles | ForEach-Object -Process {$_.GetFiles("ntuser.dat.LOG")}
            
            #Function to grab last profile data, used for allowing -FilterSID to function properly.
            function GetLastProfData ($InstanceNumber)
              {
                $Script:LastProf = ($Script:NTUserDatLog | Sort-Object -Property LastWriteTime -Descending)[$InstanceNumber]              
                $Script:UserName = $Script:LastProf.DirectoryName.Replace("$Script:ProfLoc","").Trim("\").ToUpper()
                $Script:Time = $Script:LastProf.LastAccessTime
                
                #Getting the SID of the user from the file ACE to compare
                $Script:Sddl = $Script:LastProf.GetAccessControl().Sddl
                $Script:Sddl = $Script:Sddl.split("(") | Select-String -Pattern "[0-9]\)$" | Select-Object -First 1
                #Formatting SID, assuming the 6th entry will be the users SID.
                $Script:Sddl = $Script:Sddl.ToString().Split(";")[5].Trim(")")
                
                #Convert Account to SID to detect if profile is loaded via the remote registry
                $Script:TranSID = New-Object System.Security.Principal.NTAccount($Script:UserName)
                $Script:UserSID = $Script:TranSID.Translate([System.Security.Principal.SecurityIdentifier])
              }#End function GetLastProfData
            GetLastProfData -InstanceNumber 0
            
            #If the FilterSID equals the UserSID, rerun GetLastProfData and select the next instance
            If ($Script:UserSID -eq $FilterSID)
              {
                GetLastProfData -InstanceNumber 1
              }#End If ($Script:UserSID -eq $FilterSID)
            
            #If the detected SID via Sddl matches the UserSID, then connect to the registry to detect currently loggedon.
            If ($Script:Sddl -eq $Script:UserSID)
              {
                $Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]"Users",$Computer)
                $Loaded = $Reg.GetSubKeyNames() -contains $Script:UserSID.Value
                #Convert SID to Account for friendly display
                $Script:UserSID = New-Object System.Security.Principal.SecurityIdentifier($Script:UserSID)
                $User = $Script:UserSID.Translate([System.Security.Principal.NTAccount])
              }#End If ($Script:Sddl -eq $Script:UserSID)
            Else
              {
                $User = $Script:UserName
                $Loaded = "Unknown"
              }#End Else

          }#End If ($Build -le 6000)
        
        #Creating Custom PSObject For Output
        New-Object -TypeName PSObject -Property @{
          Computer=$Computer
          User=$User
          SID=$Script:UserSID
          Time=$Script:Time
          CurrentlyLoggedOn=$Loaded
          } | Select-Object Computer, User, SID, Time, CurrentlyLoggedOn | Export-Csv c:\t.csv -NoTypeInformation
          N
      }#End Try
      
    Catch
      {
        If ($_.Exception.Message -Like "*Some or all identity references could not be translated*")
          {
            Write-Warning "Unable to Translate $Script:UserSID, try filtering the SID `nby using the -FilterSID parameter."  
            Write-Warning "It may be that $Script:UserSID is local to $Computer, Unable to translate remote SID"
          }
        Else
          {
            Write-Warning $_
          }
      }#End Catch
      
  }#End Foreach ($Computer in $ComputerName)

}#End Process

End
{
#Resetting ErrorActionPref
$ErrorActionPreference = $TempErrAct
}#End End

}# End Function Get-LastLogon

Any this is missing, please suggest.

Thanks in Advance

Your script accepts -computername as [string[]] from the pipeline ByValue; what Import-CSV produces looks like a string, so it’ll try and bind to it, but it isn’t a useful string, which is probably why it’s failing.

However, because you haven’t formatted your code (instructions are listed above the posting text box; we prefer you to store your code as a Gist in GitHub and just paste the Gist URL here), it’s difficult to completely follow the code. I would start by adding some Verbose output. E.g:

Foreach ($Computer in $ComputerName)
{
$Computer = $Computer.ToUpper().Trim()
Write-Verbose "Computer is $Computer"
...

And then running your command with the -Verbose parameter to enable that output. MOST PowerShell bugs are the result of a variable not containing what you thought it did, so the goal of debugging is to MAKE SURE you know what your variables contain by displaying their contents.

Also, I should point out that you’re not really handling errors in the preferred way ($ErrorActionPreference vs. -ErrorAction), and there’s no reason to “reset” $ErrorActionPreference as it, like all variables, is scoped to your script once you change it there. Read, “The Big Book of PowerShell Error Handling” (free, Resources menu here) for details on preferred error handling methods.

Thanks Jones,

i need csv in below format,
Computer User Time CurrentlyLoggedOn

code is in below link
https://gist.github.com/f1594cf36d79ac1cac48.git

Actually, it’s “Don.” We put our surname last and given first :). Or “Mr. Jones” but there’s no need to be formal here! :slight_smile:

Since your CSV has a Computer column, the easy fix would be to add:

ValueFromPipelineByPropertyName=$True

To your -ComputerName parameter. Then, also add the following right after its [Parameter()]

[Alias(‘computer’)]

That will let it bind the Computer column from the pipeline.

By the way, that’s an extremely useful function. If you get it working, I hope you consider writing it in an article and submitting it via email to webmaster@. We would love to publish it and offer it to others as your contribution to the community!

HI Don (is it sound good) :slight_smile:
changed below lines, getting error as below

[CmdletBinding()]
param(
[Parameter(Position=0,ValueFromPipelineByPropertyName=$True)]
[Alias(“CN”,“Computer”)][Parameter()][Alias(‘computer’)]
[String[]]$ComputerName="$env:COMPUTERNAME",
[String]$FilterSID,
[String]$WQLFilter=“NOT SID = ‘S-1-5-18’ AND NOT SID = ‘S-1-5-19’ AND NOT SID = ‘S-1-5-20’”
)

Getting below Error
The parameter “ComputerName” is declared in parameter-set “__AllParameterSets” multiple times.
At line:1 char:1

  • get-lastlogon -computername $servername
  •   + CategoryInfo          : MetadataError: (:) [], MetadataException
      + FullyQualifiedErrorId : ParameterDeclaredInParameterSetMultipleTimes

Sorry - you can’t have two [Parameter()]. It should be:

[Parameter=ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$True)]

I think you already had the Alias definition, now that I look back.

The script/function posted here seems to be copied from the TechNet Script Center.

https://gallery.technet.microsoft.com/scriptcenter/Get-LastLogon-Determining-283f98ae

it’s the same script,i am not the Author (Author: Brian C. Wilhite) i should thank him for the code. i am customizing it for my environment
i need the data out put to csv. i did that but it will stuck with single entry. it will not move further.

if i remove | to csv then it will work fine.

Thanks Mr. Don and Krebs for the support, still i am learning scripting.