Hey Guys :)
I have a script from one of the guys at work that I'm trying to modify, sorry but I'm still a total noob and still haven't had time to do basic powershell training, just flat out doing donkey work.
I think this script does other stuff that I'm not familiar with but all I want to do is have the output CSV file put the data in seperate columns as opposed to having it all in the first column.
I looked at Export-CSV and Set-Content etc but couldn't work out how to add Export-CSV to the script. I had a play with Export-CSV and it worked for command line stuff but again, no idea how to get the CSV formatting correct.
$Computers = Get-Content "C:\Data\SnagIT\Snagit Computers-LastLoggedInUsers.txt" is just a list of Computer names.
Ive just changed the txt below to csv:
$LogonFile = "C:\Data\SnagIT\LastLogon_" + $DateTimeStart + ".csv"
any help would be much appreciated and thank you kindly :-D
<# Filename: Get-LastLogonAndComputers.ps1
Written by: Sam Eng
Date: 2013-09-05
This script produces 3 outputs: ActiveComputers.txt, LastLogon_2013
This script extracts a list of all active computers from AD, extracts the last logged on
information from each computer and writes the info to a file.
Where a computer is unavailable, only the computer name is shown.
#>
Import-Module ActiveDirectory
# get today's date
$today = Get-Date
#Get today - 60 days (2 month old)
$cutoffdate = $today.AddDays(-60)
$outputfile = "C:\Data\Snagit Computers-LastLoggedInUsers.txt"
#Clear-content $outputfile;
#Get-ADComputer -Properties * -Filter {LastLogonDate -gt $cutoffdate} |`
#Select-Object -Property Name | Sort-Object -Property Name| `
#ForEach-Object {Add-Content $outputfile $_.name}
#--------------------------------------------------------------------------
Function Get-LastLogon
{
[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
}#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
Clear
$DateTimeStart = Get-Date -Format "yyyy-MM-ddThh-mm-ss";
$LogonFile = "C:\Data\SnagIT\LastLogon_" + $DateTimeStart + ".csv"
Write-Host "Start - $DaeTimeStart"
$Computers = Get-Content "C:\Data\SnagIT\Snagit Computers-LastLoggedInUsers.txt";
Set-Content -Path $LogonFile -value "Start Time: $DateTimeStart";
Add-Content $LogonFile "Computer User Time CurrentlyLoggedOn"
Add-Content $LogonFile "------------------ ------------------------- ----------------------- -----------------"
#$ErrorActionPreference = "Stop";
foreach($Computer in $Computers)
{
#$ComputerFile = "C:\Data\SnagIT\" + $Computer + ".txt"
$output = Get-LastLogon $Computer -ev myError -ea SilentlyContinue
if ($myError -ne $null)
{
# We got an error and its stored in $myError.
Write-Host $Computer ": Failed to access."
Add-Content $LogonFile $Computer;
}
else
{
# Everything went as planned, $obj should have the wmi object.
$pc = $output.Computer
$user =$output.User
$time = $output.Time
$lo = $output.CurrentlyLoggedOn
$computerstr = "{0,-25} {1,-24} {2,-10}" -f $user, $time, $lo
$logonstr = "{0,-18} {1,-25} {2,-24} {3,-10}" -f $pc, $user, $time, $lo
Write-Host $Computer ": " $user
Add-Content $ComputerFile $computerstr;
Add-Content $LogonFile $logonstr;
}
}
$DateTimeEnd = Get-Date -Format "yyyy-MM-ddThh-mm-ss";
Add-Content $LogonFile " ";
Add-Content $LogonFile "End Time: $DateTimeEnd";
#Write-Host "End - $DateTimeEnd"