I play around with XAML and PowerShell. My quest now it's to speed up to put stuff from a array into a DataGrid.
Here is the current Code:
<DataGrid x:Name="DataGrid_DisabledAccounts" Background="#FF616161" Foreground="Black" AutoGenerateColumns="True" SelectionMode="Extended">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
<DataGridTextColumn Header="SamAccountName" Binding="{Binding SamAccountName}"/>
<DataGridTextColumn Header="distinguishedName" Binding="{Binding distinguishedName}"/>
</DataGrid.Columns>
</DataGrid>
Now I am using a ForEach Loop to put Values from my Array into the DataGrid.
$obj = $null
$tmp = New-Object -TypeName PSObject
$Func_Coll_DisabledAccounts = #()
$Func_DisabledAccounts = (Get-ADGroupMember -Identity $global:gbl_SrcGroup -Recursive) | Where-Object { -not ((Get-ADUser $_.samAccountName).Enabled) } | Select-Object Name, SamAccountName, distinguishedName
ForEach($obj in $Func_DisabledAccounts) {
$tmp | Add-Member -Type NoteProperty -Name "Name" -Value $obj.Name -ErrorAction SilentlyContinue
$tmp | Add-Member -Type NoteProperty -Name "SamAccountName" -Value $obj.SamAccountName -ErrorAction SilentlyContinue
$tmp | Add-Member -Type NoteProperty -Name "distinguishedName" -Value $obj.distinguishedName -ErrorAction SilentlyContinue
$DataGrid_DisabledAccounts.AddChild([pscustomobject]#{Name=$obj.Name;SamAccountName=$obj.SamAccountName;distinguishedName=$obj.distinguishedName})
$DataGrid_DisabledAccounts.Items.Refresh()
$Func_Coll_DisabledAccounts += $tmp
}
It's not possible for me to do something like this:
$DataGrid_DisabledAccounts.AddChild($Func_DisabledAccounts)
I hope someone knows what I want :)
Thanks
Chris
Related
I'm running a simple script to check if several specific services are running on an array of computers. It works fine, except the each 'row' appears' for every iteration of the loop. In this case 3 times. How do I edit/add to a property of an existing object? I.e. I want to add extra properties for the same object/row...
ComputerName Qualys Cloud Agent SplunkForwarder Service Cb Defense
------------ ------------------ ----------------------- ----------
dc01 Found Found Found
dc01 Found Found Found
dc01 Found Found Found
dc02 Found Found Found
dc02 Found Found Found
dc02 Found Found Found
ds01 Found Found Found
ds01 Found Found Found
ds01 Found Found Found
$ComputerName = 'dc01','ds01','dc02'
$ServiceList ='Qualys Cloud Agent',
'SplunkForwarder Service',
'Cb Defense'
$objarray = #()
$obj = #()
$ServiceArray = get-service -ComputerName $ComputerName -DisplayName $ServiceList | select-object -property MachineName,DisplayName,Name,Status
Foreach ($Computer in $ComputerName){
$obj = New-Object PSObject
$obj | Add-Member -MemberType NoteProperty -Name "ComputerName" -Value $Computer
Foreach($Service in $ServiceList){
If ((gsv -computername $computer -displayname $Service).Status -eq 'Running'){
#write-output "Found $Service on $Computer"
$obj | Add-Member -MemberType NoteProperty -Name $service -Value 'Found'
$objArray += $obj
}
else{
#write-output "Not Found"
$obj | Add-Member -MemberType NoteProperty -Name $service -Value 'Not Found'
$objArray += $obj
}
}
}
$objarray | sort computername
Move the $objArray += $obj statement outside the inner loop - this way each object is only referenced by the array once:
Foreach ($Computer in $ComputerName){
$obj = New-Object PSObject
$obj | Add-Member -MemberType NoteProperty -Name "ComputerName" -Value $Computer
Foreach($Service in $ServiceList){
If ((gsv -computername $computer -displayname $Service).Status -eq 'Running'){
#write-output "Found $Service on $Computer"
$obj | Add-Member -MemberType NoteProperty -Name $service -Value 'Found'
}
else{
#write-output "Not Found"
$obj | Add-Member -MemberType NoteProperty -Name $service -Value 'Not Found'
}
}
# Only need to add the resulting object ONCE
$objArray += $obj
}
I personally prefer constructing each list of object properties as a dictionary, and then convert + output it at the very end of the loop - at which point we simply assign the result of the entire foreach() statement to the desired variable:
$objArray = foreach($Computer in $ComputerName){
# Create dictionary to keep track of the new properties
$props = [ordered]#{ ComputerName = $Computer}
foreach($Service in $ServiceList){
# Populate dictionary with remaining properties inside the inner loop
if((gsv -computername $computer -displayname $Service).Status -eq 'Running'){
$props["$service"] = 'Found'
}
else{
$props["$service"] = 'Not Found'
}
}
# convert to object,
[pscustomobject]$props
}
If you want to add a property to an object, pipe the object to "add-member". Here is a quick example:
$files = Get-childitem "$env:USERPROFILE\Documents\*"
Foreach ($item in $files)
{
$item | Add-Member -MemberType NoteProperty -Name "extention" -Value $item.Name.Substring($item.name.Length - 3)
}
$files.extention
I need to create a Powershell object, array or hash table to store a list of users and assorted details, these are extracted from a CSV file and located using Get-ADUser. As below:
$userList = Import-CSV $CSVInputFile
$users = #{}
Foreach ($csvUser in $userList)
{
$userSearchString = $csvUser | Select -ExpandProperty SamAccountName
$currentUser = (Get-ADUser -Filter {SamAccountName -eq $userSearchString} `
-Properties PasswordExpired,PasswordLastSet,EmailAddress |
Where {$_.Enabled -eq "True"})
If ($currentUser.EmailAddress -ne $null)
{
$currentUserEmailString = $csvUser | Select -ExpandProperty EmailAddress
$currentUserEmailString = ($currentUserEmailString -as [string])
$currentUser.EmailAddress = $currentUserEmailString
}
$Users = New-Object PSObject -Property #{
DistinguishedName = $currentUser.DistinguishedName
EmailAddress = $currentUser.EmailAddress
Enabled = $currentUser.Enabled
GivenName = $currentUser.GivenName
Name = $currentUser.Name
PasswordExpired = $currentUser.PasswordExpired
PasswordLastSet = $currentUser.PasswordLastSet
SamAccountName = $currentUser.SamAccountName
Surname = $currentUser.Surname
}
$Users
}
How can I add the details of each user for each iteration of the loop to the object.
I want to end up with an object containing the details of a number of users, same as the output directly from Get-ADUser:
Name SamAccountName EmailAddress
---- -------------- ------------
User1 user1 user1#domain.com
User2 user2 user2#domain.com
User3 user3 user3#domain.com
Any help would be greatly appreciated!
Not sure if I'm missing the point on this but I see you are building a custom object right in your loop. The only issue I do see is you are not keeping the results after each loop. Rather you are destroying the objects history.
I would change the declaration of $users to an array $users = #() and instead of populating a user hashtable into users add the current object into the array. You will then have an array of hashtables:
$Users += New-Object PSObject -Property #{...
Then you could the $Users output line outside the loop and you will have the whole thing. Then you could just output to a Select to get the output you desire.
$Users | Select-Object name,SamAccountName,EmailAddress
There is a potential major drawback of this approach though. When using += on arrays a new array is created and resized for the new element and the old array is discarded. This has huge performance implications for larger arrays.
An even better way to approach this would be to leverage the pipeline. This would be a performance boost when you have larger user groups.
Import-CSV $CSVInputFile | ForEach-Object{
$userSearchString = $_.SamAccountName
$currentUser = Get-ADUser -Filter {SamAccountName -eq $userSearchString} `
-Properties PasswordExpired,PasswordLastSet,EmailAddress |
Where {$_.Enabled -eq "True"}
If ($currentUser.EmailAddress -ne $null){
$currentUser.EmailAddress = $_.EmailAddress
}
[pscustomobject][ordered]#{
DistinguishedName = $currentUser.DistinguishedName
# ..... truncated
Surname = $currentUser.Surname
}
}
Now you could send that to something like Export-CSV or just save it into a variable. Your options are open now. [pscustomobject][ordered] are type accelerators available in PowerShell v3.0+
Define an $users as Array
$users = #()
and append the New-Object into $Users.
$Users += New-Object
Can't believe both of you guys got in before me! Oh well.
Hope this helps anyway.
$userList = Import-CSV $CSVInputFile
$users = #()
Foreach ($csvUser in $userList)
{
$userSearchString = $csvUser | Select -ExpandProperty SamAccountName
$currentUser = (Get-ADUser -Filter {SamAccountName -eq $userSearchString} `
-Properties PasswordExpired,PasswordLastSet,EmailAddress |
Where {$_.Enabled -eq "True"})
If ($currentUser.EmailAddress -ne $null)
{
$currentUserEmailString = $csvUser | Select -ExpandProperty EmailAddress
$currentUserEmailString = ($currentUserEmailString -as [string])
$currentUser.EmailAddress = $currentUserEmailString
}
#clears the properties of the previous object and starts collecting properties
$UserObj = New-Object PSObject
Add-Member -InputObject $UserObj -MemberType NoteProperty -Name "DistinguishedName" -Value $($currentUser.DistinguishedName)
Add-Member -InputObject $UserObj -MemberType NoteProperty -Name "EmailAddress" -Value $($currentUser.EmailAddress)
Add-Member -InputObject $UserObj -MemberType NoteProperty -Name "Enabled" -Value $($currentUser.Enabled)
Add-Member -InputObject $UserObj -MemberType NoteProperty -Name "GivenName" -Value $($currentUser.GivenName)
Add-Member -InputObject $UserObj -MemberType NoteProperty -Name "UserName" -Value $($currentUser.Name)
Add-Member -InputObject $UserObj -MemberType NoteProperty -Name "PasswordExpired" -Value $($currentUser.PasswordExpired)
Add-Member -InputObject $UserObj -MemberType NoteProperty -Name "PasswordLastSet" -Value $($currentUser.PasswordLastSet)
Add-Member -InputObject $UserObj -MemberType NoteProperty -Name "SamAccountName" -Value $($currentUser.SamAccountName)
Add-Member -InputObject $UserObj -MemberType NoteProperty -Name "Surname" -Value $($currentUser.Surname)
#saves the properties in an array that exists outside of the loop to preserve information beyond one interation
$users += $UserObj
}
$users | Format-Table -Property UserName,SamAccountName,EmailAddress
Is there a way to combine two arrays to a hashtable ?
$Name = Get-ChildItem C:\Users | Select-Object Name
$CreationTime = Get-ChildItem C:\Users | Select-Object CreationTime
$Table = New-Object psobject
foreach ($item in $Name) {
foreach ($item2 in $CreationTime) {
Add-Member -InputObject $Table -MemberType NoteProperty -Name $item -Value $item2 } }
If I simply print out $item and $item2 I get every result multiple times, I know that this is because of the nested foreachs.
The example above is not very good, i acutally would need this to import different csv files and create a hashtable to export them again.
Have a single for loop were you iterate through the first array with an index. Assuming the same index in both arrays gives the correct pair, add the pair to the hashtable. No need for nested loops.
Some Pseudo code:
for ($i = 0; $i < $Name.length; $i++) {
Add-Member -Name $Name[$i] -Value $CreationTime[$i]
}
What I requested would look something like this:
$Name = Get-ChildItem C:\Users | Select-Object Name
$CreationTime = Get-ChildItem C:\Users | Select-Object CreationTime
$Table = New-Object psobject
$i = 0
do {
Add-Member -InputObject $Table -MemberType NoteProperty -Name $Name[$i].Name -Value $CreationTime[$i].CreationTime
$i++ }
while ($i -ne $name.Length)
$Table
However, this solution is more like what I wanted:
$Name = Get-ChildItem C:\Users | Select-Object Name
$CreationTime = Get-ChildItem C:\Users | Select-Object CreationTime
$TableData =#()
$i = 0
do {
$Table = New-Object psobject
Add-Member -InputObject $Table -MemberType NoteProperty -Name "FolderName:" -Value $Name.Name[$i]
Add-Member -InputObject $Table -MemberType NoteProperty -Name "Creation Time:" -Value $CreationTime.CreationTime[$i]
$TableData += $Table
$i++ }
while ($i -ne $name.Length)
$TableData | Export-csv -Delimiter ";" -Path $PSScriptRoot\out.csv -NoTypeInformation
Sorry for being unspecific! Is there an easier way to do this ?
I am looking to create either a non-jagged array or a hash table (I am not sure the difference nor what I need to get the job done). Here is what I am trying to do.
I would like to query a list of servers for several values and then store those values for output to a CSV file. Here is the code.
$allServers = "svr1","svr2","svr3"
$a = #{}
$outData = New-Object PSObject
$allServers | ForEach-Object {
$cpu = (Get-WmiObject win32_processor -ComputerName $_).length
$mem = (Get-WmiObject win32_physicalmemory -ComputerName $_).Capacity /1GB
$outData | Add-Member -Type NoteProperty -Name "SERVERNAME" -Value $_
$outData | Add-Member -Type NoteProperty -Name "#CPU" -Value $cpu
$outData | Add-Member -Type NoteProperty -Name "#GBRAM" -Value $mem
}
Write-Host $outData
I am getting errors because it seems like it is trying to create the same entries repeatedly. Is it possible to make an empty hash table (or non-jagged array) with column names and then just populate values?
Create the object inside the loop, output it, and assign the value of the whole pipeline to your array variable:
$allServers = "svr1","svr2","svr3"
$a = $allServers | ForEach-Object {
$cpu = (Get-WmiObject win32_processor -ComputerName $_).length
$mem = (Get-WmiObject win32_physicalmemory -ComputerName $_).Capacity /1GB
$outData = New-Object PSObject
$outData | Add-Member -Type NoteProperty -Name "SERVERNAME" -Value $_
$outData | Add-Member -Type NoteProperty -Name "#CPU" -Value $cpu
$outData | Add-Member -Type NoteProperty -Name "#GBRAM" -Value $mem
$outData
}
$a | Export-Csv $path -NoTypeInformation
Im trying to genreate a report for NIc Card info using powershell, & use add member to append the properties, but if a server is having more than 1 NIC, add members return an error "Do you want to owerwrite property" Use -force, could any one please help me to sort out the issue, also im having an array $output=#() into which im appending all these inputs,i Tried adding a for loop to get the no of NICS & iterate thru them one by one as an array, i see no output, can some one help me.
<#NIC card info Check#>
$colItems1 = get-wmiobject -class "Win32_NetworkAdapter" -namespace "root\CIMV2" -computername $compname
$colItems = get-wmiobject -class "Win32_NetworkAdapterconfiguration" -namespace "root\CIMV2" -computername $compname
$lengthcol=($colItems1).length
for ($i=0;$i-lt$length;$i++){
foreach ($objitem in $colItems)
{
# Match the current $objItem with the correct $ColItems1 element.
$objItem1 = $colItems1| where-object{$_.Caption -eq $objItem.Caption}
# A test is needed here as the loop will find a number of virtual network configurations with no "Hostname"
# So if the "Hostname" does not exist, do NOT display it!
if ($objItem.ipenabled -eq "true" -and $objitem1.netconnectionid) {
# Write to screen
#write-host "Caption: " $objItem.Caption
$nicname[$i]=$objitem1.netconnectionid
$dhcpenabled[$i]=$objItem.DHCPEnabled
$ipaddress[$i]=$objItem.IPAddress
$ipsubnet[$i]=$objItem.IPSubnet
$gateway[$i]=$objItem.DefaultIPGateway
$dhcpserver[$i]=$objItem.DHCPServer
$DNSDomain[$i]=$objItem.DNSDomain
$DNSDomainSearchOrder[$i]=$objItem.DNSDomainSuffixSearchOrder
$DNSServerSearchOrder[$i]=$objItem.DNSServerSearchOrder
$output | Add-Member -MemberType Noteproperty -Name NICCardName[$i] -Value $nicname[$i]
$output | Add-Member -MemberType Noteproperty -Name DHCPEnabled[$i] -Value $dhcpenabled[$i]
$output | Add-Member -MemberType Noteproperty -Name IPAddress[$i] -Value $ipaddress[$i]
$output | Add-Member -MemberType Noteproperty -Name SubnetMask[$i] -Value $ipsubnet[$i]
$output | Add-Member -MemberType Noteproperty -Name Gateway[$i] -Value $gateway[$i]
$output | Add-Member -MemberType Noteproperty -Name DHCPServer[$i] -Value $dhcpserver[$i]
$output | Add-Member -MemberType Noteproperty -Name DNSDomain[$i] -Value $DNSDomain[$i]
$output | Add-Member -MemberType Noteproperty -Name DNSDomainSuffixSearchOrder[$i] -Value $DNSDomainSearchOrder[$i]
$output | Add-Member -MemberType Noteproperty -Name DNSServerSearchOrder[$i] -Value $DNSServerSearchOrder[$i]
}
}
}
$outputs+=$output
Try this:
Get-WmiObject Win32_NetworkAdapter -ComputerName $computer| ForEach-Object {
$NetConnectionId = $_.NetConnectionId
$nac = $_.GetRelated('Win32_NetworkAdapterconfiguration') | Select-Object IPEnabled,DHCPEnabled,IPAddress,IPSubnet,DefaultIPGateway,DHCPServer,DNSDomain,DNSDomainSuffixSearchOrder,DNSServerSearchOrder
$nac | Select-Object *,#{Name='NetConnectionId';Expression={$NetConnectionId}}
}
UPDATE (per poster request):
$compname='.'
$colItems1 = get-wmiobject -class Win32_NetworkAdapter -computername $compname
$colItems = get-wmiobject -class Win32_NetworkAdapterconfiguration -computername $compname
foreach ($objitem in $colItems)
{
$objItem1 = $colItems1 | where-object{$_.Caption -eq $objItem.Caption}
if ($objItem.ipenabled -eq $true -and $objitem1.netconnectionid)
{
$output = new-object -typename psobject
$output | Add-Member -MemberType Noteproperty -Name NICCardName -Value $objitem1.netconnectionid
$output | Add-Member -MemberType Noteproperty -Name DHCPEnabled -Value $objItem.DHCPEnabled
$output | Add-Member -MemberType Noteproperty -Name IPAddress -Value $objItem.IPAddress
$output | Add-Member -MemberType Noteproperty -Name SubnetMask -Value $objItem.IPSubnet
$output | Add-Member -MemberType Noteproperty -Name Gateway -Value $objItem.DefaultIPGateway
$output | Add-Member -MemberType Noteproperty -Name DHCPServer -Value $objItem.DHCPServer
$output | Add-Member -MemberType Noteproperty -Name DNSDomain -Value $objItem.DNSDomain
$output | Add-Member -MemberType Noteproperty -Name DNSDomainSuffixSearchOrder -Value $objItem.DNSDomainSuffixSearchOrder
$output | Add-Member -MemberType Noteproperty -Name DNSServerSearchOrder -Value $objItem.DNSServerSearchOrder -PassThru
}
}