Remove tab/extra spaces on powershell output - powershell

I've put together a simple script to output a list of computers that are members of AD groups for WSUS Patching. The problem is that when I use this list of computer names to compare in Excel, there are a load of spaces/tab in the results. I don't want to have to manually edit the results, so I was wondering if there was a more graceful way to do this within the script?
$groups = Get-Content D:\WSUS\grouplist.txt
$result =#()
foreach($group in $groups){$result += Get-ADGroupMember $Group | select name}
$result | Out-File D:\WSUS\WSUS-All-AD-Members.txt
I've had a look at other options, but can't seem to get something that works.
Thanks a lot

Fixed it, added the -ExpandProperty option....
$groups = Get-Content D:\WSUS\grouplist.txt
$result =#()
foreach($group in $groups){$result += Get-ADGroupMember $Group | select -ExpandProperty name}
$result | Out-File D:\WSUS\WSUS-All-AD-Members.txt

Related

get-adgroupmember inconsistently returns group members

I've been writing powershell since powershell 2, and I've run into something odd I've never seen before.
$groups = get-adgroup -filter {name -like 'SomeGroup*'} | select name | sort name
foreach ($group in $groups){
$groupsid = $group.name
write-host $groupsid
Get-ADGroupMember $groupsid | select name | sort name
write-host "`n`n"
}
The get-adgroupmember in the foreach loop is only enumerating members in certain groups and not in others.
If "$groupsid" = "DeveloperGroup" and I use
get-adgroupmember DeveloperGroup | select name | sort name in the shell,
then I get back what I expected to see: a list of group members. But for several groups that are enumerated by the first line, I get nothing back when the exact same cmdlet is executed within the foreach loop. I know some of the cmdlets are still a little buggy, just no idea why this is being intermittent in what the loop decides to fetch.
I have edited few lines of your cmdlet and it is working fine for me. Please use the below formatted PowerShell command to get your desire output.
$groups = get-adgroup -filter {name -like 'Group*'} | sort name
$results = foreach ($group in $groups) {
Get-ADGroupMember $group | select samaccountname, name, #{n='GroupName';e={$group}}, #{n='Description';e={(Get-ADGroup $group -Properties description).description}} | sort name
}
$results
$results | Export-csv C:\GroupMemberShip.txt -NoTypeInformation
#Doug Maurer comment is helpful and may be part of the issue.
Another problem: avoid using the name of the group.
Either use the group object directly as input of the Get-ADGroupMember cmdlet like below, or use the DistinguishedName property of the group.
foreach ($group in $groups){
Get-ADGroupMember $group | select name | sort name
write-host "`n`n"
}

How to pipe results of a foreach loop to an output file?

I have the following code that gets usernames from a list and then retrieves their emails.
I'd like to have this outputted to eventually send automatic emails to these specific addresses.
With the code below, only the last object in the text file is recorded in the outfile.
$users = (get-content c:\temp\Fredro.txt)
foreach ($EUT in $users) {
Get-ADUser -Identity $EUT | Select-Object UserPrincipalName | Out-File -filepath C:\temp\exomailinglist.txt}
How to pipe results of a foreach loop to an output file?
You are overwriting the file on every pass through your foreach loop if an ADUser is found. As Abraham Zinala mentioned in comments if you were to add -Append to the Out-File cmdlet this would solve your problem of the file only containing the last item. I would also recommend adding -ExpandProperty to Select-Object to avoid having the header "UserPrincipalName" also added to the file each time.
$users = (Get-Content c:\temp\Fredro.txt)
foreach ($EUT in $users) {
Get-ADUser -Identity $EUT |
Select-Object -ExpandProperty UserPrincipalName |
Out-File -FilePath C:\temp\exomailinglist.txt -Append
}
Rather than writing to the file in the foreach loop for each user though I would instead recommend to capture all ADUsers first and then write all of the items at once to the file, possibly like this:
$users = (Get-Content c:\temp\Fredro.txt)
$adUsers = foreach ($EUT in $users) {
Get-ADUser -Identity $EUT |
Select-Object -ExpandProperty UserPrincipalName
}
$adUsers | Out-File -FilePath C:\temp\exomailinglist.txt
And lastly, the best option in my opinion, combine it all into one pipeline which would look like this.
Get-Content c:\temp\Fredro.txt |
Get-ADUser |
Select-Object -ExpandProperty UserPrincipalName |
Out-File -FilePath C:\temp\exomailinglist.txt
This method would avoid the foreach loop completely. Get-ADUser accepts Identity from the pipeline byvalue so we can just pipe each line from Get-Content directly. Out-File will wait on all items from the pipeline before writing to the file.

