{"id":3559,"date":"2021-07-12T07:49:26","date_gmt":"2021-07-12T05:49:26","guid":{"rendered":"https:\/\/www.msb365.blog\/?p=3559"},"modified":"2021-07-13T11:39:12","modified_gmt":"2021-07-13T09:39:12","slug":"net-assemblies-in-powershell-part-3-create-active-directory-objects","status":"publish","type":"post","link":"https:\/\/www.msb365.blog\/?p=3559","title":{"rendered":".NET Assemblies In PowerShell &#8211; Part 3: Create Active Directory objects"},"content":{"rendered":"<p>In the first parts of the series &#8220;.NET Assemblies In PowerShell&#8221;, I wrote about managing existing Active Directory groups and user accounts without the PowerShell ActiveDirectory module.<\/p>\n<p>This time, I will show you how you can create new Active Directory objects with PowerShell by using the namespace <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.directoryservices.accountmanagement?view=netframework-4.7.2\"><em>System.DirectoryServices.AccountManagement<\/em><\/a>. This namespace is available on any Windows computer by default.<\/p>\n<p>As a prerequisite I recommend to read the first two parts of this series:<\/p>\n<p><a href=\"https:\/\/www.msb365.blog\/?p=1776\">Part 1: Manage Active Directory groups<\/a><br \/>\n<a href=\"https:\/\/www.msb365.blog\/?p=3261\">Part 2: Manage Active Directory group members and user accounts\u00a0<\/a><\/p>\n<p>If you want to skip this, that\u00b4s fine. Just know that the base of all this is the above mentioned namespace.<\/p>\n<p>If you want to skip all the technical details and you are only here to grab some code, that\u00b4s fine too. In this case, you can just go to <a href=\"#Functions\">functions<\/a>.<\/p>\n<h4>The name space<\/h4>\n<p>To add the namespace to your Powershell script, use the command:<\/p>\n<pre>Add-Type -AssemblyName System.DirectoryServices.AccountManagement\r\n<\/pre>\n<h4>Create a new Active Directory user account<\/h4>\n<p>To create a new account in Active Directory, we have to do two things in advance: Define the domain and set the organizational unit in which we want the new account to be created in.<\/p>\n<h5>Preparations<\/h5>\n<p>If we want to use the domain that we are currently logged on to, we can get it by using the <em><a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.directoryservices.activedirectory.domain.getcurrentdomain?view=netframework-4.7.2#System_DirectoryServices_ActiveDirectory_Domain_GetCurrentDomain\">GetCurrentDomain<\/a> <\/em>method of the <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.directoryservices.activedirectory.domain\"><em>System.DirectoryServices.ActiveDirectory.Domain<\/em><\/a> class.<\/p>\n<pre>#Get the current domain\r\n$dom = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()\r\n<\/pre>\n<p>This creates a new object of type <em><a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.directoryservices.activedirectory.domain\">Domain<\/a><\/em>, from which we only need the name right now. Therefore, we\u00b4ll grab only the name property.<\/p>\n<pre>#store domain name\r\n$domname = $dom.name<\/pre>\n<p>If you don\u00b4t want the domain name to be set dynamically, you can just define a fixed name in the format &#8220;contoso.com&#8221;<\/p>\n<pre>#Set fixed domain name \r\n$domname = \"lab.net\"<\/pre>\n<p>For the organizational unit we just need to provide its distinguished name as a string.<\/p>\n<pre>#Define the OU in which the user account will be created\r\n$OU = \"OU=Users,DC=lab,DC=net\"<\/pre>\n<p>Next, we\u00b4re going to create a <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.directoryservices.accountmanagement.principalcontext\"><em>PrincipalContext<\/em> <\/a>object. This object sets the target location in Active Directory, where the new account will be inserted.<\/p>\n<h5>Create the object<\/h5>\n<p>The constructor for our purpose needs the parameters <em><a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.directoryservices.accountmanagement.contexttype?view=netframework-4.7.2\">ContextType<\/a><\/em>, <em>Name <\/em>and <em>Container<\/em> . The <em><a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.directoryservices.accountmanagement.contexttype?view=netframework-4.7.2\">ContextType<\/a> <\/em>in this case is &#8220;Domain&#8221;. The parameter &#8220;Name&#8221; refers to the domain name and &#8220;Container&#8221; is the distinguished name of the organizational unit.<\/p>\n<p>Since we already stored this info, we can use the domain name and organizational unit variables from before to create the object:<\/p>\n<pre>#Create the PrincipalContext object\r\n$pc = [System.DirectoryServices.AccountManagement.PrincipalContext]::` \r\nnew([System.DirectoryServices.AccountManagement.ContextType]::Domain,$domname,$OU)\r\n<\/pre>\n<p>Because <em><a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.directoryservices.accountmanagement.contexttype?view=netframework-4.7.2\">ContextType<\/a> <\/em>is just an enumerator with the values &#8220;Machine&#8221;, &#8220;Domain&#8221; and &#8220;ApplicationDirectory&#8221;, we can also just use the string &#8220;Domain&#8221; as the <em><a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.directoryservices.accountmanagement.contexttype?view=netframework-4.7.2\">ContextType<\/a>\u00a0<\/em>to simplify the lines:<\/p>\n<pre>#Create the PrincipalContext object\r\n$pc = [System.DirectoryServices.AccountManagement.PrincipalContext]::new(\"Domain\",$domname,$OU)<\/pre>\n<p>Looks a little tidier, right?<\/p>\n<p>Now, we are all set to create new Active Directory user accounts using our <em><a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.directoryservices.accountmanagement.principalcontext\">PrincipalContext<\/a> <\/em>object.<\/p>\n<p>First, we initialize an object of type <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.directoryservices.accountmanagement.userprincipal\"><em>UserPrincipal<\/em><\/a>, while passing the <em>PrincipalContext<\/em> object as a parameter to the constructor<em>.<\/em><\/p>\n<pre>#Initialize a new UserPrincipal object with the PrincipalContext from before\r\n$user = [System.DirectoryServices.AccountManagement.UserPrincipal]::new($pc)<\/pre>\n<p>We now basically have an empty user account object, besides domain and organizational attributes.<\/p>\n<pre>#Check the new user object\r\nPS C:\\windows\\system32&gt; $user\r\n\r\nGivenName : \r\nMiddleName : \r\nSurname : \r\nEmailAddress : \r\nVoiceTelephoneNumber : \r\nEmployeeId : \r\nAdvancedSearchFilter : System.DirectoryServices.AccountManagement.AdvancedFilters\r\nEnabled : \r\nAccountLockoutTime : \r\nLastLogon : \r\nPermittedWorkstations : \r\nPermittedLogonTimes : \r\nAccountExpirationDate : \r\nSmartcardLogonRequired : False\r\nDelegationPermitted : False\r\nBadLogonCount : 0\r\nHomeDirectory : \r\nHomeDrive : \r\nScriptPath : \r\nLastPasswordSet : \r\nLastBadPasswordAttempt : \r\nPasswordNotRequired : False\r\nPasswordNeverExpires : False\r\nUserCannotChangePassword : False\r\nAllowReversiblePasswordEncryption : False\r\nCertificates : {}\r\nContext : System.DirectoryServices.AccountManagement.PrincipalContext\r\nContextType : Domain\r\nDescription : \r\nDisplayName : \r\nSamAccountName : \r\nUserPrincipalName : \r\nSid : \r\nGuid : \r\nDistinguishedName : \r\nStructuralObjectClass : \r\nName :<\/pre>\n<p>We can see that everything is empty, except of the domain name and the container in the context property:<\/p>\n<pre>PS C:\\windows\\system32&gt; $user.Context\r\n\r\nContextType : Domain\r\nName : lab.net\r\nContainer : OU=USERS,DC=lab,DC=net\r\nUserName : \r\nOptions : Negotiate, Signing, Sealing\r\nConnectedServer :<\/pre>\n<p>&nbsp;<\/p>\n<p>Now, let\u00b4s give this user some attributes.<\/p>\n<h5>Fill the attributes<\/h5>\n<p>The attributes are accessible as properties of the <em><a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.directoryservices.accountmanagement.userprincipal\">UserPrincipal<\/a> <\/em>object through dot notation.<\/p>\n<pre>#Set some attributes for the account\r\n$user.Surname = \"User123\"\r\n$user.GivenName = \"Test\"\r\n$user.DisplayName = \"Test User123\"\r\n$user.Name = \"Test User123\"\r\n$user.Description = \"Test account MSB365\"\r\n$user.UserPrincipalName = \"test.user123@lab.net\"\r\n$user.SamAccountName = \"test.user123\"\r\n$user.SetPassword(\"P@ssW0rd1234\")<\/pre>\n<p>By default the user is disabled. So, don\u00b4t forget to set the &#8220;enabled&#8221; attribute to true:<\/p>\n<pre>#Enable the user\r\n$user.Enabled = $true\r\n\r\n<\/pre>\n<p>The option &#8220;User must change password at next logon&#8221; will automatically be set.<\/p>\n<h5>Finalize<\/h5>\n<p>If we are sure, that the user account is set with everything it needs, we can save it. This will actually create it in our Active Directory.<\/p>\n<pre>#Save the user to AD\r\n$user.Save()\r\n\r\n<\/pre>\n<p>If we want to verify the result, we can just search the account in Active Directory:<\/p>\n<pre># Find the user in AD by SAMAccountName\r\n# using the PrincipalContext object from before and the SAMAccountname of the new account\r\nPS C:\\windows\\system32&gt; [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($pc,\"test.user123\")\r\nGivenName : Test\r\nMiddleName : \r\nSurname : User123\r\nEmailAddress : \r\nVoiceTelephoneNumber : \r\nEmployeeId : \r\nAdvancedSearchFilter : System.DirectoryServices.AccountManagement.AdvancedFilters\r\nEnabled : False\r\nAccountLockoutTime : \r\nLastLogon : \r\nPermittedWorkstations : {}\r\nPermittedLogonTimes : \r\nAccountExpirationDate : \r\nSmartcardLogonRequired : False\r\nDelegationPermitted : True\r\nBadLogonCount : 0\r\nHomeDirectory : \r\nHomeDrive : \r\nScriptPath : \r\nLastPasswordSet : \r\nLastBadPasswordAttempt : \r\nPasswordNotRequired : True\r\nPasswordNeverExpires : False\r\nUserCannotChangePassword : False\r\nAllowReversiblePasswordEncryption : False\r\nCertificates : {}\r\nContext : System.DirectoryServices.AccountManagement.PrincipalContext\r\nContextType : Domain\r\nDescription : Test account MSB365\r\nDisplayName : Test User123\r\nSamAccountName : test.user123\r\nUserPrincipalName : Test.User123@lab.net\r\nSid : S-1-5-21-4025995969-482537669-3923321509-xxxx\r\nGuid : 79556f9a-9af5-4fff-8cee-062731a91b03\r\nDistinguishedName : CN=Test User123,CN=Users,DC=lab,DC=net\r\nStructuralObjectClass : user\r\nName : Test User123\r\n\r\n<\/pre>\n<p>There you go. We created a new Active Directory user account. Now, let\u00b4s create an Active Directory group.<\/p>\n<h4>Create a new Active Directory group<\/h4>\n<h5>Preparations<\/h5>\n<p>The preparation here is the same as for creating Active Directory accounts. We need to create the <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.directoryservices.accountmanagement.principalcontext\"><em>PrincipalContext<\/em><\/a> object with our domain name and organizational unit in which the group should be created.<\/p>\n<pre>#Get the current domain \r\n$dom = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()\r\n\r\n#store the domain name\r\n$domname = $dom.name<\/pre>\n<p>Set the path of the organizational unit :<\/p>\n<pre>#Define the OU in which the group will be created\r\n$OU = \"OU=Groups,DC=lab,DC=net\"<\/pre>\n<h5>Create the object<\/h5>\n<p>Here, instead of initializing an <em>UserPrincipal<\/em> object, we create a <em><a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.directoryservices.accountmanagement.groupprincipal?view=netframework-4.7.2\">GroupPrincipal<\/a> <\/em>object:<\/p>\n<pre>#Initialize a new GroupPrincipal object with the PrincipalContext from before\r\n$group = [System.DirectoryServices.AccountManagement.GroupPrincipal]::new($pc)<\/pre>\n<p>And again, we have a nearly empty object, which is waiting to be filled with attributes. Let\u00b4s not let it wait any longer&#8230;<\/p>\n<h5>Fill the attributes<\/h5>\n<pre>#Since I\u00b4ll use the group name for multiple attributes I just store it to a variable \r\n$groupname = \"test-group-MSB365_001\"\r\n\r\n#Set the groups attributes\r\n$group.Description = \"Test group MSB365\"\r\n$group.SamAccountName = $groupname\r\n$group.DisplayName = $groupname\r\n$group.GroupScope = \"Global\" #Valid values are: \"Global\", \"Local\", \"Universal\"\r\n$group.IsSecurityGroup = $true<\/pre>\n<h5>Finalize<\/h5>\n<p>And with all necessary attributes set, we can save the group to Active Directory:<\/p>\n<pre>#Save the group to AD\r\n$group.Save()<\/pre>\n<p>Let\u00b4s check the new group and its attributes:<\/p>\n<pre>PS C:\\windows\\system32&gt; [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($pc, $groupname)\r\n\r\nIsSecurityGroup : True\r\nGroupScope : Global\r\nMembers : {}\r\nContext : System.DirectoryServices.AccountManagement.PrincipalContext\r\nContextType : Domain\r\nDescription : Test group MSB365\r\nDisplayName : test-group-MSB365_001\r\nSamAccountName : test-group-MSB365_001\r\nUserPrincipalName : \r\nSid : S-1-5-21-4025995969-482537669-3923321509-xxxxx\r\nGuid : 267c6d7e-5981-4169-8c65-10e8cc3cc45a\r\nDistinguishedName : CN=test-group-MSB365_001,OU=GROUPS,DC=lab,DC=net\r\nStructuralObjectClass : group\r\nName : test-group-MSB365_001<\/pre>\n<p>And there\u00b4s our group.<\/p>\n<p>If you want to know how to add members to our new group, you can read the how-to in<a href=\"https:\/\/www.msb365.blog\/?p=1776\"> part 1<\/a> of this series.<\/p>\n<p>&nbsp;<\/p>\n<h4>Extended properties<\/h4>\n<p>The UserPrincipal and the GroupPrincipal classes might not provide all attributes which we want to set on a new Active Directory object. For instance the &#8220;mail&#8221; attribute is not directly accessible. To set values for those attributes, we can access the underlying Active Directory object, after we have saved the PrincipalObject.<\/p>\n<p>To do so, we use the <em><a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.directoryservices.accountmanagement.principal.getunderlyingobject?view=netframework-4.7.2#System_DirectoryServices_AccountManagement_Principal_GetUnderlyingObject\">GetUnderlyingObject<\/a> <\/em>method of the <em>PrincipalObject<\/em>. Here\u00b4s an example how to add an e-mail address to the &#8220;mail&#8221; attribute of our new group.<\/p>\n<pre>#Get underlying AD object\r\n$adobject = $group.GetUnderlyingObject()\r\n<\/pre>\n<p>This will get us to the <em><a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.directoryservices.directoryentry?view=netframework-4.7.2\">DirectoryEntry<\/a> <\/em>object through which we can access the Active Directory object more directly. To get a list of all its properties and their values, we can access its property <em><a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.directoryservices.directoryentry.properties?view=netframework-4.7.2\">Properties<\/a><\/em>. Properties will give us back a <em><a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.directoryservices.propertycollection?view=netframework-4.7.2\">PropertyCollection<\/a> <\/em>object.<\/p>\n<pre>#Get current properties\r\n$adobject.Properties\r\n#Get only the property names\r\nPS C:\\Windows\\system32&gt;$adobject.Properties.PropertyNames\r\nobjectClass\r\ncn\r\ndistinguishedName\r\ninstanceType\r\nwhenCreated\r\nwhenChanged\r\ndisplayName\r\nuSNCreated\r\nuSNChanged\r\nnTSecurityDescriptor\r\nname\r\nobjectGUID\r\nobjectSid\r\nsAMAccountName\r\nsAMAccountType\r\ngroupType\r\nobjectCategory\r\ndSCorePropagationData\r\n<\/pre>\n<p>We can see, that the &#8220;mail&#8221; attribute is not in the list. To add it, we use the <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.directoryservices.propertycollection.system-collections-idictionary-add?view=netframework-4.7.2\"><em>Add<\/em><\/a> method, while indexing the property by name:<\/p>\n<pre>PS C:\\Windows\\system32&gt; $adobject.Properties[\"mail\"].Add(\"test-group-MSB365_001@lab.net\")\r\n0\r\n<\/pre>\n<p>The return code &#8220;0&#8221; tells us that everything went fine and the attribute could be set.<br \/>\nAs last step, we have to save the object by calling the method <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.directoryservices.directoryentry.commitchanges?view=netframework-4.7.2\"><em>CommitChanges<\/em><\/a>:<\/p>\n<pre>PS C:\\Windows\\system32&gt; $adobject.CommitChanges()\r\n<\/pre>\n<p>When we check in Active Directory now, we can see the group exists and that it has an e-mail address:<\/p>\n<p><img fetchpriority=\"high\" decoding=\"async\" class=\"alignnone size-full wp-image-4539\" src=\"https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2021\/06\/Screenshot-new-group-with-mail.png\" alt=\"\" width=\"401\" height=\"242\" srcset=\"https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2021\/06\/Screenshot-new-group-with-mail.png 401w, https:\/\/msb365.abstergo.ch\/wp-content\/uploads\/2021\/06\/Screenshot-new-group-with-mail-300x181.png 300w\" sizes=\"(max-width: 401px) 100vw, 401px\" \/><\/p>\n<p>This works the same way for user accounts, too. The attribute just has to be present in the Active Directory schema.<\/p>\n<h4 id=\"Functions\">As functions<\/h4>\n<h5>Create an Active Directory user account<\/h5>\n<pre>Function cCreate-ADUser {\r\n    Param(\r\n        [Parameter(Mandatory=$true,\r\n        ValueFromPipeline=$true, HelpMessage=\"Enter surname for the new user\")]\r\n        [String]\r\n        $surname,\r\n\r\n        [Parameter(Mandatory=$true,\r\n        ValueFromPipeline=$true, HelpMessage=\"Enter givenname for the new user\")]\r\n        [String]\r\n        $givenname,\r\n\r\n        [Parameter(Mandatory=$false,\r\n        ValueFromPipeline=$true, HelpMessage=\"Enter a description for the new user\")]\r\n        [String]\r\n        $description,\r\n\r\n        [Parameter(Mandatory=$false,\r\n        ValueFromPipeline=$true, HelpMessage=\"Enter a initial password for the new user. Default password will be used if left blank.\")]\r\n        [String]\r\n        $InitialPW\r\n   )\r\n    \r\n    #use default password as initial password or use provided\r\n    if ($InitialPW){\r\n        $password = $InitialPW\r\n    }Else{\r\n        $password = \"P@ssW0rd1234\"\r\n    }\r\n\r\n    #Add the assembly\r\n    Add-Type -AssemblyName System.DirectoryServices.AccountManagement\r\n\r\n    #Get the current domain\r\n    $dom = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()\r\n\r\n    #Set domain name\r\n    $domname = $dom.Name\r\n\r\n    #Define the container in which the user account will be created\r\n    $OU = \"OU=Users,\" + $dom.GetDirectoryEntry().distinguishedname\r\n\r\n    #Create the Principalcontext object\r\n    $pc = [System.DirectoryServices.AccountManagement.PrincipalContext]::new( `\r\n    [System.DirectoryServices.AccountManagement.ContextType]::Domain,$domname,$OU)\r\n\r\n    #Initialize the new UserPrincipal object with the Principalcontext from before\r\n    $user = [System.DirectoryServices.AccountManagement.UserPrincipal]::new($pc)\r\n\r\n    #Set the attributes of the user\r\n    $user.Surname = $surname\r\n    $user.GivenName = $givenname\r\n    $user.DisplayName = $givenname + \" \" + $surname\r\n    $user.Name = $givenname + \" \" + $surname\r\n    $user.Description = $description\r\n    $user.UserPrincipalName = $givenname + \".\" + $surname + \"@\" + $domname\r\n    $user.SamAccountName = $givenname + \".\" + $surname\r\n    $user.SetPassword($password)\r\n    #Enable the user\r\n    $user.Enabled = $true\r\n    #Save the user to AD\r\n    $user.Save()\r\n    \r\n    #clean up\r\n\t$user.Dispose()\r\n\t$pc.Dispose()\r\n    $dom.Dispose()\r\n\tReturn \"Done\"\r\n}\r\n<\/pre>\n<p>The function will create a new Active Directory user with surname, given name and description provided in the parameters. As SAMaccountName and UserPrincipalName it will use a combination of surname and givenname.<\/p>\n<p>You can set your own initial password through the parameter &#8220;InitialPW&#8221; as plain text string. If this parameter is left empty, the function will set a predefined password.<\/p>\n<p>Here\u00b4s an example how to create an account with the function, using a specific initial password:<\/p>\n<pre>PS C:\\Windows\\system32&gt; cCreate-ADUser -surname TestMSB365 -givenname User01 -description \"test user MSB365\" -InitialPW \"W\u20aclc0me2021!\"<\/pre>\n<h5>Create an Active Directory group<\/h5>\n<pre>Function cCreate-ADGroup {\r\n    Param(\r\n        [Parameter(Mandatory=$true,\r\n        ValueFromPipeline=$true, HelpMessage=\"Enter a name for the new group\")]\r\n        [String]\r\n        $groupname,\r\n\r\n        [Parameter(Mandatory=$true,\r\n        ValueFromPipeline=$true, HelpMessage=\"Enter a description for the new group\")]\r\n        [String]\r\n        $description,\r\n\r\n        [Parameter(Mandatory=$false,\r\n        ValueFromPipeline=$true, HelpMessage=\"Enter a group scope for the new group\")]\r\n        [ValidateSet(\"Global\", \"Local\", \"Universal\")]\r\n        [String]\r\n        $Scope = \"Global\",\r\n\r\n        [Parameter(Mandatory=$false,\r\n        ValueFromPipeline=$true, HelpMessage=\"Choose if group is security group. If not set a distribution group will be created\")]\r\n        [Switch]\r\n        $IsSecurityGroup,\r\n\r\n        [Parameter(Mandatory=$false,\r\n        ValueFromPipeline=$true, HelpMessage=\"Only for distribution groups: Enter an e-mail address for the new group. If not specified groupname@domainname will be used.\")]\r\n        [String]\r\n        $mail\r\n   )\r\n    \r\n    \r\n    #Add the assembly\r\n    Add-Type -AssemblyName System.DirectoryServices.AccountManagement\r\n\r\n    #Get the current domain\r\n    $dom = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()\r\n\r\n    #Set domain name\r\n    $domname = $dom.Name\r\n\r\n    \r\n    #Define the container in which the group will be created\r\n    $OU = \"OU=Groups,\" + $dom.GetDirectoryEntry().distinguishedname\r\n    \r\n    #Create the Principalcontext object\r\n    $pc = [System.DirectoryServices.AccountManagement.PrincipalContext]::new( `\r\n    [System.DirectoryServices.AccountManagement.ContextType]::Domain,$domname,$OU)\r\n\r\n    #Initialize the new GroupPrincipal object with the PrincipalContext from before\r\n    $group = [System.DirectoryServices.AccountManagement.GroupPrincipal]::new($pc)\r\n\r\n    #Set the attributes of the group\r\n    \r\n    $group.DisplayName = $groupname\r\n    $group.Description = $description\r\n    $group.SamAccountName = $groupname\r\n    $group.IsSecurityGroup = $IsSecurityGroup.IsPresent\r\n    $group.GroupScope = $Scope\r\n    \r\n    \r\n    #Save the group to AD\r\n    $group.Save()\r\n\r\n    #Set e-mail address if group type is distribution group\r\n    if (!$IsSecurityGroup){\r\n        #Generate e-mail address if none provided\r\n        If (!$mail){\r\n            $mail = $groupname + \"@\" + $domname\r\n        }\r\n        #get underlying AD object\r\n        $adobject = $group.GetUnderlyingObject()\r\n        #Add mail property and save\r\n        $result = $adobject.Properties[\"mail\"].Add($mail)\r\n        $adobject.CommitChanges()\r\n    }\r\n    \r\n    #clean up\r\n\t$group.Dispose()\r\n\t$pc.Dispose()\r\n    $dom.Dispose()\r\n\tReturn \"Done\"\r\n}\r\n<\/pre>\n<p>This function creates an Active Directory group, while using the value in the parameter &#8220;Groupname&#8221; as SAMaccountName and DisplayName. If the switch parameter &#8220;IsSecurityGroup&#8221; is not set a distribution group will be created. Then, you can also provide an e-mail address. If none is provided, the function will build one using the group name and the domain name of the current domain.<\/p>\n<p>Here\u00b4s an example how to create a distribution group with a specified mail address:<\/p>\n<pre>cCreate-ADGroup -groupname testgroup-msb365_002 -description \"test distgrp MSB365\" -Scope Universal -mail \"testgroup.msb365@lab.net\"<\/pre>\n<p>And here\u00b4s how to create a simple global security group:<\/p>\n<pre>PS C:\\Windows\\system32&gt; cCreate-ADGroup -groupname testgroup-msb365_003 -description \"test sec group global MSB365\" -Scope Global -IsSecurityGroup<\/pre>\n<h4>Further info<\/h4>\n<p>The <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.directoryservices.accountmanagement?view=netframework-4.7.2\" target=\"_blank\" rel=\"noopener noreferrer\">&#8220;System.DirectoryServices.AccountManagement&#8221; namespace<\/a><\/p>\n<p>The <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.directoryservices.accountmanagement.principalcontext?view=netframework-4.7.2\" target=\"_blank\" rel=\"noopener noreferrer\">PrincipalContext class<\/a><\/p>\n<p>The\u00a0<a href=\"https:\/\/docs.microsoft.com\/en-us\/powershell\/module\/microsoft.powershell.utility\/add-type?view=powershell-5.0\" target=\"_blank\" rel=\"noopener noreferrer\">Add-Type cmdlet<\/a><\/p>\n<p><a href=\"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2010\/11\/11\/use-powershell-to-work-with-the-net-framework-classes\/\" target=\"_blank\" rel=\"noopener noreferrer\">How to work with .Net classes in PowerShell<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the first parts of the series &#8220;.NET Assemblies In PowerShell&#8221;, I wrote about managing existing Active Directory groups and user accounts without the PowerShell ActiveDirectory module. This time, I will show you how you can create new Active Directory objects with PowerShell by using the namespace System.DirectoryServices.AccountManagement. This namespace is available on any Windows [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":4505,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_crdt_document":"","om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[685,3],"tags":[],"class_list":["post-3559","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-active-directory","category-powershell"],"post_mailing_queue_ids":[],"_links":{"self":[{"href":"https:\/\/www.msb365.blog\/index.php?rest_route=\/wp\/v2\/posts\/3559","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.msb365.blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.msb365.blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.msb365.blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.msb365.blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3559"}],"version-history":[{"count":39,"href":"https:\/\/www.msb365.blog\/index.php?rest_route=\/wp\/v2\/posts\/3559\/revisions"}],"predecessor-version":[{"id":4586,"href":"https:\/\/www.msb365.blog\/index.php?rest_route=\/wp\/v2\/posts\/3559\/revisions\/4586"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.msb365.blog\/index.php?rest_route=\/wp\/v2\/media\/4505"}],"wp:attachment":[{"href":"https:\/\/www.msb365.blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3559"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.msb365.blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3559"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.msb365.blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3559"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}