Running this code in a script (that grabs details from a form) to get a list of users groups and remove from all except group named "Group1" and "Group2":
#remove any group memberships except Group1 and Group2
$groups = Get-ADPrincipalGroupMembership $Inputsamaccountname.Text | Where-Object -filter {$_.name -ne 'Group1' -And $_.name -ne 'Group2'}
foreach ($group in $groups) {
$group = $groups.Name
$RemovegroupMsg = "Removing " + $inputSamAccountName.Text + " from " + $group
logentryDateTime $removeGroupMsg
Remove-ADPrincipalGroupMembership -Identity $inputSamAccountName.Text -MemberOf $group -Confirm:$false
if ($Error) {
$errorMessage = "Error removing " + $inputSamAccountName.Text + " from " + $group + " " + ($Error[0].ToString()) + " continuing."
logentryDateTime $errorMessage
$Error.Clear()
continue
} elseif (!$Error) {
Write-Output "" >> $outlogfile
logentryDateTime "Successfully removed " + $inputSamAccountName.Text + " from " + $group
}
}
The script works and you can see that the groups have been removed, however logs show a "Cannot bind argument to parameter 'Name' because it is null." error for each group that matches that criteria":
[2016-10-19 113117-820] : Removing user.test1 from Other-group
[2016-10-19 113117-820] : Error removing user.test1 from Other-group Cannot bind argument to parameter 'Name' because it is null. continuing.
I know it's likely something really simple in the logic of the foreach loop I'm missing.
This line seems like your problem: $group = $groups.name It is surprising to see you accessing the array ($groups) inside a foreach loop iterating across those elements. Did you mean $group = $group.name?
Related
I needed to create a script that checks to see if an IIS App Pool for a specific site and its child App Pools are started. (I have a separate script to start "stopped" App Pools as I just want to check if they are stopped) I was able to create the script however when I modified it to format the output better I keep getting this error,
At E:\iis\scripts\svc_pl_fm_app_pool_status.ps1:12 char:6
+ App Pool = $item.Name;
+ ~
Missing '=' operator after key in hash literal.
At E:\iis\scripts\svc_pl_fm_app_pool_status.ps1:7 char:29
+ foreach ($item in $results) {
+ ~
Missing closing '}' in statement block.
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : MissingEqualsInHashLiteral
I checked here and Microsoft but I left more confused about the error then when I first saw it. I saw this Missing closing '}' in statement block. so i assumed I was in fact missing one but I checked and I am not. I am not sure if it is a spacing/ indentation issue but I do not know enough about this error message. Here is my script below.
$results = $item = $appPool = $status = $NULL
$status = "1"
import-module WebAdministration
$AppPoolList = #()
$results = Get-ChildItem IIS:\AppPools\* | Where-Object { ($_.Name -like "someAppPool*" -and $_.Name -like "someChildAppPool*" )}
foreach ($item in $results) {
if ($item.State -ne "Started") {$status = "0"}
$AppPoolList += [PSCustomObject]#{
App Pool = $item.Name;
Status = $item.State;
}
}
$AppPoolList | Format-List
I have been trying to re-format this command by making it cleaner but I just can't seem to get around the write-output.
Get-QARSOperation -ParentContainer 'somedomain.com/OU1/OU2' -TargetObjectType 'user' |
Where-Object {$_.Status -eq 'Completed' -and $_.Controls.ID -eq 'OperationReason'} |
ForEach-Object {Get-QARSApprovalTask -Operation $_.ID} |
ForEach-Object {
Write-OutPut ("Target: " + $_.Operation.TargetObjectInfo.DN.Replace("CN=","").Replace("cn=","").Replace("\","").Replace(",","").Replace("OU","").Split('=')[0]);
Write-OutPut ("Operation ID: "+ $_.Operation.ID);
Write-OutPut ("Approver: " + $_.CompletedBy.DN.Replace("CN=","").Replace("\","").Replace(",","").Replace("OU","").Split('=')[0]);
Write-OutPut ("StartedOn: " + $_.Created);
Write-OutPut ("Completed: " + $_.Completed);
Write-OutPut ("Comments: " + $_.CompletionReason);
Write-OutPut ("Operation Type: " + $_.Operation.Type);
Write-OutPut ""
}
Also the format when I export to csv doesn't put the data into columns. What suggestions do you have to make this script look neater?
Thank you!
As suggested in the comments the correct thing to do is use Export-Csv to generate a CSV file. As for creating an object that you want to export and making that easy to read in the code you could do something similar to what you have, and use it to create a custom object that could then be piped to Export-Csv. Also, I think your whole .Replace("CN=","").Replace("cn=","").Replace("\","").Replace(",","").Replace("OU","").Split('=')[0] can be simplified to .Split('=,')[1]. The string's .Split() method accepts multiple characters to split on, and it will split on any of the characters provided. Here's what I would suggest, you will need to update the path at the end, and may have to revert to your longer .Replace bit if mine doesn't work for you.
Get-QARSOperation -ParentContainer 'somedomain.com/OU1/OU2' -TargetObjectType 'user' |
Where-Object {$_.Status -eq 'Completed' -and $_.Controls.ID -eq 'OperationReason'} |
ForEach-Object {Get-QARSApprovalTask -Operation $_.ID} |
ForEach-Object {
[PSCustomObject][Ordered]#{
"Target" = $_.Operation.TargetObjectInfo.DN.Split('=,')[1]
"Operation ID" = $_.Operation.ID
"Approver" = $_.CompletedBy.DN.Split('=,')[1]
"StartedOn" = $_.Created
"Completed" = $_.Completed
"Comments" = $_.CompletionReason
"Operation Type" = $_.Operation.Type
}
} |
Export-Csv C:\Path\To\File.csv -NoTypeInformation
You could use a Select statement, but I think this looks cleaner for you.
I can't seem to figure out why this script won't work. There are no errors, but the $User object isn't getting evaluated to $True. The object is to enable a re-hired user's AD account if another system shows the re-hire date to be less than or equal to 8 days out from today.
$CSVLine = "C:\scripts\adp\Test ADP Import spec.csv"
$ErrorLog = "C:\scripts\adp\ADPProcessErrors.csv"
$a = Get-Date
ForEach ($row in (import-csv $CSVLine)) {
$User = Get-ADUser -LDAPFilter ("(sAMAccountName=" + $Row.sAMAccountName + ")") -Properties *
#Write-Host ("User:" + $user.samaccountname + " enabled =" + $user.enabled + " ")
If ((($User.Enabled -eq $False)) -and ($Row.'Date of hire/rehire' -gt $a) -and (($Row.'Date of hire/rehire') -le ($a.AddDays(8))) ) {
(Set-ADUser -Enabled $True -Identity $User)
("SID:" + $Row.sAMAccountName + ", User:[" + $User.givenName + " " + $User.sn + "] Re-Hire date is in range. Account enabled.") | Out-File -FilePath $ErrorLog -Append
}
}
Write-Host ("CSV Object: " + $Row.'Date of hire/rehire'.GetType())
Write-Host ("CSV Object Value:" + $Row.'Date of hire/rehire' + " " )
Write-Host ("User:" + $user.samaccountname + " enabled =" + $user.enabled + " ")
Those dates might need to be casted as [datetime]/dates so that the math against $a would work. It is most likely treating those as string to just doing alphabetical comparison.
PS C:\Users\mcameron> "b" -gt "a"
True
Can't tell you exactly what to do without sample dates so we can see the formats. From the comment if you dates are formatted like "2/8/2015" then a simple cast would address this.
PS C:\Users\mcameron> [datetime]"2/8/2015"
Sunday, February 08, 2015 12:00:00 AM
Update your if to the following:
If ((($User.Enabled -eq $False)) -and ([datetime]($Row.'Date of hire/rehire') -gt $a) -and ([datetime]($Row.'Date of hire/rehire') -le ($a.AddDays(8))) ){
#.....Process
}
It's a bit difficult to say without a sample of the input file but, if you're getting no error, I'd start by checking if $Row.sAMAccountName is evaluating to anything inside the loop. Like you have with your commented-out Write-Host line, for the $user properties.
Cheers.
Here get-adgroups returns false when querying from script while it returns true when run manually using the very same PowerShell ISE Window. Please see the following code which produces the error. Group, OU and DN exist. Quite likely no Typo. Reproducible by manually running the command (see further below), which works fine.
Import-Module ActiveDirectory
$Group="ProductInternalInstallProductOnNextLogin"
$BaseDN="OU=Product,DC=int,DC=Domain,DC=de"
write-host "get-adgroup -Filter DistinguishedName -eq CN=$Group,$BaseDN"
$Result=get-adgroup -Filter {(DistinguishedName -eq "CN=$Group,$BaseDN")}
if($Result)
{
write-host "Group $Group found"
}
else
{
write-host "Group $Group not found, trying to create $Group"
New-ADGroup -path "$BaseDN" -GroupScope Global -name $Group
if (!$?)
{
write-host "ERROR creating new group $Group"
exit
}
}
This results in the following output where you can see the error:
____________________________________________________________________________________________________________________________________________________________________________________________________________________
PS C:\Users\MyName.INT> G:\DevPath\Tools\PowerShell-Scripte\Unbenannt2.ps1
get-adgroup -Filter DistinguishedName -eq CN=ProductInternalInstallProductOnNextLogin,OU=Product,DC=int,DC=Domain,DC=de
Group ProductInternalInstallProductOnNextLogin not found, trying to create ProductInternalInstallProductOnNextLogin
New-ADGroup : Die angegebene Gruppe ist bereits vorhanden
Bei G:\DevPath\Tools\PowerShell-Scripte\Unbenannt2.ps1:13 Zeichen:16
+ New-ADGroup <<<< -path "$BaseDN" -GroupScope Global -name $Group
+ CategoryInfo : NotSpecified: (CN=ProductInte...nt,DC=Domain,DC=de:String) [New-ADGroup], ADException
+ FullyQualifiedErrorId : Die angegebene Gruppe ist bereits vorhanden,Microsoft.ActiveDirectory.Management.Commands.NewADGroup
ERROR creating new group ProductInternalInstallProductOnNextLogin
____________________________________________________________________________________________________________________________________________________________________________________________________________________
How can New-ADGroup fail if I'm only running it in case the group is not there? PowerShell is running in German here, so the error message "New-ADGroup : Die angegebene Gruppe ist bereits vorhanden" means "This group already exists".
To verify this, I ran this manually in the console, where it works out fine:
PS C:\Users\MyName.INT> write-host "the following command was run manually from the commandline of the PowerShellISE"
$Result=get-adgroup -Filter {(DistinguishedName -eq "CN=ProductInternalInstallProductOnNextLogin,OU=Product,DC=int,DC=Domain,DC=de")}
write-host $Result
which produces the correct output:
the following command was run manually from the commandline of the PowerShellISE
CN=ProductInternalInstallProductOnNextLogin,OU=Product,DC=int,DC=Domain,DC=de
In my struggling I tried also
try {get-adgroups [...]} catch {new-adgroup[...]}
but that didn't work out either.
Have you tried pulling the string concatenation for your target group outside the Get-ADGroup command? I was actually able to replicate your issue from my PowerShell ISE session. When I updated the 'filter' it cleared things up and I was able to retrieve the information successfully.
Original:
$Group = "ProductInternalInstallProductOnNextLogin"
$BaseDN = "OU=Product,DC=int,DC=Domain,DC=de"
$Result = get-adgroup -Filter {(DistinguishedName -eq "CN=$Group,$BaseDN")}
Modified:
$Group = "ProductInternalInstallProductOnNextLogin"
$BaseDN = "OU=Product,DC=int,DC=Domain,DC=de"
$Target = "CN=" + $Group + "," + $BaseDN
$Result = get-adgroup -Filter {DistinguishedName -eq $Target}
I am new in powershell world , I got some project on powershell for inventory reconciling .
I am not sure how to proceed on this , I tried some basic steps and I am able to export
users/group/group membership.
Following are the requirements :
Now What I have achieved - Thanks to Govnah
AD query:
Get-QADUser -searchRoot $OuDomain -SizeLimit 0 |
Select-Object dn, sAMAccountName, #{Name="Groups";Expression={(Get-QADMemberOf $_ | Select-Object -expandProperty Name) -join ";"}} |
Sort-Object SamAccountName |
export-csv $FilePath
I have now two csv files likes AD_users.csv and Oracle_users.csv
I want to compare both files and redirect the difference like
AD users does not exist in Oracle
Oracle User does not exist in AD
Sample data
AD_users.csv
u388848993
K847447388
u994888484
Oracle_users.csv
k095848889
u388848993
I can query oracle database , AD query is also fine the only concern is that I am not able to compare the output.
I did it something like this in a script I wrote:
[System.Collections.ArrayList]$adlist = Get-Content c:\users\sverker\desktop\ad.csv |Sort-Object
[System.Collections.ArrayList]$oraclelist = Get-Content c:\users\sverker\desktop\oracle.csv |Sort-Object
$Matching_numbers = #()
ForEach ($number in $adlist)
{
if ($oraclelist.Contains($number))
{
$Matching_numbers += $number
}
}
ForEach ($number in $Matching_numbers)
{
$adlist.Remove($number)
$oraclelist.Remove($number)
}
now $Matching_numbers now contains the matching numbers
and $adlist contains only numbers from AD
and $oraclelist only numbers from Oracle
you can then loop through the list and display values:
Write-Host "Matches:"
ForEach ($value in $Matching_numbers)
{
$Message += $value + [Environment]::NewLine
}
Write-Host $Message
Write-Host "AD only:"
ForEach ($value in $adlist)
{
$MessageAd += $value + [Environment]::NewLine
}
Write-Host $MessageAd
Write-Host "Oracle only:"
ForEach ($value in $oraclelist)
{
$MessageOracle += $value + [Environment]::NewLine
}
Write-Host $MessageOracle
or simply by writing
$Matching_numbers
will output the list to console
You can output the $Message variables to a file or so..
No doubt, there is a nicer way to do it, but this worked for me for a certain type of file.