PowerShell to pull all empty DLs with no members

I am hoping someone can help me here. I was able, thanks to help of Google, find a PowerShell script online that displayed all empty DLs in our environment since we are trying to do a cleanup. Here is that script:
Get-DistributionGroup -ResultSize Unlimited |? {!(Get-DistributionGroupMember $_.PrimarySMTPAddress).Count} | select DisplayName,PrimarySMTPAddress | Export-Csv DLsToRemove3.csv
I added an Export-Csv to it in order to get the list into a file. I started looking through the list and noticed that some of the DLs listed actually have one member in them. At this point I tried to run another script against my CSV file to get a list of any if the DLs with one member in it and the that one member. Here is that script:
Import-Csv "C:\Users\177626\DLsToRemove3.csv" | foreach {$Group=$_.PrimarySmtpAddress; Get-DistributionGroupMember -Identity $Group | select #{Name="Group";Expression={$Group}}, DisplayName | Export-Csv Members.csv -NoType}
When I ran that, there was no information at all populating in my CSV. I am looking for help with either being able to add the second step to the first step and combine both scripts into one or at least being able to get the second script to work to view the DLs with that one member in them.
Thanks!
This never failed me to get the empty DL's
$emptyGroups = foreach ($grp in Get-DistributionGroup -ResultSize Unlimited) {
if (#(Get-DistributionGroupMember –Identity $grp.DistinguishedName -ResultSize Unlimited).Count –eq 0 ) {
[PsCustomObject]#{
DisplayName = $grp.DisplayName
PrimarySMTPAddress = $grp.PrimarySMTPAddress
DistinguishedName = $grp.DistinguishedName
}
}
}
$emptyGroups | Export-Csv 'C:\Users\177626\DLsToRemove4.csv' -NoTypeInformation
The #() forces the Get-DistributionGroupMember results into an array to get an accurat .Count property
Try this instead.
Get-DistributionGroup -ResultSize Unlimited | ? { (Get-DistributionGroupMember $_.PrimarySMTPAddress | Measure-Object).Count -eq 0 } | select DisplayName,PrimarySMTPAddress | Export-Csv DLsToRemove3.csv
Measure-Object is more reliable when counting objects in an array.
There's the attribute msExchGroupMemberCount which is maintained by Exchange, so a quicker way is to filter on that attribute using get-adgroup.
get-adgroup -Filter "msExchGroupMemberCount -eq 0" -Properties DisplayName,mail | select DisplayName,mail

Powershell - create CSV of users with CRM licences who haven't logged in for more than 30 days

