powershell passwordlastset export to spread sheet - powershell

Why is this coming up blank for all machines in the passwordlastset attribute, when I export it in the csv file? Everything else works perfectly.
$Searcher = New-ObjectSystem.DirectoryServices.DirectorySearcher([ADSI]"LDAP://dc=amers,dc=jhe,dc=domain,dc=com")
$Searcher.Filter = "(&(objectCategory=computer)(objectClass=computer)(!UserAccountControl:1.2.840.113556.1.4.803:=2)(operatingSystem=Windows XP*))"
$Searcher.PageSize = 100000
$results = $Searcher.Findall()
$results | ForEach-Object { $_.GetDirectoryEntry() } |
select #{ n = 'CN'; e = { ($_.CN) } },
#{ n = 'DistinguishedName'; e = { $_.DistinguishedName } },
#{ n = 'extensionattribute7'; e = { $_.extensionattribute7 } },
#{ n = 'LastLogon'; e = { [DateTime]::FromFileTime($_.PasswordLastSet) } },
#{ n = 'OperatingSystem'; e = { $_.OperatingSystem } } |
Export-Csv 'C:\temp\WindowsXP_Only.csv' -NoType -Force

By default not all properties are returned, so you need to specify the additional properties you want.
Also, if you're looking for the last logon date (per your output), you should be using lastLogonTimestamp and not PasswordLastSet.
Here's an example using Get-ADComputer, which I greatly prefer over using older methods of searching AD. Just add your Export-CSV when you're happy with the results.
$results = get-adcomputer -Filter "operatingSystem -like 'Windows XP*'" -properties cn,lastlogontimestamp,operatingsystem,extensionattribute7,PasswordLastSet -searchbase "dc=amers,dc=jhe,dc=domain,dc=com";
$results |
select #{ n = 'CN'; e = { ($_.cn) } },
#{ n = 'DistinguishedName'; e = { $_.DistinguishedName } },
#{ n = 'extensionattribute7'; e = { $_.extensionattribute7 } },
#{ n = 'LastLogon'; e = { [DateTime]::FromFileTime($_.lastLogonTimestamp) } },
#{ n = 'PasswordLastSet'; e = { [DateTime]::FromFileTime($_.PasswordLastSet) } },
#{ n = 'OperatingSystem'; e = { $_.OperatingSystem } }
You might also find this script useful

Related

How to get the name of a PsCustomObject?

I have a Powershell-script which includes a lot of PsCustomObjects like this (names do not have a specific pattern):
$myObject1 = [PSCustomObject]#{
Name = 'Kevin'
State = 'Texas'
}
$myObject2 = [PSCustomObject]#{
Name = 'Peter'
Lastname = 'Fonda'
State = 'Florida'
}
Now I need to convert this programmatically into the following object-format to have a global hashtable:
$result = #{
'myObject1.Name' = 'Kevin'
'myObject1.State' = 'Texas'
'myObject2.Name' = 'Peter'
'myObject2.Lastname' = 'Fonda'
'myObject2.Sate' = 'Florida'
}
For this task I need a loop in which I can either read the name of each PsCustomOject or I need to specify the names of all object as a string-array and lookup the object-properties with the matching name.
The loop-constructor could look something like this:
$result = #{}
foreach($name in #('myObject1','myObject2')) {
$obj = myMissingFunction1 $name
foreach($p in $obj.PsObject.Properties) {
$result["$name.$($p.Name)"] = $p.Value
}
}
or this
$result = #{}
foreach($obj in #($myObject1, $myObject2)) {
$name = myMissingFunction2 $obj
foreach($p in $obj.PsObject.Properties) {
$result["$name.$($p.Name)"] = $p.Value
}
}
Unfortunately I cannot bring any of the two approaches to life. Can someone please help?
Here is how you could do it .
$Result = [Ordered]#{}
$index = 0
Foreach ($obj in $ArrayOfObject) {
foreach ($prop in ($obj | Get-Member -MemberType NoteProperty).Name) {
$Result."SomeObject$Index.$Prop" = $obj.$prop
}
$index += 1
}
Result
Name Value
---- -----
SomeObject0.Name Kevin
SomeObject0.State Texas
SomeObject1.Lastname Fonda
SomeObject1.Name Peter
SomeObject1.State Florida
Dataset used for this example
$ArrayOfObject = #(
[PSCustomObject]#{
Name = 'Kevin'
State = 'Texas'
}
[PSCustomObject]#{
Name = 'Peter'
Lastname = 'Fonda'
State = 'Florida'
}
)
Solved it finally. I completely forgot the "Get-Variable" function:
$result = #{}
foreach($name in #('myObject1','myObject2')) {
$obj = (Get-Variable $name).Value
foreach($p in $obj.PsObject.Properties) {
$result["$name.$($p.Name)"] = $p.Value
}
}

