How do I add the value of $i as a new parameter to the object so that if $i is part of distinguishedName?
param([string[]]$Country="Norway,Denmark")
foreach ($i in $Country)
{
$users += Get-ADUser -searchbase "ou=$i,ou=FMS,dc=ce,dc=xxxx,dc=net" -ldapfilter $ldapfilter -properties CN,SamAccountName,mail,title,department,company,pager,employeeNumber,distinguishedName,extensionAttribute12
$users | Add-Member -MemberType NoteProperty -Name "OOU" -Force -Value ""
{missing code to add $i as value for property .OOU}
}
$users | Add-Member -MemberType NoteProperty -Name "license" -Force -Value ""
$users | where extensionAttribute12 -Like "*EOP1*" | %{$_.license="EOP1"}
$users | where extensionAttribute12 -Like "*E1*" | %{$_.license="E1"}
$users | where extensionAttribute12 -Like "*E3*" | %{$_.license="E3"}
I have tried to do the same as with the where clause in the bottom part, but the foreach loop makes it overwrite all values with the last member of $i
Use the -Value parameter to specify the initial value of a new property:
$users | Add-Member -MemberType NoteProperty -Name "OOU" -Force -Value $i
To avoid re-assigning the newest values to all the existing users that have already received their new OOP property, use an intermediary variable to hold the output from Get-ADUser:
foreach ($i in $Country)
{
$country_users = Get-ADUser -searchbase "ou=$i,ou=FMS,dc=ce,dc=xxxx,dc=net" -ldapfilter $ldapfilter -properties CN,SamAccountName,mail,title,department,company,pager,employeeNumber,distinguishedName,extensionAttribute12
$users += #($country_users | Add-Member -MemberType NoteProperty -Name "OOU" -Force -Value $i)
}
Related
Is it possible to adjust this code to export all lines outside foreach loop:
This works fine (inside loop):
$vms = Get-VM | Where { $_.State –eq ‘Running’ } | Select-Object -ExpandProperty Name
foreach($vm in $vms) {
# Get network interface details
$out = Get-VMNetworkAdapter -vmname $vm | select VMName, MacAddress, IPAddresses
$vm_name = $out.VMName | Get-Unique
$ip = ($out.IPAddresses | ForEach-Object {
$_ | ? {$_ -notmatch ':'}
}) -join " "
# If more than 1 MAC , put it in same row separated by space (00:15:5D:58:12:5E 00:15:5D:58:12:5F )
$mac = ($out.MacAddress | ForEach-Object {
$_.Insert(2,":").Insert(5,":").Insert(8,":").Insert(11,":").Insert(14,":")
}) -join ' '
$results = #()
$comp = Get-WmiObject Win32_ComputerSystem | Select-Object -ExpandProperty name
$obj = New-Object -TypeName psobject
$obj | Add-Member -MemberType NoteProperty -Name "VM NAME" -Value $vm_name
$obj | Add-Member -MemberType NoteProperty -Name "IP ADDRESS" -Value $ip
$obj | Add-Member -MemberType NoteProperty -Name "MAC ADDRESS" -Value $mac
$obj | Add-Member -MemberType NoteProperty -Name "HYPER-V HOST" -Value $comp
$results += $obj
Write-Output $results
$results| Export-Csv -Path "c:\1.csv" -NoTypeInformation -append
}
However, when i move $results| Export-Csv -Path "c:\1.csv" -NoTypeInformation -append outside loop,
only one (last) line is saved to CSV
Inside loop, $results variable contains all lines, when i move this variable outside loop write-host $results only one (last) line is printed
For what it's worth, your code can be condensed quite a bit. Many of your steps are not necessary:
$results = Get-VM | Where State –eq Running | Get-VMNetworkAdapter | ForEach-Object {
[pscustomobject]#{
'VM NAME' = $_.VMName
'IP ADDRESS' = ($_.IPAddresses -notmatch ':') -join ' '
'MAC ADDRESS' = ($_.MacAddress -replace '(..)(..)(..)(..)(..)','$1:$2:$3:$4:$5:') -join ' '
'HYPER-V HOST' = $env:COMPUTERNAME
}
}
$results | Export-Csv -Path "c:\1.csv" -NoTypeInformation
Notes:
You can pipe the VMs that Get-VM returns directly into Get-VMNetworkAdapter
If you filter on a single property you don't need a script block for Where-Object. Where State -eq Running is a bit easier to write and read than Where { $_.State -eq 'Running' }.
$_.IPAddresses -notmatch ':' Operators like -notmatch work on arrays. 'a','b','0','c' -notmatch '\d' will return 'a','b','c'.
The same goes for -replace. 'a0','b1','c2' -replace '\d','' will return return 'a','b','c'. No foreach loops necessary at all.
$env:COMPUTERNAME should be faster than using WMI to get the computer name
Any object you create in a script block (like the ForEach-Object {...} script block) that you do not assign to a variable will be in the script block's output. This is why $results = ... | ForEach-Object {...} works. There is no need to explicitly create arrays with #() and add values to them.
Casting a hash table to [pscustomobject] is much easier than using Add-Member.
Figured it out:
moved $results variable outside loop (make it "global")
$vms = Get-VM | Where { $_.State –eq ‘Running’ } | Select-Object -ExpandProperty Name
$results = #()
foreach($vm in $vms) {
# Get network interface details
$out = Get-VMNetworkAdapter -vmname $vm | select VMName, MacAddress, IPAddresses
# Remove duplicate VM names
$vm_name = $out.VMName | Get-Unique
# In case more than 1 IP, put it in same row separated by space (192.168.1.1, 192.168.1.2)
$ip = ($out.IPAddresses | ForEach-Object {
$_ | ? {$_ -notmatch ':'}
}) -join " "
# If more than 1 MAC , put it in same row separated by space (00:15:5D:58:12:5E 00:15:5D:58:12:5F )
$mac = ($out.MacAddress | ForEach-Object {
$_.Insert(2,":").Insert(5,":").Insert(8,":").Insert(11,":").Insert(14,":")
}) -join ' '
$comp = Get-WmiObject Win32_ComputerSystem | Select-Object -ExpandProperty name
$obj = New-Object -TypeName psobject
$obj | Add-Member -MemberType NoteProperty -Name "VM NAME" -Value $vm_name
$obj | Add-Member -MemberType NoteProperty -Name "IP ADDRESS" -Value $ip
$obj | Add-Member -MemberType NoteProperty -Name "MAC ADDRESS" -Value $mac
$obj | Add-Member -MemberType NoteProperty -Name "HYPER-V HOST" -Value $comp
$results += $obj
}
$results| Export-Csv -Path "c:\1.csv" -NoTypeInformation
I want to migrate from one server to another one and because of that it is needed to add some local groups in the new server. In these local groups the users added belong to the domain.
Ex.:
Server | Members
---------------------------|------------------
Server\Group1 | Domain\User1, Domain\User2
Server\Group2 | Domain\User2, Domain\User3
The following link https://www.petri.com/use-powershell-to-find-local-groups-and-members seems to resolve this, but I am getting an unexpected result
This is the PowerShell script
# set variables
$server = $env:COMPUTERNAME
$localgroup = "Administrators"
$Group= [ADSI]"WinNT://$Server/$LocalGroup,group"
# get users name
$members = $Group.psbase.Invoke("Members")
$members | ForEach-Object
{
$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)
}
Get-WMIObject win32_group -filter "LocalAccount='True'" -computername $Server | Select PSComputername,Name,#{Name="Members";Expression={$_.GetRelated("Win32_UserAccount").Name -join ";"}}
The shown output is a two columns(although it should be 3, but PSComputerName is not being displayed where the Members column is empty)
Well, this is how I achieved the output and also exported it to a *.csv file
# set variables
$server = $env:COMPUTERNAME
$tableOutput = New-Object System.Collections.ArrayList
# get members
Function Get-Members($groupName){
$testgroup = [ADSI]"WinNT://$Server/$tmpGroupName,group"
$members = New-Object System.Collections.ArrayList
$testgroup.psbase.Invoke("Members") | ForEach-Object{
$searchFilter = $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null) -replace "\."," "
$tmpUser = Get-ADUser -Filter {(Name -like $searchFilter) -or (SamAccountName -like $searchFilter)}
if($tmpUser){
[void]$members.Add($tmpUser.UserPrincipalName)
}
}
$members
}
Get-WMIObject win32_group -Filter { (LocalAccount='True') } -computername $Server | ForEach-Object{
$tmpGroup = $_
# get data
$tmpGroupName = $tmpGroup.Name
$members = Get-Members($tmpGroupName)
$tmpGroupDescription = $tmpGroup.Description
# save into object
$groupObject = New-Object -TypeName PSObject
$groupObject | Add-Member -MemberType NoteProperty -Name GroupName -Value $tmpGroupName
$groupObject | Add-Member -MemberType NoteProperty -Name GroupDescription -Value $tmpGroupDescription
$groupObject | Add-Member -MemberType NoteProperty -Name UsersList -Value $members
[void]$tableOutput.Add($groupObject)
}
$tableOutput | Select GroupName, GroupDescription, #{Name='Users';Expression={$_.UsersList -join ','}} | Export-CSV -Path 'C:\test\users.csv' -Delimiter ';' -NoTypeInformation
Any correction would be appreciated.
below code when inputting a few users, but fails is not returning expected results when querying for all users in AD. Not understanding why it's failing on bulk users versus a relatively small user list
Code below:
$Users = #('user1',"user2",'user3','user4')
$Mailboxes = $Users | Get-ADuser -pr *
$OU = 'DC=local,DC=local,DC=org'
$Mailboxes = Get-ADUser -Filter {SamAccountName -notlike '*$*'} -pr samaccountname
$Mailboxes = Get-ADUser -Filter * -SearchBase $OU -Properties samaccountname
foreach ($Mbx in $Mailboxes)
{
$ADUser = Get-ADUser $Mbx.SamAccountName -Properties * #Enabled,AccountExpirationDate
$UserObj = New-Object PSObject
$UserObj | Add-Member NoteProperty -Name "Username" -Value $ADUser.SamAccountName
If($mbx.msExchRecipientTypeDetails -eq $null)
{
$UserObj | Add-Member NoteProperty -Name "E-Mail" -Value "NoEmailAddress"
$UserObj | Add-Member NoteProperty -Name "email ItemCount" -Value "NoMailBox"
$UserObj | Add-Member NoteProperty -Name "TotalItemSize(GB)" -Value "NoMailBox"
Write-Host $Mbx.SamAccountName "has no mailbox" -ForegroundColor green
}
Else
{
If($mbx.msExchRecipientTypeDetails -eq 1)
{
$stats = $Mbx.EmailAddress | Get-MailboxStatistics | Select-Object TotalItemSize,TotalDeletedItemSize,ItemCount,LastLogonTime,LastLoggedOnUserAccount
$MbxSizeb = $stats.TotalItemSize -replace "(.*\()|,| [a-z]*\)"
$Tmp_gb = $MbxSizeb/1GB
$MbxSizeGB = [math]::Round($Tmp_gb,2)
$UserObj | Add-Member NoteProperty -Name "E-Mail" -Value $ADUser.EmailAddress
$UserObj | Add-Member NoteProperty -Name "email ItemCount" -Value $stats.ItemCount
$UserObj | Add-Member NoteProperty -Name "TotalItemSize(GB)" -Value $MbxSizeGB
}
}
$Report = $Report += $UserObj
}
Results with selected users
enter image description here
Results against all users:
enter image description here
You are missing the property msExchRecipientTypeDetails when populating the $Mailboxes variable. Lines 5 and 6 should read -Properties msExchRecipientTypeDetails
Update: So this wasn't completely correct. You can use your code if you change If($mbx.msExchRecipientTypeDetails -eq $null) to If($aduser.msExchRecipientTypeDetails -eq $null). However, you really don't need to get the ADUser again. $Mailboxes is a collection of ADUsers. Changes lines 2,6,7 to -Properties EmailAddress,msExchRecipientTypeDetails,SamAccountName
$Users = #('user1',"user2",'user3','user4')
$Mailboxes = $Users | Get-ADuser -Properties EmailAddress,msExchRecipientTypeDetails,SamAccountName
#$OU = 'DC=local,DC=local,DC=org'
#$Mailboxes = Get-ADUser -Filter {SamAccountName -notlike '*$*'} -Properties EmailAddress,msExchRecipientTypeDetails,SamAccountName
#$Mailboxes = Get-ADUser -Filter * -SearchBase $OU -Properties EmailAddress,msExchRecipientTypeDetails,SamAccountName
$Report = #()
foreach ( $Mbx in $Mailboxes ) {
switch ( $Mbx.msExchRecipientTypeDetails ) {
1 {
$Stats = $Mbx.EmailAddress | Get-MailboxStatistics | Select-Object TotalItemSize,ItemCount
$Report += [pscustomobject] #{
'Username' = $_.SamAccountName
'E-Mail' = $Mbx.EmailAddress
'E-Mail ItemCount' = $Stats.ItemCount
'TotalItemSize(GB)' = ( [math]::Round( ( $Stats.TotalItemSize -replace "(.*\()|,| [a-z]*\)" )/1GB ),2 )
}
break
}
default {
$Report += [pscustomobject] #{
'Username' = $_.SamAccountName
'E-Mail' = 'NoEmailAddress'
'E-Mail ItemCount' = 'NoMailBox'
'TotalItemSize(GB)' = 'NoMailBox'
}
break
}
}
}
#Shawn Esterman - thanks for the input -- below code works like a charm. Explicitly stated properties to search on.
cls
$Users = #()
$Report = #()
$UserObj = #()
$ADUser = #()
$Mbx = #()
$OU = #()
$Mailboxes = #()
$Users = #("user1",'user2','user3','user4','user5')
$Mailboxes = $Users | Get-ADuser -Properties EmailAddress,msExchRecipientTypeDetails,SamAccountName
$OU = 'DC=local,DC=local,DC=local'
$Mailboxes = Get-ADUser -SearchBase $OU -Filter {SamAccountName -notlike '*$*'} -ResultSetSize 50 -Properties EmailAddress,msExchRecipientTypeDetails,SamAccountName
foreach ($Mbx in $Mailboxes)
{
$UserObj = New-Object PSObject
$UserObj | Add-Member NoteProperty -Name "Username" -Value $Mbx.SamAccountName
If($mbx.msExchRecipientTypeDetails -eq $null)
{
$UserObj | Add-Member NoteProperty -Name "E-Mail" -Value "NoEmailAddress"
$UserObj | Add-Member NoteProperty -Name "email ItemCount" -Value "NoMailBox"
$UserObj | Add-Member NoteProperty -Name "TotalItemSize(GB)" -Value "NoMailBox"
Write-Host $Mbx.SamAccountName "has no mailbox" -ForegroundColor green
}
Else
{
If($mbx.msExchRecipientTypeDetails -eq 1)
{
$stats = $Mbx.EmailAddress | Get-MailboxStatistics | Select-Object TotalItemSize,TotalDeletedItemSize,ItemCount,LastLogonTime,LastLoggedOnUserAccount
$MbxSizeb = $stats.TotalItemSize -replace "(.*\()|,| [a-z]*\)"
$Tmp_gb = $MbxSizeb/1GB
$MbxSizeGB = [math]::Round($Tmp_gb,2)
$UserObj | Add-Member NoteProperty -Name "E-Mail" -Value $Mbx.EmailAddress
$UserObj | Add-Member NoteProperty -Name "email ItemCount" -Value $stats.ItemCount
$UserObj | Add-Member NoteProperty -Name "TotalItemSize(GB)" -Value $MbxSizeGB
}
}
$Report = $Report += $UserObj
}
Hi I am trying to run a script to get users in a network into an array so that it can be outputted to a csv file along with other data that I am going to get, such as distribution groups.
The code script I am running is giving an error:
Method invocation failed because [System.Management.Automation.PSObject] doesn't contain a method named 'op_Addition'.
The script is a simple for loop:
$ActiveDirectoryList=#()
$UserDetails = get-aduser -filter {enabled -eq $true} -properties * | Select DisplayName,EmailAddress, SAMAccountName
$counter = 0
foreach($User in $UserDetails){
$ActiveDirectoryList = New-Object PSObject
$Users = get-aduser $User.SAMAccountName -properties *
if(!$Users.EmailAddress -eq ""){
$counter++
$ActiveDirectoryList | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value $Users.DisplayName
$ActiveDirectoryList | Add-Member -MemberType NoteProperty -Name "Email Address" -Value $Users.EmailAddress
write-host $Users.DisplayName
$ActiveDirectoryList+=$ActiveDirectoryList
}
}
Tried looking on the internet for a solution but they don't seem to solve anything.
Don't reuse the same variable name for the array, and the individual objects that you want to add to the array. Here I've renamed the PSObject variable to $ActiveDirectoryObject:
$ActiveDirectoryList=#()
$UserDetails = get-aduser -filter {enabled -eq $true} -properties * | Select DisplayName,EmailAddress, SAMAccountName
$counter = 0
foreach($User in $UserDetails){
$ActiveDirectoryObject = New-Object PSObject
$Users = get-aduser $User.SAMAccountName -properties *
if(!$Users.EmailAddress -eq ""){
$counter++
$ActiveDirectoryObject | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value $Users.DisplayName
$ActiveDirectoryObject | Add-Member -MemberType NoteProperty -Name "Email Address" -Value $Users.EmailAddress
write-host $Users.DisplayName
$ActiveDirectoryList += $ActiveDirectoryObject
}
}
Additional Note: This can also occur if you don't declare the array as an array or mistype it when you declare it. Simple little error. But, maybe it will help someone that comes here and still can't get it resolved. Check your array variable name declaration carefully.
# Example 1 of how you could unintentionally fubar it.
$ActiveDirectoryList=$null
# Example 2 of how you could unintentionally fubar it.
$ActiveDirectoryList_ExaggeratedExampleWrongName=#()
# Example 3. Same as 2 above, but not as easily identifiable type error
$ActiveDirectoryLists=#()
$UserDetails = get-aduser -filter {enabled -eq $true} -properties * | Select DisplayName,EmailAddress, SAMAccountName
$counter = 0
foreach($User in $UserDetails){
$ActiveDirectoryObject = New-Object PSObject
$Users = get-aduser $User.SAMAccountName -properties *
if(!$Users.EmailAddress -eq ""){
$counter++
$ActiveDirectoryObject | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value $Users.DisplayName
$ActiveDirectoryObject | Add-Member -MemberType NoteProperty -Name "Email Address" -Value $Users.EmailAddress
write-host $Users.DisplayName
$ActiveDirectoryList += $ActiveDirectoryObject
}
}
+= kills puppies. (the whole array is copied every time)
$UserDetails = get-aduser -filter {enabled -eq $true} -properties |
Select DisplayName,EmailAddress, SAMAccountName
$counter = 0
$ActiveDirectoryList = foreach($User in $UserDetails){
$Users = get-aduser $User.SAMAccountName -properties *
if(!$Users.EmailAddress -eq ""){
$counter++
New-Object PSObject -property #{
Displayname = $Users.DisplayName
'Email Address' = $Users.EmailAddress
}
write-host $Users.DisplayName
}
}
This can be simplified to:
$ActiveDirectoryList = get-aduser -filter {enabled -eq $true -and
EmailAddress -like '*'} -properties Displayname,EmailAddress |
select Displayname,#{n='Email Address';e={$_.EmailAddress}}
I have a small script which retrieves the LastLogonTimestamp and the SAMAccount for all users in a particular OU in AD and converts the timestamp to a date and extracts just the date from the string. That part works fine. I then would like to output that to a CSV so it may be opened in Excel and be perfectly formated into columns and look all pretty.
I have tried ConvertTo-Csv and Export-Csv but have been uncuccessful. The problem is I am new to Powershell. This is my first script and I don't fully understand how this works. My script is probably terribly messy and illogical but it does the job so far.
Please help. Thanks.
$userlist = Get-ADUser -SearchBase "OU=IT,DC=whatever,DC=com,DC=au" -Filter * -Properties * | Select-Object -Property Name,LastLogonTimestamp,SAMAccountName | Sort-Object -Property Name
$userlist | ForEach-Object {
$last = $_.LastLogonTimestamp;
$ADName = $_.SAMAccountName;
$tstamp = w32tm /ntte $last;
if($tstamp.Length -lt "40"){}else
{
$ADDate = [DateTime]::Parse($tstamp.Split('-')[1]).ToString("dd/MM/yyyy")
write-host $ADDate;
write-host $ADName;
}
}
You will have to create objects for each user and pipe those to the Export-CSV cmdlet:
$usersList | %{
# current logic
$user = new-object psobject
$user | add-member -membertype noteproperty -name LastLogon -value $last
$user | add-member -membertype noteproperty -name ADName -value $ADName
$user | add-member -membertype noteproperty -name ADDate -value $ADDate
$user
} | export-csv test.csv -notype
Alternative syntax for populating the object:
$properties = #{"LastLogon" = $last; "ADName" = $ADName; "ADDate" = $ADDate}
$user = new-object psobject -property $properties