Powershell get computer name and add to AD group - powershell

I am trying to utilize Powershell to get the computer name it’s currently running on and then add that computer to a security group and I’m stuck.
Forcing myself to learn Powershell better and got this from a co-worker but not sure how to edit it for my needs. This script will be used to run after a certain package has been installed to grant access. Here is what I have so far:
param(
[string[]]$mname,
[string[]]$gname
)
foreach($m in $mname.split(','))
{
$mobj = get-adcomputer $m
foreach($g in $gname.split(','))
{
Add-ADGroupMember "GROUP_NAME" -Members $mobj
}
}
ERROR:
You cannot call a method on a null-valued expression.
At C:\Scripts\Add-MachineToCollectionGroup.ps1:6 char:15
+ foreach($m in $mname.split(','))

Just add your groupname at the top, also if you aren't running Powershell 5 you may need to change Add-ADGroupMember $groupobj -Members $computerobj to be Add-ADGroupMember $groupobj -Member $computerobj I think they changed that.
Also add -whatif to the end of the last line to test it (It'll tell you what it would have done without the whatif).
Oh also you will need to run this from an account that has AD access to add the machine to the group and the computer must have the activedirectory module installed.
$Groupname = "ENTER GROUP NAME HERE"
$computerobj = Get-ADComputer $env:COMPUTERNAME
$groupobj = Get-ADGroup $Groupname
Add-ADGroupMember $groupobj -Members $computerobj -WhatIf

Related

Bulk Disable PowerShell Script Not Executing

I am kinda new to powershell and started a role in support. Working on a powershell script that will do the following things:
Disable a user account
Remove all AD Groups except for Domain Users
Edit the description
Move AD object to a disabled users OU
I think I can probalby change the "$TargetOU = OUPath" because the disabled users OU is never really going to change...if that's the issue then i'll feel like a dumby lol.
I am trying and failing to complete this! I don't know what is going wrong. Powershell isn't faulting out or anything it is just not executing?
Thank you for any help!
My code is here:
Import-Module ActiveDirectory
$TargetOU = "OU=DisabledUsers"
Import-Csv "C:temp\DisableTest.csv" | ForEach-Object {
$samAccountName = $_."samAccountName"
Get-AdPrincipalGroupMembership -Identity $samAccountName {Where-Object -Property Name -Ne -Value 'Domain Users' | Remove-AdGroupMember -Members $samAccountName}
Get-ADUser -Identity $samAccountName | Disable-ADAccount
Get-ADUser -Identity $samAccountName -Description "Disabled Per Request XXXX"
Move-ADObject -Identity $UserDN -TargetPath $TargetOU
}
Need it to do four things:
Disable a user account
Remove all AD Groups except for Domain Users
Edit the description
Move AD object to a disabled users OU
You have several issues:
$TargetOU = "OU=DisabledUsers"
This should be the full distinguished name, so something like OU=DisabledUsers,DC=example,DC=com
Get-AdPrincipalGroupMembership -Identity $samAccountName {Where-Object -Property Name -Ne -Value 'Domain Users' | Remove-AdGroupMember -Members $samAccountName}
The sytax here is messed up. You want to pipe (|) the results from Get-AdPrincipalGroupMembership into Where-Object, but you have braces ({). The closing brace at the end of the line is thus unnecessary. The Where-Object cmdlet also lets you simplify the syntax to something more readable, like Where Name -ne 'Domain Users'.
Get-ADUser -Identity $samAccountName -Description "Disabled Per Request XXXX"
This should be Set-ADUser, which is explains why this isn't changing anything.
Move-ADObject -Identity $UserDN -TargetPath $TargetOU
You haven't defined $UserDN, so it's not going to find the user. And as already mentioned , the target path should be the full distinguished name.
You're also looking up the account several times. Every time you pass just the username, it has to search for the account. As you have it, it would be searching for the account 5 times. You can avoid that (and speed things up) by calling Get-ADUser once and passing the result into each of the other commands.
And just for simplicity, you can omit -Identity since the first parameter is assumed to be the identity.
Putting everything together, it would look something like this:
Import-Module ActiveDirectory
$TargetOU = "OU=DisabledUsers,DC=example,DC=com" #Change this to the real value
Import-Csv "C:temp\DisableTest.csv" | ForEach-Object {
$user = Get-ADUser $_."samAccountName"
Get-AdPrincipalGroupMembership $user | Where Name -ne 'Domain Users' | Remove-AdGroupMember -Members $user
Disable-ADAccount $user
Set-ADUser $user -Description "Disabled Per Request XXXX"
Move-ADObject $user -TargetPath $TargetOU
}

I need to copy computers from the default active directory "container" to security group using powershell

I'm trying to remove all computers from the wk_test security group and then add all the computers in the default 'Computers' container in AD to the (now-empty) wk_test security group.
However, I don't want to export the computers to a list and then import them back into the security group.
I have the first part of the script working properly, and it removes the computers from the wk_test group with no errors. My issue is adding the computers to the wk_test group from the "computers" container.
Remove-ADGroupMember "wk_test" -Members (Get-ADGroupMember "wk_test") -Confirm:$false
Add-ADGroupMember -Identity "wk_test" -Members (Get-ADComputer -SearchBase "CN=computers,DC=ad,dc=org") -filter*
I think the main problem is that I am attempting to copy from the computers container. Most of the advice on the internet refers to copying from an OU and not a container.
The Add-ADGroupMember documentation says:
You cannot pass user, computer, or group objects through the pipeline to this cmdlet.
Which I think is what you are trying to do.
I've used this method before to add computers from an OU to a group:
Get-ADComputer -SearchBase "CN=computers,DC=ad,dc=org" -Filter * | foreach {Add-ADGroupMember "wk_test" -Members $_.DistinguishedName }
But I think you could also modify your code like this, but I've not tested this as I'm not on domain at the moment.
$Computers = Get-ADComputer -SearchBase "CN=computers,DC=ad,dc=org" -filter* | select -ExpandProperty DistinguishedName
Add-ADGroupMember -Identity "wk_test" -Members $Computers
If you are moving them, why not use Move-ADObject.
So it would be:
Get-ADGroupMember "wk_test" | Move-ADObject -TargetPath <ou path>

Errors when using Set-ADUser and Add-ADGroupMember in child domains (across forest)

I've built a script that is supposed to query for users across the forest and do a few things:
Set ExtensionAttribute2
Add the user to a domain-specific group in their own domain
Add the user to a group in the root domain
When I run this against a GC in the root domain of the forest, users in the root domain are processed just fine. Users in child domains process step #3 just file, but steps #1 and #2 cause errors.
Edit for clarification: These commands are being run against a 2012 domain controller in the root forest that is also a global catalog server. I'm running these commands as an Enterprise Admin with access to all child domains. Using these same credentials and the same server I can make all of these edits manually using Active Directory Users and Computers.
Here is the script that I've created:
$csvpath = ".\users.csv"
$groupcbr = Get-ADGroup "CN=test group,OU=Test OU,DC=contoso,DC=com"
Import-CSV -Path $csvpath | Foreach-Object {
$userprincipalname = $_.userprincipalname
$activationkey = $_.activationkey
Get-ADUser -Filter {userprincipalname -like $userprincipalname} -SearchBase "DC=contoso,DC=com" -Server "ROOTGC.contoso.com:3268" | Foreach-Object {
$dn = $_.DistinguishedName
#Set default as root domain
$domain = "contoso"
$domainserver = "ROOTGC.contoso.com"
$groupscript = Get-ADGroup -Identity "$domain Test Group Users"
If ($dn -like "*DC=childdomain1*") {
$domain = "childdomain1"
$domainserver = "childgc1.childdomain1.contoso.com"
$groupscript = Get-ADGroup -Identity "$domain Test Group Users" -Server "ROOTGC.contoso.com:3268"
}
If ($dn -like "*DC=childdomain2*") {
$domain = "childdomain2"
$domainserver = "childgc2.childdomain2.contoso.com"
$groupscript = Get-ADGroup -Identity "$domain Office 365 Users" -Server "ROOTGC.contoso.com:3268"
}
Write-Host "$domain | $userprincipalname [$($_.SamAccountName)] will get $activationkey added, and put into groups: $groupscript | [$dn]"
#Set ExtensionAttribute2
SET-ADUSER -Identity $dn -replace #{ExtensionAttribute2="$activationkey"}
#Add the user to their own domain-based group
Add-ADGroupMember -Identity $groupscript -Members $_
#Add the user to the root domain's universal group
Add-ADGroupMember -Identity $groupcbr -Members $_
}
}
Again, the users in the root domain process just fine. The users in the child domains hit errors on #1 (set the extensionattribute2) and #2 (add the their local domain group).
Here are the errors:
Setting ExtensionAttribute2:
SET-ADUSER : A referral was returned from the server
At C:\***\Untitled1.ps1:52 char:3
+ SET-ADUSER -Identity $dn -replace #{ExtensionAttribute2="$activationkey"}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (CN=User1...contoso,DC=com:ADUser) [Set-ADUser], ADReferralException
+ FullyQualifiedErrorId : ActiveDirectoryServer:8235,Microsoft.ActiveDirectory.Management.Commands.SetADUser
Adding to the local domain group:
Add-ADGroupMember : The server is unwilling to process the request
At C:\***\Untitled1.ps1:53 char:3
+ Add-ADGroupMember -Identity $groupscript -Members $_
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (CN=ChildDomain1 Tes...contoso,DC=com:ADGroup) [Add-ADGroupMember], ADInvalidOperationException
+ FullyQualifiedErrorId : ActiveDirectoryServer:8245,Microsoft.ActiveDirectory.Management.Commands.AddADGroupMember
I've searched all over the place but haven't found any way to figure this out yet. I've tried the following (and more):
Added -Server "ROOTGC.contoso.com:3268" to each command to see if that helped, but all it did was break those commands for everyone (including the root users who were working already).
Tried to add the individual domain servers for each domain to the end of the command (as per the variable that I populated: $domainserver), but all of the child domain DC's are Windows 2003; the servers don't accept the connection.
Moved pieces of code around to various places (making it less efficient, but what the heck - I'm trying anything).
What am I missing? Help me please!! I had to go through my CSV file manually and set what needed to be set because it had to get done tonight, but I'm going to be processing thousands of users in the next 2 weeks.
The server you run this against must have a copy of the global catalog, otherwise it won't be able to resolve the referrals. Or you must run the command against a DC of the target domain. Also, your user must have Enterprise Admin privileges in order to be able to create/modify/delete objects in other domains of the forest (or appropriate delegations must be made in the target domains).
Another problem is that the shiny AD cmdlets won't work without the Active Directory Web Service, which isn't available prior to Windows Server 2008 R2, running on all involved DCs. You can work around that by handling the foreign security principals and directory objects yourself, though:
$fsp = New-Object Security.Principal.NTAccount('DOM1', 'username')
$sid = $fsp.Translate([Security.Principal.SecurityIdentifier]).Value
$dn = Get-ADGroup -Identity 'groupname' | select -Expand distinguishedName
$group = New-Object DirectoryServices.DirectoryEntry("LDAP://$dn")
[void]$group.member.Add("<SID=$sid>")
$group.CommitChanges()
$group.Close()
With that said: you do realize that Windows Server 2003 will reach end-of-life the day after tomorrow, don't you? Why are your DCs still running that antique version?

Using a different active directory tree in powershell

So I have a script with the purpose of scanning devices that start with a certain name, then return results of computers missing a group. My problem is, the device I need it to run from turns out not to be in the same tree. I have seen some commands, but I wanted to be sure I had the syntax right. I will include part of the script for context:
Import-Module ActiveDirectory
$Group = "A-Certain-Group"
$Groupname = (Get-ADGroup $Group).distinguishedName
$Computers = Get-ADComputer -filter "name -like 'Big*'" -Prop MemberOf | Where{$_.MemberOf -notcontains $Groupname}
So let's say I am running it from "company.net", and it needs to perform the above script on "companynet.net" instead. What is the proper method?
The AD cmdlets all have a -server parameter which lets you specify other domains. Just use it to specify the other domain assuming there is a trust.
$Groupname = (Get-ADGroup $Group -Server companynet.net).distinguishedName
$Computers = Get-ADComputer -Server companynet.net -filter "name -like 'Big*'" -Prop MemberOf | Where{$_.MemberOf -notcontains $Groupname}
Note that if you don't have permission to perform actions in the domain you will also need to use the -credential parameter.

Hiding Errors When Using Get-ADGroup

I'm working on a script that will build a new group if it doesn't exist. I'm using Get-ADGroup to make sure the group doesn't exist using the following command:
$group = get-adgroup $groupName -ErrorAction:SilentlyContinue -WarningAction:SilentlyContinue
But when I do I get the following error (I removed any domain specific data from the error):
Get-ADGroup : Cannot find an object with identity: '*group name*' under: '*domain*'.
At U:\Scripts\Windows\Create-FolderAccessGroup.ps1:23 char:24
+ $group = get-adgroup <<<< $groupName -ErrorAction:SilentlyContinue -WarningAction:SilentlyContinue
+ CategoryInfo : ObjectNotFound: (y:ADGroup) [Get-ADGroup], ADIdentityNot
FoundException
+ FullyQualifiedErrorId : Cannot find an object with identity: '' under: ''.,Microsoft.ActiveDirectory.Management.Commands.GetADGroup
I assumed setting ErrorAction and WarningAction to SilentlyContinue would keep this error from being displayed but it hasn't.
I find that this works best:
$Group = Get-ADGroup -Filter {SamAccountName -eq $GroupName}
If the filter returns no results, then $Group is simply set to $null and no error message is generated. Also, since a SAM account name must be unique in Active Directory, there is no risk of $Group being set to an array of more than one object.
I find that using -Filter to get the group rather than -Identity works really well when checking for the existence of groups (or users) in If statements. For example:
If (Get-ADGroup -Filter {SamAccountName -eq $GroupName})
{
Add-ADGroupMember -Identity $GroupName -Members $ListOfUserSamAccountNames
}
Else
{
Write-Warning "Users could not be added to $GroupName because $GroupName
does not exist in Active Directory."
}
I find that is a lot easier to deal with logically (if the group exists, add the users; if not, display a message) than mjolinor's suggestion of try/catch with using the Get-ADGroup cmdlet with the -Identity parameter. Consider the try/catch method of doing the same as above, using the -Identity parameter:
Try
{
Get-ADGroup -Identity $GroupName
Add-ADGroupMember -Identity $GroupName -Members $ListOfUserSamAccountNames
}
Catch
{
Write-Warning "Users could not be added to $GroupName because $GroupName
does not exist in Active Directory."
}
You see if any of the commands in the try block throws a terminating error. If one does, it means the group doesn't exist and will move on and process the command(s) in the catch block. It will work, but I don't think try/catch here flows as well, logically, in comparison to if/else.
Don't get me wrong, mjolinor is a PowerShell genius. It's just that in this case I don't think his solution is the best one.
try {get-adgroup <groupname>}
catch {
<make new group>
}
#mjolinor gives the good answer, but I think some explanation can also help.
Windows PowerShell provides two mechanisms for reporting errors: one mechanism for terminating errors and another mechanism for non-terminating errors.
Internal CmdLets code can call a ThrowTerminatingError method when an error occurs that does not or should not allow the cmdlet to continue to process its input objects. The script writter can them use exception to catch these error.
Internal CmdLets code can call a WriteError method to report non-terminating errors when the cmdlet can continue processing the input objects. The script writer can then use -ErrorAction option to hide the messages.
I realize this is old, but I also had this problem and solved it like this:
If (Get-ADObject -Filter {objectClass -eq "Group -and samAccountName -eq "groupname"}) { //do stuff// }