Extracting specific columns from multiple CSVs into new CSV

I want to extract columns by header name from multiple CSVs into one 'master file'. I have tried multiple things but each time there is something else that occurs.
I have this code which is working now, but extremely tedious typing out which header name I need for every column, as there will be upwards of 20 of columns I need from each CSV.
Anyone have any suggestions? I'm currently using PS, but am open to other methods.
Import-Csv -Path $inputFilePath1 | ForEach-Object {
$File1Values.Add($_.HBA_ID, $_)
}
Import-Csv -Path $inputFilePath2 | Select-Object *,
| Export-Csv -Path $outputFilePath -NoTypeInformation
#{ N = "TOPF_IQ_Zscore"; E = { $File1Values[$_.HBA_ID].TOPF_IQ_Zscore } },
#{ N = "TMT_A_Zscore"; E = { $File1Values[$_.HBA_ID].TOPF_IQ_Zscore } },
#{ N = "TOPF_IQ_Zscore"; E = { $File1Values[$_.HBA_ID].TOPF_IQ_Zscore } },
#{ N = "TOPF_IQ_Zscore"; E = { $File1Values[$_.HBA_ID].TOPF_IQ_Zscore } },
#{ N = "TOPF_IQ_Zscore"; E = { $File1Values[$_.HBA_ID].TOPF_IQ_Zscore } },
#{ N = "TOPF_IQ_Zscore"; E = { $File1Values[$_.HBA_ID].TOPF_IQ_Zscore } },
#{ N = "TOPF_IQ_Zscore"; E = { $File1Values[$_.HBA_ID].TOPF_IQ_Zscore } },
#{ N = "TOPF_IQ_Zscore"; E = { $File1Values[$_.HBA_ID].TOPF_IQ_Zscore } },
#{ N = "TOPF_IQ_Zscore"; E = { $File1Values[$_.HBA_ID].TOPF_IQ_Zscore } } |
Export-Csv -Path $outputFilePath -NoTypeInformation
Thanks in advance!

Array does not wipe

