I am trying to get my script to do the following things:
- read a CSV script
- compare what is in the CSV script to AD
- Determine which of the accounts in the CSV are active in AD
- Put those results into a CSV in a designated folder
- Notify me when done via email (I know how to do this).
This is what I have:
Import-Csv -Path [path to csv]" | Foreach-Object { $PSItem | Get-Member } | Get-ADUser -Filter * -Searchbase "DC=xxx,DC=xxx" -Properties ipPhone,EmailAddress | Where-Object {$_.Enabled -eq $true} | Select-Object SAMAccountName,ipPhone,EmailAddress | Export-Csv -Path [export location] -NoTypeInformation
Any assistance is really appreciated. I've removed sensitive information due to confidentiality reasons.
Also, it works to print out all the enabled users in AD, but it is not comparing the imported CSV. I think the error is in the foreach-object line, but I cannot figure out how to fix it.
You do not show or explain what is in your Csv, thus leaving us to guess.
What do you mean by compare?
You have not compare code in this post. What you do have is a read of a Csv file and a create of a new Csv file of information relative to what you passed in. That is not a compare, that is an extract.
The cmdlet for compare is Compare-Object, yet, I don’t see how that will help you.
And why are you doing this…
$PSItem | Get-Member
… it has nothing to do with your end goal, and will bring back unnecessary information.
Get-Member is used for getting all properties and methods of an object, not anything specific about ADS or users. So, IMHO, get rid of that.
You have specific bullets as to what you are trying to accomplish, but you have not addressed them point by point t make sure you are getting the results and final outcome that you are after.
Ultimately, you really only have to end goals.
1 - Determine which of the accounts in the CSV are active in AD
2 - Put those results into a CSV in a designated folder
3 - Notify me when done via email
So …
1 – There are plenty of pre-built scripts / script samples that already do this on this MS powershellgallery.com that you can use as is and or tweak as needed.
2 – The script mentioned above, most of them already do this as well.
3 – Plenty of scripts that show how to do this as well.
Powershell Script to export Active Directory users to CSV
https://gallery.technet.microsoft.com/scriptcenter/Powershell-script-to-5edcdaea
1 – As for searching for disabled accounts, there is a cmdlet for that.
https://docs.microsoft.com/en-us/powershell/module/activedirectory/search-adaccount
https://ss64.com/ps/search-adaccount.html
As for …
Also, it works to print out all the enabled users in AD, but it is not comparing the imported CSV.
… that is because you are not writing and y compare code, and based on what you are after, it is really moot, as all you’d end up doing is this…
Compare-Object -ReferenceObject 'Input.csv' -DifferenceObject 'Output.csv'
See –
# get function / cmdlet details
(Get-Command -Name Compare-Object).Parameters
Get-help -Name Compare-Object -Examples
Get-help -Name Compare-Object -Full
Get-help -Name Compare-Object -Online
Yet, what you’d get back is that they are identical, because you are only going to get back what you passed in.
You are trying to pass collections on the pipeline, without iterating thru them. That's really not a thing.
Step back and rethink this, by taking your bullets one at a time.
since the full code has been asked for:
But I came here since I am relatively new to powershell coding. Didn't expect to get someone who was going to be so condescending about things. But this is the age of the internet.
Import-Csv -Path S:\threat_intelligence\scripts\"collection33.csv" | Foreach-Object { $PSItem | Get-Member } | Get-ADUser -Filter * -Searchbase "DC=xxx,DC=xxx" -Properties ipPhone,EmailAddress | Where-Object {$_.Enabled -eq $true} | Select-Object SAMAccountName,ipPhone,EmailAddress | Export-Csv -Path S:\threat_intelligence\scripts\Results -NoTypeInformation
Sine thus far I seem to be the only reply to your post, I can only that this…
“Didn't expect to get someone who was going to be so condescending about things. But this is the age of the internet.”
.. as directed at me.
At no point when I respond to anyone over the years I been in IT and work to help folks, have I ever made any effort to be condescending. I have no proclivities to do that and has no value to anyone in exchanges. However, what I do strive for is to states the facts and request information and clarity. If that comes off as condescending, then, mea culpa.
You say that …
“But I came here since I am relatively new to powershell coding”
… and that’s all well and good, and we all have been here / there. Yet, you should also spend some time ramping up before diving in, so, that you can limit any confusion, frustration, misconceptions you will encounter. Trust me you will find things that are really cool, and really frustrating, and you’d just have to work around the later. See the list of resources at the end of this post.
My points in my earlier response is that what you are doing is not valid, and because you did not show a sample of your csv, we’d have no idea what you are passing into your script and syntax-wise, it has some additional issues beyond the whole compare thing.
So, the questions / observations still stands.
Import-Csv -Path S:\threat_intelligence\scripts\"collection33.csv"
What is in this file, and single list of use names, as SamAccounts, or a multi-column file. Also, the double quotes are not in the right place. In your case, since you don’t have any spaces, or variables, they are not needed at all, or should be this..
Import-Csv -Path “S:\threat_intelligence\scripts\collection33.csv"
… or this
Import-Csv -Path S’:\threat_intelligence\scripts\collection33.csv’
You only need double quotes, when you need variable expansion, and or special formatting needs. Further this…
| Foreach-Object { $PSItem | Get-Member }
… if this is a single column, file, then this is fine for passing in that single column item. Yet, if this is a multi-column file, then this is not valid, and you have to specify the property name you want to use, and if you want all the other code to be in the loop for process, then that ForLoop is not correct.For example, it should be this:
Foreach-Object { $PSItem.UserName# Other code to run }
Doing things the what you have them, means that ForLoop will read the entire list before ever hitting the pipe, because you cannot send a collection down the pipe that way.
Event that means, your file has to have column names, or you have to add them on the import.
Import-Csv -Path S’:\threat_intelligence\scripts\collection33.csv’ -Header Name
PowerShell, will only match columns by PropertyName or by value, by design. However, this Get-Member, should not be used for this. Again, Get-Member return all properties and methods for a passed in object, not any values at all. So, it does not provide information about the user. You use Get-Member to only discover properties the you need to know about and methods you’d need to know about and may need to use, in order to get information.
| Get-ADUser -Filter * -Searchbase "DC=xxx,DC=xxx" -Properties ipPhone,EmailAddress
Here, you are asking for every user in ADDS, not the $PSItem, which I assume is a username only, which makes passing that in moot, since you are not using it at all.
| Where-Object {$_.Enabled -eq $true}
This is fine, since you are asking for all enabled users
| Select-Object SAMAccountName,ipPhone,EmailAddress This is fine, since you are only asking for these property values for all user in ADDS.
| Export-Csv -Path S:\threat_intelligence\scripts\Results -NoTypeInformationThis is fine as an export, but it’s again going to be for all users in ADDS only, because you are not using any code to address that $PSItem you passed at the beginning.
Also, your second posted code block would not run at all, because you have the pipe command to the left without a terminator before it. You need to use the ‘grave yard character often called a backtick. You will see many complain about it’s use, but I personally use it for line breaks because it’s quick, easy, and I prefer my pipes to be left aligned. Except when I am on project where the team is against it.
IF you are really trying to get only the users on the csv, you need to change this…
… to this (I took out the search base thing – just to keep it simple)
Import-Csv -Path 'C:\temp\TargetUsers.csv' `| Foreach-Object { Get-ADUser -Identity $_.UserName -Properties ipPhone,EmailAddress ` | Where-Object {$_.Enabled -eq $true} ` | Select-Object SAMAccountName,ipPhone,EmailAddress } | Export-Csv -Path 'C:\temp\Results.csv' -NoTypeInformation
Get-Content -Path 'C:\temp\Results.csv'
# Results"SAMAccountName","ipPhone","EmailAddress""Administrator",,"Administrator@xxx.com""postanote",,"postanote@xxx.com"
Yet, if you need to use the -SearchBase thing, and you need to specify the user, there are examples in the help files on how to to this.
Get-Help -Name Get-Aduser -Examples
https://docs.microsoft.com/en-us/powershell/module/activedirectory/get-aduser?view=winserver2012-psGet all properties of the user with samAccountName 'GlenJohn'.-------------------------- EXAMPLE 4 --------------------------C:\PS>Get-ADUser -Filter {Name -eq "GlenJohn"} -SearchBase "DC=AppNC" -Properties mail -Server lds.Fabrikam.com:50000
Now for that resource list…
### Learning PowerShell Resources
There are lots of solid references available. What are the best is a matter of opinion. This is why rankings on books, say on Amazon and other sites that allow user ratings vary can vary wildly. You too will have your take on the topics when you read them. My suggestion is first do some - free - live video beginner training via Microsoft virtual academy, and even on Youtube. Be sure to follow the authors blogs mentioned in the references below as well.
See these discussionshttps://social.technet.microsoft.com/wiki/contents/articles/183.windows-powershell-survival-guide.aspxhttps://mva.microsoft.com/training-topics/powershell#!jobf=IT%20Pros&lang=1033https://www.reddit.com/r/PowerShell/comments/95y82g/whats_the_best_youtube_powershell_tutorial_serieshttps://www.reddit.com/r/PowerShell/comments/98dw5v/need_beginner_level_script_ideas_to_learnhttps://www.reddit.com/r/PowerShell/comments/7oir35/help_with_teaching_others_powershellhttps://www.reddit.com/r/PowerShell/comments/9apwyo/i_want_to_convince_my_managers_to_enable_pshttps://www.reddit.com/r/PowerShell/comments/98qkzn/powershell_advicehttps://www.reddit.com/r/PowerShell/comments/96rn7y/college_level_student_looking_for_a_good_onlinehttps://www.reddit.com/r/PowerShell/comments/99dc5d/powershell_for_a_noobhttps://blogs.technet.microsoft.com/heyscriptingguyhttps://adventofcode.comhttps://www.thecodeasylum.com
Youtube, just serach for 'Beginning Powershell', 'intermediate PowerShell, 'advanced PowerShell', etc.
MS Channel9 and TechNet Virtrual lab - there are no seperate PowerShell specific ones, but anything on Exchange, AD, Azure, etc., all have PowerShell requirements
--- Microsoft Virtual Academy ---https://mva.microsoft.com/liveevents/powershell-jumpstart https://mva.microsoft.com/search/SearchResults.aspx#!q=PowerShell&lang=1033https://mva.microsoft.com/en-us/training-courses/getting-started-with-microsoft-powershell-8276 https://mva.microsoft.com/en-us/training-courses/getting-started-with-microsoft-powershell-8276?l=r54IrOWy_2304984382
--- Microsoft Channe9 ---https://channel9.msdn.com/Series/GetStartedPowerShell3 https://channel9.msdn.com/Search?term=powershell#ch9Search&lang-en=en&pubDate=year
--- Youtube ---https://www.youtube.com/watch?v=wrSlfAfZ49E https://www.youtube.com/results?search_query=beginning+powershell https://www.youtube.com/results?search_query=powershell+ise+scripting+for+beginnershttps://www.youtube.com/playlist?list=PL6D474E721138865A - Learn Windows PowerShell in a Month of Lunches - YouTube
--- eBooks and sites ---https://powertheshell.com/cookbookshttps://powershell.org/ebookshttps://leanpub.com/u/devopscollectivehttps://powershell.org/free-resourceshttps://rkeithhill.wordpress.com/2009/03/08/effective-windows-powershell-the-free-ebookhttps://veeam.com/wp-powershell-newbies-start-powershell.htmlhttps://reddit.com/r/PowerShell/comments/3cki73/free_powershell_reference_ebooks_for_downloadhttps://blogs.technet.microsoft.com/pstips/2014/05/26/free-powershell-ebooks https://www.idera.com/resourcecentral/whitepapers/powershell-ebook http://mikefrobbins.com/2015/04/17/free-ebook-on-powershell-advanced-functionshttps://books.goalkicker.com/PowerShellBookhttps://github.com/vexx32/PSKoans
--- Windows PowerShell Survival Guide ---https://social.technet.microsoft.com/wiki/contents/articles/183.windows-powershell-survival-guide.aspx
--- And start with lots of examples. ---https://www.powershellgallery.com https://gallery.technet.microsoft.com/scriptcenter/site/requests https://technet.microsoft.com/en-us/scriptcenter/bb410849.aspx
Thoroughly read / re-read and understand built-in the help files and review all the scripts on your machine.
# Get parameters, examples, full and Online help for a cmdlet or function
(Get-Command -Name Get-Content).ParametersGet-help -Name Get-Content -ExamplesGet-help -Name Get-Content -FullGet-help -Name Get-Content -Online
Get-Help about_*Get-Help about_Functions
# Find all cmdlets / functions with a target parameterGet-Help * -Parameter Append
# All Help topics locationsexplorer "$pshome\$($Host.CurrentCulture.Name)"
Read the help files and about_* files, leverage the examples in the help files. Tweak the examples in the help files.
Use any Windows tool that will write the baseline code for you (which you can then tweak), such as the Windows Server 2012 ADAC console leveraging the PowerShell History Viewer.
Active Directory Administrative Center: Getting Started 'technet.microsoft.com/.../dd560651(v=ws.10).aspx'
Active Directory Administrative Center 'docs.microsoft.com/.../active-directory-administrative-center'
Step-By-Step: Utilizing PowerShell History Viewer in Windows Server 2012 R2 'blogs.technet.microsoft.com/.../step-by-step-utilizing-powershell-history-viewer-in-windows-server-2012-r2'
Make a copy of...
C:\Windows\System32\WindowsPowerShell\v1.0\Modules
... then, open the scripts, modules, functions in the default Windows PowerShell folder, in the PowerShell ISE or VSCode and review that's going on in them. Make a copy of them to play with and tweak. Also look for any other location that has .ps files, make a copy and review.
You can also directly look at many of the function code in PowerShell by doing this approach... Spying on Function Source Code 'community.idera.com/.../spying-on-function-source-code'
Thank you for fixing my code. I knew there was something I was doing wrong, but just for the life of me could not see it.
I appreciate the help. Now I just need to add error checking (which I think I can figure out) and the email sending (which you've added) to the end and I think this can be closed as resolved and answered.
No worries. Glad that it will get you going.
After being in IT for 4+ decades (teaching it for the last 2+ decades as well) and messing with all types of environments and languages, it is always a challenge to get up to speed on what’s next.
Just know that when you hit the forums and Q&A sites, like this one. Folks are generally kind and people providing help/guidance for free on their own time.
Sometimes, responses can be terse, but they are not meant to be negative / condescending, but trying to get to the concise / informative / educational way to deliver an acceptable answer, and guide more informative question exchange. Well, don’t get me wrong, on many of the forms/Q&A side, there are real some real Jerks, and are Jerks on purpose. There are also those, who just try to make you believe their answer is the only answer and that, in most cases is simply not the case. I’ve seen this over the years I’ve participated in the forums / Q&A site, and it still boggles the mind.
Any language, can and often does provide multiple ways to achieve a give goal. You have to choose what works for you. Don’t let the responses from anyone rile you. Just come to expect some of that, and just ignore it, take from the response what is useful and throw away the rest.
In IT today. There is really not a legitimate question, that one can ask, that more than likely has not already been asked and answered somewhere on the internet. It’ just a matter of knowing, you may not find your complete answer in one spot or even from one person, but if you break you use case in to bite sized pieces, and attack them one at a time to make sure you are on the right track and getting what you’d expect, it’s far easier to put it all together.
Rule of thumb, always, always, start with the Examples the language / products gives you in the built-in help.
Here is a snippet of code I give to all my students to help them find help, text examples, and often leads them to better understanding and questions:
### Begin Help Options
# Get a list of all functions Get-Command -CommandType Function | Out-GridView -PassThru -Title 'Available functions'
# Get a list of all commandlets Get-Command -CommandType Cmdlet | Out-GridView -PassThru -Title 'Available cmdlets'
# Get a list of all functions for the specified name Get-Command -Name '*ADGroup*' -CommandType Function | Out-GridView -PassThru -Title 'Available named functions'
# Get a list of all commandlets for the specified name Get-Command -Name '*ADGroup**' -CommandType Cmdlet | Out-GridView -PassThru -Title 'Available named cmdlet'
# get function / cmdlet details (Get-Command -Name Get-ADUser).Parameters Get-help -Name Get-ADUser -Examples Get-help -Name Get-ADUser -Full Get-help -Name Get-ADUser -Online
# Get parameter that accepts pipeline input Get-Help Get-ADUser -Parameter * | Where-Object {$_.pipelineInput -match 'true'} | Select *
# List of all parameters that a given cmdlet supports along with a short description: Get-Help dir -para * | Format-Table Name, { $_.Description[0].Text } -wrap
# Get Powershell Version info per cmdlet / function # Errors displayed can be ignored $TargetCmdlets = (Get-Command).Name -match 'process' $CmdletSupportedPowerShellVersion = ForEach($Command in $TargetCmdlets) { $Command (Get-Module (Get-Command -Name $Command).Module) | Select-Object -Property ModuleType,Name,PowerShellVersion, @{Name = 'CmdletName_FinctionName';Expression = {$Command}} } $CmdletSupportedPowerShellVersion | Select-Object -Property ModuleType,Name,CmdletName_FinctionName,PowerShellVersion | Sort-Object -Property Name,PowerShellVersion | Out-GridView -PassThru -Title 'Show list of supported PowerShel version for modules/cmdlet/functions'
Get-Help about_* Get-Help about_Functions
# Find all cmdlets / functions with a target parameter Get-Command -CommandType Function | Where-Object { $_.parameters.keys -match 'credential'} | Out-GridView -PassThru -Title 'Available functions which has a specific parameter'
Get-Command -CommandType Cmdlet | Where-Object { $_.parameters.keys -match 'credential'} | Out-GridView -PassThru -Title 'Results for cmdlets which has a specific parameter'
# Get named aliases Get-Alias | Out-GridView -PassThru -Title 'Available aliases'
# Get cmdlet / function parameter aliases (Get-Command Get-ADUser).Parameters.Values | where aliases | select Name, Aliases | Out-GridView -PassThru -Title 'Alias results for a given cmdlet or function.'
# All Help topics locations Get-Help about* | Select Name, Synopsis
Get-Help about* | Select-Object -Property Name, Synopsis | Out-GridView -Title 'Select Topic' -OutputMode Multiple | ForEach-Object { Get-Help -Name $_.Name -ShowWindow }
explorer "$pshome\$($Host.CurrentCulture.Name)"
# Get any .NET types and their static methods from PowerShell. # Enumerate all that are currently loaded into your AppDomain. # [AppDomain]::CurrentDomain.GetAssemblies() | foreach { $_.GetTypes() } | foreach { $_.GetMethods() } | where { $_.IsStatic } | select DeclaringType, Name | Out-GridView -PassThru -Title '.NET types and their static methods'
# Instantiate the types using new-object and call instance methods. # You can use get-member on an instance to get the methods on a type.
# Best Practices PowerShell scripting best practices 'blogs.technet.microsoft.com/.../powershell-scripting-best-practices'
The Unofficial PowerShell Best Practices and Style Guide https://blogs.technet.microsoft.com/pstips/2014/06/17/powershell-scripting-best-practices
Using PSScriptAnalyzer to check your PowerShell code for best practices 'mikefrobbins.com/.../using-psscriptanalyzer-to-check-your-powershell-code-for-best-practices'
### End Help Options