Powershell script giving an error but runs in shell - powershell

I have a requirement to create and update a distribution list for a specific manager and 2 levels down of direct reports. I admit I am not a creative person so I used powershell and did it the best way I could think to do it. The problem is this will be scheduled to run every couple weeks to update the list so it needs to see if a user exists, if not then add him. in the "If" statement to do this I am running into errors when running the script, but if I pull the section of code out and just run manually in powershell it works.
My Execution policy is set to unrestricted so I do not think that is the issue.
We are running Powershell 2 and Unfortunately I can't change that.
Here is my script and the error I am getting.I realize two strings do not match in the lower part of the code, even though they both do the same thing to different files. If I ever get past errors in the first one I should be able to put the same code in both for it to work. Any help would be greatly appreciated.
$Identity="User"
$Listname="Global-Leader"
# This Script will work from a specified Manager and get his direct reports down 2 Levels then #add them to a specified list. This Script works in the AD Module.
# ====================
#| My Company
#| SCRIPT NAME: Leader
#| VERSION: 1
#| VERSION DATE: 3/24/2015
#| AUTHOR: Powershell Rookie
#====================
#load ActiveDirectory module If not already loaded.
if (!(Get-Module -Name ActiveDirectory)) {import-module ActiveDirectory}
Get-AdUser $Identity -properties DirectReports | Select-Object -ExpandProperty DirectReports | Get-ADUser -Property * | Select SamAccountName, DisplayName, Office | Export-csv c:\work\leaders.csv
Import-Csv c:\work\Leaders.csv | ForEach-Object {Get-AdUser $_.SamAccountName -Property DirectReports | Select-Object -ExpandProperty DirectReports | Get-Aduser -Property * | Select SamAccountName, DisplayName, Office} | Export-csv c:\work\leaders1.csv
Import-csv C:\work\leaders.csv | Foreach-Object If (!(Get-ADUser $_.SamAccountName –properties MemberOf).MemberOf –like “$listname”) {Add-ADGroupMember $listname –member $_.samAccountName}
Import-csv C:\work\leaders1.csv | Foreach-Object If ((Get-ADUser $_.SamAccountName –properties MemberOf).MemberOf –like “$listname”) {Add-ADGroupMember $listname –member $_.samAccountName}
if ((Get-ADUser $user -Properties MemberOf).memberOf -like "$listName") {
Write-Host -ForegroundColor Green "$user is already a member of $listName"
} else {
Write-Host -ForegroundColor Yellow "Adding $user to $listName"
Add-ADGroupMember $ListName -member $user
}
And here is the error I keep getting:
[PS] C:\work>.\leader.ps1
Unexpected token '{' in expression or statement.
At C:\work\leader.ps1:25 char:143
+ Import-csv C:\work\leaders.csv | Foreach-Object If (!(Get-ADUser $_.SamAccountName â?"properties MemberOf).MemberOf â?"like â?o$listnameâ
??) { <<<< Add-ADGroupMember $listname â?"member $_.samAccountName}
+ CategoryInfo : ParserError: ({:String) [], ParseException
+ FullyQualifiedErrorId : UnexpectedToken

Quick answer when using -like you need to be less specific with your criteria.
-like "*$Listname*"
Like is looking for that specific text at the beginning of the item to be
searched. If that item can appear anywhere in the memberof then you need to either add the wildcards or use -match instead. -match implies * around your search item.
Since most responses from that command should start with
CN=
Your member group will not be the first thing it finds
Hope that helps
Difference between -like and -match

Related

Delete users from mailbox rule

I have a problem with some script that I want to write. I have for example a TEST rule in local Exchange. There are accounts added manually which are disabled. I'm looking for a way to clear the rule of disabled accounts and leave the enabled accounts as they were. I thought that I will export through Exchange Management Shell a list of people from this rule. Then through foreach and Get-ADUser I will add the missing data and then load the .CSV file once again and based on the email and disabled account I will remove these people from the rule.
I don't know if this is feasible, but I'm trying. I would appreciate any hints on what I am doing wrong in the script.
When I want to run the script, I get the message:
Get-ADUser : Error parsing query: ' "UserPrincipalName -like
'$($_.Mail)'" -and "Enabled -eq '$false'"' Error Message: 'syntax
error' at position: '2'.
Below is my code:
<#
The first step is to export the list of users who are in the TEST rule
#>
Get-TransportRule "TEST" |
select -ExpandProperty "ExceptIfSentTo" |
Export-Csv -Path C:\TEST.csv -NoTypeInformation
<#
Second, the list of users is displayed and then I add the data of these users such as:
Name, SamAccountName, UserPrincipalName, Enabled
#>
Import-Csv C:\TEST.csv | foreach {
Get-ADUser -Filter "UserPrincipalName -eq '$($_.RawIdentity)'"} |
select name, sAMAccountName, UserPrincipalName, Enabled
#Export data with attributes to a second .csv file
Import-Csv C:\TEST.csv | foreach {
Get-ADUser -Filter "UserPrincipalName -eq '$($_.RawIdentity)'"} |
select name, sAMAccountName, UserPrincipalName, Enabled |
Export-Csv -Path C:\TEST_with_attributes.csv -Delimiter ";" -Encoding UTF8 -Force
Start-Sleep -Seconds 3
<#Here it wants to load a file and, based on the UserPrinicalName and the fact that the account is disabled, remove users from the TEST rule#>
Import-Csv C:\TEST_with_attributes.csv | foreach {
Get-ADUser -Filter { "UserPrincipalName -like '$($_.UserPrincipalName)'" -and "Enabled -eq '$false'"} } | Disable-InboxRule "TEST" -AlwaysDeleteOutlookRulesBlob

Getting AD info using Get-ADGroupMember not working as expected

So i am trying to write a script that basically gets a list of AD groups, and then with each group, gets the members and memberof.
So far i have this :
Import-Module ActiveDirectory
$groupList = get-adgroup -filter *| select-object Name | sort-object -property name
Which works fine. nice and simple. No problem. When i run write-output $groupList, it spits out the list of my AD groups. Happy days!
Then I add this :
foreach($group in $groupList){
Get-ADGroupMember -Identity $group
So my code block looks like this :
Import-Module ActiveDirectory
$groupList = get-adgroup -filter *| select-object Name | sort-object -property name
foreach($group in $groupList){
Get-ADGroupMember -Identity $group
}
And get this error :
Get-ADGroupMember : Cannot bind parameter 'Identity'. Cannot create object of type
"Microsoft.ActiveDirectory.Management.ADGroup". The adapter cannot set the value of property "Name".
I have also tried this :
Get-ADGroup -filter * -Properties MemberOf | Where-Object {$_.MemberOf -ne $null} | Select-Object Name,MemberOf
Which works great in Powershell:
Image of working script results
Yet strangley, when i then add the export-csv on the end, that same error returns :
Exported-CSV image
Can someone please educate me, as no doubt its myself being a little stoopid.
Thanks.
$groupList does not directly contain an array of strings / names.
Use the following command to get only the names:
$groupList = Get-ADGroup -Filter * | Sort-Object -Property Name | Select-Object -ExpandProperty Name
MemberOf and Members are arrays. Export-Csv does not know how to export them into a file. Here an example, how to handle this.
Get-ADGroup -Filter * -Properties MemberOf, Members | `
Select-Object -Property Name, #{Name = 'MemberOf'; Expression = {$_.MemberOf -join ';'}}, #{Name = 'Members'; Expression = {$_.Members -join ';'}} | `
Export-Csv -Path 'path' -NoClobber -NoTypeInformation

get deactivated computers in ad from csv list

i'm tryin to figure out which computers are deactivated. for that i provide the computer names in a csv list. i just want to output the computers which are deactivated. this is what i have. unfortunately i get all deactivated computers. but i only want that names provided in the csv
Import-CSV -Path "C:\pc_names" | Select -expand Name | Get-ADComputer -searchbase 'XXX' -Filter {(Enabled -eq $False)} -Properties Name, OperatingSystem | Export-CSV “C:\Temp\DisabledComps.CSV” -NoTypeInformation
The problem is likely in the Get-ADComputer command, you specify a SearchBase (assumedly an OU), and a filter for all disabled computers - but never actually include the name of the PC that you piped in from the CSV, so it just returns every disabled PC under that search base.
Try something like this instead;
Import-CSV -Path "C:\pc_names" | Select -Expand Name | Get-ADComputer -SearchBase 'XXX' -Filter {(Enabled -eq $False) -and ($_.Name)} -Properties Name, OperatingSystem | Export-CSV "C:\Temp\DisabledComps.CSV" -NoTypeInformation
Note the $_.Name in the filter.
I've probably got that filter syntax wrong - but that should be the cause.
There is no way you can test if the computername is to be found in an array of names using the -Filter parameter..
You need to first collect computer objects within your SearchBase OU and filter the disabled ones only.
Following that, you filter out the ones that can be found in the $pcNames array using a Where-Object clause:
$pcNames = (Import-Csv -Path "C:\pc_names.csv").Name
Get-ADComputer -SearchBase 'XXX' -Filter "Enabled -eq 'False'" -Properties OperatingSystem |
Where-Object { $pcNames -contains $_.Name } | # or: Where-Object { $_.Name -in $pcNames }
Export-Csv -Path "C:\Temp\DisabledComps.csv" -NoTypeInformation
Note: Get-ADComputer by default already returns these properties: DistinguishedName, DNSHostName, Enabled, Name, ObjectClass, ObjectGUID, SamAccountName, SID, UserPrincipalName. That means you only have to ask for the extra property OperatingSystem in this case
It's pretty obvious that something like this ignores what's piped in and returns many computers.
'comp001' | get-adcomputer -filter 'Enabled -eq $False'
If you wait until the end, there is an error message:
get-adcomputer : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its
properties do not match any of the parameters that take pipeline input.
At line:1 char:13
+ 'comp001' | get-adcomputer -filter 'Enabled -eq $false'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (comp001:String) [Get-ADComputer], ParameterBindingException
+ FullyQualifiedErrorId : InputObjectNotBound,Microsoft.ActiveDirectory.Management.Commands.GetADComputer
You can do get-adcomputer inside a foreach loop and test Name as well:
$list = echo comp001 comp002 comp003
$list | % { get-adcomputer -filter 'Enabled -eq $False -and Name -eq $_' }

Powershell invoke-expression doesn't work with filter switch

I'm trying to write a program that lets users to do different kinds of queries on Active Directory. I want to make it in a way that lets them to chose which attributes they want to show in the output, and also filter the output in several ways.
As I don't know during writing the code how many attributes they will chose, it seemd the easiest way to produce a string out of the attributelist, and invoke the string with invoke-expression. This way works perfectly with attributes, but not at all with filters.
I've found several kinds of filter syntaxes but neither works when I put them in a string and try to invoke that with "Invoke-expression"
This:
$time = (Get-Date).Adddays(-(19))
Get-ADUser -Filter {LastLogonTimeStamp -gt $time} -SearchBase 'CN=Users,DC=home,DC=local' -Properties samAccountname, LastLogonDate | Select-Object #{n='Felhasználónév'; e='samAccountName'}, #{n='Utolsó bejelentkezés'; e='LastLogonDate'} | Out-String
Gives me the result I want.
While this:
$time = (Get-Date).Adddays(-(19))
$out = "Get-ADUser -Filter {LastLogonTimeStamp -gt $time} -SearchBase 'CN=Users,DC=home,DC=local' -Properties samAccountname, LastLogonDate | Select-Object #{n='Felhasználónév'; e='samAccountName'}, #{n='Utolsó bejelentkezés'; e='LastLogonDate'} | Out-String"
Write-Host $out
Invoke-Expression $out
Gives me the following result:
Get-ADUser -Filter {LastLogonTimeStamp -gt 05/05/2019 19:05:46} -SearchBase 'OU=Testing,DC=home,DC=local' -Properties samAccountname, LastLogonDate | Select-Object #{n='Username'; e='samAccountName'}, #{n='Last Logon'; e='LastLogonDat
e'}
Get-ADUser : Error parsing query: 'LastLogonTimeStamp -gt 05/05/2019 19:05:46' Error Message: 'Operator Not supported: ' at
position: '26'.
At line:1 char:1
+ Get-ADUser -Filter {LastLogonTimeStamp -gt 05/05/2019 19:05:46} -Sear ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ParserError: (:) [Get-ADUser], ADFilterParsingException
+ FullyQualifiedErrorId : ActiveDirectoryCmdlet:Microsoft.ActiveDirectory.Management.ADFilterParsingException,Microsoft
.ActiveDirectory.Management.Commands.GetADUser
Why does every other command works perfectly when invoking them from a string, but not this one? Is there any other way to filter the result? At first I wanna stick to filtering before the query, and not with the where clause, but I'm gonna try that too, if filtering won't work.
It feels stupid to answer my own question, but I think I found the answer.
Placing escape character before the variable did the trick.
$time = (Get-Date).Adddays(-(19))
$out = "Get-ADUser -Filter {lastlogontimestamp -gt `$time} -SearchBase 'CN=Users,DC=home,DC=local' -Properties samAccountname, LastLogonDate | Select-Object #{n='Felhasználónév'; e='samAccountName'}, #{n='Utolsó bejelentkezés'; e='LastLogonDate'} | Out-String"
Write-Host $out
$expr = Invoke-Expression $out
$expr
Returns
Felhasználónév Utolsó bejelentkezés
-------------- --------------------
Administrator 2019. 05. 24. 18:18:28
I had a similar situation, but mine was specific to $true $false parameters that are $true if present, $false if absent for [switch] type [params]. I had never needed to override the default params, because those were originally intended for single-use/manual invocation from the command line.
Invoke-Expression simplified calling .ps1 files as subroutines, but this would work directly from the command line console
\temp\00405-LoadW.ps1 -skipinit -showbanner:$false | Out-File -filepath 'c:\temp\today\00405-LoadW.log'
while this would not work when called inside a .ps1 file:
Invoke-Expression "\temp\00405-LoadW.ps1 -skipinit -showbanner:$false | Out-File -filepath 'c:\temp\today\00405-LoadW.log'"
This post (directly above) has the solution, the back-tick
`
This works both on the command console and from inside a .ps1:
Invoke-Expression "\temp\00405-LoadW.ps1 -skipinit -showbanner:`$false | Out-File -filepath 'c:\temp\today\00405-LoadW.log'"
PS: More time spent on figuring out how to escape the back-tick here than the actual answer.

AD query Powershell and Export to txt file

Can someone help me?
I have to create a .txt file with the following format:
user("SamAccountName","GivenName Surname"){}
I'm able to create just this:
#Get AD Users Info
cls
$SamAccountName = New-Item 'c:\SamAccountName.txt' -type file -Force
Get-ADUser -Filter * -Properties SamAccountName |
select -First 15 | Sort-Object SamAccountName |
Format-Table SamAccountName | Out-File $SamAccountName
$content = Get-Content $SamAccountName
$content | Foreach {$_.TrimEnd() } | where {$_ -ne ""} | Select-Object -Skip 3 | Set-Content $SamAccountName
#Write quotes (make it nice and readable!)
$ACTIVEDIRECTORY = New-Item 'c:\ACTIVEDIRECTORY.lst' -type file -Force
Clear-Content $ACTIVEDIRECTORY
$quotes= '"'
(Get-Content $SamAccountName) |
ForEach-Object {Add-Content $ACTIVEDIRECTORY "$quotes$_$quotes"}
Get-Content $ACTIVEDIRECTORY
This give me this result:
"GivenName"
"GivenName"
"GivenName"
I agree with #notjustme about your question being a mess, but I'll throw an answer out there anyway.
Your first problem is how you set these two variables. They end up being objects, but you're trying to use them like file paths.
$SamAccountName = "c:\SamAccountName.txt"
$ACTIVEDIRECTORY = "c:\ACTIVEDIRECTORY.lst"
This will get you a comma separated list of your users, which is (sort of) what part of your code is doing.
Get-ADUser -Filter * | Select-Object SamAccountName, GivenName, SurName -First 15 | Sort-Object SamAccountName | Export-Csv $SamAccountName -NoTypeInformation
This will get you the list of users with the string format you specified at the top, which is odd, but whatever.
Import-Csv $SamAccountName | ForEach-Object {"user(`"$($_.SamAccountName)`",`"$($_.GivenName) $($_.Surname)`"){}"} | Out-File $ACTIVEDIRECTORY
Can't try it out myself at the moment but... from experience...
-properties * | select SamAccountName, GivenName, Surname
Should get ya in the ballpark.
Re-read your code a few times and well... it seems a mess to be honest. You state what you wanna accomplish and then there's a crud-load of other stuff that make close to no sense in this case. Maybe I'm just too tired, I'll check back in the morning and edit/delete if needed.
Allright, re-read a few more times and the headache is given but still...
In general I'd like to advise you (or anyone, really) if Powershell get's confuzzling to break it down in easily processable pieces.
For the users;
$users = Get-ADUser -Filter { Name -like '*' } -Properties * | select SamAccountName, Givenname, Surname
For the output;
foreach ($user in $users)
{
'("{0}""{1}{2}"' -f $user.SamAccountName, $user.GivenName, $user.Surname
}
Unfortunatly I have no way to try this out myself at the moment but it should be in the ballpark... if you end up getting some errors, lemme know and I'm sure I can guide ya through it. I'm not 100% sure about them single and doublequotes in this particular case... I'd have to try it out.