I don't understand why my $ReturnedAnyTypeMembers array doesn't wipe every time the function recurses. I don't want it to wipe. Its actually doing what I want it to do right now, which is keep an accurate growing list. I just don't understand why the contents of the array don't wipe every time the function is called. Any help understanding?
function Get-GroupMembers {
Param($Group)
[System.Collections.ArrayList] $ReturnedAnyTypeMembers = #()
$GroupMembersArray = gam print group-members group $Group | ConvertFrom-Csv
foreach ($GroupMember in $GroupMembersArray) {
$GroupMemberType = ($GroupMember.type)
$GroupMemberEmail = ($GroupMember.email)
$GroupMemberIsAGroup = ($GroupMemberType -eq "GROUP")
$ReturnedAnyTypeMembers.Add($GroupMember) | Out-Null
if($GroupMemberIsAGroup) {
Get-GroupMembers $GroupMemberEmail
}
}
$ReturnedGroupMembers = #{
"all" = $ReturnedAnyTypeMembers
}
Return $ReturnedGroupMembers
}
Is this the result you are after...
function Get-GroupMembers
{
Param($Group)
[System.Collections.ArrayList] $ReturnedAnyTypeMembers = #()
$GroupMembersArray = Get-LocalGroupMember -Group $Group
foreach ($GroupMember in $GroupMembersArray) {
$GroupMemberType = ($GroupMember.type)
$GroupMemberEmail = ($GroupMember.email)
$GroupMemberIsAGroup = ($GroupMemberType -eq "GROUP")
$ReturnedAnyTypeMembers.Add($GroupMember) | Out-Null
if($GroupMemberIsAGroup) {
Get-GroupMembers $GroupMemberEmail
}
}
$ReturnedGroupMembers = #{
"all" = $ReturnedAnyTypeMembers
}
Return $ReturnedGroupMembers
}
'Administrators','Users' |
ForEach-Object {Get-GroupMembers -Group $PSItem} |
Format-Table -AutoSize
# Results
<#
Name Value
---- -----
all {104DB2FE-76B8-4\Administrator, 104DB2FE-76B8-4\WDAGUtilityAccount}
all {NT AUTHORITY\Authenticated Users, NT AUTHORITY\INTERACTIVE}
#>
... or something else?

How to get a template list from several clusters?