I'm trying to combine the output from two commandlets. I need to list all the users with a particular licence SKUID (CRMPLAN) who haven't logged in for over 30 days.
Is something along these lines even close?
$UserList = get-MSOLUser -All | where {$_.isLicensed -eq "TRUE" -and $_.Licenses.AccountSKUID -eq "Domain:CRMPLAN"}
$MasterList = #()
foreach ($DisplayName in $UserList) {
$MyObject = New-Object PSObject -Property #{
LastLogonTime = (Search-ADAccount -AccountInactive -TimeSpan 30.00:00:00 | where {$_.ObjectClass -eq 'user'} | FT Name,ObjectClass –A}).LastLogonTime
}
$MasterList += $MyObject
}
$MasterList | select displayname,IsLicenced,LastLogonTime - export-CSV C:\LastLogonDate.csv
Ok so right now your basically getting a list of users in $userList and then getting a list of ALL of the last logon times of users who have not logged in within the last 30 days for each of them and adding it to an array, then trying to do some selects on data that is not there since your only selecting the lastlogontime, which does not actually exist in AD. What you need to do instead is loop through them and check their lastlogondate to see if they have logged in within the last 30 days and then add their info to the array if they have not(you can also do this by collecting both arrays and then processing using group-object but that's a lot more tricky). You also have to remember that if the property you are selecting is not part of the object you are working with in the pipeline you will need to use an expression in your select to stuff it into the object
So your foreach loop would look something like this.
$masterList = #()
foreach($user in $userList){
$oldDate = (get-date).AddDays(-30)
$userObj = Get-ADUser -Identity $user.UserPrincipalName -Properties lastlogondate | Select-Object displayname,LastLogonDate,#{Name="IsLicensed"; Expression={$user.isLicensed}}
if($userObj.lastLogonDate -le $oldDate){
$masterList += $userObj
}
}
Finally make sure that when you do your export to use a pipe rather than a subtraction symbol. so your last line should look like
$masterlist | export-csv c:\tmp\lastlogondate.csv
Note that there is no need to do the select here since we have already done a select to get the data we need inside of the loop, also try to avoid placing files on the root of C:\, any machine with UAC enabled will throw permissions errors when trying to do that unless you are running as an admin, which is unneeded for this script. Hope this helps and please let me know if you have any questions.

Output data with no column headings using PowerShell

I want to be able to output data from PowerShell without any column headings. I know I can hide the column heading using Format-Table -HideTableHeaders, but that leaves a blank line at the top.
Here is my example:
get-qadgroupmember 'Domain Admins' | Select Name | ft -hide | out-file Admins.txt
How do I eliminate the column heading and the blank line?
I could add another line and do this:
Get-Content Admins.txt | Where {$_ -ne ""} | out-file Admins1.txt
But can I do this on one line?
In your case, when you just select a single property, the easiest way is probably to bypass any formatting altogether:
get-qadgroupmember 'Domain Admins' | foreach { $_.Name }
This will get you a simple string[] without column headings or empty lines. The Format-* cmdlets are mainly for human consumption and thus their output is not designed to be easily machine-readable or -parseable.
For multiple properties I'd probably go with the -f format operator. Something along the lines of
alias | %{ "{0,-10}{1,-10}{2,-60}" -f $_.COmmandType,$_.Name,$_.Definition }
which isn't pretty but gives you easy and complete control over the output formatting. And no empty lines :-)
A better answer is to leave your script as it was. When doing the Select name, follow it by -ExpandProperty Name like so:
Get-ADGroupMember 'Domain Admins' | Select Name -ExpandProperty Name | out-file Admins.txt
If you use "format-table" you can use -hidetableheaders
add the parameter -expandproperty after the select-object, it will return only data without header.
The -expandproperty does not work with more than 1 object. You can use this one :
Select-Object Name | ForEach-Object {$_.Name}
If there is more than one value then :
Select-Object Name, Country | ForEach-Object {$_.Name + " " + $Country}
Joey mentioned that Format-* is for human consumption. If you're writing to a file for machine consumption, maybe you want to use Export-*? Some good ones are
Export-Csv - Comma separated value. Great for when you know what the columns are going to be
Export-Clixml - You can export whole objects and collections. This is great for serialization.
If you want to read back in, you can use Import-Csv and Import-Clixml. I find that I like this better than inventing my own data formats (also it's pretty easy to whip up an Import-Ini if that's your preference).
First we grab the command output, then wrap it and select one of its properties. There is only one and its "Name" which is what we want. So we select the groups property with ".name" then output it.
to text file
(Get-ADGroupMember 'Domain Admins' |Select name).name | out-file Admins1.txt
to csv
(Get-ADGroupMember 'Domain Admins' |Select name).name | export-csv -notypeinformation "Admins1.csv"
$server = ('*')+(Read-Host -prompt "What Server Context?")+'*'
$Report = (Get-adcomputer -SearchBase "OU=serverou,DC=domain,DC=com" -filter {name -like $server} -SearchScope Subtree|select Name |Sort -Unique Name)
$report.Name | Out-File .\output\out.txt -Encoding ascii -Force
$Report
start notepad .\output\out.txt
Put your server SearchBase in above.
If you are not sure what your server OU is try this function below...
#Function Get-OSCComputerOU($Computername)
{
$Filter = "(&(objectCategory=Computer)(Name=$ComputerName))"
$DirectorySearcher = New-Object System.DirectoryServices.DirectorySearcher
$DirectorySearcher.Filter = $Filter
$SearcherPath = $DirectorySearcher.FindOne()
$DistinguishedName = $SearcherPath.GetDirectoryEntry().DistinguishedName
$OUName = ($DistinguishedName.Split(","))[1]
$OUMainName = $OUName.SubString($OUName.IndexOf("=")+1)
# $Obj = New-Object -TypeName PSObject -Property #{"ComputerName" = $ComputerName
# "BelongsToOU" = $OUMainName
# "Full" = $DistinguishedName}
$Obj = New-Object -TypeName PSObject -Property #{"Full" = $DistinguishedName}
$Obj
}
Makes sure to run the Get-OSCComputerOU Servername with a select -expandproperty Full filter.
Then just plug in the response to the Searchbase...
All thanks to http://www.jaapbrasser.com