In this post you find guidance on using a script to add the local computer to an Active Directory group during deployment. This script has basic logging built-in, supports multiple domains, and is available on GitHub.
Note #1: While I typically would use a web service for any AD operations – either managed code, or PowerShell driven – sometimes the security team are a bit hesitant of allowing that. Even though that design by its very nature is more secure. Anyway, sometimes you need to get the work done and resort to client-side scripting. PowerShell to the rescue.
Note #2: This post also serves as an example of what you need to configure when running PowerShell scripts in the task sequence as a different user.
Update December 9, 2023: Added a section for MDT Lite Touch, the main article is for ConfigMgr.
Download the script: https://github.com/DeploymentResearch/DRFiles/blob/master/Scripts/AddComputerToADGroup/AddComputerToADGroup.ps1
Prerequisites
For the script to work you obviously need have an Active Directory group created, and you need to have a service account that has permissions to add machines to that group. In my example I created a user account named AD_SA and a global security group named ViaMonstra Computers.
Permissions
The service account used to add the computer to the group needs permission to do so in Active Directory. The account needs to have Read Members and Write Members permissions on the group, in this case on the ViaMonstra Computers group.

Addin the script to the Task Sequence
Adding the script to the task sequence is quite straightforward, and ConfigMgr offers multiple options of running scripts in a task sequence. You have the Run PowerShell Script action, or the old school Run Command Line action to choose from. Now, for a small script like this I would prefer to use the Run PowerShell Script action since it allows me to embed the script in the task sequence itself, removing the need for me to create a package, and distribute the package to all my DPs.
The fine print: Sounds pretty easy, right? Well, since I'm running a client-side script, I need to authenticate as the service account, and when doing so I will be running as a normal user account. This account will actually not have access to the location the ConfigMgr Client is storing embedded task sequence scripts. Meaning the C:\WINDOWS\TEMP\SMSTSPowerShellScripts folder. So, to fix this you need to temporarily grant the service account local admin rights, and then when the script has completed, remove the rights.
Step 1. Add a Run Command Line action, name it Add Service Account to Admin Group, and set the following command line: net localgroup administrators /add VIAMONSTRA\AD_SA
Step 2, Add a Run PowerShell Script action, name it Add Computer to AD Group, paste the script in the Enter a PowerShell script area, and add the following parameters: -GroupName 'ViaMonstra Computers'
Note: Since the group name had spaces in it, I had to surround the name with single quotes.
Set the PowerShell execution policy to Bypass, and configure the Add Computer to AD Group action to run as the VIAMONSTRA\AD_SA service account.
Step 3, Add a Run Command Line action, name it Remove Service Account from Admin Group, and set the following command line: net localgroup administrators /delete VIAMONSTRA\AD_SA

MDT Lite Touch
If using MDT Lite Touch, you have to use a slightly different command:
Powershell.exe -ExecutionPolicy Bypass -Command "New-Item -Path C:\temp -ItemType Directory -Force;Copy-Item '%SCRIPTROOT%\AddComputerToADGroup.ps1' -Destination C:\Temp; C:\Temp\AddComputerToADGroup.ps1 -GroupName 'ViaMonstra Computers'; Remove-Item C:\Temp\AddComputerToADGroup.ps1 -Force"

Troubleshooting Reference
Here is the smsts.log file showing the error you will see when running a PowerShell script as a different user that is not a local admin on the device:

Hey Johan, this script is working great for one of our domains, but, if I try putting in a group that is not on the primary domain, it fails with "Grouo not found, aborting…" Is there a specific way to denote the domain\group in the script so that it knows where to find the AD group?
The script can probably be updated to support that, but I would need access to the environment, so more likely part of a support engagement.
Hey Johan I'm attempting to use your method above to add a newly imaged system to an AD group as the final step in my OSD, and I'm getting this error – C:\WINDOWS\TEMP\SMSTSPowerShellScripts\{9B83C4C3-BFC0-436A-A881-467E859FEF87}.PS1 : A positional parameter cannot be RunPowerShellScript 1/10/2025 12:33:50 PM 5456 (0x1550) found that accepts argument 'Domain'. RunPowerShellScript 1/10/2025 12:33:50 PM 5456 (0x1550) At line:1 char:1 RunPowerShellScript 1/10/2025 12:33:50 PM 5456 (0x1550) + & 'C:\WINDOWS\TEMP\SMSTSPowerShellScripts\{9B83C4C3-BFC0-436A-A881-46 … RunPowerShellScript 1/10/2025 12:33:50 PM 5456 (0x1550) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RunPowerShellScript 1/10/2025 12:33:50 PM 5456 (0x1550) + CategoryInfo : InvalidArgument: (:) [{9B83C4C3-BFC0-…7E859FEF87}.PS1], ParameterBindingException RunPowerShellScript 1/10/2025 12:33:50 PM 5456 (0x1550) + FullyQualifiedErrorId : PositionalParameterNotFound,{9B83C4C3-BFC0-436A-A881-467E859FEF87}.PS1 RunPowerShellScript… Read more »
Try using a group name without a space to see if that's the issue.
A few things. First You don't need the account added as a local administrator. Just let it run as System, and have a means to get the service account credential object (preferably a secrets store like Azure Key Vault, Keepass, etc something the PowerShell.Secrets.Management module can hook into) Then here $Group = [ADSI]"$GroupDn" Replace it with (Assuming you have pulled $Credential as a [PSCredential] object) $Group = [ADSI]::new( $GroupDN, $Credential. UserName, $Credential. GetNetworkCredential( ). Password ) Now that [System.DirectoryServices.DirectoryEntry] will self contain the credentials and will pass them along to AD for any operations you need to do. Just be… Read more »
Thanks for the info!
Hello I'm getting the below error when running from SCCM OSD. Any ideas? I've confirmed the user referenced can in fact add computer objects into the group that's referenced. At C:\WINDOWS\TEMP\SMSTSPowerShellScripts\{1606D456-B7E9-47A8-84EB-09B08C4C8983}.PS1:5 char:1 RunPowerShellScript 8/20/2024 8:53:32 AM 2896 (0x0B50) + [CmdletBinding()] RunPowerShellScript 8/20/2024 8:53:32 AM 2896 (0x0B50) + ~~~~~~~~~~~~~~~~~ RunPowerShellScript 8/20/2024 8:53:32 AM 2896 (0x0B50) Unexpected attribute 'CmdletBinding'. RunPowerShellScript 8/20/2024 8:53:32 AM 2896 (0x0B50) At C:\WINDOWS\TEMP\SMSTSPowerShellScripts\{1606D456-B7E9-47A8-84EB-09B08C4C8983}.PS1:6 char:1 RunPowerShellScript 8/20/2024 8:53:32 AM 2896 (0x0B50) + param( RunPowerShellScript 8/20/2024 8:53:32 AM 2896 (0x0B50) + ~~~~~ RunPowerShellScript 8/20/2024 8:53:32 AM 2896 (0x0B50) Unexpected token 'param' in expression or statement. RunPowerShellScript 8/20/2024 8:53:32 AM 2896… Read more »
Hi Erick,
Hard to tell from the error message you sent. Use this technique to open a PowerShell prompt as the task sequence, and run the script interactively. https://www.deploymentresearch.com/troubleshooting-cm2012-task-sequence-actions-using-serviceui/
Hi Johan,
How do I add the device to multiple groups?
Either you modify the script to accept multiple groups, or simply run it multiple times, but with different group names as parameter.
Hollo Johan,
It's working, but my MDT ending with this warning:
ZTI ERROR – Unhandled error returned by ZTIGather: Out of memory (7) FAILURE: 7: Running wscript.exe
Do you know how it solve?
Thank you
Hi Tomas, have not seen that error. How much memory does the machine have? (if you're testing in a VM, make sure it's not configure for dynamic memory)
Is there a way to embed the username and password in the script rather than using the run as functionality built into the task sequence? The reason for this is that I'm trying to use it on a non OSD task sequence and I get an error because the account doesn't have interactive login. This same account works fine when run from a normal OSD task sequence and it's not easy getting approval for interactive login. I've tried embedding it with a very basic script that calls the PowerShell AD module and it works, but I'm trying to avoid having… Read more »
Sure, you can embed credentials in the script, but in general its more secure to keep them as variables.
Is there a way to make Primary group for the specific computer ?
Not that I know…
The script is not consistent for me and mostly fails. I see this in the SMSTS.log: Process completed with exit code 1 Retrieving the COM class factory for component with CLSID {00000000-0000-0000-0000-000000000000} failed due to the following error: 80070005 Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)). PowerShell command line returned code 1 Process completed with exit code 1 ….and the machine does not get added to the group I assume this happens because we are using a RUN-AS account and it is trying to access the TS environment and fails: $TSEnv = New-Object -ComObject Microsoft.SMS.TSEnvironment -ErrorAction SilentlyContinue Any way… Read more »
The service account you use must be added (temporarily) to the local admin groups, and have the required permissions in AD. If you login as that service account on a device, can you run the script then? (for troubleshooting)
Thanks for the response. I can confirm that the service account gets added to local admin before the script runs, and that account has the required AD permissions. If I login with the account and run the script it works as expected, but does not work in the the task sequence. I will try and capture the exception to see why it exits in the TS with an error code 1. I can see the log file in C:\Windows\Temp, so it must be exited on the main part of the script where it has the exception and exit of 1
I think I've found the issue. It was installing this after a sub task sequence full of apps, and if I removed that sub task sequence it works. This has security related software in and I can only assume that it was interfering with script running successfully, so I've moved the script before it installs any apps.
Hello,
I tried your script with MDT, with "Run command line" :
Powershell.exe -ExecutionPolicy Bypass -File "%SCRIPTROOT%\AddComputerToADGroup.ps1" -GroupMember "mygroup" with the another user's checkbox checked.
Unfortunately, the script doesn't run. I see warning mentionning " is not digitally signed. You cannot run this script on the current system.".
Running manually with the account used in the "Run Command Line" the command Powershell.exe -ExecutionPolicy Bypass -File "%SCRIPTROOT%\AddComputerToADGroup.ps1" -GroupMember "mygroup" with %SCRIPTROOT% replaced is working.
Do you know how to solve it ? Thanks a lot for your work.
If using ConfigMgr, make sure to change the police on the Run PowerShell Script step to Bypass.
Hello, i'm only using MDT with "Run Command Line", Powershell.exe -ExecutionPolicy Bypass -File "%SCRIPTROOT%\AddComputerToADGroup.ps1" -GroupMember "mygroup" ;
with the another user's checkbox checked with credentials.
When i run this script as this user, it's working, but not with MDT. Looks like -Bypass isn't working
Ah, for MDT Lite Touch, you have to run a different command:
Powershell.exe -ExecutionPolicy Bypass -Command "New-Item -Path C:\temp -ItemType Directory -Force;Copy-Item '%SCRIPTROOT%\AddComputerToADGroup.ps1' -Destination C:\Temp; C:\Temp\AddComputerToADGroup.ps1 -GroupName 'ViaMonstra Computers'; Remove-Item C:\Temp\AddComputerToADGroup.ps1 -Force"
I have a lots of errors in the smsts.log At C:\Windows\TEMP\SMSTSPowerShellScripts\{424DE257-2F7C-4677-8330-D00D5E8D3FE7}.PS1:209 char:17 RunPowerShellScript 2023. 03. 10. 13:50:24 4056 (0x0FD8) + Sign up RunPowerShellScript 2023. 03. 10. 13:50:24 4056 (0x0FD8) + ~ RunPowerShellScript 2023. 03. 10. 13:50:24 4056 (0x0FD8) The ampersand (&) character is not allowed. The & operator is reserved for future use; wrap an amp RunPowerShellScript 2023. 03. 10. 13:50:24 4056 (0x0FD8) ersand in double quotation marks ("&") to pass it as part of a string. RunPowerShellScript 2023. 03. 10. 13:50:24 4056 (0x0FD8) At C:\Windows\TEMP\SMSTSPowerShellScripts\{424DE257-2F7C-4677-8330-D00D5E8D3FE7}.PS1:214 char:209 RunPowerShellScript 2023. 03. 10. 13:50:24 4056 (0x0FD8) + … k Button–medium Button d-lg-none color-fg-inherit p-1"> <span cla … RunPowerShellScript 2023. 03. 10. 13:50:24 4056 (0x0FD8) + ~ RunPowerShellScript 2023. 03. 10. 13:50:24 4056 (0x0FD8) The '<' operator is reserved for future use. RunPowerShellScript 2023.… Read more »
Sounds like a copy and paste issue of sorts. Does it work if you run it in full Windows via PowerShell ISE or VS Code?
Yes, it was a copy-paste error from the browser.
Thank a bunch for sharing this Johan. Implemented this in our organization – and it works like a charm! Note to anyone who stumbles upon this. Beware that when you get to this step: net localgroup administrators that it is language specific. For instance we deploy Windows 10/11 with danish language, and I had to change it to net localgroup administratorer to make it work. If you deploy another language than English – then check on a client – in a command prompt: net localgroup That will list the local groups and with the proper names to be used. Just… Read more »
Thank you very much Johan, fortunately you shared this article ! I was looking for a fix since this morning.
Thanks Johan, for your dedicated supports and efforts.
matt