I'm trying to migrate from a 6.0 vCenter to a 6.5 vCenter, and want to migrate all templates. How can I select all clusters at once to retrieve the full template list?
I have a lot of templates in my 6.0 vCenter and need to export a list to migrate them all at once in my new 6.5 vCenter, using Powercli. The only way I found is by using a foreach loop, in which I must provide a cluster name.
I tried using "get-datacenter" instead of "get-cluster" but the result is even worse.
$toto = foreach ($vmhost in Get-Cluster 'my_cluster'|Get-VMHost) {
Get-Template -Location $vmhost |
select name, #{n='VMHOST';e={$vmhost.name}},
#{n='VMTX';e={$_.extensiondata.config.files.VmPathName}}
}
$toto | Export-Csv C:\scripts\Templates.csv
The code works but doesn't show me all templates in the vCenter.
How can I make it work so that I can have all templates in all clusters at once, without using a loop for each?
The function extracts all templates from a single datacenter target by scanning all available clusters and hosts within; dumping the complete result into an $array_list variable.
Function Render_Template_List {
Clear-Host
$array_list = [System.Collections.ArrayList]#()
if (!($global:templates_bool)) {
$host.ui.RawUI.WindowTitle = "Retrieving available templates for use with '$global:datacenter' datacenter...Please Wait!"
if ($global:datacenter -eq 'none'){
$ESX = get-datacenter | get-VMhost | %{$_.Extensiondata.MoRef}
} else {
$ESX = get-datacenter -name "$global:datacenter" | get-VMhost | %{$_.Extensiondata.MoRef}
}
If ($global:Template -eq 'none') {
$Query = Get-Template | where {$ESX -contains $_.Extensiondata.Runtime.Host} | Sort-Object
} else {
$Query = Get-Template -name "$global:Template" | where {$ESX -contains $_.Extensiondata.Runtime.Host} | Sort-Object
}
$global:templates_bool = $true
$global:templates_query = $query
}
$seperator = "{,}"
$query = 0
$arr = 1
foreach ($template in $global:templates_query ) {
if ($arr -eq 1) {
foreach ($array in $global:templates_array) {
If (!($array -like "*#*")) {
$query = $query + 1
$val_template = $array.split($seperator)[2]
$val_template = $val_template.replace("`"","")
if ("$val_template" -eq "$template") {
$val_datacenter = $array.split($seperator)[1]
$val_datacenter = $val_datacenter.replace("`"","")
if ("$val_datacenter" -eq "$global:datacenter") {
$array_list.Add("$val_template") | Out-Null
}
}
}
}
}
if ($query -eq 0) {
$array_list.Add("$template") | Out-Null
$arr = 0
}
}
return $array_list
}

Import-CSV Nested HashTable

Say I have a CSV file that looks like:
arch,osversion,kb
32,6.1,KB1,http://kb1
32,6.2,KB2,http://kb2
64,6.1,KB3,http://kb3
64,6.2,KB4,http://kb4
How would this CSV get imported into structured hash table that looks like this?
32 -> 6.1 -> KB1 -> http://kb1
-> 6.2 -> KB2 -> http://kb2
64 -> 6.1 -> KB3 -> http://kb3
-> 6.2 -> KB4 -> http://kb4
The command below yields http://kb1:
$data['32'].'6.1'.'KB1'
Probably Group-Object is what you want.
$csv = #'
arch,osversion,kb,link
32,6.1,KB1,http://kb1
32,6.2,KB2,http://kb2
64,6.1,KB3,http://kb3
64,6.2,KB4,http://kb4
'#
$data = ConvertFrom-Csv $csv
$data | Group-Object -Property arch
Or maybe closer to what you want to query:
$groups = $data | Group-Object -Property arch, osversion, kb
($groups | ? Name -eq '32, 6.1, KB1').Group.link
You could even use variables...
$a = '32'
$o = '6.1'
$k = 'KB1'
($groups | ? Name -eq "$a, $o, $k").Group.link
From this, you can determine if such a pattern works for you.
Interesting task. The following code snippet could help (solves arch duplicates):
Remove-Variable data*, aux* -ErrorAction SilentlyContinue ### clear for debugging purposes
$datacsv = #'
arch,osversion,kb,link
32,6.1,KB1,http://kb1
32,6.2,KB2,http://kb2
64,6.1,KB3,http://kb3
64,6.2,KB4,http://kb4
'#
$datac = ConvertFrom-Csv $datacsv
$datag = #{}
$datac | ForEach-Object {
$auxLeaf = #{ $_.kb = $_.link }
$auxParent = #{ $_.osversion = $auxLeaf }
if ( $datag.ContainsKey( $_.arch) ) {
$auxParent += $datag[ $_.arch]
}
$datag.Set_Item( $_.arch, $auxParent )
}
Then, $datag['32']['6.1']['KB1'] returns desired value http://kb1
Another interesting problem: solve osversion duplicates in a particular arch:
Remove-Variable data*, aux* -ErrorAction SilentlyContinue ### clear for debugging purposes
$datacsv = #'
arch,osversion,kb,link
32,6.1,KB1,http://kb1
32,6.1,KB5,http://kb5
32,6.1,KB7,http://kb7
32,6.2,KB2,http://kb2
64,6.1,KB3,http://kb3
64,6.2,KB4,http://kb4
'#
$datac = ConvertFrom-Csv $datacsv
$datag = #{}
$datac | ForEach-Object {
$auxLeaf = #{ $_.kb = $_.link }
$auxParent = #{ $_.osversion = $auxLeaf }
if ( $datag.ContainsKey( $_.arch) ) {
if ( $datag[$_.arch].ContainsKey($_.osversion) ) {
$auxLeaf += $datag[$_.arch][$_.osversion]
$auxParent = #{ $_.osversion = $auxLeaf }
} else {
$auxParent += $datag[ $_.arch]
}
}
$datag.Set_Item( $_.arch, $auxParent )
}
The latter code snippet is roughly equivalent to
$datag =
#{
'32' = #{ '6.1' = #{ 'KB1'='http://kb1';
'KB5'='http://kb5';
'KB7'='http://kb7' };
'6.2' = #{ 'KB2'='http://kb2' }
};
'64' = #{ '6.1' = #{ 'KB3'='http://kb3' };
'6.2' = #{ 'KB4'='http://kb4' }
}
}