AdsiPS.psm1
function Add-ADSIGroupMember { <# .SYNOPSIS Function to add a group member .DESCRIPTION Function to add a group member .PARAMETER Identity Specifies the Identity of the group You can provide one of the following properties DistinguishedName Guid Name SamAccountName Sid UserPrincipalName Those properties come from the following enumeration: System.DirectoryServices.AccountManagement.IdentityType .PARAMETER Member Specifies the member account. Performing an Ambiguous Name Resolution LDAP query to find the account. http://social.technet.microsoft.com/wiki/contents/articles/22653.active-directory-ambiguous-name-resolution.aspx .PARAMETER Credential Specifies the alternative credential to use. By default it will use the current user windows credentials. .PARAMETER DomainName Specifies the alternative Domain where the user should be created By default it will use the current domain. .EXAMPLE Add-ADSIGroupMember -Identity TestADSIGroup -Member 'UserTestAccount1' Adding the User account 'UserTestAccount1' to the group 'TestADSIGroup' .EXAMPLE Add-ADSIGroupMember -Identity TestADSIGroup -Member 'GroupTestAccount1' Adding the Group account 'GroupTestAccount1' to the group 'TestADSIGroup' .EXAMPLE Add-ADSIGroupMember -Identity TestADSIGroup -Member 'ComputerTestAccount1' Adding the Computer account 'ComputerTestAccount1' to the group 'TestADSIGroup' .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)] $Identity, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$DomainName, $Member ) begin { $FunctionName = (Get-Variable -Name MyInvocation -Scope 0 -ValueOnly).Mycommand Write-Verbose -Message "[$FunctionName] Loading assembly System.DirectoryServices.AccountManagement" Add-Type -AssemblyName System.DirectoryServices.AccountManagement -ErrorAction Stop # Create Context splatting Write-Verbose -Message "[$FunctionName] Create context splatting" $ContextSplatting = @{ Contexttype = "Domain" } if ($PSBoundParameters['Credential']) { Write-Verbose -Message "[$FunctionName] Context splatting - Add Credential" $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { Write-Verbose -Message "[$FunctionName] Context splatting - Add DomainName" $ContextSplatting.DomainName = $DomainName } Write-Verbose -Message "[$FunctionName] Create New Principal Context using Context Splatting" $Context = New-ADSIPrincipalContext @ContextSplatting -ErrorAction Stop } process { try { # Resolving member # Directory Entry object Write-Verbose -Message "[$FunctionName] Copy Context splatting and remove ContextType property" $DirectoryEntryParams = $ContextSplatting $DirectoryEntryParams.remove('ContextType') Write-Verbose -Message "[$FunctionName] Create New Directory Entry using using the copied context" $DirectoryEntry = New-ADSIDirectoryEntry @DirectoryEntryParams # Principal Searcher Write-Verbose -Message "[$FunctionName] Create a System.DirectoryServices.DirectorySearcher" $DirectorySearcher = new-object -TypeName System.DirectoryServices.DirectorySearcher Write-Verbose -Message "[$FunctionName] Append DirectoryEntry to in the property SearchRoot of DirectorySearcher" $DirectorySearcher.SearchRoot = $DirectoryEntry # Adding an Ambiguous Name Resolution (ANR) LDAP Filter Write-Verbose -Message "[$FunctionName] Append LDAP Filter '(anr=$member)' to the property Filter of DirectorySearcher" $DirectorySearcher.Filter = "(anr=$member)" # Retrieve a single object Write-Verbose -Message "[$FunctionName] Retrieve the account" $Account = $DirectorySearcher.FindOne().GetDirectoryEntry() if ($Account) { Write-Verbose -Message "[$FunctionName] Account Retrieved" switch ($Account.SchemaClassName) { 'user' { $member = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($Context, $Account.distinguishedname) } 'group' { $member = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($Context, $Account.distinguishedname) } 'computer' { $member = [System.DirectoryServices.AccountManagement.ComputerPrincipal]::FindByIdentity($Context, $Account.distinguishedname) } } } else { Write-Error -Message "[$FunctionName] Can't retrieve the identity '$identity'" } if ($pscmdlet.ShouldProcess("$Identity", "Add Account member $member")) { Write-Verbose -Message "[$FunctionName] Retrieve group with the identity '$identity' using Get-ADSIGroup using the Context Splatting" $group = (Get-ADSIGroup -Identity $Identity @ContextSplatting -ErrorAction Stop) $group.members.add($Member) $group.Save() } } catch { $pscmdlet.ThrowTerminatingError($_) } } end { Write-Verbose -Message "[$FunctionName] Done." } } Function Compare-ADSITeamGroups { <# .SYNOPSIS Function to compare AD groups of a team .DESCRIPTION See if all your team's members have the same AD groups. Make a snapshot of your team's members current AD groups .PARAMETER Credential Specifies alternative credential .PARAMETER DomainName Specifies the Domain Name where the function should look .PARAMETER BaseGroupIdentity Specifies the Identity of one team's users group You can provide one of the following properties DistinguishedName Guid Name SamAccountName Sid UserPrincipalName Those properties come from the following enumeration: System.DirectoryServices.AccountManagement.IdentityType .PARAMETER TeamUsersIdentity Specifies the Identity of team's users (array) .EXAMPLE Compare-ADSITeamGroups -BaseGroupIdentity 'MainGroup' Get groups of all users in MainGroup .EXAMPLE Compare-ADSITeamGroups -TeamUsersIdentity @('User1','User2','User3') Get groups of all users in the array .EXAMPLE Compare-ADSITeamGroups -TeamUsersIdentity @('User1','User2','User3') -Credential (Get-Credential) Use a different credential to perform the comparison .EXAMPLE Compare-ADSITeamGroups -TeamUsersIdentity @('User1','User2','User3') -DomainName "CONTOSO.local" Use a different domain name to perform the comparison .EXAMPLE Compare-ADSITeamGroups -BaseGroupIdentity 'MainGroup' -DomainDistinguishedName 'DC=CONTOSO,DC=local' Use a different domain distinguished name to perform the comparison .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] param ( [Parameter(ParameterSetName = 'TeamUsers', Mandatory = $true)] [array]$TeamUsersIdentity, [Parameter(ParameterSetName = 'Identity', Mandatory = $true)] [string]$BaseGroupIdentity, [Alias('RunAs')] [System.Management.Automation.pscredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.pscredential]::Empty, [Alias('Domain')] [ValidateScript( { if ($_ -match '^(?:(?!-)[A-Za-z0-9-]{1,63}(?<!-)\.)+[A-Za-z]{2,6}$') { $true } else { throw ("DomainName must be FQDN. Ex: contoso.locale - Hostname like '{0}' is not working" -f $_) } })] [String]$DomainName ) begin { # Create Context splatting $ContextSplatting = @{ } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } } process { $AllUsersGroups = @() if ($PSBoundParameters['BaseGroupIdentity']) { $TeamUsersIdentity = @((Get-ADSIGroupMember -Identity ('{0}' -f $BaseGroupIdentity) -Recurse).SamAccountName) } $Result = @() $ResultUsersInfos = @() $ResultGoupsInfos = @() foreach ($User in $TeamUsersIdentity) { # Get all groups of a user $Usergroups = $null $UserInfos = Get-ADSIUser -Identity $user @ContextSplatting $Usergroups = Get-ADSIPrincipalGroupMembership -UserInfos $UserInfos $AllUsersGroups += $Usergroups $ResultUsersInfos += [pscustomobject]@{ SamAccountName = [string]$UserInfos.name DisplayName = [string]$UserInfos.description Groups = $Usergroups } } $AllUsersGroups = $AllUsersGroups | Sort-Object -Property name -Unique $ResultGoupsInfos += $AllUsersGroups $ResultAuditUsersGroups = @() foreach ($item in $ResultUsersInfos) { $Object = $null $Object = [ordered]@{} $Object.SamAccountName = $item.SamAccountName $Object.DisplayName = $item.DisplayName foreach ($group in $AllUsersGroups) { if ($item.Groups.name -contains $group.name) { $Object.$($group.name) = 'x' } else { $Object.$($group.name) = '' } } $ResultAuditUsersGroups += [pscustomobject]$Object } $Result += $ResultAuditUsersGroups, $ResultGoupsInfos $Result } } function Disable-ADSIComputer { <# .SYNOPSIS Function to disable a Computer Account .DESCRIPTION Function to disable a Computer Account .PARAMETER Identity Specifies the Identity of the Computer. You can provide one of the following properties DistinguishedName Guid Name SamAccountName Sid .PARAMETER Credential Specifies the alternative credential to use. By default it will use the current user windows credentials. .PARAMETER DomainName Specifies the alternative Domain. By default it will use the current domain. .EXAMPLE Disable-ADSIComputer TESTSERVER01 This command will disable the account TESTSERVER01 .EXAMPLE Disable-ADSIComputer TESTSERVER01 -whatif This command will emulate disabling the account TESTSERVER01 .EXAMPLE Disable-ADSIComputer TESTSERVER01 -credential (Get-Credential) This command will disable the account TESTSERVER01 using the alternative credential specified .EXAMPLE Disable-ADSIComputer TESTSERVER01 -credential (Get-Credential) -domain LazyWinAdmin.local This command will disable the account TESTSERVER01 using the alternative credential specified in the domain lazywinadmin.local .NOTES https://github.com/lazywinadmin/ADSIPS .LINK https://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.computerprincipal(v=vs.110).aspx #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)] $Identity, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$DomainName) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } } process { try { if ($pscmdlet.ShouldProcess("$Identity", "Disable Account")) { $Account = Get-ADSIComputer -Identity $Identity @ContextSplatting $Account.enabled = $false $Account.Save() } } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Disable-ADSIUser { <# .SYNOPSIS Function to Disable a User Account .DESCRIPTION Function to Disable a User Account .PARAMETER Identity Specifies the Identity of the User. You can provide one of the following properties DistinguishedName Guid Name SamAccountName Sid UserPrincipalName Those properties come from the following enumeration: System.DirectoryServices.AccountManagement.IdentityType .PARAMETER Credential Specifies the alternative credential to use. By default it will use the current user windows credentials. .PARAMETER DomainName Specifies the alternative Domain. By default it will use the current domain. .EXAMPLE Disable-ADSIUser fxtest02 This will disable the fxtest02 account .EXAMPLE Disable-ADSIUser fxtest02 -whatif This will emulate disabling the fxtest02 account .EXAMPLE Disable-ADSIUser fxtest02 -credential (Get-Credential) This will disable the fxtest02 account using the credential specified .EXAMPLE Disable-ADSIUser fxtest02 -credential (Get-Credential) -DomainName LazyWinAdmin.local This will disable the fxtest02 account using the credential specified in the domain LazyWinAdmin.local .NOTES https://github.com/lazywinadmin/ADSIPS .LINK https://msdn.microsoft.com/en-us/library/System.DirectoryServices.AccountManagement.UserPrincipal(v=vs.110).aspx #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)] $Identity, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$DomainName) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } } process { try { if ($pscmdlet.ShouldProcess("$Identity", "Disable Account")) { $Account = Get-ADSIUser -Identity $Identity @ContextSplatting $Account.Enabled = $false $Account.Save() } } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Enable-ADSIComputer { <# .SYNOPSIS Function to enable a Computer Account .DESCRIPTION Function to enable a Computer Account .PARAMETER Identity Specifies the Identity of the Computer. You can provide one of the following properties DistinguishedName Guid Name SamAccountName Sid .PARAMETER Credential Specifies the alternative credential to use. By default it will use the current user windows credentials. .PARAMETER DomainName Specifies the alternative Domain. By default it will use the current domain. .EXAMPLE Enable-ADSIComputer TESTSERVER01 This command will enable the account TESTSERVER01 .EXAMPLE Enable-ADSIComputer TESTSERVER01 -whatif This command will emulate disabling the account TESTSERVER01 .EXAMPLE Enable-ADSIComputer TESTSERVER01 -credential (Get-Credential) This command will enable the account TESTSERVER01 using the alternative credential specified .EXAMPLE Enable-ADSIComputer TESTSERVER01 -credential (Get-Credential) -domain LazyWinAdmin.local This command will enable the account TESTSERVER01 using the alternative credential specified in the domain lazywinadmin.local .NOTES https://github.com/lazywinadmin/ADSIPS .LINK https://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.computerprincipal(v=vs.110).aspx #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)] $Identity, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$DomainName) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } } process { try { if ($pscmdlet.ShouldProcess("$Identity", "enable Account")) { $Account = Get-ADSIComputer -Identity $Identity @ContextSplatting $Account.enabled = $true $Account.Save() } } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Enable-ADSIDomainControllerGlobalCatalog { <# .SYNOPSIS Function to enable the Global Catalog role on a Domain Controller .DESCRIPTION Function to enable the Global Catalog role on a Domain Controller .PARAMETER ComputerName Specifies the Domain Controller .PARAMETER Credential Specifies alternate credentials to use. Use Get-Credential to create proper credentials. .EXAMPLE Enable-ADSIDomainControllerGlobalCatalog -ComputerName dc1.ad.local Connects to remote domain controller dc1.ad.local using current credentials and enable the GC role. .EXAMPLE Enable-ADSIDomainControllerGlobalCatalog -ComputerName dc2.ad.local -Credential (Get-Credential SuperAdmin) Connects to remote domain controller dc2.ad.local using SuperAdmin credentials and enable the GC role. .NOTES https://github.com/lazywinadmin/ADSIPS Version History 1.0 Initial Version (Micky Balladelli) 1.1 Update (Francois-Xavier Cat) Rename from Enable-ADSIReplicaGC to Enable-ADSIDomainControllerGlobalCatalog Add New-ADSIDirectoryContext to take care of the Context Other minor modifications #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$ComputerName, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) process { try { $Context = New-ADSIDirectoryContext -ContextType 'DirectoryServer' @PSBoundParameters $DomainController = [System.DirectoryServices.ActiveDirectory.DomainController]::GetDomainController($context) if ($DomainController.IsGlobalCatalog()) { Write-Verbose -Message "[Enable-ADSIDomainControllerGlobalCatalog][PROCESS] $($DomainController.name) is already a Global Catalog" } else { Write-Verbose -Message "[Enable-ADSIDomainControllerGlobalCatalog][PROCESS] $($DomainController.name) Enabling Global Catalog ..." $DomainController.EnableGlobalCatalog() } Write-Verbose -Message "[Enable-ADSIDomainControllerGlobalCatalog][PROCESS] $($DomainController.name) Done." } catch { Write-Error -Message "[Enable-ADSIDomainControllerGlobalCatalog][PROCESS] Something wrong happened" $pscmdlet.ThrowTerminatingError($_) } } } function Enable-ADSIUser { <# .SYNOPSIS Function to Enable a User Account .DESCRIPTION Function to Enable a User Account .PARAMETER Identity Specifies the Identity of the User. You can provide one of the following properties DistinguishedName Guid Name SamAccountName Sid UserPrincipalName Those properties come from the following enumeration: System.DirectoryServices.AccountManagement.IdentityType .PARAMETER Credential Specifies the alternative credential to use. By default it will use the current user windows credentials. .PARAMETER DomainName Specifies the alternative Domain. By default it will use the current domain. .EXAMPLE Enable-ADSIUser fxtest02 This will Enable the fxtest02 account .EXAMPLE Enable-ADSIUser fxtest02 -whatif This will emulate the following action: Enable the fxtest02 account .EXAMPLE Enable-ADSIUser fxtest02 -credential (Get-Credential) This will enable the fxtest02 account using the credential specified .EXAMPLE Enable-ADSIUser fxtest02 -credential (Get-Credential) -DomainName LazyWinAdmin.local This will enable the fxtest02 account using the credential specified in the domain LazyWinAdmin.local .NOTES https://github.com/lazywinadmin/ADSIPS .LINK https://msdn.microsoft.com/en-us/library/System.DirectoryServices.AccountManagement.UserPrincipal(v=vs.110).aspx #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)] $Identity, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$DomainName) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } } process { try { if ($pscmdlet.ShouldProcess("$Identity", "Enable Account")) { $Account = Get-ADSIUser -Identity $Identity @ContextSplatting $Account.Enabled = $true $Account.Save() } } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Get-ADSIComputer { <# .SYNOPSIS Function to retrieve a Computer in Active Directory .DESCRIPTION Function to retrieve a Computer in Active Directory .PARAMETER Identity Specifies the Identity of the computer You can provide one of the following: DistinguishedName Guid Name SamAccountName Sid System.DirectoryService.AccountManagement.IdentityType https://msdn.microsoft.com/en-us/library/bb356425(v=vs.110).aspx .PARAMETER Credential Specifies alternative credential By default it will use the current user windows credentials. .PARAMETER DomainName Specifies the alternative Domain. By default it will use the current domain. .EXAMPLE Get-ADSIComputer -Identity 'SERVER01' This command will retrieve the computer account SERVER01 .EXAMPLE Get-ADSIComputer -Identity 'SERVER01' -Credential (Get-Credential) This command will retrieve the computer account SERVER01 with the specified credential .EXAMPLE Get-ADSIComputer TESTSERVER01 -credential (Get-Credential) -domain LazyWinAdmin.local This command will retrieve the account TESTSERVER01 using the alternative credential specified in the domain lazywinadmin.local .EXAMPLE $Comp = Get-ADSIComputer -Identity 'SERVER01' $Comp.GetUnderlyingObject()| Select-Object -Property * Help you find all the extra properties .NOTES https://github.com/lazywinadmin/ADSIPS .LINK https://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.computerprincipal(v=vs.110).aspx #> [CmdletBinding(DefaultParameterSetName = "All")] param ([Parameter(Mandatory = $true, ParameterSetName = "Identity")] [string]$Identity, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$DomainName ) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ ContextType = "Domain" } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } $Context = New-ADSIPrincipalContext @ContextSplatting } process { try { if ($Identity) { [System.DirectoryServices.AccountManagement.ComputerPrincipal]::FindByIdentity($Context, $Identity) } else { $ComputerPrincipal = New-object -TypeName System.DirectoryServices.AccountManagement.ComputerPrincipal -ArgumentList $Context $Searcher = new-object -TypeName System.DirectoryServices.AccountManagement.PrincipalSearcher $Searcher.QueryFilter = $ComputerPrincipal $Searcher.FindAll() } } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Get-ADSIComputerSite { <# .SYNOPSIS Function to retrieve the AD Site of a Computer .DESCRIPTION Function to retrieve the AD Site of a Computer This function does not rely on the .NET Framework to retrieve the information http://www.pinvoke.net/default.aspx/netapi32.dsgetsitename There is .NET method to get this information but only works on the local machine. [System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]::GetComputerSite() .PARAMETER ComputerName Specifies the computer name(s) that you want to know the site. .EXAMPLE Get-ADSIComputerName -ComputerName TestServer01 This will retrieve the Site of the Computer TestServer01 .EXAMPLE Get-ADSIComputerName -ComputerName TestServer01,TestServer02 This will retrieve the Site of the Computers TestServer01 and TestServer02 .NOTES https://github.com/lazywinadmin/ADSIPS Thanks to the Reddit folks for their help! :-) https://www.reddit.com/r/PowerShell/comments/4cjdk8/get_the_ad_site_name_of_a_computer/ #> [CmdletBinding()] [OutputType('System.Management.Automation.PSCustomObject')] param ( [parameter()] [String[]]$ComputerName = $env:computername ) begin { $code = @" using System; using System.Collections.Generic; using System.Runtime.InteropServices; public static class NetApi32 { private class unmanaged { [DllImport("NetApi32.dll", CharSet=CharSet.Auto, SetLastError=true)] internal static extern UInt32 DsGetSiteName([MarshalAs(UnmanagedType.LPTStr)]string ComputerName, out IntPtr SiteNameBuffer); [DllImport("Netapi32.dll", SetLastError=true)] internal static extern int NetApiBufferFree(IntPtr Buffer); } public static string DsGetSiteName(string ComputerName) { IntPtr siteNameBuffer = IntPtr.Zero; UInt32 hResult = unmanaged.DsGetSiteName(ComputerName, out siteNameBuffer); string siteName = Marshal.PtrToStringAuto(siteNameBuffer); unmanaged.NetApiBufferFree(siteNameBuffer); if(hResult == 0x6ba) { throw new Exception("ComputerName not found"); } return siteName; } } "@ Add-Type -TypeDefinition $code } process { foreach ($Computer in $ComputerName) { try { $Properties = @{ ComputerName = $Computer SiteName = [NetApi32]::DsGetSiteName($Computer) } New-Object -TypeName PSObject -property $Properties } catch { $pscmdlet.ThrowTerminatingError($_) } } } } Function Get-ADSIDefaultDomainAccountLockout { <# .SYNOPSIS Function to retrieve default Domain Account Lockout Policy .DESCRIPTION Function to retrieve default Domain Account Lockout Policy .PARAMETER Credential Specifies alternative credential .PARAMETER DomainName Specifies the Domain Name where the function should look .PARAMETER DomainDistinguishedName Specifies the DistinguishedName of the Domain to query .EXAMPLE Get-ADSIDefaultDomainAccountLockout .EXAMPLE Get-ADSIDefaultDomainAccountLockout -Credential (Get-Credential) .EXAMPLE Get-ADSIDefaultDomainAccountLockout -DomainName "CONTOSO.local" .EXAMPLE Get-ADSIDefaultDomainAccountLockout -DomainDistinguishedName 'DC=CONTOSO,DC=local' .OUTPUTS LockoutDuration This attribute specifies the lockout duration for locked-out user accounts Unit : minutes EXAMPLE lockoutDuration : 10 minutes LockoutObservationWindow This attribute specifies the observation window for lockout of user accounts. Unit : minutes EXAMPLE lockoutObservationWindow : 10 minutes LockoutThreshold This attribute specifies the lockout threshold for lockout of user accounts. EXAMPLE lockoutThreshold : 7 .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] param ( [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [Alias("Domain")] [ValidateScript( { if ($_ -match "^(?:(?!-)[A-Za-z0-9-]{1,63}(?<!-)\.)+[A-Za-z]{2,6}$") { $true } else { throw "DomainName must be FQDN. Ex: contoso.locale - Hostname like '$_' is not working" } })] [String]$DomainName, [Alias("DomainDN")] [String]$DomainDistinguishedName = $(([adsisearcher]"").Searchroot.path) ) begin { } process { if ($PSBoundParameters['DomainName']) { $DomainDistinguishedName = "LDAP://DC=$($DomainName.replace(".", ",DC="))" Write-Verbose -Message "Current Domain: $DomainDistinguishedName" } elseif ($PSBoundParameters['DomainDistinguishedName']) { if ($DomainDistinguishedName -notlike "LDAP://*") { $DomainDistinguishedName = "LDAP://$DomainDistinguishedName" } Write-Verbose -Message "Different Domain specified: $DomainDistinguishedName" } if ($PSBoundParameters['Credential']) { $DomainAccount = New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList $DomainDistinguishedName, $($Credential.UserName), $($Credential.GetNetworkCredential().password) } else { $DomainAccount = New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList $DomainDistinguishedName } $Properties = @{ "lockoutDuration" = ($DomainAccount.ConvertLargeIntegerToInt64($DomainAccount.'lockoutDuration'[0]) / -600000000) -as [int] "lockoutObservationWindow" = ($DomainAccount.ConvertLargeIntegerToInt64($DomainAccount.'lockoutObservationWindow'[0]) / -600000000) -as [int] "lockoutThreshold" = $DomainAccount.lockoutThreshold -as [int] } New-Object -TypeName psobject -Property $Properties } } Function Get-ADSIDefaultDomainPasswordPolicy { <# .SYNOPSIS Function to retrieve default Domain Password Policy .DESCRIPTION Function to retrieve default Domain Password Policy .PARAMETER Credential Specifies the alternative credential to use. By default it will use the current user windows credentials. .PARAMETER DomainName Specifies the alternative Domain where the user should be created By default it will use the current domain. .EXAMPLE Get-ADSIDefaultDomainPasswordPolicy .EXAMPLE Get-ADSIDefaultDomainPasswordPolicy -Credential (Get-Credential) .EXAMPLE Get-ADSIDefaultDomainPasswordPolicy -DomainName "CONTOSO.local" .OUTPUTS DomainMinimumPasswordAge specifies the minimum amount of time that a password can be used Unit : days EXAMPLE minPwdAge : 3 days DomainMaximumPasswordAge specifies the maximum amount of time that a password is valid Unit : days EXAMPLE maxPwdAge : 180 days DomainMinimumPasswordLength specifies the minimum number of characters that a password has to contain EXAMPLE minPwdLength : 8 DomainPasswordHistoryLength specifies the number of old passwords to save EXAMPLE pwdHistoryLength : 5 PasswordProperties Part of Domain Policy. A bitfield to indicate complexity and storage restrictions. EXAMPLE pwdProperties : 1 DOMAIN_PASSWORD_COMPLEX : The server enforces password complexity policy 2 DOMAIN_PASSWORD_NO_ANON_CHANGE : Reserved. No effect on password policy 4 DOMAIN_PASSWORD_NO_CLEAR_CHANGE : Change-password methods that provide the cleartext password are disabled by the server 8 DOMAIN_LOCKOUT_ADMINS : Reserved. No effect on password policy 16 DOMAIN_PASSWORD_STORE_CLEARTEXT : The server MUST store the cleartext password, not just the computed hashes 32 DOMAIN_REFUSE_PASSWORD_CHANGE : Reserved. No effect on password policy .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] param ( [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$DomainName ) begin { $DirectoryEntryParams = @{} if ($PSBoundParameters['Credential']) { $DirectoryEntryParams.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $DirectoryEntryParams.DomainName = $DomainName } } process { $DirectoryEntry = New-ADSIDirectoryEntry @DirectoryEntryParams $Properties = @{ "minPwdAge" = ($DirectoryEntry.ConvertLargeIntegerToInt64($DirectoryEntry.'minPwdAge'[0]) / -864000000000) -as [int] "maxPwdAge" = ($DirectoryEntry.ConvertLargeIntegerToInt64($DirectoryEntry.'maxPwdAge'[0]) / -864000000000) -as [int] "minPwdLength" = $DirectoryEntry.minPwdLength.value "pwdHistoryLength" = $DirectoryEntry.pwdHistoryLength.value "pwdProperties" = switch ($DirectoryEntry.pwdProperties) { 1 { "DOMAIN_PASSWORD_COMPLEX : The server enforces password complexity policy"; break } 2 { "DOMAIN_PASSWORD_NO_ANON_CHANGE : Reserved. No effect on password policy"; break } 4 { "DOMAIN_PASSWORD_NO_CLEAR_CHANGE : Change-password methods that provide the cleartext password are disabled by the server"; break } 8 { "DOMAIN_LOCKOUT_ADMINS : Reserved. No effect on password policy"; break } 16 { "DOMAIN_PASSWORD_STORE_CLEARTEXT : The server MUST store the cleartext password, not just the computed hashes."; break } 32 { "DOMAIN_REFUSE_PASSWORD_CHANGE : Reserved. No effect on password policy"; break } DEFAULT { $DirectoryEntry.pwdProperties } } } New-Object -TypeName psobject -Property $Properties } } Function Get-ADSIDomain { <# .SYNOPSIS Function to retrieve the current or specified domain .DESCRIPTION Function to retrieve the current or specified domain .PARAMETER Credential Specifies alternative credential to use .PARAMETER DomainName Specifies the DomainName to query .EXAMPLE Get-ADSIDomain Retrieve the current domain .EXAMPLE Get-ADSIDomain -DomainName lazywinadmin.com Retrieve the domain lazywinadmin.com .EXAMPLE Get-ADSIDomain -Credential (Get-Credential superAdmin) -Verbose Retrieve the current domain with the specified credential. .EXAMPLE Get-ADSIDomain -DomainName lazywinadmin.com -Credential (Get-Credential superAdmin) -Verbose Retrieve the domain lazywinadmin.com with the specified credential. .NOTES https://github.com/lazywinadmin/ADSIPS .OUTPUTS 'System.DirectoryServices.ActiveDirectory.Domain' .LINK https://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectory.domain(v=vs.110).aspx #> [cmdletbinding()] [OutputType('System.DirectoryServices.ActiveDirectory.Domain')] param ( [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, $DomainName = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() ) process { try { if ($PSBoundParameters['Credential'] -or $PSBoundParameters['DomainName']) { Write-Verbose -Message '[PROCESS] Credential or DomainName specified' $Splatting = @{ } if ($PSBoundParameters['Credential']) { $Splatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $Splatting.DomainName = $DomainName } $DomainContext = New-ADSIDirectoryContext @splatting -contextType Domain [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext) } else { [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() } } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Get-ADSIDomainBackup { <# .SYNOPSIS Function to retrieve last backup for each partitions of a given domain .DESCRIPTION Function to retrieve last backup for each partitions of a given domain. It look at the dsaSignature for each naming context. dsaSignature attribute change after a succesfull backup .PARAMETER Credential Specifies alternative credential to use .PARAMETER DomainName Specifies the DomainName to query .EXAMPLE get-ADSIDomainBackup Retrieve Backup information for the current domain .EXAMPLE get-ADSIDomainBackup -DomainName mytest.local Retrieve Backup information for the domain mytest.local .EXAMPLE get-ADSIDomainBackup -Credential (Get-Credential superAdmin) -Verbose Retrieve Backup information for the current domain with the specified credential. .EXAMPLE get-ADSIDomainBackup -DomainName mytest.local -Credential (Get-Credential superAdmin) -Verbose Retrieve Backup information for the domain mytest.local with the specified credential. .NOTES https://github.com/lazywinadmin/ADSIPS .OUTPUTS 'Ps' #> [cmdletbinding()] [OutputType('pscustomobject[]')] param ( [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, $DomainName = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().name ) process { try { if ($PSBoundParameters['Credential']){ $ContextObject = new-object System.DirectoryServices.ActiveDirectory.DirectoryContext($ContextObjectType, $DomainName, $Credential.UserName, $Credential.GetNetworkCredential().password) } else { $ContextObjectType = [System.DirectoryServices.ActiveDirectory.DirectoryContextType]::Domain } $DomainControlerObject = [System.DirectoryServices.ActiveDirectory.DomainController]::findOne($ContextObject) $ActiveDirectoryPartitions = $DomainControlerObject.Partitions $ArrayListBackupInfo = [System.Collections.ArrayList]::new() foreach ($partition in $ActiveDirectoryPartitions) { $ActiveDirectoryPartitionMetaData = $domainController.GetReplicationMetadata($partition) $DsaSignatureAtribute = $ActiveDirectoryPartitionMetaData.item("dsaSignature") $LastBackupDate = $DsaSignatureAtribute.LastOriginatingChangeTime.DateTime $PartitionBackupInfo = [pscustomobject]@{ PartitionName=$partition BackupDateTime=$LastBackupDate } [void]$ArrayListBackupInfo.Add($PartitionBackupInfo) } return $ArrayListBackupInfo } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Get-ADSIDomainController { <# .SYNOPSIS Function to retrieve Domain Controllers .DESCRIPTION Function to retrieve Domain Controllers .PARAMETER Credential Specifies alternative credential .PARAMETER DomainName Specifies the Domain Name where the function should look .EXAMPLE Get-ADSIDomainController .EXAMPLE Get-ADSIDomainController -Credential (Get-Credential) .EXAMPLE Get-ADSIDomainController -DomainName "FXTEST.local" .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] [OutputType('System.DirectoryServices.ActiveDirectory.DomainController')] param ( [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, $DomainName = [System.DirectoryServices.ActiveDirectory.Domain]::Getcurrentdomain() ) begin { if ($PSBoundParameters['Credential']) { $Context = New-ADSIDirectoryContext -Credential $Credential -contextType Domain if ($PSBoundParameters['DomainName']) { $Context = New-ADSIDirectoryContext -Credential $Credential -contextType Domain -DomainName $DomainName } } else { $Context = New-ADSIDirectoryContext -contextType Domain if ($PSBoundParameters['DomainName']) { $Context = New-ADSIDirectoryContext -contextType Domain -DomainName $DomainName } } } process { [System.DirectoryServices.ActiveDirectory.DomainController]::FindAll($Context) } } Function Get-ADSIDomainMode { <# .SYNOPSIS Function to retrieve Domain mode .DESCRIPTION Function to retrieve Domain mode .PARAMETER Credential Specifies alternative credential .PARAMETER DomainName Specifies the Domain Name where the function should look .EXAMPLE Get-ADSIDomainMode .EXAMPLE Get-ADSIDomainMode -Credential (Get-Credential) .EXAMPLE Get-ADSIDomainMode -DomainName "FXTEST.local" .NOTES https://github.com/lazywinadmin/ADSIPS #> [cmdletbinding()] param ( [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, $DomainName = [System.DirectoryServices.ActiveDirectory.Domain]::Getcurrentdomain() ) process { try { if ($PSBoundParameters['Credential'] -or $PSBoundParameters['DomainName']) { Write-Verbose -Message '[PROCESS] Credential or DomainName specified' $Splatting = @{ } if ($PSBoundParameters['Credential']) { $Splatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $Splatting.DomainName = $DomainName } (Get-ADSIDomain @splatting).DomainMode } else { (Get-ADSIDomain).DomainMode } } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Get-ADSIDomainRoot { <# .SYNOPSIS Function to retrieve the Domain Root in the Forest .DESCRIPTION Function to retrieve the Domain Root in the Forest .PARAMETER Credential Specifies the alternative credential to use. Default is the current one. .PARAMETER ForestName Specifies the alternative forest name to query. Default is the current one. .EXAMPLE Get-ADSIDomainRoot Retrieve the current Domain Root .EXAMPLE Get-ADSIDomainRoot -ForestName ForestTest.lab Retrieve the Domain root of ForestTest.lab .EXAMPLE Get-ADSIDomainRoot -ForestName ForestTest.lab -credential (Get-Credential) Retrieve the Domain root of ForestTest.lab with the specified credential .NOTES https://github.com/lazywinadmin/ADSIPS .OUTPUTS System.DirectoryServices.ActiveDirectory.Domain .LINK https://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectory.domain(v=vs.110).aspx #> [CmdletBinding()] [OutputType('System.DirectoryServices.ActiveDirectory.Domain')] param ( [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, $ForestName = [System.DirectoryServices.ActiveDirectory.Forest]::Getcurrentforest() ) (Get-ADSIForest @PSBoundParameters).RootDomain } function Get-ADSIDomainTrustRelationship { <# .SYNOPSIS Function to retrieve the Trust relationship of a domain. Current one by default. .DESCRIPTION Function to retrieve the Trust relationship of a domain. Current one by default. .PARAMETER Credential Specifies the alternative credential to use. Default is the current user. .PARAMETER DomainName Specifies the alternative domain name to use. Default is the current one. .EXAMPLE Get-ADSIDomainTrustRelationship Retrieve the Trust relationship(s) of a current domain .EXAMPLE Get-ADSIDomainTrustRelationship -DomainName FX.lab Retrieve the Trust relationship(s) of domain fx.lab .EXAMPLE Get-ADSIDomainTrustRelationship -DomainName FX.lab -Credential (Get-Credential) Retrieve the Trust relationship(s) of domain fx.lab with the credential specified .NOTES https://github.com/lazywinadmin/ADSIPS .OUTPUTS System.DirectoryServices.ActiveDirectory.TrustRelationshipInformation .LINK https://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectory.trustrelationshipinformation(v=vs.110).aspx #> [CmdletBinding()] [OutputType('System.DirectoryServices.ActiveDirectory.TrustRelationshipInformation')] param ( [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, $DomainName = [System.DirectoryServices.ActiveDirectory.Domain]::GetcurrentDomain() ) process { try { if ($PSBoundParameters['Credential'] -or $PSBoundParameters['DomainName']) { Write-Verbose -Message '[PROCESS] Credential or FirstName specified' $Splatting = @{ } if ($PSBoundParameters['Credential']) { $Splatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $Splatting.DomainName = $DomainName } (Get-ADSIDomain @splatting).GetAllTrustRelationships() } else { (Get-ADSIDomain).GetAllTrustRelationships() } } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Get-ADSIFineGrainedPasswordPolicy { <# .SYNOPSIS This function will query and list Fine-Grained Password Policies in Active Directory .DESCRIPTION This function will query and list Fine-Grained Password Policies in Active Directory it return name : the Name of the Policy MinimumPasswordLength : Minimum PassWord Size int passwordreversibleencryptionenabled : Encryption Type reversible (not secure) or not minimumpasswordage : The number of day before the user Can change the password maximumpasswordage : The number of day that a password can be used before the system requires the user to change it passwordcomplexityenabled : True of Fals passwordsettingsprecedence : Integer needed to determine which policy to apply in a user is mapped to more than one policy lockoutduration : Time in minute before reseting failed logon count lockoutobservationwindow : Time between 2 failed logoin attemps before reseting the counter to 0 lockoutthreshold : Number of failed login attempt to trigger lockout psoappliesto : Groups and/or Users WhenCreated WhenChanged .PARAMETER Name Specify the name of the policy to retreive .PARAMETER Credential Specify the Credential to use .PARAMETER DomainDistinguishedName Specify the DistinguishedName of the Domain to query .PARAMETER SizeLimit Specify the number of item(s) to output .EXAMPLE Get-ADSIFineGrainedPasswordPolicy Retreive all the password policy on the current domain .EXAMPLE Get-ADSIFineGrainedPasswordPolicy -Name Name Retreive the password policy nammed 'Name' on the current domain .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] param ( [Parameter(ParameterSetName = "Name")] [String]$Name, [Parameter(ValueFromPipelineByPropertyName = $true)] [Alias("Domain", "DomainDN", "SearchRoot", "SearchBase")] [String]$DomainDistinguishedName = $(([adsisearcher]"").Searchroot.path), [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [Alias("ResultLimit", "Limit")] [int]$SizeLimit = '100' ) process { try { $FunctionName = (Get-Variable -Name MyInvocation -ValueOnly -Scope 0).MyCommand Write-Verbose -Message "[$FunctionName] Create DirectorySearcher" $Search = New-Object -TypeName System.DirectoryServices.DirectorySearcher -ErrorAction 'Stop' $Search.SizeLimit = $SizeLimit $Search.SearchRoot = $DomainDistinguishedName $Search.filter = "(objectclass=msDS-PasswordSettings)" if ($PSBoundParameters['name']) { $Search.filter = "(|(name=$name))" Write-Verbose -Message "[$FunctionName] Set Filter to '$($Search.filter)'" } if ($PSBoundParameters['DomainDistinguishedName']) { if ($DomainDistinguishedName -notlike "LDAP://*") { $DomainDistinguishedName = "LDAP://$DomainDistinguishedName" }#if Write-Verbose -Message "Different Domain specified: $DomainDistinguishedName" $Search.SearchRoot = $DomainDistinguishedName Write-Verbose -Message "[$FunctionName] Set SearchRoot to '$($Search.SearchRoot)'" } if ($PSBoundParameters['Credential']) { Write-Verbose -Message "[$FunctionName] Add Credential'" $Cred = New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList $DomainDistinguishedName, $($Credential.UserName), $($Credential.GetNetworkCredential().password) $Search.SearchRoot = $Cred } foreach ($Object in $($Search.FindAll())) { # Define the properties # The properties need to be lowercase! $Properties = @{ "name" = $Object.properties.name -as [string] "passwordhistorylength" = $Object.Properties.Item("msds-passwordhistorylength") -as [int] "minimumpasswordlength" = $Object.Properties.Item("msds-minimumpasswordlength") -as [int] "passwordreversibleencryptionenabled" = $Object.Properties.Item("msds-passwordreversibleencryptionenabled") -as [string] "minimumpasswordage" = $Object.Properties.Item("msds-minimumpasswordage") -as [string] "maximumpasswordage" = $Object.Properties.Item("msds-maximumpasswordage") -as [string] "passwordcomplexityenabled" = $Object.Properties.Item("msds-passwordcomplexityenabled") -as [string] "passwordsettingsprecedence" = $Object.Properties.Item("msds-passwordsettingsprecedence") -as [string] "lockoutduration" = $Object.Properties.Item("msds-lockoutduration") -as [string] "lockoutobservationwindow" = $Object.Properties.Item("msds-lockoutobservationwindow") -as [string] "lockoutthreshold" = $Object.Properties.Item("msds-lockoutthreshold") -as [string] "psoappliesto" = $Object.Properties.Item("msds-psoappliesto") -as [string] "WhenCreated" = $Object.properties.whencreated -as [string] "WhenChanged" = $Object.properties.whenchanged -as [string] } # Output the info New-Object -TypeName PSObject -Property $Properties } } catch { # Return current error $PSCmdlet.ThrowTerminatingError($_) } } end { Write-Verbose -Message "[$FunctionName] Done" } } function Get-ADSIForest { <# .SYNOPSIS Function to retrieve the current or specified forest .DESCRIPTION Function to retrieve the current or specified forest .PARAMETER Credential Specifies alternative credential to use .PARAMETER ForestName Specifies the ForestName to query .EXAMPLE Get-ADSIForest .EXAMPLE Get-ADSIForest -ForestName lazywinadmin.com .EXAMPLE Get-ADSIForest -Credential (Get-Credential superAdmin) -Verbose .EXAMPLE Get-ADSIForest -ForestName lazywinadmin.com -Credential (Get-Credential superAdmin) -Verbose .OUTPUTS System.DirectoryServices.ActiveDirectory.Forest .NOTES https://github.com/lazywinadmin/ADSIPS .LINK https://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectory.forest(v=vs.110).aspx #> [CmdletBinding()] [OutputType('System.DirectoryServices.ActiveDirectory.Forest')] param ( [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, $ForestName = [System.DirectoryServices.ActiveDirectory.Forest]::Getcurrentforest() ) process { try { if ($PSBoundParameters['Credential'] -or $PSBoundParameters['ForestName']) { Write-Verbose -Message "[PROCESS] Credential or FirstName specified" $Splatting = @{ } if ($PSBoundParameters['Credential']) { $Splatting.Credential = $Credential } if ($PSBoundParameters['ForestName']) { $Splatting.ForestName = $ForestName } $ForestContext = New-ADSIDirectoryContext @splatting -contextType Forest [System.DirectoryServices.ActiveDirectory.Forest]::GetForest($ForestContext) } else { [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest() } } catch { $pscmdlet.ThrowTerminatingError($_) } } } Function Get-ADSIForestDomain { <# .SYNOPSIS Function to retrieve the forest domain(s) .DESCRIPTION Function to retrieve the forest domain(s) .PARAMETER Credential Specifies alternative credential to use .PARAMETER ForestName Specifies the ForestName to query .EXAMPLE Get-ADSIForest .EXAMPLE Get-ADSIForest -ForestName lazywinadmin.com .EXAMPLE Get-ADSIForest -Credential (Get-Credential superAdmin) -Verbose .EXAMPLE Get-ADSIForest -ForestName lazywinadmin.com -Credential (Get-Credential superAdmin) -Verbose .OUTPUTS System.DirectoryServices.ActiveDirectory.Forest .NOTES https://github.com/lazywinadmin/ADSIPS #> [cmdletbinding()] param ( [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, $ForestName = [System.DirectoryServices.ActiveDirectory.Forest]::Getcurrentforest() ) process { try { if ($PSBoundParameters['Credential'] -or $PSBoundParameters['ForestName']) { Write-Verbose -Message '[PROCESS] Credential or FirstName specified' $Splatting = @{ } if ($PSBoundParameters['Credential']) { $Splatting.Credential = $Credential } if ($PSBoundParameters['ForestName']) { $Splatting.ForestName = $ForestName } (Get-ADSIForest @splatting).Domains } else { (Get-ADSIForest).Domains } } catch { $pscmdlet.ThrowTerminatingError($_) } } } Function Get-ADSIForestMode { <# .SYNOPSIS Function to retrieve the forest mode .DESCRIPTION Function to retrieve the forest mode .PARAMETER Credential Specifies alternative credential to use .PARAMETER ForestName Specifies the ForestName to query .EXAMPLE Get-ADSIForestMode Retrieve the forest mode of the current forest .EXAMPLE Get-ADSIForestMode -ForestName lazywinadmin.com Retrieve the forest mode of the forest lazywinadmin.com .EXAMPLE Get-ADSIForestMode -Credential (Get-Credential superAdmin) -Verbose Retrieve the forest mode of the current forest using the credentials specified .EXAMPLE Get-ADSIForestMode -ForestName lazywinadmin.com -Credential (Get-Credential superAdmin) -Verbose Retrieve the forest mode of the forest lazywinadmin.com using the credentials specified .OUTPUTS System.directoryservices.activedirectory.forest.forestmode .NOTES https://github.com/lazywinadmin/ADSIPS .LINK https://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectory.forest.forestmode(v=vs.110).aspx #> [cmdletbinding()] [OutputType('System.directoryservices.activedirectory.forest.forestmode')] param ( [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, $ForestName = [System.DirectoryServices.ActiveDirectory.Forest]::Getcurrentforest() ) process { try { if ($PSBoundParameters['Credential'] -or $PSBoundParameters['ForestName']) { Write-Verbose -Message '[PROCESS] Credential or FirstName specified' $Splatting = @{ } if ($PSBoundParameters['Credential']) { $Splatting.Credential = $Credential } if ($PSBoundParameters['ForestName']) { $Splatting.ForestName = $ForestName } (Get-ADSIForest @splatting).ForestMode } else { (Get-ADSIForest).ForestMode } } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Get-ADSIForestTrustRelationship { <# .SYNOPSIS Function to retrieve the Forest Trust Relationship(s) .DESCRIPTION Function to retrieve the Forest Trust Relationship(s) .PARAMETER Credential Specifies the alternative credential to use. Default is the current user. .PARAMETER ForestName Specifies the alternative Forest name to query. Default is the current one. .NOTES https://github.com/lazywinadmin/ADSIPS .EXAMPLE Get-ADSIForestTrustRelationship Retrieve the Forest Trust Relationship of the current domain .EXAMPLE Get-ADSIForestTrustRelationship -ForestName 'lazywinadmin.com' Retrieve the Forest Trust Relationship of the forest lazywinadmin.com .EXAMPLE Get-ADSIForestTrustRelationship -ForestName 'lazywinadmin.com' -credential (Get-Credential) Retrieve the Forest Trust Relationship of the forest lazywinadmin.com using the specified credential .OUTPUTS System.DirectoryServices.ActiveDirectory.ForestTrustRelationshipInformation .LINK https://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectory.foresttrustrelationshipinformation(v=vs.110).aspx #> [CmdletBinding()] [OutputType('System.DirectoryServices.ActiveDirectory.ForestTrustRelationshipInformation')] param ( [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, $ForestName = [System.DirectoryServices.ActiveDirectory.Forest]::Getcurrentforest() ) process { try { Write-Verbose -Message '[Get-ADSIForestTrustRelationship][PROCESS] Credential or FirstName specified' (Get-ADSIForest @PSBoundParameters).GetAllTrustRelationships() } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Get-ADSIFsmo { <# .SYNOPSIS Function to retrieve the Flexible single master operation (FSMO) roles owner(s) .DESCRIPTION Function to retrieve the Flexible single master operation (FSMO) roles owner(s) .PARAMETER Credential Specifies the Alternative credential to use .PARAMETER ForestName Specifies the alternative forest name .EXAMPLE Get-ADSIFsmo Retrieve the Flexible single master operation (FSMO) roles owner(s) of the current domain/forest .EXAMPLE Get-ADSIFsmo -ForestName 'lazywinadmin.com' Retrieve the Flexible single master operation (FSMO) roles owner(s) of the root domain/forest lazywinadmin.com .EXAMPLE Get-ADSIFsmo -ForestName 'lazywinadmin.com' -credential (Get-Credential) Retrieve the Flexible single master operation (FSMO) roles owner(s) of the root domain/forest lazywinadmin.com using the specified credential. .NOTES https://github.com/lazywinadmin/ADSIPS .OUTPUTS System.Management.Automation.PSCustomObject #> [CmdletBinding()] [OutputType('System.Management.Automation.PSCustomObject')] param ( [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, $ForestName = [System.DirectoryServices.ActiveDirectory.Forest]::Getcurrentforest() ) process { try { $FunctionName = (Get-Variable -Name MyInvocation -Scope 0 -ValueOnly).Mycommand if ($PSBoundParameters['Credential'] -or $PSBoundParameters['ForestName']) { $Splatting = @{ } if ($PSBoundParameters['Credential']) { Write-Verbose -message "[$FunctionName] Add Credential to splatting" $Splatting.Credential = $Credential } if ($PSBoundParameters['ForestName']) { Write-Verbose -message "[$FunctionName] Add ForestName to splatting" $Splatting.ForestName = $ForestName } # Forest Query Write-Verbose -message "[$FunctionName] Retrieve Forest information '$ForestName'" $Forest = (Get-ADSIForest @splatting) # Domain Splatting cleanup $Splatting.Remove("ForestName") $Splatting.DomainName = $Forest.RootDomain.name # Domain Query Write-Verbose -message "[$FunctionName] Retrieve Domain information '$($Forest.RootDomain.name)'" $Domain = (Get-ADSIDomain @Splatting) } else { Write-Verbose -message "[$FunctionName] Retrieve Forest information '$ForestName'" $Forest = Get-ADSIForest Write-Verbose -message "[$FunctionName] Retrieve Domain information" $Domain = Get-ADSIDomain } Write-Verbose -message "[$FunctionName] Prepare Output" $Properties = @{ SchemaRoleOwner = $Forest.SchemaRoleOwner NamingRoleOwner = $Forest.NamingRoleOwner InfrastructureRoleOwner = $Domain.InfrastructureRoleOwner RidRoleOwner = $Domain.RidRoleOwner PdcRoleOwner = $Domain.PdcRoleOwner } New-Object -TypeName PSObject -property $Properties } catch { $pscmdlet.ThrowTerminatingError($_) } } end { Write-Verbose -message "[$FunctionName] Done." } } function Get-ADSIGlobalCatalog { <# .SYNOPSIS Function to retrieve the Global Catalog in the Forest .DESCRIPTION Function to retrieve the Global Catalog in the Forest .PARAMETER Credential Specifies the alternative credential to use. Default is the current user. .PARAMETER ForestName Specifies the alternative Forest name to query. Default is the current one. .EXAMPLE Get-ADSIGlobalCatalog Retrieve the Global Catalog in the current Forest .EXAMPLE Get-ADSIGlobalCatalog -forestname 'lazywinadmin.com' Retrieve the Global Catalog in the forest 'lazywinadmin.com' .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] [OutputType('System.DirectoryServices.ActiveDirectory.GlobalCatalog')] param ( [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, $ForestName = [System.DirectoryServices.ActiveDirectory.Forest]::Getcurrentforest() ) process { try { Write-Verbose -Message '[Get-ADSIGlobalCatalog][PROCESS] Credential or FirstName specified' (Get-ADSIForest @PSBoundParameters).GlobalCatalogs } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Get-ADSIGroup { <# .SYNOPSIS Function to retrieve a group in Active Directory .DESCRIPTION Function to retrieve a group in Active Directory .PARAMETER Identity Specifies the Identity of the group You can provide one of the following properties DistinguishedName Guid Name SamAccountName Sid UserPrincipalName Those properties come from the following enumeration: System.DirectoryServices.AccountManagement.IdentityType .PARAMETER Credential Specifies the alternative credential to use. By default it will use the current user windows credentials. .PARAMETER DomainName Specifies the alternative Domain where the user should be created By default it will use the current Domain. .PARAMETER GroupScope Specifies the Group Scope (Global, Local or Universal) .PARAMETER IsSecurityGroup Specifies if you look for security group, default is $true. .PARAMETER Description Specifies the description of the group .PARAMETER UserPrincipalName Specifies the UPN .PARAMETER Displayname Specifies the DisplayName .PARAMETER Name Specifies the Name .PARAMETER SID Specifies the SID .PARAMETER LDAPFilter Specifies the LDAP query to perform .EXAMPLE Get-ADSIGroup -Identity 'SERVER01' Retrieve the group TestGroup in the current domain. .EXAMPLE Get-ADSIGroup -Identity 'TestGroup' -Credential (Get-Credential) Retrieve the group TestGroup in the current domain using alternative credential .EXAMPLE Get-ADSIGroup -Name "*ADSIPS*" Retrieve all the group(s) that contains 'ADSIPS' in their name .EXAMPLE Get-ADSIGroup -ISSecurityGroup $true -Description "*" Retrieve all the security group(s) that have a description .EXAMPLE $Comp = Get-ADSIGroup -Identity 'Finance' $Comp.GetUnderlyingObject()| Select-Object -Property * Help you find all the extra properties of the Finance group object .EXAMPLE Get-ADSIGroup -GroupScope Universal -IsSecurityGroup:$false This will retrieve the Universal groups object with the SamAccountName TestGroup01 in the current domain. .EXAMPLE Get-ADSIGroup -LDAPFilter "(SamAccountName=TestGroup01)" This will retrieve the group object with the SamAccountName TestGroup01 in the current domain. .NOTES https://github.com/lazywinadmin/ADSIPS .OUTPUTS System.DirectoryServices.AccountManagement.GroupPrincipal .LINK https://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.groupprincipal(v=vs.110).aspx #> [CmdletBinding(DefaultParameterSetName = 'All')] [OutputType('System.DirectoryServices.AccountManagement.GroupPrincipal')] param ( [Parameter(ParameterSetName = 'Identity')] [string]$Identity, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [Alias('Domain', 'Server')] $DomainName = [System.DirectoryServices.ActiveDirectory.Domain]::Getcurrentdomain(), [Parameter(ParameterSetName = 'Filter')] [System.DirectoryServices.AccountManagement.GroupScope]$GroupScope, [Parameter(ParameterSetName = 'Filter')] [bool]$IsSecurityGroup, [Parameter(ParameterSetName = 'Filter')] $Description, [Parameter(ParameterSetName = 'Filter')] $UserPrincipalName, [Parameter(ParameterSetName = 'Filter')] $Displayname, [Parameter(ParameterSetName = 'Filter')] $Name, [Parameter(ParameterSetName = 'Filter')] $SID, [Parameter(ParameterSetName = 'LDAPFilter')] $LDAPFilter ) begin { # Create Context splatting $ContextSplatting = @{ ContextType = "Domain" } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } $Context = New-ADSIPrincipalContext @ContextSplatting } process { try { if ($Identity) { Write-Verbose -Message "Identity" [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($Context, $Identity) } elseif ($PSBoundParameters['LDAPFilter']) { Write-Verbose -Message "LDAPFilter" # Directory Entry object $DirectoryEntryParams = $ContextSplatting $DirectoryEntryParams.remove('ContextType') $DirectoryEntry = New-ADSIDirectoryEntry @DirectoryEntryParams # Principal Searcher $DirectorySearcher = new-object -TypeName System.DirectoryServices.DirectorySearcher $DirectorySearcher.SearchRoot = $DirectoryEntry $DirectorySearcher.Filter = "(&(objectCategory=group)$LDAPFilter)" $DirectorySearcher.FindAll() | Foreach-Object -Process { [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($Context, ($_.path -replace 'LDAP://')) } } else { Write-Verbose -Message "Other Filters" $GroupPrincipal = New-object -TypeName System.DirectoryServices.AccountManagement.GroupPrincipal -ArgumentList $Context #$GroupPrincipal.Name = $Identity $searcher = new-object -TypeName System.DirectoryServices.AccountManagement.PrincipalSearcher $searcher.QueryFilter = $GroupPrincipal if ($PSBoundParameters['IsSecurityGroup']) { $searcher.QueryFilter.IsSecurityGroup = $IsSecurityGroup } if ($PSBoundParameters['GroupScope']) { $searcher.QueryFilter.GroupScope = $GroupScope } if ($PSBoundParameters['UserPrincipalName']) { $searcher.QueryFilter.UserPrincipalName = $UserPrincipalName } if ($PSBoundParameters['Description']) { $searcher.QueryFilter.Description = $Description } if ($PSBoundParameters['DisplayName']) { $searcher.QueryFilter.DisplayName = $DisplayName } #if($PSBoundParameters['DistinguishedName']){$searcher.QueryFilter.DistinguishedName = $DistinguishedName} if ($PSBoundParameters['Sid']) { $searcher.QueryFilter.Sid.Value = $SID } if ($PSBoundParameters['Name']) { $searcher.QueryFilter.Name = $Name } $searcher.FindAll() } } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Get-ADSIGroupManagedBy { <# .SYNOPSIS This function retrieve the group that the current user manage in the ActiveDirectory. .DESCRIPTION This function retrieve the group that the current user manage in the ActiveDirectory. Typically the function will search for group(s) and look at the 'ManagedBy' property where it matches the current user. .PARAMETER SamAccountName Specify the SamAccountName of the Manager of the group You can also use the alias: ManagerSamAccountName. .PARAMETER AllManagedGroups Specify to search for groups with a Manager (managedby property) .PARAMETER NoManager Specify to search for groups without Manager (managedby property) .PARAMETER Credential Specify the Credential to use for the query .PARAMETER SizeLimit Specify the number of item maximum to retrieve .PARAMETER DomainDistinguishedName Specify the Domain or Domain DN path to use .EXAMPLE Get-ADSIGroupManagedBy -SamAccountName fxcat This will list all the group(s) where fxcat is designated as Manager. .EXAMPLE Get-ADSIGroupManagedBy This will list all the group(s) where the current user is designated as Manager. .EXAMPLE Get-ADSIGroupManagedBy -NoManager This will list all the group(s) without Manager .EXAMPLE Get-ADSIGroupManagedBy -AllManagedGroup This will list all the group(s) without Manager .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding(DefaultParameterSetName = "One")] param ( [Parameter(ParameterSetName = "One")] [Alias("ManagerSamAccountName")] [String]$SamAccountName = $env:USERNAME, [Parameter(ParameterSetName = "All")] [Switch]$AllManagedGroups, [Parameter(ParameterSetName = "No")] [Switch]$NoManager, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [Alias("DomainDN", "Domain", "SearchBase", "SearchRoot")] [String]$DomainDistinguishedName = $(([adsisearcher]"").Searchroot.path), [Alias("ResultLimit", "Limit")] [int]$SizeLimit = '100' ) begin { } process { try { # Building the basic search object with some parameters $Search = New-Object -TypeName System.DirectoryServices.DirectorySearcher -ErrorAction 'Stop' $Search.SizeLimit = $SizeLimit $Search.SearchRoot = $DomainDN if ($PSBoundParameters['DomainDistinguishedName']) { # Fixing the path if needed if ($DomainDistinguishedName -notlike "LDAP://*") { $DomainDistinguishedName = "LDAP://$DomainDistinguishedName" }#if Write-Verbose -Message "Different Domain specified: $DomainDistinguishedName" $Search.SearchRoot = $DomainDistinguishedName } if ($PSBoundParameters['Credential']) { Write-Verbose -Message "Different Credential specified: $($Credential.UserName)" $Cred = New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList $DomainDistinguishedName, $($Credential.UserName), $($Credential.GetNetworkCredential().password) $Search.SearchRoot = $Cred } if ($PSBoundParameters['SamAccountName']) { Write-Verbose -Message "SamAccountName" #Look for User DN $UserSearch = $search $UserSearch.Filter = "(&(SamAccountName=$SamAccountName))" $UserDN = $UserSearch.FindOne().Properties.distinguishedname -as [string] # Define the query to find the Groups managed by this user $Search.Filter = "(&(objectCategory=group)(ManagedBy=$UserDN))" } if ($PSBoundParameters['AllManagedGroups']) { Write-Verbose -Message "All Managed Groups Param" $Search.Filter = "(&(objectCategory=group)(managedBy=*))" } if ($PSBoundParameters['NoManager']) { Write-Verbose -Message "No Manager param" $Search.Filter = "(&(objectCategory=group)(!(!managedBy=*)))" } if (-not ($PSBoundParameters['SamAccountName']) -and -not ($PSBoundParameters['AllManagedGroups']) -and -not ($PSBoundParameters['NoManager'])) { Write-Verbose -Message "No parameters used" #Look for User DN $UserSearch = $search $UserSearch.Filter = "(&(SamAccountName=$SamAccountName))" $UserDN = $UserSearch.FindOne().Properties.distinguishedname -as [string] # Define the query to find the Groups managed by this user $Search.Filter = "(&(objectCategory=group)(ManagedBy=$UserDN))" } foreach ($group in $Search.FindAll()) { $Properties = @{ "SamAccountName" = $group.properties.samaccountname -as [string] "DistinguishedName" = $group.properties.distinguishedname -as [string] "GroupType" = $group.properties.grouptype -as [string] "Mail" = $group.properties.mail -as [string] } New-Object -TypeName psobject -Property $Properties } }#try catch { $pscmdlet.ThrowTerminatingError($_) } }#Process end { Write-Verbose -Message "[END] Function Get-ADSIGroupManagedBy End." } } function Get-ADSIGroupMember { <# .SYNOPSIS Function to retrieve the members from a specific group in Active Directory .DESCRIPTION Function to retrieve the members from a specific group in Active Directory .PARAMETER Identity Specifies the Identity of the Group You can provide one of the following properties DistinguishedName Guid Name SamAccountName Sid UserPrincipalName Those properties come from the following enumeration: System.DirectoryServices.AccountManagement.IdentityType .PARAMETER Credential Specifies alternative credential .PARAMETER Recurse Retrieves all the recursive members (Members of group(s)'s members) .PARAMETER DomainName Specifies the alternative Domain where the user should be created By default it will use the current domain. .PARAMETER GroupsOnly Specifies that you only want to retrieve the members of type Group only. .EXAMPLE Get-ADSIGroupMember -Identity 'Finance' Retrieve the direct members of the group 'Finance' .EXAMPLE Get-ADSIGroupMember -Identity 'Finance' -Recursive Retrieve the direct and nested members of the group 'Finance' .EXAMPLE Get-ADSIGroupMember -Identity 'Finance' -GroupsOnly Retrieve the direct groups members of the group 'Finance' .EXAMPLE Get-ADSIGroupMember -Identity 'Finance' -Credential (Get-Credential) Retrieve the direct members of the group 'Finance' using alternative Credential .EXAMPLE Get-ADSIGroupMember -Identity 'Finance' -Credential (Get-Credential) -DomainName FX.LAB Retrieve the direct members of the group 'Finance' using alternative Credential in the domain FX.LAB .EXAMPLE $Comp = Get-ADSIGroupMember -Identity 'SERVER01' $Comp.GetUnderlyingObject()| Select-Object -Property * Help you find all the extra properties .LINK https://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.groupprincipal%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396 .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding(DefaultParameterSetName = 'All')] param ([Parameter(Mandatory = $true)] [System.String]$Identity, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [System.String]$DomainName, [Parameter(ParameterSetName = 'All')] [Switch]$Recurse, [Parameter(ParameterSetName = 'Groups')] [Switch]$GroupsOnly ) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ ContextType = "Domain" } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } $Context = New-ADSIPrincipalContext @ContextSplatting } process { try { if ($PSBoundParameters['GroupsOnly']) { Write-Verbose -Message "GROUP: $($Identity.toUpper()) - Retrieving Groups only" $Account = ([System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($Context, $Identity)) $Account.GetGroups() } else { Write-Verbose -Message "GROUP: $($Identity.toUpper()) - Retrieving All members" if ($PSBoundParameters['Recursive']) { Write-Verbose -Message "GROUP: $($Identity.toUpper()) - Recursive parameter Specified" } # Returns a collection of the principal objects that is contained in the group. # When the $recurse flag is set to true, this method searches the current group recursively and returns all nested group members. ([System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($Context, $Identity)).GetMembers($Recurse) } } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Get-ADSIGroupPolicyObject { <# .SYNOPSIS This function will query Active Directory Group Policy Objects .DESCRIPTION This function will query Active Directory Group Policy Objects .PARAMETER Credential Specifies alternative Credential to use .PARAMETER DomainDistinguishedName Specify the DistinguishedName of the Domain to query. .PARAMETER SizeLimit Specify the number of item(s) to output. Default is 100. .EXAMPLE Get-ADSIGroupPolicyObject Retrieve all the group policy in the current domain .NOTES https://github.com/lazywinadmin/ADSIPS .LINK https://msdn.microsoft.com/en-us/library/cc232507.aspx #> [CmdletBinding()] param ( [Parameter()] [Alias("Domain", "DomainDN")] [String]$DomainDistinguishedName = $(([adsisearcher]"").Searchroot.path), [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [Alias("ResultLimit", "Limit")] [int]$SizeLimit = '100' ) begin { } process { try { $ScriptName = (Get-Variable -name MyInvocation -Scope 0 -ValueOnly).MyCommand # Building the basic search object with some parameters Write-Verbose -message "[$ScriptName] Create DirectorySearcher" $Search = New-Object -TypeName System.DirectoryServices.DirectorySearcher -ErrorAction 'Stop' Write-Verbose -message "[$ScriptName] Set SizeLimit of '$SizeLimit'" $Search.SizeLimit = $SizeLimit Write-Verbose -message "[$ScriptName] Set Filter '(objectCategory=groupPolicyContainer)'" $Search.Filter = "(objectCategory=groupPolicyContainer)" if ($PSBoundParameters['DomainDistinguishedName']) { Write-Verbose -message "[$ScriptName] DomainDistinguishedName specified = '$DomainDistinguishedName'" if ($DomainDistinguishedName -notlike "LDAP://*") { Write-Verbose -message "[$ScriptName] DomainDistinguishedName notlike 'LDAP://*', prepending LDAP://" $DomainDistinguishedName = "LDAP://$DomainDistinguishedName" }#if $Search.SearchRoot = $DomainDistinguishedName } if ($PSBoundParameters['Credential']) { Write-Verbose -message "[$ScriptName] Different Credential specified: '$($credential.username)'" $Cred = New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList $DomainDistinguishedName, $($Credential.UserName), $($Credential.GetNetworkCredential().password) $Search.SearchRoot = $Cred } if (-not $PSBoundParameters["SizeLimit"]) { Write-Warning -Message "[$ScriptName] Default SizeLimit: 100 Results" } Write-Verbose -message "[$ScriptName] Looking for objects..." foreach ($GPO in $($Search.FindAll())) { # Define the properties # The properties need to be lowercase!!!!!!!! $Properties = @{ adspath = $gpo.properties.adspath -as [system.string] gpcfunctionalityversion = $gpo.properties.gpcfunctionalityversion -as [system.int32] usnchanged = $gpo.properties.usnchanged -as [system.string] showinadvancedviewonly = $gpo.properties.showinadvancedviewonly -as [system.string] displayname = $gpo.properties.displayname -as [system.string] whencreated = $gpo.properties.whencreated -as [System.DateTime] gpcmachineextensionnames = $gpo.properties.gpcmachineextensionnames -as [system.string] instancetype = $gpo.properties.instancetype -as [system.string] versionnumber = $gpo.properties.versionnumber -as [system.int32] gpcfilesyspath = $gpo.properties.gpcfilesyspath -as [system.string] usncreated = $gpo.properties.usncreated -as [system.string] flags = $gpo.properties.flags -as [system.int32] whenchanged = $gpo.properties.whenchanged -as [System.DateTime] cn = $gpo.properties.cn -as [system.string] objectguid = $gpo.properties.objectguid distinguishedname = $gpo.properties.distinguishedname -as [system.string] objectcategory = $gpo.properties.objectcategory -as [system.string] iscriticalsystemobject = $gpo.properties.iscriticalsystemobject -as [system.string] objectclass = $gpo.properties.objectclass systemflags = $gpo.properties.systemflags -as [system.string] dscorepropagationdata = $gpo.properties.dscorepropagationdata -as [system.string] name = $gpo.properties.name -as [system.string] raw = $gpo } # Output the info New-Object -TypeName PSObject -Property $Properties } }#try catch { Write-Warning -Message "[$ScriptName] Something wrong happened!" $PSCmdlet.ThrowTerminatingError($_) } }#process end { Write-Verbose -message "[$ScriptName] End." } } function Get-ADSIObject { <# .SYNOPSIS This function will query any kind of object in Active Directory .DESCRIPTION This function will query any kind of object in Active Directory .PARAMETER SamAccountName Specify the SamAccountName of the object. This parameter also search in Name and DisplayName properties Name and Displayname are alias. .PARAMETER DistinguishedName Specify the DistinguishedName of the object your are looking for .PARAMETER Credential Specify the Credential to use .PARAMETER DomainDistinguishedName Specify the DistinguishedName of the Domain to query .PARAMETER SizeLimit Specify the number of item(s) to output .PARAMETER IncludeDeletedObjects Deleted objects are included in the search .PARAMETER DeletedOnly Return only deleted objects .EXAMPLE Get-ADSIObject -SamAccountName Fxcat Get informations on objects with a SamAccountName equal to Fxcat .EXAMPLE Get-ADSIObject -SamAccountName Fx* Get informations on objects with a SamAccountName starting with Fx* .EXAMPLE Get-ADSIObject -SamAccountName Fx* -IncludeDeletedObjects Get informations on objects deleted or not with a SamAccountName starting with Fx* .EXAMPLE Get-ADSIObject -SamAccountName Fx* -IncludeDeletedObjects -DeletedOnly Get informations on deleted objects with a SamAccountName starting with Fx* .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] param ( [Parameter(ParameterSetName = "SamAccountName")] [Parameter(ParameterSetName = "Deleted")] [Alias("Name", "DisplayName")] [String]$SamAccountName, [Parameter(ParameterSetName = "DistinguishedName")] [Parameter(ParameterSetName = "Deleted")] [String]$DistinguishedName, [Parameter(ValueFromPipelineByPropertyName = $true)] [Alias("Domain", "DomainDN", "SearchRoot", "SearchBase")] [String]$DomainDistinguishedName = $(([adsisearcher]"").Searchroot.path), [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [Alias("ResultLimit", "Limit")] [int]$SizeLimit = '100', [Parameter(ParameterSetName = "Deleted", Mandatory = $true)] [switch]$IncludeDeletedObjects, [Parameter(ParameterSetName = "Deleted")] [switch]$DeletedOnly ) begin { } process { try { # Building the basic search object with some parameters $Search = New-Object -TypeName System.DirectoryServices.DirectorySearcher -ErrorAction 'Stop' $Search.SizeLimit = $SizeLimit $Search.SearchRoot = $DomainDistinguishedName if ($PSBoundParameters['SamAccountName']) { if ($PSBoundParameters['DeletedOnly']) { $Search.filter = "(&(isDeleted=True)(|(name=$SamAccountName)(samaccountname=$SamAccountName)(displayname=$samaccountname)))" } else { $Search.filter = "(|(name=$SamAccountName)(samaccountname=$SamAccountName)(displayname=$samaccountname))" } } if ($PSBoundParameters['DistinguishedName']) { if ($PSBoundParameters['DeletedOnly']) { $Search.filter = "(&(isDeleted=True)(distinguishedname=$DistinguishedName))" } else { $Search.filter = "(&(distinguishedname=$DistinguishedName))" } } if ($PSBoundParameters['DomainDistinguishedName']) { if ($DomainDistinguishedName -notlike "LDAP://*") { $DomainDistinguishedName = "LDAP://$DomainDistinguishedName" } Write-Verbose -Message "Different Domain specified: $DomainDistinguishedName" $Search.SearchRoot = $DomainDistinguishedName } if ($PSBoundParameters['Credential']) { $Cred = New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList $DomainDistinguishedName, $($Credential.UserName), $($Credential.GetNetworkCredential().password) $Search.SearchRoot = $Cred } if ($PSBoundParameters['IncludeDeletedObjects']) { $Search.Tombstone = $true } foreach ($Object in $($Search.FindAll())) { # Define the properties $Properties = @{ "displayname" = $Object.properties.displayname -as [string] "name" = $Object.properties.name -as [string] "objectcategory" = $Object.properties.objectcategory -as [string] "objectclass" = $Object.properties.objectclass -as [string] "samaccountName" = $Object.properties.samaccountname -as [string] "description" = $Object.properties.description -as [string] "distinguishedname" = $Object.properties.distinguishedname -as [string] "adspath" = $Object.properties.adspath -as [string] "lastlogon" = $Object.properties.lastlogon -as [string] "whencreated" = $Object.properties.whencreated -as [string] "whenchanged" = $Object.properties.whenchanged -as [string] "deleted" = $Object.properties.isDeleted -as [string] "recycled" = $Object.properties.isRecycled -as [string] } # Output the info New-Object -TypeName PSObject -Property $Properties } } catch { $pscmdlet.ThrowTerminatingError($_) } } end { Write-Verbose -Message "[END] Function Get-ADSIObject End." } } function Get-ADSIOrganizationalUnit { <# .SYNOPSIS This function will query Active Directory for Organization Unit Objects .DESCRIPTION This function will query Active Directory for Organization Unit Objects .PARAMETER Name Specify the Name of the OU .PARAMETER DistinguishedName Specify the DistinguishedName path of the OU .PARAMETER All Will show all the OU in the domain .PARAMETER GroupPolicyInheritanceBlocked Will show only the OU that have Group Policy Inheritance Blocked enabled. .PARAMETER Credential Specify the Credential to use .PARAMETER DomainDistinguishedName Specify the DistinguishedName of the Domain to query .PARAMETER SizeLimit Specify the number of item(s) to output .EXAMPLE Get-ADSIOrganizationalUnit This returns all the OU in the Domain (Result Size is 100 per default) .EXAMPLE Get-ADSIOrganizationalUnit -name FX This returns the OU with the name FX .EXAMPLE Get-ADSIOrganizationalUnit -name FX* This returns the OUs where the name starts by FX .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding(DefaultParameterSetName = "All")] param ( [Parameter(ParameterSetName = "Name")] [String]$Name, [Parameter(ParameterSetName = "DistinguishedName")] [String]$DistinguishedName, [Parameter(ParameterSetName = "All")] [String]$All, [Switch]$GroupPolicyInheritanceBlocked, [Parameter(ValueFromPipelineByPropertyName = $true)] [Alias("Domain", "DomainDN")] [String]$DomainDistinguishedName = $(([adsisearcher]"").Searchroot.path), [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [Alias("ResultLimit", "Limit")] [int]$SizeLimit = '100' ) begin { } process { try { # Building the basic search object with some parameters $Search = New-Object -TypeName System.DirectoryServices.DirectorySearcher -ErrorAction 'Stop' $Search.SizeLimit = $SizeLimit $Search.SearchRoot = $DomainDistinguishedName if ($Name) { $Search.filter = "(&(objectCategory=organizationalunit)(name=$Name))" if ($psboundparameters["GroupPolicyInheritanceBlocked"]) { $Search.filter = "(&(objectCategory=organizationalunit)(name=$Name)(gpoptions=1))" } } if ($DistinguishedName) { $Search.filter = "(&(objectCategory=organizationalunit)(distinguishedname=$distinguishedname))" if ($psboundparameters["GroupPolicyInheritanceBlocked"]) { $Search.filter = "(&(objectCategory=organizationalunit)(distinguishedname=$distinguishedname)(gpoptions=1))" } } if ($all) { $Search.filter = "(&(objectCategory=organizationalunit))" if ($psboundparameters["GroupPolicyInheritanceBlocked"]) { $Search.filter = "(&(objectCategory=organizationalunit)(gpoptions=1))" } } if ($DomainDistinguishedName) { if ($DomainDistinguishedName -notlike "LDAP://*") { $DomainDistinguishedName = "LDAP://$DomainDistinguishedName" }#if Write-Verbose -Message "Different Domain specified: $DomainDistinguishedName" $Search.SearchRoot = $DomainDistinguishedName } if ($PSBoundParameters['Credential']) { $Cred = New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList $DomainDistinguishedName, $($Credential.UserName), $($Credential.GetNetworkCredential().password) $Search.SearchRoot = $Cred } if (-not $PSBoundParameters["SizeLimit"]) { Write-Warning -Message "Default SizeLimit: 100 Results" } foreach ($ou in $($Search.FindAll())) { # Define the properties # The properties need to be lowercase!!!!!!!! $Properties = @{ "Name" = $ou.properties.name -as [string] "DistinguishedName" = $ou.properties.distinguishedname -as [string] "ADsPath" = $ou.properties.adspath -as [string] "ObjectCategory" = $ou.properties.objectcategory -as [string] "ObjectClass" = $ou.properties.objectclass -as [string] "ObjectGuid" = $ou.properties.objectguid "WhenCreated" = $ou.properties.whencreated -as [string] -as [datetime] "WhenChanged" = $ou.properties.whenchanged -as [string] -as [datetime] "usncreated" = $ou.properties.usncreated -as [string] "usnchanged" = $ou.properties.usnchanged -as [string] "dscorepropagationdata" = $ou.properties.dscorepropagationdata "instancetype" = $ou.properties.instancetype -as [string] } # Output the info New-Object -TypeName PSObject -Property $Properties } }#try catch { $pscmdlet.ThrowTerminatingError($_) } }#process end { Write-Verbose -Message "[END] Function Get-ADSIOrganizationalUnit End." } } Function Get-ADSIPrincipalGroupMembership { <# .SYNOPSIS Function to retrieve groups from a user in Active Directory .DESCRIPTION Get all AD groups of a user, primary one and others .PARAMETER Identity Specifies the Identity of the User You can provide one of the following properties DistinguishedName Guid Name SamAccountName Sid UserPrincipalName Those properties come from the following enumeration: System.DirectoryServices.AccountManagement.IdentityType .PARAMETER UserInfos UserInfos is a UserPrincipal object. Type System.DirectoryServices.AccountManagement.AuthenticablePrincipal .PARAMETER GroupInfos GroupInfos is a GroupPrincipal object. Type System.DirectoryServices.AccountManagement.Principal .PARAMETER Credential Specifies the alternative credential to use. By default it will use the current user windows credentials. .PARAMETER DomainName Specifies the alternative Domain where the user should be created By default it will use the current domain. .EXAMPLE Get-ADSIPrincipalGroupMembership -Identity 'User1' Get all AD groups of user User1 .EXAMPLE Get-ADSIPrincipalGroupMembership -Identity 'User1' -Credential (Get-Credential) Use a different credential to perform the query .EXAMPLE Get-ADSIPrincipalGroupMembership -Identity 'User1' -DomainName "CONTOSO.local" Use a different domain name to perform the query .EXAMPLE Get-ADSIPrincipalGroupMembership -Identity 'Group1' Get all AD groups of group Group1 .EXAMPLE Get-ADSIPrincipalGroupMembership -Identity 'Group1' -Credential (Get-Credential) Use a different credential to perform the query .EXAMPLE Get-ADSIPrincipalGroupMembership -Identity 'Group1' -DomainName "CONTOSO.local" Use a different domain name to perform the query .EXAMPLE Get-ADSIPrincipalGroupMembership -UserInfos (Get-ADSIUser -Identity "User1") Get all ad groups of User1 using type System.DirectoryServices.AccountManagement.AuthenticablePrincipal .EXAMPLE Get-ADSIPrincipalGroupMembership -UserInfos (Get-ADSIUser -Identity "User1" -DomainName "CONTOSO.local") Get all ad groups of User1 using type System.DirectoryServices.AccountManagement.AuthenticablePrincipal on a different domain .EXAMPLE Get-ADSIPrincipalGroupMembership -GroupInfos (Get-ADSIGroup -Identity "Group1") Get all ad groups of Group1 using type System.DirectoryServices.AccountManagement.Principal .EXAMPLE Get-ADSIPrincipalGroupMembership -GroupInfos (Get-ADSIGroup -Identity "Group1" -DominName "CONTOSO.local") Get all ad groups of Group1 using type System.DirectoryServices.AccountManagement.Principal on a different domain .NOTES https://github.com/lazywinadmin/ADSIPS CHANGE LOG - 0.1 | 2019/06/22 | Matt Oestreich (oze4) - Initial Change Log creation - Fixed issue 70 where primary group was not being pulled in for users #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ParameterSetName = "Identity")] [string]$Identity, [Parameter(Mandatory = $true, ParameterSetName = "UserInfos")] [System.DirectoryServices.AccountManagement.AuthenticablePrincipal]$UserInfos, [Parameter(Mandatory = $true, ParameterSetName = "GroupInfos")] [System.DirectoryServices.AccountManagement.Principal]$GroupInfos, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [Parameter(ParameterSetName = "Identity")] [String]$DomainName ) begin { # Stores our output $ObjectGroups = @() switch($PSBoundParameters.Keys) { 'UserInfos' { $UnderlyingProperties = $UserInfos.GetUnderlyingObject() $ObjectGroups += Get-ADSIUserPrimaryGroup -Identity $UserInfos -ReturnNameAndDescriptionOnly } 'GroupInfos' { $UnderlyingProperties = $GroupInfos.GetUnderlyingObject() } 'Identity' { $ObjectSplatting = @{} if ($PSBoundParameters["DomainName"]) { # Turn Domain Name into DN $ObjectSplatting.DomainDistinguishedName = ($DomainName.Split(".").ForEach({ "DC=$($_)," }) -join '').TrimEnd(',') } if ($PSBoundParameters["Credential"]) { $ObjectSplatting.Credential = $Credential } $FoundObject = $null # Get the ADSIObject for what we were provided foreach($IdType in [System.DirectoryServices.AccountManagement.IdentityType].GetEnumNames()) { $splat = @{ $IdType = $Identity } try { if ($ObjectSplatting) { $FoundObject = Get-ADSIObject @splat @ObjectSplatting } else { $FoundObject = Get-ADSIObject @splat } } catch { # do nothing, only here to suppress errors } if ($FoundObject -ne $null) { $FoundObjectObjectClass = $FoundObject.objectclass.Split(" ") break; } } if (($FoundObjectObjectClass -contains "person") -or ($FoundObjectObjectClass -contains "user")) { $UserInfos = Get-ADSIUser -Identity $FoundObject.samaccountName $UnderlyingProperties = $UserInfos.GetUnderlyingObject() $ObjectGroups += Get-ADSIUserPrimaryGroup -Identity $UserInfos -ReturnNameAndDescriptionOnly } if ($FoundObjectObjectClass -contains "group") { $GroupInfos = Get-ADSIGroup -Identity $FoundObject.samaccountName $UnderlyingProperties = $GroupInfos.GetUnderlyingObject() } } } } process { $Objectmemberof = $UnderlyingProperties.memberOf if ($Objectmemberof) { foreach ($item in $Objectmemberof) { $ADSIobjectgroup = [adsi]"LDAP://$item" $ObjectGroups += [pscustomobject]@{ 'name' = [string]$ADSIobjectgroup.Properties.name 'description' = [string]$ADSIobjectgroup.Properties.description } } } $ObjectGroups } } function Get-ADSIPrintQueue { <# .SYNOPSIS Function to retrieve PrintQueue in Active Directory from PrinterQueue name or server name .DESCRIPTION Function to retrieve PrintQueue in Active Directory from PrinterQueue name or server name .PARAMETER PrinterQueueName Specify the PrinterQueue, you can use * as wildcard .PARAMETER ServerName Specify the ServerName to use .PARAMETER DomainName Specify the Domain to use .PARAMETER Credential Specify the Credential to use .PARAMETER DomainDistinguishedName Specify the DistinguishedName of the Domain to query .PARAMETER SizeLimit Specify the number of item(s) to output (1 to 1000) Use NoResultLimit for more than 1000 objects .PARAMETER NoResultLimit Remove the SizeLimit of 1000 Warning : can take time! depend number of queues on your domain NoResultLimit parameter override SizeLimit parameter .EXAMPLE Get-ADSIPrintQueue Get all published printQueue on your current domain (default function SizeLimit return 100 objects Max) .EXAMPLE Get-ADSIPrintQueue -SizeLimit 200 Get 200 published printQueue on your current domain .EXAMPLE Get-ADSIPrintQueue -NoResultLimit Get all published printQueue on your current domain Warning : can take time! depend number of queues on your domain .EXAMPLE Get-ADSIPrintQueue -PrinterQueueName MyPrinterQueue .EXAMPLE Get-ADSIPrintQueue -PrinterQueueName *Printer* .EXAMPLE Get-ADSIPrintQueue -ServerName TestServer01 Get all published printQueue for the server TestServer01 (default function SizeLimit return 100 objects Max) .EXAMPLE Get-ADSIPrintQueue -ServerName TestServer01.contoso.com Get all published printQueue for the server TestServer01.contoso.com (default function SizeLimit return 100 objects Max) .EXAMPLE Get-ADSIPrintQueue -ServerName TestServer01 -SizeLimit 200 Get only 200 published printQueue for the server TestServer01 .EXAMPLE Get-ADSIPrintQueue -ServerName TestServer01 -NoResultLimit This example will retrieve all printQueue on TestServer01 without limit of 1000 objects returned. .EXAMPLE Get-ADSIPrintQueue -DomainDistinguishedName 'OU=Mut,DC=CONTOSO,DC=COM' This example will retrieve all printQueue located in the 'Mut' OU (default function SizeLimit return 100 objects Max) .EXAMPLE Get-ADSIPrintQueue -PrinterQueueName MyPrinterQueue -ServerName TestServer01 -DomainDistinguishedName 'OU=Mut,DC=CONTOSO,DC=COM' This define the searchbase to the 'Mut' OU and filter on server and printQueue .EXAMPLE Get-ADSIPrintQueue -ServerName TestServer01 -DomainName contoso2.com -NoResultLimit You will get all the printQueue from TestServer01 on contoso2.com domain .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] param ( [Parameter(ValueFromPipelineByPropertyName = $true)] [Alias("PrinterQueue")] [String]$PrinterQueueName, [Alias("Server")] [String]$ServerName, [Alias("Domain")] [String]$DomainName, [Alias("DomainDN", "SearchRoot", "SearchBase")] [String]$DomainDistinguishedName = $(([adsisearcher]"").Searchroot.path), [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [Alias("ResultLimit", "Limit")] [int]$SizeLimit = '100', [Switch]$NoResultLimit ) begin { } process { try { # Building the basic search object with some parameters $Search = New-Object -TypeName System.DirectoryServices.DirectorySearcher -ErrorAction 'Stop' $Search.SearchRoot = $DomainDistinguishedName $Search.filter = "(&(objectClass=printQueue))" if ($PSBoundParameters['ServerName']) { $Search.filter = "(&(objectClass=printQueue)(|(serverName=$ServerName)(shortServerName=$ServerName)))" } elseif ($PSBoundParameters['PrinterQueue']) { $Search.filter = "(&(objectClass=printQueue)(printerName=$PrinterQueueName))" } else { $Search.filter = "(objectClass=printQueue)" } if ($PSBoundParameters['DomainName']) { $DomainDistinguishedName = "LDAP://DC=$($DomainName.replace(".", ",DC="))" $Search.SearchRoot = $DomainDistinguishedName } elseif ($PSBoundParameters['DomainDistinguishedName']) { if ($DomainDistinguishedName -notlike "LDAP://*") { $DomainDistinguishedName = "LDAP://$DomainDistinguishedName" } Write-Verbose -Message "Different Domain specified: $DomainDistinguishedName" $Search.SearchRoot = $DomainDistinguishedName } if ($PSBoundParameters['Credential']) { $Cred = New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList $DomainDistinguishedName, $($Credential.UserName), $($Credential.GetNetworkCredential().password) $Search.SearchRoot = $Cred } if (-not$PSBoundParameters['NoResultLimit']) { $Search.SizeLimit = $SizeLimit Write-Warning -Message "Result is limited to $SizeLimit entries, specify a specific number on the parameter SizeLimit or use -NoResultLimit switch to remove the limit" } else { Write-Verbose -Message "Use NoResultLimit switch, all objects will be returned. no limit" $Search.PageSize = 10000 } foreach ($Object in $($Search.FindAll())) { # Define the properties # The properties need to be lowercase!!!!!!!! $Properties = @{ "DisplayName" = $Object.properties.displayname -as [string] "Name" = $Object.properties.name -as [string] "printerName" = $Object.properties.printername -as [string] "location" = $Object.properties.location -as [string] "Description" = $Object.properties.description -as [string] "portName" = $Object.properties.portname -as [string] "driverName" = $Object.properties.drivername -as [string] "ObjectCategory" = $Object.properties.objectcategory -as [string] "ObjectClass" = $Object.properties.objectclass -as [string] "DistinguishedName" = $Object.properties.distinguishedname -as [string] "WhenCreated" = $Object.properties.whencreated -as [string] "WhenChanged" = $Object.properties.whenchanged -as [string] "serverName" = $Object.properties.servername -as [string] "uNCName" = $Object.properties.uncname -as [string] "printShareName" = $Object.properties.printsharename -as [string] "printStatus" = $Object.properties.printstatus -as [string] } # Output the info New-Object -TypeName PSObject -Property $Properties } } catch { $pscmdlet.ThrowTerminatingError($_) } } end { Write-Verbose -Message "[END] Function Get-ADSIPrintQueue End." } } function Get-ADSIReplicaCurrentTime { <# .SYNOPSIS Get-ADSIReplicaCurrentTime retrieves the current time of a given DC. .DESCRIPTION Get-ADSIReplicaCurrentTime retrieves the current time of a given DC. When using the verbose switch, this cmdlet will display the time difference with the current system. .PARAMETER ComputerName Defines the remote computer to connect to. .PARAMETER Credential Defines alternate credentials to use. Use Get-Credential to create proper credentials. .EXAMPLE Get-ADSIReplicaCurrentTime -ComputerName dc1.ad.local Connects to remote domain controller dc1.ad.local using current credentials and retrieves the current time. .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] param ([Parameter(Mandatory = $true)] [string]$ComputerName, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) if ($ComputerName) { if ($Credential) { $context = new-object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList "DirectoryServer", $ComputerName, $Credential.UserName, $Credential.GetNetworkCredential().Password } else { $context = new-object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList "DirectoryServer", $ComputerName } } if ($context) { Write-Verbose -Message "Connecting to $ComputerName" $dc = [System.DirectoryServices.ActiveDirectory.DomainController]::GetDomainController($context) } if ($dc) { $now = Get-Date $minDiff = (New-TimeSpan -start $dc.CurrentTime -end ([System.TimeZoneInfo]::ConvertTimeToUtc($now))).minutes Write-Verbose -Message "Difference in minutes between $($dc.name) and current system is $minDiff" $dc.CurrentTime } } function Get-ADSIReplicaDomainInfo { <# .SYNOPSIS Get-ADSIReplicaDomainInfo returns information about the connected DC's Domain. .DESCRIPTION Get-ADSIReplicaDomainInfo returns information about the connected DC's Domain. .PARAMETER ComputerName Defines the remote computer to connect to. .PARAMETER Credential Defines alternate credentials to use. Use Get-Credential to create proper credentials. .PARAMETER Recurse Recursively retrieves information about child domains .EXAMPLE Get-ADSIReplicaDomainInfo -ComputerName dc1.ad.local Forest : ad.local DomainControllers : {DC1.ad.local, DC2.ad.local} Children : {} DomainMode : Windows2012R2Domain DomainModeLevel : 6 Parent : PdcRoleOwner : DC1.ad.local RidRoleOwner : DC1.ad.local InfrastructureRoleOwner : DC1.ad.local Name : ad.local Connects to remote domain controller dc1.ad.local using current credentials retrieves domain info. .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] param ([Parameter(Mandatory = $true)] [string]$ComputerName, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [Switch]$Recurse ) if ($ComputerName) { if ($Credential) { $context = new-object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList "DirectoryServer", $ComputerName, $Credential.UserName, $Credential.GetNetworkCredential().Password } else { $context = new-object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList "DirectoryServer", $ComputerName } } if ($context) { Write-Verbose -Message "Connecting to $ComputerName" $dc = [System.DirectoryServices.ActiveDirectory.DomainController]::GetDomainController($context) } if ($dc) { $dc.domain if ($Recurse.IsPresent) { $dc.domain.children | Foreach-Object -Process { $_ } } } } function Get-ADSIReplicaForestInfo { <# .SYNOPSIS Get-ADSIReplicaForestInfo returns information about the connected DC's Forest. .DESCRIPTION Get-ADSIForestInfo returns information about the connected DC's Forest. .PARAMETER ComputerName Defines the remote computer to connect to. .PARAMETER Credential Defines alternate credentials to use. Use Get-Credential to create proper credentials. .EXAMPLE Get-ADSIReplicaForestInfo -ComputerName dc1.ad.local Name : ad.local Sites : {Default-First-Site-Name} Domains : {ad.local} GlobalCatalogs : {DC1.ad.local, DC2.ad.local} ApplicationPartitions : {DC=DomainDnsZones,DC=ad,DC=local, DC=ForestDnsZones,DC=ad,DC=local} ForestModeLevel : 6 ForestMode : Windows2012R2Forest RootDomain : ad.local Schema : CN=Schema,CN=Configuration,DC=ad,DC=local SchemaRoleOwner : DC1.ad.local NamingRoleOwner : DC1.ad.local Connects to remote domain controller dc1.ad.local using current credentials retrieves forest info. .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] param ([Parameter(Mandatory = $true)] [string]$ComputerName, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) if ($ComputerName) { if ($Credential) { $context = new-object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList "DirectoryServer", $ComputerName, $Credential.UserName, $Credential.GetNetworkCredential().Password } else { $context = new-object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList "DirectoryServer", $ComputerName } } if ($context) { Write-Verbose -Message "Connecting to $ComputerName" $dc = [System.DirectoryServices.ActiveDirectory.DomainController]::GetDomainController($context) } if ($dc) { Write-Verbose -Message "Information about forest $($dc.forest.name)" $dc.forest } } function Get-ADSIReplicaGCInfo { <# .SYNOPSIS Get-ADSIReplicaGCInfo finds out if a given DC holds the GC role. .DESCRIPTION Get-ADSIReplicaGCInfo finds out if a given DC holds the Global Catalog role. .PARAMETER ComputerName Defines the remote computer to connect to. .PARAMETER Credential Defines alternate credentials to use. Use Get-Credential to create proper credentials. .EXAMPLE Get-ADSIReplicaGCInfo -ComputerName dc1.ad.local Connects to remote domain controller dc1.ad.local using current credentials retrieves GC info. .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] param ([Parameter(Mandatory = $true)] [string]$ComputerName, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) if ($ComputerName) { if ($Credential) { $context = new-object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList "DirectoryServer", $ComputerName, $Credential.UserName, $Credential.GetNetworkCredential().Password } else { $context = new-object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList "DirectoryServer", $ComputerName } } if ($context) { Write-Verbose -Message "Connecting to $ComputerName" $dc = [System.DirectoryServices.ActiveDirectory.DomainController]::GetDomainController($context) } if ($dc) { $IsGC = $dc.IsGlobalCatalog() if ($IsGC) { Write-Verbose -Message "$($dc.name) is a Global Catalog" } else { Write-Verbose -Message "$($dc.name) is a normal Domain Controller" } $IsGC } } function Get-ADSIReplicaInfo { <# .SYNOPSIS Get-ADSIReplicaInfo retrieves Active Directory replication information .DESCRIPTION Get-ADSIReplicaInfo connects to an Active Directory Domain Controller and retrieves Active Directory replication information such as latency of replication and replication status. If no switches are used, latency information is returned. .PARAMETER ComputerName Defines the remote computer to connect to. If ComputerName and Domain are not used, Get-ADSIReplicaInfo will attempt at connecting to the Active Directory using information stored in environment variables. .PARAMETER Domain Defines the domain to connect to. If Domain is used, Get-ADSIReplicaInfo will find a domain controller to connect to. This parameter is ignored if ComputerName is used. .PARAMETER Credential Defines alternate credentials to use. Use Get-Credential to create proper credentials. .PARAMETER NamingContext Defines for which naming context replication information is to be displayed: All, Configuration, Schema, Domain. The default is Domain. .PARAMETER Neighbors Displays replication partners for the current Domain Controller. .PARAMETER Latency Organizes replication latency information by groups, such as Hour, Day, Week, Month, TooLong, Other .PARAMETER Cursors Displays replication cursors for the current Domain Controller. .PARAMETER DisplayDC Displays additional information about the currently connected Domain Controller. .PARAMETER DisplayDC Displays additional information about the errors .PARAMETER errors Display additional information on the replication errors .PARAMETER FormatTable Formats the output as a auto-sized table and rearranges elements according to relevance. Get-ADSIReplicaInfo -Latency -FormatTable Hour Day Week Month TooLong Other ---- --- ---- ----- ------- ----- {DC1.ad.local, DC2.ad.local} {} {} {} {} {} .EXAMPLE Get-ADSIReplicaInfo Tries to find a domain to connect to and if it succeeds, it will find a domain controller to retrieve replication information. .EXAMPLE Get-ADSIReplicaInfo -ComputerName dc1.ad.local -Credential $Credential Connects to remote domain controller dc1.ad.local using alternate credentials. .EXAMPLE Get-ADSIReplicaInfo -Domain ad.local Connects to remote domain controller dc1.ad.local using current credentials. .EXAMPLE Get-ADSIReplicaInfo -Domain ad.local Connects to remote domain controller dc1.ad.local using current credentials. .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] param ([string]$ComputerName = $null, [string]$Domain = $null, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [ValidateSet("Schema", "Configuration", "Domain", "All")] [String]$NamingContext = "Domain", [Switch]$Neighbors, [Switch]$Latency, [Switch]$Cursors, [Switch]$Errors, [Switch]$DisplayDC, [Switch]$FormatTable ) # Try to determine how to connect to the remote DC. # A few possibilities: # A computername was provided # A domain name was provided # None of the above was provided, so try with either USERDNSDOMAIN or LOGONSERVER # Use alternate credentials if provided if ($ComputerName) { if ($Credential) { $context = new-object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList "DirectoryServer", $ComputerName, $Credential.UserName, $Credential.GetNetworkCredential().Password } else { $context = new-object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList "DirectoryServer", $ComputerName } } elseif ($domain) { if ($Credential) { $context = new-object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList "Domain", $domain, $Credential.UserName, $Credential.GetNetworkCredential().Password } else { $context = new-object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList "Domain", $domain } } elseif ($env:USERDNSDOMAIN) { if ($Credential) { $context = new-object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList "Domain", $env:USERDNSDOMAIN, $Credential.UserName, $Credential.GetNetworkCredential().Password } else { $context = new-object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList "Domain", $env:USERDNSDOMAIN } } elseif ($env:LOGONSERVER -ne '\\MicrosoftAccount') { $logonserver = $env:LOGONSERVER.replace('\\', '') if ($Credential) { $context = new-object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList "DirectoryServer", $logonserver, $Credential.UserName, $Credential.GetNetworkCredential().Password } else { $context = new-object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList "DirectoryServer", $logonserver } } else { Write-Error -Message "Could not determine where to connect to" return } # If none of switches are present, default to at least one, so we have something to show if (!$Latency.IsPresent -and !$Neighbors.IsPresent -and !$Errors.IsPresent -and !$Cursors.IsPresent) { [switch]$Latency = $true } # Determine which DC to use depending on the context type. # If the context is Directory Server, simply get the provided domain controller, # if the context is a domain, then find a DC. switch ($context.ContextType) { "DirectoryServer"{ $dc = [System.DirectoryServices.ActiveDirectory.DomainController]::GetDomainController($context) } "Domain" { $dc = [System.DirectoryServices.ActiveDirectory.DomainController]::FindOne($context) } default { return } } if ($dc) { if ($DisplayDC.IsPresent) { Write-Verbose -Message "Information about $($dc.Name)" $dc } $domainDN = "" $obj = $domain.Replace(',', '\,').Split('/') $obj[0].split(".") | Foreach-Object -Process { $domainDN += ",DC=" + $_ } $domainDN = $domainDN.Substring(1) if ($Cursors.IsPresent) { foreach ($partition in $dc.Partitions) { if ($NamingContext -eq "All" -or ($NamingContext -eq "Domain" -and $partition -eq $domainDN) -or ($NamingContext -eq "Schema" -and $partition.Contains("Schema")) -or ($NamingContext -eq "Configuration" -and $partition.split(",")[0].Contains("Configuration")) ) { Write-Verbose -Message "Replication cursors for partition $partition on $($dc.Name)" $dc.GetReplicationCursors($partition) | Foreach-Object -Process { $_ } } } } if ($Latency.IsPresent) { foreach ($partition in $dc.Partitions) { if ($NamingContext -eq "All" -or ($NamingContext -eq "Domain" -and $partition -eq $domainDN) -or ($NamingContext -eq "Schema" -and $partition.Contains("Schema")) -or ($NamingContext -eq "Configuration" -and $partition.split(",")[0].Contains("Configuration")) ) { Write-Verbose -Message "Replication latency for partition $partition on $($dc.Name)" $cursorsArray = $dc.GetReplicationCursors($partition) $sortedCursors = $cursorsArray | Sort-Object -Descending -Property LastSuccessfulSyncTime $hour = @() $day = @() $week = @() $month = @() $tooLong = @() $other = @() foreach ($cursor in $sortedCursors) { $timespan = New-TimeSpan -Start $cursor.LastSuccessfulSyncTime -End $(Get-Date) if ($timespan) { if ($timespan.Days -eq 0 -and $timespan.Hours -eq 0) { $hour += $cursor.SourceServer } elseif ($timespan.Days -eq 0 -and $timespan.Hours -ge 1) { $day += $cursor.SourceServer } elseif ($timespan.Days -lt 7) { $week += $cursor.SourceServer } elseif ($timespan.Days -le 30 -and $timespan.Days -gt 7) { $month += $cursor.SourceServer } else { $tooLong += $cursor.SourceServer } } else { # no timestamp we might have a Windows 2000 server here $other += $cursor.SourceServer } } $latencyObject = New-Object -TypeName PsCustomObject -Property @{ Hour = $hour; Day = $day; Week = $week; Month = $month; TooLong = $tooLong; Other = $other } if ($FormatTable.IsPresent) { $latencyObject | Select-Object -Property Hour, Day, Week, Month, TooLong, Other | Format-Table -AutoSize } else { $latencyObject } } } } if ($Neighbors.IsPresent -or $Errors.IsPresent) { $replicationNeighbors = $dc.GetAllReplicationNeighbors() foreach ($neighbor in $replicationNeighbors) { if ($NamingContext -eq "All" -or ($NamingContext -eq "Domain" -and $neighbor.PartitionName -eq $domainDN) -or ($NamingContext -eq "Schema" -and $neighbor.PartitionName.Contains("Schema")) -or ($NamingContext -eq "Configuration" -and $neighbor.PartitionName.split(",")[0].Contains("Configuration")) ) { Write-Verbose -Message "Replication neighbors for partition $($neighbor.PartitionName) on $($dc.Name)" if (($Errors.IsPresent -and $neighbor.LastSyncResult -ne 0) -or $Neighbors.IsPresent) { if ($FormatTable.IsPresent) { $neighbor | Select-Object SourceServer, LastSyncMessage, LastAttemptedSync, LastSuccessfulSync, PartitionName | Format-Table -AutoSize } else { $neighbor } } } } } } } function Get-ADSIRootDSE { <# .SYNOPSIS Get-ADSIRootDSE Gets the root of a directory server information tree. .DESCRIPTION Get-ADSIRootDSE Gets the root of a directory server information tree. .PARAMETER Credential Defines alternate credentials to use. Use Get-Credential to create proper credentials. .PARAMETER DomainName Specifies the DomainName to query .EXAMPLE Get-ADSIRootDSE Retrieve informations for the current domain .EXAMPLE Get-ADSIRootDSE -DomainName lazywinadmin.com Retrieve informations for the domain lazywinadmin.com .NOTES https://github.com/lazywinadmin/ADSIPS #> [cmdletbinding()] param ( [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, $DomainName = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() ) process { try { $Splatting = @{ } if ($PSBoundParameters['Credential']) { Write-Verbose -Message '[PROCESS] Credential specified' $Splatting.ArgumentList += $($Credential.UserName) $Splatting.ArgumentList += $($Credential.GetNetworkCredential().password) } if ($PSBoundParameters['DomainName']) { Write-Verbose -Message '[PROCESS] DomainName specified' $Splatting.ArgumentList += "LDAP://$DomainName/RootDSE" } else { $Splatting.ArgumentList += "LDAP://RootDSE" } $DomainRootDSE = New-Object -TypeName System.DirectoryServices.DirectoryEntry @splatting } catch { $pscmdlet.ThrowTerminatingError($_) } # Define the properties $Properties = @{ "currentTime" = $DomainRootDSE.currentTime "subschemaSubentry" = $DomainRootDSE.subschemaSubentry "dsServiceName" = $DomainRootDSE.dsServiceName "namingContexts" = $DomainRootDSE.namingContexts "defaultNamingContext" = $DomainRootDSE.defaultNamingContext "schemaNamingContext" = $DomainRootDSE.schemaNamingContext "configurationNamingContext" = $DomainRootDSE.configurationNamingContext "rootDomainNamingContext" = $DomainRootDSE.rootDomainNamingContext "supportedControl" = $DomainRootDSE.supportedControl "supportedLDAPVersion" = $DomainRootDSE.supportedLDAPVersion "supportedLDAPPolicies" = $DomainRootDSE.supportedLDAPPolicies "highestCommittedUSN" = $DomainRootDSE.highestCommittedUSN "supportedSASLMechanisms" = $DomainRootDSE.supportedSASLMechanisms "dnsHostName" = $DomainRootDSE.dnsHostName "ldapServiceName" = $DomainRootDSE.ldapServiceName "serverName" = $DomainRootDSE.serverName "supportedCapabilities" = $DomainRootDSE.supportedCapabilities "isSynchronized" = $DomainRootDSE.isSynchronized "isGlobalCatalogReady" = $DomainRootDSE.isGlobalCatalogReady "domainFunctionality" = $DomainRootDSE.domainFunctionality "forestFunctionality" = $DomainRootDSE.forestFunctionality "domainControllerFunctionality" = $DomainRootDSE.domainControllerFunctionality "distinguishedName" = $DomainRootDSE.distinguishedName } # Output the info New-Object -TypeName PSObject -Property $Properties } } function Get-ADSISchema { <# .SYNOPSIS The Get-ADSISchema function gather information about the current Active Directory Schema .DESCRIPTION The Get-ADSISchema function gather information about the current Active Directory Schema .PARAMETER PropertyType Specify the type of property to return .PARAMETER ClassName Specify the name of the Class to retrieve .PARAMETER AllClasses This will list all the property present in the domain .PARAMETER FindClassName Specify the exact or partial name of the class to search .PARAMETER ForestName Specifies the Forest name .PARAMETER Credential Specifies alternative credential to use .EXAMPLE Get-ADSISchema -PropertyType Mandatory -ClassName user .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding(DefaultParameterSetName = 'Default')] param ( [Parameter(ParameterSetName = 'Default', Mandatory = $true)] [ValidateSet("mandatory", "optional")] [String]$PropertyType, [Parameter(ParameterSetName = 'Default', Mandatory = $true)] [String]$ClassName, [Parameter(ParameterSetName = 'AllClasses', Mandatory = $true)] [Switch]$AllClasses, [Parameter(ParameterSetName = 'FindClasses', Mandatory = $true)] [String]$FindClassName, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, $ForestName = [System.DirectoryServices.ActiveDirectory.Forest]::Getcurrentforest() ) begin { try { if ($PSBoundParameters['Credential'] -or $PSBoundParameters['ForestName']) { Write-Verbose -Message '[PROCESS] Credential or ForestName specified' $Splatting = @{ } if ($PSBoundParameters['Credential']) { $Splatting.Credential = $Credential } if ($PSBoundParameters['ForestName']) { $Splatting.ForestName = $ForestName } $SchemaContext = New-ADSIDirectoryContext @splatting -contextType Forest $schema = [DirectoryServices.ActiveDirectory.ActiveDirectorySchema]::GetSchema($SchemaContext) } else { $schema = [DirectoryServices.ActiveDirectory.ActiveDirectorySchema]::GetCurrentSchema() } } catch { $pscmdlet.ThrowTerminatingError($_) } } process { if ($PSBoundParameters['AllClasses']) { $schema.FindAllClasses().Name } if ($PSBoundParameters['FindClassName']) { $schema.FindAllClasses() | Where-Object -FilterScript { $_.name -match $FindClassName } | Select-Object -Property Name } else { switch ($PropertyType) { "mandatory" { ($schema.FindClass("$ClassName")).MandatoryProperties } "optional" { ($schema.FindClass("$ClassName")).OptionalProperties } }#switch }#else }#process } function Get-ADSISite { <# .SYNOPSIS Function to retrieve the Active Directory Site(s) .DESCRIPTION Function to retrieve the Active Directory Site(s) .PARAMETER Credential Specifies alternative credential to use. Default is the current user. .PARAMETER ForestName Specifies the ForestName to query. Default is the current one .PARAMETER SiteName Specifies the Site Name to find. .EXAMPLE Get-ADSISite .EXAMPLE Get-ADSISite -ForestName lazywinadmin.com .EXAMPLE Get-ADSISite -Credential (Get-Credential superAdmin) -Verbose .EXAMPLE Get-ADSISite -ForestName lazywinadmin.com -Credential (Get-Credential superAdmin) -Verbose .EXAMPLE Get-ADSISite -Name 'Montreal' .OUTPUTS System.DirectoryServices.ActiveDirectory.ActiveDirectorySite .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] [OutputType('System.DirectoryServices.ActiveDirectory.ActiveDirectorySite')] param ( [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, $ForestName = [System.DirectoryServices.ActiveDirectory.Forest]::Getcurrentforest(), [Alias("Name")] [String]$SiteName ) process { try { if ($PSBoundParameters['Name']) { # Remove Name from the PSBoundParameters Splatting [Void]$PSBoundParameters.Remove('Name') # Create a Forest Context $Context = New-ADSIDirectoryContext -ContextType Forest @PSBoundParameters # Get the site name specified [System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]::FindByName($Context, $Name) } else { [Void]$PSBoundParameters.Remove('Name') (Get-ADSIForest @PSBoundParameters).Sites } } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Get-ADSISiteLink { <# .SYNOPSIS Function to retrieve the Active Directory Site Link(s) .DESCRIPTION Function to retrieve the Active Directory Site Link(s) .PARAMETER Credential Specifies alternative credential to use. Default is the current user. .PARAMETER ForestName Specifies the ForestName to query. Default is the current one .PARAMETER Name Specifies the Site Name to find. .EXAMPLE Get-ADSISiteLink .EXAMPLE Get-ADSISiteLink -ForestName lazywinadmin.com .EXAMPLE Get-ADSISiteLink -Credential (Get-Credential superAdmin) -Verbose .EXAMPLE Get-ADSISiteLink -ForestName lazywinadmin.com -Credential (Get-Credential superAdmin) -Verbose .EXAMPLE Get-ADSISiteLink -Name 'Azure' .OUTPUTS System.DirectoryServices.ActiveDirectory.ActiveDirectorySiteLink .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] [OutputType('System.DirectoryServices.ActiveDirectory.ActiveDirectorySiteLink')] param ( [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, $ForestName = [System.DirectoryServices.ActiveDirectory.Forest]::Getcurrentforest(), [Parameter(ValueFromPipelineByPropertyName = $true)] [String]$Name ) process { try { (Get-ADSISite @PSBoundParameters).Sitelinks } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Get-ADSISiteServer { <# .SYNOPSIS Function to retrieve the Active Directory Site Servers .DESCRIPTION Function to retrieve the Active Directory Site Servers .PARAMETER Credential Specifies alternative credential to use. Default is the current user. .PARAMETER ForestName Specifies the ForestName to query. Default is the current one .PARAMETER Name Specifies the Site Name to find. .EXAMPLE Get-ADSISiteServer .EXAMPLE Get-ADSISiteServer -ForestName lazywinadmin.com .EXAMPLE Get-ADSISiteServer -Credential (Get-Credential superAdmin) -Verbose .EXAMPLE Get-ADSISiteServer -ForestName lazywinadmin.com -Credential (Get-Credential superAdmin) -Verbose .EXAMPLE Get-ADSISiteServer -Name 'Azure' .OUTPUTS System.DirectoryServices.ActiveDirectory.DomainController .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] [OutputType('System.DirectoryServices.ActiveDirectory.DomainController')] param ( [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, $ForestName = [System.DirectoryServices.ActiveDirectory.Forest]::Getcurrentforest(), [Parameter(ValueFromPipelineByPropertyName = $true)] [String]$Name ) process { try { (Get-ADSISite @PSBoundParameters).servers } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Get-ADSISiteSubnet { <# .SYNOPSIS Function to retrieve the Active Directory Site subnets .DESCRIPTION Function to retrieve the Active Directory Site subnets .PARAMETER Credential Specifies alternative credential to use. Default is the current user. .PARAMETER ForestName Specifies the ForestName to query. Default is the current one .PARAMETER SubnetName Specifies the Site Name to find. .EXAMPLE Get-ADSISiteSubnet .EXAMPLE Get-ADSISiteSubnet -ForestName lazywinadmin.com .EXAMPLE Get-ADSISiteSubnet -Credential (Get-Credential superAdmin) -Verbose .EXAMPLE Get-ADSISiteSubnet -ForestName lazywinadmin.com -Credential (Get-Credential superAdmin) -Verbose .EXAMPLE Get-ADSISiteSubnet -Name 'Azure' .OUTPUTS System.DirectoryServices.ActiveDirectory.ActiveDirectorySubnet .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] [OutputType('System.DirectoryServices.ActiveDirectory.ActiveDirectorySubnet')] param ( [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, $ForestName = [System.DirectoryServices.ActiveDirectory.Forest]::Getcurrentforest(), [Parameter(ValueFromPipelineByPropertyName = $true)] [Alias("Name")] [String]$SubnetName ) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ ContextType = "Forest" } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['ForestName']) { $ContextSplatting.ForestName = $ForestName } $Context = New-ADSIDirectoryContext @ContextSplatting -contextType Forest } process { try { if ($PSBoundParameters['SubnetName']) { [System.DirectoryServices.ActiveDirectory.ActiveDirectorySubnet]::FindByName($Context, $SubnetName) } if (-not $PSBoundParameters['SubnetName']) { (Get-ADSISite @PSBoundParameters).subnets } } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Get-ADSITokenGroup { <# .SYNOPSIS Retrieve the list of group present in the tokengroups of a user or computer object. .DESCRIPTION Retrieve the list of group present in the tokengroups of a user or computer object. TokenGroups attribute https://msdn.microsoft.com/en-us/library/ms680275%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396 .PARAMETER SamAccountName Specifies the SamAccountName to retrieve .PARAMETER Credential Specifies Credential to use .PARAMETER DomainDistinguishedName Specify the Domain or Domain DN path to use .PARAMETER SizeLimit Specify the number of item maximum to retrieve .EXAMPLE Get-ADSITokenGroup -SamAccountName 'testaccount' Retrieve the list of groups present in the TokenGroups for the user 'testaccount' .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] param ( [Parameter(ValueFromPipeline = $true)] [Alias('UserName', 'Identity')] [String]$SamAccountName, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [Alias('DomainDN', 'Domain')] [String]$DomainDistinguishedName = $(([adsisearcher]"").Searchroot.path), [Alias('ResultLimit', 'Limit')] [int]$SizeLimit = '100' ) process { try { # Building the basic search object with some parameters $Search = New-Object -TypeName System.DirectoryServices.DirectorySearcher -ErrorAction 'Stop' $Search.SizeLimit = $SizeLimit $Search.SearchRoot = $DomainDN #$Search.Filter = "(&(anr=$SamAccountName))" $Search.Filter = "(&((objectclass=user)(samaccountname=$SamAccountName)))" # Credential if ($PSBoundParameters['Credential']) { $Cred = New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList $DomainDistinguishedName, $($Credential.UserName), $($Credential.GetNetworkCredential().password) $Search.SearchRoot = $Cred } # Different Domain if ($DomainDistinguishedName) { if ($DomainDistinguishedName -notlike "LDAP://*") { $DomainDistinguishedName = "LDAP://$DomainDistinguishedName" }#if Write-Verbose -Message "[PROCESS] Different Domain specified: $DomainDistinguishedName" $Search.SearchRoot = $DomainDistinguishedName } foreach ($Account in $Search.FindAll()) { $AccountGetDirectory = $Account.GetDirectoryEntry(); # Add the properties tokenGroups $AccountGetDirectory.GetInfoEx(@("tokenGroups"), 0) foreach ($Token in $($AccountGetDirectory.Get("tokenGroups"))) { # Create SecurityIdentifier to translate into group name $Principal = New-Object -TypeName System.Security.Principal.SecurityIdentifier($token, 0) # Prepare Output $Properties = @{ SamAccountName = $Account.properties.samaccountname -as [string] GroupName = $principal.Translate([System.Security.Principal.NTAccount]) } # Output Information New-Object -TypeName PSObject -Property $Properties } } } catch { $pscmdlet.ThrowTerminatingError($_) } }#process end { Write-Verbose -Message "[END] Function Get-ADSITokenGroup End." } }#Function function Get-ADSITombstoneLifetime { <# .SYNOPSIS Get-ADSITombstoneLifetime returns the number of days before a deleted object is removed from the directory services. .DESCRIPTION Get-ADSITombstoneLifetime returns the number of days before a deleted object is removed from the directory services. .PARAMETER Credential Defines alternate credentials to use. Use Get-Credential to create proper credentials. .PARAMETER DomainName Specifies the DomainName to query .EXAMPLE Get-ADSITombstoneLifetime For the current domain, returns the number of days before a deleted object is removed from the directory services. .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] param ( [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, $DomainName = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() ) try { if ($PSBoundParameters['Credential'] -or $PSBoundParameters['DomainName']) { Write-Verbose -Message '[PROCESS] Credential or DomainName specified' $Splatting = @{ } if ($PSBoundParameters['Credential']) { $Splatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $Splatting.DomainName = $DomainName } $configurationNamingContext = (Get-ADSIRootDSE @splatting).configurationNamingContext } else { $configurationNamingContext = (Get-ADSIRootDSE).configurationNamingContext } } catch { $pscmdlet.ThrowTerminatingError($_) } $nTDSService = New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList "LDAP://CN=Directory Service,CN=Windows NT,CN=Services,$configurationNamingContext" Write-Verbose "Domain : $DomainName" $nTDSService.tombstoneLifetime } function Get-ADSIUser { <# .SYNOPSIS Function to retrieve a User in Active Directory .DESCRIPTION Function to retrieve a User in Active Directory .PARAMETER Identity Specifies the Identity of the User You can provide one of the following properties DistinguishedName Guid Name SamAccountName Sid UserPrincipalName Those properties come from the following enumeration: System.DirectoryServices.AccountManagement.IdentityType .PARAMETER Credential Specifies the alternative credential to use. By default it will use the current user windows credentials. .PARAMETER DomainName Specifies the alternative Domain where the user should be created By default it will use the current domain. .PARAMETER NoResultLimit Remove the SizeLimit of 1000 SizeLimit is useless, it can't go over the server limit which is 1000 by default .PARAMETER LDAPFilter Specifies the LDAP query to apply .EXAMPLE Get-ADSIUser This example will retrieve all accounts in the current domain using the current user credential. There is a limit of 1000 objects returned. .EXAMPLE Get-ADSIUser -NoResultLimit This example will retrieve all accounts in the current domain using the current user credential. Using the parameter -NoResultLimit will remove the Sizelimit on the Result. .EXAMPLE Get-ADSIUser -Identity 'testaccount' This example will retrieve the account 'testaccount' in the current domain using the current user credential .EXAMPLE Get-ADSIUser -Identity 'testaccount' -Credential (Get-Credential) This example will retrieve the account 'testaccount' in the current domain using the specified credential .EXAMPLE Get-ADSIUSer -LDAPFilter "(&(objectClass=user)(samaccountname=*fx*))" -DomainName 'fx.lab' This example will retrieve the user account that contains fx inside the samaccountname property for the domain fx.lab. There is a limit of 1000 objects returned. .EXAMPLE Get-ADSIUSer -LDAPFilter "(&(objectClass=user)(samaccountname=*fx*))" -DomainName 'fx.lab' -NoResultLimit This example will retrieve the user account that contains fx inside the samaccountname property for the domain fx.lab. There is NO limit of 1000 objects returned. .EXAMPLE $user = Get-ADSIUser -Identity 'testaccount' $user.GetUnderlyingObject()| Select-Object -Property * Help you find all the extra properties and methods available .NOTES https://github.com/lazywinadmin/ADSIPS .LINK https://msdn.microsoft.com/en-us/library/System.DirectoryServices.AccountManagement.UserPrincipal(v=vs.110).aspx #> [CmdletBinding(DefaultParameterSetName = "All")] [OutputType('System.DirectoryServices.AccountManagement.UserPrincipal')] param ( [Parameter(Mandatory = $true, Position = 0, ParameterSetName = "Identity")] [string]$Identity, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$DomainName, [Parameter(Mandatory = $true, ParameterSetName = "LDAPFilter")] [string]$LDAPFilter, [Parameter(ParameterSetName = "LDAPFilter")] [Parameter(ParameterSetName = "All")] [Switch]$NoResultLimit ) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ ContextType = "Domain" } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } $Context = New-ADSIPrincipalContext @ContextSplatting } process { if ($Identity) { Write-Verbose -Message "Identity" [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($Context, $Identity) } elseif ($PSBoundParameters['LDAPFilter']) { # Directory Entry object $DirectoryEntryParams = $ContextSplatting $DirectoryEntryParams.remove('ContextType') $DirectoryEntry = New-ADSIDirectoryEntry @DirectoryEntryParams # Principal Searcher $DirectorySearcher = new-object -TypeName System.DirectoryServices.DirectorySearcher $DirectorySearcher.SearchRoot = $DirectoryEntry $DirectorySearcher.Filter = "(&(objectCategory=user)$LDAPFilter)" #$DirectorySearcher.PropertiesToLoad.AddRange("'Enabled','SamAccountName','DistinguishedName','Sid','DistinguishedName'") if (-not$PSBoundParameters['NoResultLimit']) { Write-Warning -Message "Result is limited to 1000 entries, specify a specific number on the parameter SizeLimit or 0 to remove the limit" } else { # SizeLimit is useless, even if there is a$Searcher.GetUnderlyingSearcher().sizelimit=$SizeLimit # the server limit is kept $DirectorySearcher.PageSize = 10000 } $DirectorySearcher.FindAll() | Foreach-Object -Process { [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($Context, $_.Properties["distinguishedname"]) }# Return UserPrincipale object } else { Write-Verbose -Message "Searcher" $UserPrincipal = New-object -TypeName System.DirectoryServices.AccountManagement.UserPrincipal -ArgumentList $Context $Searcher = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalSearcher $Searcher.QueryFilter = $UserPrincipal if (-not$PSBoundParameters['NoResultLimit']) { Write-Warning -Message "Result is limited to 1000 entries, specify a specific number on the parameter SizeLimit or 0 to remove the limit" } else { # SizeLimit is useless, even if there is a$Searcher.GetUnderlyingSearcher().sizelimit=$SizeLimit # the server limit is kept $Searcher.GetUnderlyingSearcher().pagesize = 10000 } #$Searcher.GetUnderlyingSearcher().propertiestoload.AddRange("'Enabled','SamAccountName','DistinguishedName','Sid','DistinguishedName'") $Searcher.FindAll() # Return UserPrincipale } } } function Get-ADSIUserPrimaryGroup { <# .SYNOPSIS Function to retrieve User's primary group .DESCRIPTION Get primary AD group of a user .PARAMETER Identity Specifies the Identity of the User Uses the return of "Get-ADSIUser" .PARAMETER ReturnNameAndDescriptionOnly Returns a PSCustomObject of just the name and description ex: $return = [pscustomobject]@{ 'name' = [string]$primaryGroup.Properties.name 'description' = [string]$primaryGroup.Properties.description } .EXAMPLE Get-ADSIUserPrimaryGroup -Identity (Get-ADSIUser 'User1') Get primary AD group of user User1 .NOTES https://github.com/lazywinadmin/ADSIPS CHANGE LOG -1.0 | 2019/06/22 | Matt Oestreich (oze4) - Initial creation #> param( [Parameter(Mandatory=$true)] [System.DirectoryServices.AccountManagement.AuthenticablePrincipal]$Identity, [Parameter(Mandatory=$false)] [switch]$ReturnNameAndDescriptionOnly ) try { $UnderlyingProperties = $Identity.GetUnderlyingObject() $userSid = (New-Object System.Security.Principal.SecurityIdentifier ($($UnderlyingProperties.properties.objectSID), 0)).AccountDomainSid.Value $groupSid = ('{0}-{1}' -f $userSid, $UnderlyingProperties.properties.primarygroupid.ToString()) $primaryGroup = [adsi]("LDAP://<SID=$groupSid>") if ($PSBoundParameters["ReturnNameAndDescriptionOnly"]) { [pscustomobject]@{ 'name' = [string]$primaryGroup.Properties.name 'description' = [string]$primaryGroup.Properties.description } } else { $primaryGroup } } catch { $PSCmdlet.ThrowTerminatingError($_) } } function Move-ADSIComputer { <# .SYNOPSIS Function to Move a Computer in Active Directory .DESCRIPTION Function to Move a Computer in Active Directory .PARAMETER Identity Specifies the Identity of the computer You can provide one of the following: DistinguishedName Guid Name SamAccountName Sid System.DirectoryService.AccountManagement.IdentityType https://msdn.microsoft.com/en-us/library/bb356425(v=vs.110).aspx .PARAMETER Credential Specifies alternative credential By default it will use the current user windows credentials. .PARAMETER DomainName Specifies the alternative Domain. By default it will use the current domain. .PARAMETER Destination Specifies the Distinguished Name where the object will be moved .EXAMPLE Move-ADSIComputer -identity 'TESTCOMP01' -Destination 'OU=Servers,DC=FX,DC=LAB' .NOTES https://github.com/lazywinadmin/ADSIPS .LINK https://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.computerprincipal(v=vs.110).aspx #> [CmdletBinding()] param ([Parameter(Mandatory = $true)] [string]$Identity, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, $DomainName, $Destination ) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ ContextType = "Domain" } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } $Context = New-ADSIPrincipalContext @ContextSplatting } process { try { $Computer = [System.DirectoryServices.AccountManagement.ComputerPrincipal]::FindByIdentity($Context, $Identity) # Retrieve DirectoryEntry #$Computer.GetUnderlyingObject() # Create DirectoryEntry object $NewDirectoryEntry = New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList "LDAP://$Destination" # Move the computer $Computer.GetUnderlyingObject().psbase.moveto($NewDirectoryEntry) $Computer.Save() } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Move-ADSIDomainControllerRole { <# .SYNOPSIS Function to transfers or Seizes Active Directory roles to the current DC. .DESCRIPTION Function to transfers or Seizes Active Directory roles to the current DC. .PARAMETER ComputerName Specifies the Domain Controller .PARAMETER Credential Specifies alternate credentials to use. Use Get-Credential to create proper credentials. .PARAMETER Role Specifies the Role(s) to transfer to Seize .PARAMETER Force Forces the role(s) to be seized .EXAMPLE Move-ADSIDomainControllerRole -ComputerName dc1.ad.local -Roles "PDCRole" Connects to remote domain controller dc1.ad.local using current credentials and attempts to transfer the PDCrole to dc1.ad.local. .EXAMPLE Move-ADSIDomainControllerRole -ComputerName DC1 -Credential $cred -Verbose -Roles InfrastructureRole,PDCRole,RidRole,NamingRole,SchemaRole -Force Connects to remote domain controller dc1.ad.local using alternate credentials and seizes all the roles. .NOTES Version History 1.0 Initial Version (Micky Balladelli) 1.1 Update (Francois-Xavier Cat) Rename from Move-ADSIDomainControllerRole to Move-ADSIDomainControllerRole Add New-ADSIDirectoryContext to take care of the Context Other minor modifications https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$ComputerName, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [Parameter(Mandatory = $true)] [System.Directoryservices.ActiveDirectory.ActiveDirectoryRole[]]$Role, [Switch]$Force ) process { try { # DirectoryContext Splatting $Splatting = $PSBoundParameters.Remove("Force") $Splatting = $Splatting.Remove("Role") # Create the Context $Context = New-ADSIDirectoryContext -ContextType 'DirectoryServer' @Splatting # Get the DomainController $DomainController = [System.DirectoryServices.ActiveDirectory.DomainController]::GetDomainController($Context) if ($PSBoundParameters['Force']) { foreach ($RoleObj in $Role) { Write-Verbose -Message "[Move-ADSIDomainControllerRole][PROCESS] $($DomainController.name) Forcing a role transfer of role $RoleObj" $DomainController.SeizeRoleOwnership($RoleObj) } } else { foreach ($RoleObj in $Role) { Write-Verbose -Message "[Move-ADSIDomainControllerRole][PROCESS] $($DomainController.name) Transferring role $RoleObj" $DomainController.TransferRoleOwnership($RoleObj) } } Write-Verbose -Message "[Move-ADSIDomainControllerRole][PROCESS] $($DomainController.name) Done." } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Move-ADSIDomainControllerToSite { <# .SYNOPSIS Move-ADSIDomainControllerToSite moves the current DC to another site. .DESCRIPTION Move-ADSIDomainControllerToSite moves the current DC to another site. MSDN Documention on 'DirectoryServer.MoveToAnotherSite Method' https://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectory.directoryserver.movetoanothersite(v=vs.110).aspx .PARAMETER ComputerName Specifies the Domain Controller .PARAMETER Credential Specifies alternate credentials to use. Use Get-Credential to create proper credentials. .PARAMETER Site Name of the Active Directory site .EXAMPLE Move-ADSIDomainControllerToSite -ComputerName dc1.ad.local -site "Paris" Connects to remote domain controller dc1.ad.local using current credentials and moves it to the site "Paris". .NOTES https://github.com/lazywinadmin/ADSIPS Version History 1.0 Initial Version (Micky Balladelli) 1.1 Update (Francois-Xavier Cat) Rename from Move-ADSIReplicaToSite to Move-ADSIDomainControllerToSite Add New-ADSIDirectoryContext to take care of the Context Other minor modifications #> [CmdletBinding()] param ( [Parameter(Mandatory)] [string]$ComputerName, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [Parameter(Mandatory = $true)] [string]$Site ) process { try { # DirectoryContext Splatting $Splatting = $PSBoundParameters.Remove("Site") # Create the Context $Context = New-ADSIDirectoryContext -ContextType 'DirectoryServer' @Splatting $DomainController = [System.DirectoryServices.ActiveDirectory.DomainController]::GetDomainController($context) Write-Verbose -Message "[Move-ADSIDomainControllerToSite][PROCESS] $($DomainController.name) to site $Site" $DomainController.MoveToAnotherSite($Site) } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Move-ADSIGroup { <# .SYNOPSIS Function to Move an Active Directory group in a different Organizational Unit (OU) .DESCRIPTION Function to Move an Active Directory group in a different Organizational Unit (OU) .PARAMETER Identity Specifies the Identity of the group You can provide one of the following properties DistinguishedName Guid Name SamAccountName Sid UserPrincipalName Those properties come from the following enumeration: System.DirectoryServices.AccountManagement.IdentityType .PARAMETER Credential Specifies the alternative credential to use. By default it will use the current user windows credentials. .PARAMETER DomainName Specifies the alternative Domain where the user should be created By default it will use the current Domain. .PARAMETER Destination Specifies the Distinguished Name where the object will be moved .EXAMPLE Move-ADSIGroup -Identity 'FXGROUPTEST01' -Destination 'OU=TEST,DC=FX,DC=lab' .NOTES https://github.com/lazywinadmin/ADSIPS .LINK https://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.groupprincipal(v=vs.110).aspx #> [CmdletBinding()] [OutputType('System.DirectoryServices.AccountManagement.GroupPrincipal')] param ( [Parameter(Mandatory = $true)] [string]$Identity, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [Alias('Domain', 'Server')] $DomainName = [System.DirectoryServices.ActiveDirectory.Domain]::Getcurrentdomain(), $Destination ) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ ContextType = "Domain" } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } $Context = New-ADSIPrincipalContext @ContextSplatting } process { try { $Group = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($Context, $Identity) # Create DirectoryEntry object $NewDirectoryEntry = New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList "LDAP://$Destination" # Move the computer $Group.GetUnderlyingObject().psbase.moveto($NewDirectoryEntry) $Group.Save() } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Move-ADSIUser { <# .SYNOPSIS Function to move a User in Active Directory .DESCRIPTION Function to move a User in Active Directory .PARAMETER Identity Specifies the Identity of the User You can provide one of the following properties DistinguishedName Guid Name SamAccountName Sid UserPrincipalName Those properties come from the following enumeration: System.DirectoryServices.AccountManagement.IdentityType .PARAMETER Credential Specifies the alternative credential to use. By default it will use the current user windows credentials. .PARAMETER DomainName Specifies the alternative Domain where the user should be created By default it will use the current domain. .PARAMETER Destination Specifies the Distinguished Name where the object will be moved .EXAMPLE Move-ADSIUser -Identity 'fxtest01' -Destination "OU=Test,DC=FX,DC=lab" .EXAMPLE Move-ADSIUser -Identity 'fxtest01' -Destination "OU=Test,DC=FX,DC=lab" -Credential (Get-Credential) .NOTES https://github.com/lazywinadmin/ADSIPS .LINK https://msdn.microsoft.com/en-us/library/System.DirectoryServices.AccountManagement.UserPrincipal(v=vs.110).aspx #> [CmdletBinding()] [OutputType('System.DirectoryServices.AccountManagement.UserPrincipal')] param ( [Parameter(Mandatory = $true)] [string]$Identity, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$DomainName, $Destination ) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ ContextType = "Domain" } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } $Context = New-ADSIPrincipalContext @ContextSplatting } process { if ($Identity) { $user = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($Context, $Identity) # Retrieve DirectoryEntry #$User.GetUnderlyingObject() # Create DirectoryEntry object $NewDirectoryEntry = New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList "LDAP://$Destination" # Move the computer $User.GetUnderlyingObject().psbase.moveto($NewDirectoryEntry) $User.Save() } } } function New-ADSIComputer { <# .SYNOPSIS function to create a new computer .DESCRIPTION function to create a new computer .PARAMETER Name Specifies the property Name .PARAMETER DisplayName Specifies the property DisplayName .PARAMETER Description Specifies the property Description .PARAMETER Enable Specifies you want the account enabled after creation. By Default the account is disable .PARAMETER Passthru Specifies if you want to see the object created after running the command. .PARAMETER Credential Specifies if you want to specifies alternative credentials .PARAMETER DomainName Specifies if you want to specifies alternative DomainName .EXAMPLE New-ADSIComputer FXTEST01 -Description 'Dev system' Create a new computer account FXTEST01 and add the description 'Dev System' .EXAMPLE New-ADSIComputer FXTEST01 -enable Create a new computer account FXTEST01 inside the default Computers Organizational Unit and Enable the account .EXAMPLE New-ADSIComputer FXTEST01 -Description 'Dev system' Create a new computer account FXTEST01 and add the description 'Dev System' .EXAMPLE New-ADSIComputer FXTEST01 -Passthru Create a new computer account FXTEST01 and return the object created and its properties. .NOTES https://github.com/lazywinadmin/ADSIPS .LINK https://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.computerprincipal(v=vs.110).aspx #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter(Mandatory = $true)] $Name, [String]$DisplayName, [String]$Description, [switch]$Passthru, [Switch]$Enable, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$DomainName ) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ ContextType = "Domain" } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } $Context = New-ADSIPrincipalContext @ContextSplatting } process { try { if ($PSCmdlet.ShouldProcess($Name, "Create Computer")) { $newObject = New-Object -TypeName System.DirectoryServices.AccountManagement.ComputerPrincipal -ArgumentList $Context $newObject.SamAccountName = $Name if ($PSBoundParameters['Enable']) { $newObject.Enabled = $true } if ($PSBoundParameters['Description']) { $newObject.Description = $Description } if ($PSBoundParameters['DisplayName']) { $newObject.DisplayName } # Push to ActiveDirectory $newObject.Save($Context) if ($PSBoundParameters['Passthru']) { $ContextSplatting.Remove('ContextType') Get-ADSIComputer -Identity $Name @ContextSplatting } } } catch { $pscmdlet.ThrowTerminatingError($_) } } end { } } function New-ADSIDirectoryContext { <# .SYNOPSIS Function to create an Active Directory DirectoryContext objects .DESCRIPTION Function to create an Active Directory DirectoryContext objects .PARAMETER Credential Specifies the alternative credentials to use. It will use the current credential if not specified. .PARAMETER ContextType Specifies the ContextType. The following choices are available: ApplicationPartition ConfigurationSet DirectoryServer Domain Forest .PARAMETER DomainName Specifies the domain to query. Default is the current domain. This need to be used with the ContextType Domain .PARAMETER ForestName Specifies the forest to query. Default is the current forest. This need to be used with the ContextType Forest .PARAMETER Server Specifies the Domain Controller to use This need to be used with the ContextType DirectoryServer .EXAMPLE New-ADSIDirectoryContext -ContextType Domain This will create a new Directory Context of type Domain in the current domain .EXAMPLE New-ADSIDirectoryContext -ContextType Domain -DomainName "FXTEST.local" This will create a new Directory Context of type Domain in the domain "FXTEST.local" .EXAMPLE New-ADSIDirectoryContext -ContextType Forest This will create a new Directory Context of type Forest in the current forest .EXAMPLE New-ADSIDirectoryContext -ContextType Forest -ForestName "FXTEST.local" This will create a new Directory Context of type Forest in the forest FXTEST.local .EXAMPLE New-ADSIDirectoryContext -ContextType Forest -ForestName "FXTEST.local" -credential (Get-Credential) This will create a new Directory Context of type Forest with Alternative credentials .EXAMPLE New-ADSIDirectoryContext -ContextType DirectoryServer -Server "DCSERVER01.FXTEST.local" This will create a new Directory Context of type DirectoryServer against the Domain Controller DCSERVER01.FXTEST.local .EXAMPLE $Domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($(New-ADSIDirectoryContext -ContextType Domain -Credential (Get-Credential))) $Domain.DomainControllers $Domain.InfrastructureRoleOwner This will retrieve all the Domain Controllers and the Infrastructure Role owner (FSMO Role) .EXAMPLE [System.DirectoryServices.ActiveDirectory.DomainController]::GetDomainController(New-ADSIDirectoryContext -ContextType DirectoryServer -Server "DC01.FXTEST.local").forest.sites This will retrieve all the sites in the forest .NOTES https://github.com/lazywinadmin/ADSIPS .LINK https://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectory.directorycontext(v=vs.110).aspx #> [CmdletBinding(DefaultParameterSetName = 'Server', SupportsShouldProcess = $true)] param ( [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [Parameter(Mandatory)] [System.DirectoryServices.ActiveDirectory.DirectoryContextType]$ContextType, [Parameter(ParameterSetName = 'Domain')] $DomainName = [System.DirectoryServices.ActiveDirectory.Domain]::Getcurrentdomain(), [Parameter(ParameterSetName = 'Forest')] $ForestName = [System.DirectoryServices.ActiveDirectory.Forest]::Getcurrentforest(), [Parameter(ParameterSetName = 'Server')] [ValidateNotNullOrEmpty] [Alias("ComputerName", "DomainController")] $Server ) process { try { switch ($ContextType) { "Domain" { $ArgumentList = $ContextType, $DomainName } "Forest" { $ArgumentList = $ContextType, $ForestName } "DirectoryServer" { $ArgumentList = $ContextType, $Server } "ApplicationPartition" { $ArgumentList = $ContextType } "ConfigurationSet" { $ArgumentList = $ContextType } } if ($PSBoundParameters['Credential']) { # Query the specified domain or current if not entered, with the specified credentials $ArgumentList += $($Credential.UserName), $($Credential.GetNetworkCredential().password) } if ($PSCmdlet.ShouldProcess("Create Directory Entry")) { # Query the specified domain or current if not entered, with the current credentials New-Object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList $ArgumentList } } #try catch { $pscmdlet.ThrowTerminatingError($_) } } #process } function New-ADSIDirectoryEntry { <# .SYNOPSIS Function to create a DirectoryEntry instance .DESCRIPTION Function to create a DirectoryEntry instance This function is typically a helper function used by some of the other functions in the module ADSIPS .PARAMETER Path The path of this DirectoryEntry. Default is $(([adsisearcher]"").Searchroot.path) https://msdn.microsoft.com/en-us/library/system.directoryservices.directoryentry.path.aspx .PARAMETER Credential Specifies alternative credential to use .PARAMETER AuthenticationType Specifies the optional AuthenticationType secure flag(s) to use The Secure flag can be used in combination with other flags such as ReadonlyServer, FastBind. See the full detailed list here: https://msdn.microsoft.com/en-us/library/system.directoryservices.authenticationtypes(v=vs.110).aspx .EXAMPLE New-ADSIDirectoryEntry Create a new DirectoryEntry object for the current domain .EXAMPLE New-ADSIDirectoryEntry -Path "LDAP://DC=FX,DC=lab" Create a new DirectoryEntry object for the domain FX.Lab .EXAMPLE New-ADSIDirectoryEntry -Path "LDAP://DC=FX,DC=lab" -Credential (Get-Credential) Create a new DirectoryEntry object for the domain FX.Lab with the specified credential .LINK https://msdn.microsoft.com/en-us/library/system.directoryservices.directoryentry.aspx .LINK http://www.lazywinadmin.com/2013/10/powershell-using-adsi-with-alternate.html .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Alias('DomainName')] $Path = $(([adsisearcher]"").Searchroot.path), [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [System.DirectoryServices.AuthenticationTypes[]]$AuthenticationType ) try { #If path isn't prefixed with LDAP://, add it if ($PSBoundParameters['Path']) { if ($Path -notlike "LDAP://*") { $Path = "LDAP://$Path" } } #Building Argument if ($PSBoundParameters['Credential']) { $ArgumentList = $Path, $($Credential.UserName), $($Credential.GetNetworkCredential().password) } else { $ArgumentList = $Path } if ($PSBoundParameters['AuthenticationType']) { $ArgumentList += $AuthenticationType } if ($PSCmdlet.ShouldProcess($Path, "Create Directory Entry")) { # Create object New-Object -TypeName DirectoryServices.DirectoryEntry -ArgumentList $ArgumentList } } catch { $PSCmdlet.ThrowTerminatingError($_) } } function New-ADSIGroup { <# .SYNOPSIS function to create a new group .DESCRIPTION function to create a new group .PARAMETER Name Specifies the property Name .PARAMETER DisplayName Specifies the property DisplayName .PARAMETER UserPrincipalName Specifies the property UserPrincipalName .PARAMETER Description Specifies the property Description .PARAMETER GroupScope Specifies the Group Scope (Global, Local or Universal) .PARAMETER IsSecurityGroup Specify if you want to create a Security Group. By default this is $true. .PARAMETER Passthru Specifies if you want to see the object created after running the command. .PARAMETER Credential Specifies if you want to specifies alternative credentials .PARAMETER DomainName Specifies if you want to specifies alternative DomainName .EXAMPLE PS C:\> New-ADSIGroup -Name "TestfromADSIPS3" -Description "some description" -GroupScope Local -IsSecurityGroup .NOTES https://github.com/lazywinadmin/ADSIPS .LINK https://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.groupprincipal(v=vs.110).aspx #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter(Mandatory = $true)] $Name, [String]$DisplayName, [String]$UserPrincipalName, [String]$Description, [Parameter(Mandatory = $true)] [system.directoryservices.accountmanagement.groupscope]$GroupScope, [switch]$IsSecurityGroup = $true, [switch]$Passthru, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$DomainName ) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ ContextType = "Domain" } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } $Context = New-ADSIPrincipalContext @ContextSplatting } process { try { if ($PSCmdlet.ShouldProcess($Name, "Create Group")) { $newGroup = [System.DirectoryServices.AccountManagement.GroupPrincipal]::new($Context, $Name) $newGroup.Description = $Description $newGroup.GroupScope = $GroupScope $newGroup.IsSecurityGroup = $IsSecurityGroup $newGroup.DisplayName #$newGroup.DistinguishedName = #$newGroup.Members $newGroup.SamAccountName = $Name if ($PSBoundParameters['UserPrincipalName']) { $newGroup.UserPrincipalName = $UserPrincipalName } # Push to ActiveDirectory $newGroup.Save($Context) if ($PSBoundParameters['Passthru']) { $ContextSplatting.Remove('ContextType') Get-ADSIGroup -Identity $Name @ContextSplatting } } } catch { $pscmdlet.ThrowTerminatingError($_) } } end { } } function New-ADSIPrincipalContext { <# .SYNOPSIS Function to create an Active Directory PrincipalContext object .DESCRIPTION Function to create an Active Directory PrincipalContext object .PARAMETER Credential Specifies the alternative credentials to use. It will use the current credential if not specified. .PARAMETER ContextType Specifies which type of Context to use. Domain, Machine or ApplicationDirectory. .PARAMETER DomainName Specifies the domain to query. Default is the current domain. Should only be used with the Domain ContextType. .PARAMETER Container Specifies the scope. Example: "OU=MyOU" .PARAMETER ContextOptions Specifies the ContextOptions. Negotiate Sealing SecureSocketLayer ServerBind Signing SimpleBind .EXAMPLE New-ADSIPrincipalContext -ContextType 'Domain' .EXAMPLE New-ADSIPrincipalContext -ContextType 'Domain' -DomainName "Contoso.com" -Cred (Get-Credential) .NOTES https://github.com/lazywinadmin/ADSIPS .LINK https://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.principalcontext(v=vs.110).aspx #> [CmdletBinding(SupportsShouldProcess = $true)] [OutputType('System.DirectoryServices.AccountManagement.PrincipalContext')] param ( [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [Parameter(Mandatory = $true)] [System.DirectoryServices.AccountManagement.ContextType]$ContextType, $DomainName = [System.DirectoryServices.ActiveDirectory.Domain]::Getcurrentdomain(), $Container, [System.DirectoryServices.AccountManagement.ContextOptions[]]$ContextOptions ) begin { $ScriptName = (Get-Variable -name MyInvocation -Scope 0 -ValueOnly).MyCommand Write-Verbose -Message "[$ScriptName] Add Type System.DirectoryServices.AccountManagement" Add-Type -AssemblyName System.DirectoryServices.AccountManagement } process { try { switch ($ContextType) { "Domain" { $ArgumentList = $ContextType, $DomainName } "Machine" { $ArgumentList = $ContextType, $ComputerName } "ApplicationDirectory" { $ArgumentList = $ContextType } } if ($PSBoundParameters['Container']) { $ArgumentList += $Container } if ($PSBoundParameters['ContextOptions']) { $ArgumentList += $($ContextOptions) } if ($PSBoundParameters['Credential']) { # Query the specified domain or current if not entered, with the specified credentials $ArgumentList += $($Credential.UserName), $($Credential.GetNetworkCredential().password) } if ($PSCmdlet.ShouldProcess($DomainName, "Create Principal Context")) { # Query New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList $ArgumentList } } #try catch { $PSCmdlet.ThrowTerminatingError($_) } } #process } function New-ADSISite { <# .SYNOPSIS Function to create a new Site .DESCRIPTION Function to create a new Site .PARAMETER SiteName Specifies the SiteName .PARAMETER Location Specifies the Location of the site .PARAMETER Credential Specifies the alternative credential to use. By default it will use the current user windows credentials. .PARAMETER ForestName Specifies the alternative Forest where the subnet should be created By default it will use the current forest. .EXAMPLE PS C:\> New-ADSISite -SiteName "MTL01" -Location "Montreal, QC, Canada" .NOTES https://github.com/lazywinadmin/ADSIPS .LINK https://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectory.activedirectorysite(v=vs.110).aspx #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter(Mandatory = $true)] [Alias('Name')] [String]$SiteName, [String]$Location, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$ForestName ) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ ContextType = "Forest" } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['ForestName']) { $ContextSplatting.ForestName = $ForestName } $Context = New-ADSIDirectoryContext @ContextSplatting } process { try { if ($PSCmdlet.ShouldProcess($SiteName, "Create Site")) { $Site = New-Object -TypeName System.DirectoryServices.ActiveDirectory.ActiveDirectorySite -ArgumentList $Context, $SiteName $Site.Location = $Location $Site.Save() #$site.GetDirectoryEntry() } } catch { $PSCmdlet.ThrowTerminatingError($_) } } end { } } function New-ADSISiteSubnet { <# .SYNOPSIS Function to create a new Site Subnet .DESCRIPTION Function to create a new Site Subnet .PARAMETER SubnetName Specifies the SubnetName. Example '192.168.8.0/24' .PARAMETER SiteName Specifies the SiteName where the subnet will be assigned .PARAMETER Location Specifies the location of the subnet .PARAMETER Credential Specifies the alternative credential to use. By default it will use the current user windows credentials. .PARAMETER ForestName Specifies the alternative Forest where the subnet should be created By default it will use the current forest. .EXAMPLE PS C:\> New-ADSISiteSubnet -SubnetName "5.5.5.0/24" -SiteName "FX3" -Location "test" .NOTES https://github.com/lazywinadmin/ADSIPS .LINK https://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectory.activedirectorysubnet(v=vs.110).aspx #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter(Mandatory = $true)] [String]$SubnetName, [Parameter(Mandatory = $true)] [String]$SiteName, [String]$Location, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$ForestName ) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ ContextType = "Forest" } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['ForestName']) { $ContextSplatting.ForestName = $ForestName } $Context = New-ADSIDirectoryContext @ContextSplatting } process { try { if ($PSCmdlet.ShouldProcess($SubnetName, "Create new Subnet")) { $Subnet = New-Object -TypeName System.DirectoryServices.ActiveDirectory.ActiveDirectorysubnet -ArgumentList $Context, $SubnetName, $SiteName if ($PSBoundParameters['Location']) { $Subnet.Location = $Location } $Subnet.Save() #$SubnetEntry = $Subnet.GetDirectoryEntry() #$SubnetEntry.Description = $subnetdescription #$SubnetEntry.CommitChanges() #$SubnetEntry } } catch { $pscmdlet.ThrowTerminatingError($_) break } } end { } } function New-ADSIUser { <# .SYNOPSIS Function to create a new User .DESCRIPTION Function to create a new User .PARAMETER SamAccountName Specifies the SamAccountName parameter .PARAMETER AccountPassword Specifies the password parameter .PARAMETER Enabled Specifies if the user need to be enabled on creation. Default is $False. .PARAMETER GivenName Specifies the GivenName parameter .PARAMETER SurName Specifies the Surname parameter .PARAMETER UserPrincipalName Specifies the UserPrincipalName parameter. .PARAMETER DisplayName Specifies the DisplayName parameter. .PARAMETER Name Specifies the Name parameter. .PARAMETER PasswordNeverExpires Specifies if the Password Never Expires .PARAMETER UserCannotChangePassword Specifies if the User Cannot Change Password .PARAMETER PasswordNotRequired Specifies if the Password is Not Required .PARAMETER Credential Specifies the alternative credential to use. By default it will use the current user windows credentials. .PARAMETER DomainName Specifies the alternative Domain where the user should be created By default it will use the current domain. .PARAMETER Passthru Specifies if you want to see the object created after running the command. .EXAMPLE PS C:\> New-ADSIUser -SamAccountName "fxtest04" -Enabled -AccountPassword (Read-Host -AsSecureString "AccountPassword") -Passthru .EXAMPLE PS C:\> New-ADSIUser -SamAccountName "fxtest04" -Enabled -AccountPassword (Read-Host -AsSecureString "AccountPassword") -Passthru # You can test the credential using the following function Test-ADSICredential -AccountName "fxtest04" -AccountPassword (Read-Host -AsSecureString "AccountPassword") .NOTES https://github.com/lazywinadmin/ADSIPS .LINK https://msdn.microsoft.com/en-us/library/System.DirectoryServices.AccountManagement.UserPrincipal(v=vs.110).aspx #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter(Mandatory = $true)] [String]$SamAccountName, [System.Security.SecureString]$AccountPassword, [switch]$Enabled = $false, [String]$GivenName, [String]$SurName, [String]$UserPrincipalName, [String]$DisplayName, [String]$Name, [Switch]$PasswordNeverExpires = $false, [Switch]$UserCannotChangePassword = $false, [Switch]$PasswordNotRequired = $false, [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$DomainName, [Switch]$Passthru ) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ ContextType = "Domain" } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } $Context = New-ADSIPrincipalContext @ContextSplatting } process { try { if ($PSCmdlet.ShouldProcess($SamAccountName, "Create User Account")) { Write-Verbose -message "Build the user object" $User = New-Object -TypeName System.DirectoryServices.AccountManagement.UserPrincipal -ArgumentList $context Write-Verbose -message "set the properties" $User.SamAccountName = $SamAccountName $User.Enabled = $Enabled $user.PasswordNeverExpires = $PasswordNeverExpires $user.UserCannotChangePassword = $UserCannotChangePassword $User.PasswordNotRequired = $PasswordNotRequired if ($PSBoundParameters['Name']) { $User.Name = $Name } if ($PSBoundParameters['DisplayName']) { $User.DisplayName = $DisplayName } if ($PSBoundParameters['GivenName']) { $User.GivenName = $GivenName } if ($PSBoundParameters['SurName']) { $User.SurName = $SurName } if ($PSBoundParameters['UserPrincipalName']) { $User.UserPrincipalName = $UserPrincipalName } if ($PSBoundParameters['Description']) { $user.Description = $Description } if ($PSBoundParameters['EmployeeId']) { $user.EmployeeId = $EmployeeId } if ($PSBoundParameters['HomeDirectory']) { $user.HomeDirectory = $HomeDirectory } if ($PSBoundParameters['HomeDrive']) { $user.HomeDrive = $HomeDrive } if ($PSBoundParameters['MiddleName']) { $user.MiddleName = $MiddleName } if ($PSBoundParameters['VoiceTelephoneNumber']) { $user.VoiceTelephoneNumber } if ($PSBoundParameters['AccountPassword']) { $User.SetPassword((New-Object -TypeName PSCredential -ArgumentList "user", $AccountPassword).GetNetworkCredential().Password) } Write-Verbose -message "Create the Account in Active Directory" $User.Save($Context) } } catch { $pscmdlet.ThrowTerminatingError($_) break } } end { if ($PSBoundParameters['Passthru']) { $ContextSplatting.Remove("ContextType") Get-ADSIUser -Identity $SamAccountName @ContextSplatting } } } function Remove-ADSIComputer { <# .SYNOPSIS Function to Remove a Computer Account .DESCRIPTION Function to Remove a Computer Account .PARAMETER Identity Specifies the Identity of the Computer. You can provide one of the following: DistinguishedName Guid Name SamAccountName Sid .PARAMETER Credential Specifies the alternative credential to use. By default it will use the current user windows credentials. .PARAMETER DomainName Specifies the alternative Domain. By default it will use the current domain. .PARAMETER Recursive Specifies that any child object should be deleted as well Typically you would use this parameter if you get the error "The directory service can perform the requested operation only on a leaf object" when you try to delete the object without the -recursive param .EXAMPLE Remove-ADSIComputer -identity TESTSERVER01 This command will Remove the account TESTSERVER01 .EXAMPLE Remove-ADSIComputer -identity TESTSERVER01 -recursive This command will Remove the account TESTSERVER01 and all the child leaf .EXAMPLE Remove-ADSIComputer -identity TESTSERVER01 -whatif This command will emulate removing the account TESTSERVER01 .EXAMPLE Remove-ADSIComputer -identity TESTSERVER01 -credential (Get-Credential) This command will Remove the account TESTSERVER01 using the alternative credential specified .EXAMPLE Remove-ADSIComputer -identity TESTSERVER01 -credential (Get-Credential) -domain LazyWinAdmin.local This command will Remove the account TESTSERVER01 using the alternative credential specified in the domain lazywinadmin.local .NOTES https://github.com/lazywinadmin/ADSIPS .LINK https://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.computerprincipal(v=vs.110).aspx #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)] $Identity, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$DomainName, [Switch]$Recursive ) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } } process { try { # Not Recursive if (-not $PSBoundParameters['Recursive']) { if ($pscmdlet.ShouldProcess("$Identity", "Remove Account")) { $Account = Get-ADSIComputer -Identity $Identity @ContextSplatting $Account.delete() } } # Recursive (if the computer is the parent of one leaf or more) if ($PSBoundParameters['Recursive']) { if ($pscmdlet.ShouldProcess("$Identity", "Remove Account and any child objects")) { $Account = Get-ADSIComputer -Identity $Identity @ContextSplatting $Account.GetUnderlyingObject().deletetree() } } } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Remove-ADSIGroup { <# .SYNOPSIS function to remove a group .DESCRIPTION function to remove a group .PARAMETER Identity Specifies the Identity You can provide one of the following properties DistinguishedName Guid Name SamAccountName Sid UserPrincipalName Those properties come from the following enumeration: System.DirectoryServices.AccountManagement.IdentityType .PARAMETER Credential Specifies the alternative credential to use. By default it will use the current user windows credentials. .PARAMETER DomainName Specifies the alternative Domain where the user should be created By default it will use the current domain. .EXAMPLE Remove-ADSIGroup FXTESTGROUP .EXAMPLE Remove-ADSIGroup FXTESTGROUP -whatif .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)] $Identity, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$DomainName) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ Contexttype = "Domain" } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } } process { try { if ($pscmdlet.ShouldProcess("$Identity", "Delete Account")) { (Get-ADSIGroup -Identity $Identity @ContextSplatting).delete() } } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Remove-ADSIGroupMember { <# .SYNOPSIS Function to Remove a group member .DESCRIPTION Function to Remove a group member .PARAMETER Identity Specifies the Identity of the group You can provide one of the following properties DistinguishedName Guid Name SamAccountName Sid UserPrincipalName Those properties come from the following enumeration: System.DirectoryServices.AccountManagement.IdentityType .PARAMETER Member Specifies the member account. Performing an Ambiguous Name Resolution LDAP query to find the account. http://social.technet.microsoft.com/wiki/contents/articles/22653.active-directory-ambiguous-name-resolution.aspx .PARAMETER Credential Specifies the alternative credential to use. By default it will use the current user windows credentials. .PARAMETER DomainName Specifies the alternative Domain where the user should be created By default it will use the current domain. .EXAMPLE Remove-ADSIGroupMember -Identity TestADSIGroup -Member 'UserTestAccount1' Removing the User account 'UserTestAccount1' to the group 'TestADSIGroup' .EXAMPLE Remove-ADSIGroupMember -Identity TestADSIGroup -Member 'GroupTestAccount1' Removing the Group account 'GroupTestAccount1' to the group 'TestADSIGroup' .EXAMPLE Remove-ADSIGroupMember -Identity TestADSIGroup -Member 'ComputerTestAccount1' Removing the Computer account 'ComputerTestAccount1' to the group 'TestADSIGroup' .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)] $Identity, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$DomainName, $Member ) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ Contexttype = "Domain" } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } $Context = New-ADSIPrincipalContext @ContextSplatting } process { try { # Resolving member # Directory Entry object $DirectoryEntryParams = $ContextSplatting $DirectoryEntryParams.remove('ContextType') $DirectoryEntry = New-ADSIDirectoryEntry @DirectoryEntryParams # Principal Searcher $DirectorySearcher = new-object -TypeName System.DirectoryServices.DirectorySearcher $DirectorySearcher.SearchRoot = $DirectoryEntry # Adding an Ambiguous Name Resolution LDAP Filter $DirectorySearcher.Filter = "(anr=$member)" # Retrieve a single object $Account = $DirectorySearcher.FindOne().GetDirectoryEntry() if ($Account) { switch ($Account.SchemaClassName) { 'user' { $member = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($Context, $Account.distinguishedname) } 'group' { $member = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($Context, $Account.distinguishedname) } 'computer' { $member = [System.DirectoryServices.AccountManagement.ComputerPrincipal]::FindByIdentity($Context, $Account.distinguishedname) } } } if ($pscmdlet.ShouldProcess("$Identity", "Remove Account member $member")) { $group = (Get-ADSIGroup -Identity $Identity @ContextSplatting) [void]$group.members.remove($Member) #Void because this method returns $True/$false ($group.Save()) } } catch { $pscmdlet.ThrowTerminatingError($_) } } } Function Remove-ADSISite { <# .SYNOPSIS function to remove a Site .DESCRIPTION function to remove a Site .PARAMETER SiteName Specifies the Site Name .PARAMETER Credential Specifies the alternative credential to use. By default it will use the current user windows credentials. .PARAMETER ForestName Specifies the alternative Forest where the user should be created By default it will use the current Forest. .EXAMPLE Remove-ADSISite -SiteName WOW01 .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [parameter(Mandatory = $true)] [String]$SiteName, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$ForestName ) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{} if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['ForestName']) { $ContextSplatting.ForestName = $ForestName } } process { try { if ($PSCmdlet.ShouldProcess($SiteName, "Delete")) { # Delete Site (Get-ADSISite -Name $SiteName @ContextSplatting).Delete() } } catch { $pscmdlet.ThrowTerminatingError($_) break } } } function Remove-ADSISiteSubnet { <# .SYNOPSIS function to remove a Subnet .DESCRIPTION function to remove a Subnet .PARAMETER SubnetName Specifies the Subnet Name .PARAMETER Credential Specifies the alternative credential to use. By default it will use the current user windows credentials. .PARAMETER ForestName Specifies the alternative Forest where the user should be created By default it will use the current Forest. .EXAMPLE Remove-ADSISiteSubnet -SubnetName '192.168.8.0/24' .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter(Mandatory = $true)] [String]$SubnetName, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$ForestName ) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['ForestName']) { $ContextSplatting.ForestName = $ForestName } } process { try { if ($PSCmdlet.ShouldProcess($SubnetName, "Remove Subnet")) { (Get-ADSISiteSubnet -SubnetName $SubnetName @ContextSplatting).Delete() } } catch { $pscmdlet.ThrowTerminatingError($_) break } } end { } } function Remove-ADSIUser { <# .SYNOPSIS Function to delete a User Account .DESCRIPTION Function to delete a User Account .PARAMETER Identity Specifies the Identity of the User. You can provide one of the following properties DistinguishedName Guid Name SamAccountName Sid UserPrincipalName Those properties come from the following enumeration: System.DirectoryServices.AccountManagement.IdentityType .PARAMETER Credential Specifies the alternative credential to use. By default it will use the current user windows credentials. .PARAMETER DomainName Specifies the alternative Domain. By default it will use the current domain. .PARAMETER Recursive Specifies that any child object should be deleted as well Typically you would use this parameter if you get the error "The directory service can perform the requested operation only on a leaf object" when you try to delete the object without the -recursive param Typically used when you have Exchange/ActiveSync in your domain, some users happens to have sub child items. .EXAMPLE Remove-ADSIUser -identity fxtest02 This command will Remove the account fxtest02 from the current domain .EXAMPLE Remove-ADSIUser -identity fxtest02 -whatif This command will emulate removing the account fxtest02 .EXAMPLE Remove-ADSIUser -identity fxtest02 -credential (Get-Credential) This command will Remove the account fxtest02 using the alternative credential specified .EXAMPLE Remove-ADSIUser -identity fxtest02 -credential (Get-Credential) -domain LazyWinAdmin.local This command will Remove the account fxtest02 using the alternative credential specified in the domain lazywinadmin.local .EXAMPLE Remove-ADSIUser -identity fxtest02 -recursive This command will Remove the account fxtest02 and all the child objects. .NOTES https://github.com/lazywinadmin/ADSIPS .LINK https://msdn.microsoft.com/en-us/library/System.DirectoryServices.AccountManagement.UserPrincipal(v=vs.110).aspx #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)] $Identity, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$DomainName, [Switch]$Recursive ) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } } process { try { # Not Recursive if (-not $PSBoundParameters['Recursive']) { if ($pscmdlet.ShouldProcess("$Identity", "Remove Account")) { (Get-ADSIUser -Identity $Identity @ContextSplatting).Delete() } } # Recursive if ($PSBoundParameters['Recursive']) { if ($pscmdlet.ShouldProcess("$Identity", "Remove Account and any child objects")) { (Get-ADSIUser -Identity $Identity @ContextSplatting).GetUnderlyingObject().deletetree() } } } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Reset-ADSIUserPasswordAge { <# .SYNOPSIS Function to reset a User's password age to zero .DESCRIPTION Function to reset a User's password age to zero .PARAMETER Identity Specifies the Identity .PARAMETER Credential Specifies alternative credential .EXAMPLE Reset-ADSIUserPasswordAge -Identity 'testaccount' .EXAMPLE Reset-ADSIUserPasswordAge -Identity 'testaccount' -Credential (Get-Credential) .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter(Mandatory = $true)] [string]$Identity, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) process { if ($pscmdlet.ShouldProcess("$Identity", "Change Account Password")) { (Get-ADSIUser @PSBoundParameters).RefreshExpiredPassword() } } } Function Search-ADSIAccount { <# .SYNOPSIS Function to retrieve AD accounts from differents filters .DESCRIPTION Function to retrieve AD accounts from differents filters .PARAMETER Credential Specifies alternative credential .PARAMETER DomainName Specifies the Domain Name where the function should look .PARAMETER DomainDistinguishedName Specifies the DistinguishedName of the Domain to query .PARAMETER SizeLimit Specify the number of item(s) to output (1 to 1000) Use NoResultLimit for more than 1000 objects .PARAMETER NoResultLimit Remove the SizeLimit of 1000 Warning : can take time! it depends on the number of objects in your domain NoResultLimit parameter override SizeLimit parameter .PARAMETER Users Users accounts only .PARAMETER Computers Computer accounts only .PARAMETER AccountNeverLogged Accounts that never logged on .PARAMETER ChangePassword Specify that you want to see the account that need to change password .PARAMETER PasswordNeverExpire Accounts where the password never expire .PARAMETER AccountDisabled Accounts disabled .PARAMETER PasswordNeverExpires Accounts where the password never expire .PARAMETER AccountExpired Expired Accounts .PARAMETER AccountExpiring Accounts Expiring (By default 30 days, see -Days parameter) .PARAMETER AccountInactive Inactive accounts (By default 30 days, see -Days parameter) .PARAMETER Days Used with inactive and Expiring parameters. 30 days by default .PARAMETER PasswordExpired Expired Accounts .PARAMETER AccountNeverExpire Accounts where the password never expire .EXAMPLE Search-ADSIAccount -Users -AccountNeverLogged Get all not disabled user accounts that have never logged .EXAMPLE Search-ADSIAccount -Users -AccountNeverLogged -PasswordNeverExpire Get all not disabled user accounts that have never logged in and whose password never expires .EXAMPLE Search-ADSIAccount -Users -AccountNeverLogged -ChangePassword Get all not disabled user accounts that have never logged in and need to change their password .EXAMPLE Search-ADSIAccount -Users -AccountDisabled Get all disabled user accounts .EXAMPLE Search-ADSIAccount -Users -PasswordNeverExpires Get all not disabled user accounts whose password never expire .EXAMPLE Search-ADSIAccount -Users -AccountExpired Get all not disabled user accounts that have expired .EXAMPLE Search-ADSIAccount -Users -AccountExpiring -Days 10 Get all not disabled user accounts that will expire within the next 10 days. Valide Range : 1 to 365 Default expiration : 30 Days .EXAMPLE Search-ADSIAccount -Users -PasswordExpired Get all not disabled user accounts whose password has expired and are not disabled .EXAMPLE Search-ADSIAccount -Users -AccountNeverExpire Get all not disabled user accounts that never expire .EXAMPLE Search-ADSIAccount -Users -AccountDisabled -SizeLimit 10 Get only 10 user accounts disabled Default AD limit :1000 .EXAMPLE Search-ADSIAccount -Users -AccountDisabled -NoResultLimit Remove the default AD limit of 1000 objects returned, in example the search is about disabled user accounts .EXAMPLE Search-ADSIAccount -Users -AccountDisabled -Credential (Get-Credential) Use a different credential to perform the search, in example the search is about disabled user accounts .EXAMPLE Search-ADSIAccount -Users -AccountDisabled -DomainName "CONTOSO.local" Use a different domain name to perform the search, in example the search is about disabled user accounts .EXAMPLE Search-ADSIAccount -Users -AccountDisabled -DomainDistinguishedName 'DC=CONTOSO,DC=local' Use a different domain distinguished name to perform the search, in example the search is about disabled user accounts .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] param ( [Parameter(ParameterSetName = 'uAccountInactive', Mandatory = $true)] [Parameter(ParameterSetName = 'uAccountNeverExpire', Mandatory = $true)] [Parameter(ParameterSetName = 'uPasswordExpired', Mandatory = $true)] [Parameter(ParameterSetName = 'uAccountExpiring', Mandatory = $true)] [Parameter(ParameterSetName = 'uAccountExpired', Mandatory = $true)] [Parameter(ParameterSetName = 'uPasswordNeverExpires', Mandatory = $true)] [Parameter(ParameterSetName = 'uAccountDisabled', Mandatory = $true)] [Parameter(ParameterSetName = 'uAccountNeverLoggedChangePassword', Mandatory = $true)] [Parameter(ParameterSetName = 'uAccountNeverLoggedPasswordNeverExpire', Mandatory = $true)] [Parameter(ParameterSetName = 'uAccountNeverLogged', Mandatory = $true)] [switch]$Users, [Parameter(ParameterSetName = 'cAccountInactive', Mandatory = $true)] [Parameter(ParameterSetName = 'cAccountNeverExpire', Mandatory = $true)] [Parameter(ParameterSetName = 'cPasswordExpired', Mandatory = $true)] [Parameter(ParameterSetName = 'cAccountExpiring', Mandatory = $true)] [Parameter(ParameterSetName = 'cAccountExpired', Mandatory = $true)] [Parameter(ParameterSetName = 'cPasswordNeverExpires', Mandatory = $true)] [Parameter(ParameterSetName = 'cAccountDisabled', Mandatory = $true)] [Parameter(ParameterSetName = 'cAccountNeverLogged', Mandatory = $true)] [switch]$Computers, [Parameter(ParameterSetName = 'cAccountNeverLogged', Mandatory = $true)] [Parameter(ParameterSetName = 'uAccountNeverLoggedChangePassword', Mandatory = $true)] [Parameter(ParameterSetName = 'uAccountNeverLoggedPasswordNeverExpire', Mandatory = $true)] [Parameter(ParameterSetName = 'uAccountNeverLogged', Mandatory = $true)] [switch]$AccountNeverLogged, [Parameter(ParameterSetName = 'uAccountNeverLoggedChangePassword', Mandatory = $true)] [switch]$ChangePassword, [Parameter(ParameterSetName = 'uAccountNeverLoggedPasswordNeverExpire', Mandatory = $true)] [switch]$PasswordNeverExpire, [Parameter(ParameterSetName = 'cAccountDisabled', Mandatory = $true)] [Parameter(ParameterSetName = 'uAccountDisabled', Mandatory = $true)] [switch]$AccountDisabled, [Parameter(ParameterSetName = 'cPasswordNeverExpires', Mandatory = $true)] [Parameter(ParameterSetName = 'uPasswordNeverExpires', Mandatory = $true)] [switch]$PasswordNeverExpires, [Parameter(ParameterSetName = 'cAccountExpired', Mandatory = $true)] [Parameter(ParameterSetName = 'uAccountExpired', Mandatory = $true)] [switch]$AccountExpired, [Parameter(ParameterSetName = 'cAccountExpiring', Mandatory = $true)] [Parameter(ParameterSetName = 'uAccountExpiring', Mandatory = $true)] [switch]$AccountExpiring, [Parameter(ParameterSetName = 'cAccountInactive', Mandatory = $true)] [Parameter(ParameterSetName = 'uAccountInactive', Mandatory = $true)] [switch]$AccountInactive, [Parameter(ParameterSetName = 'cAccountInactive')] [Parameter(ParameterSetName = 'uAccountInactive')] [Parameter(ParameterSetName = 'cAccountExpiring')] [Parameter(ParameterSetName = 'uAccountExpiring')] [ValidateRange(1, 365)] [int]$Days = 30, [Parameter(ParameterSetName = 'cPasswordExpired', Mandatory = $true)] [Parameter(ParameterSetName = 'uPasswordExpired', Mandatory = $true)] [switch]$PasswordExpired, [Parameter(ParameterSetName = 'cAccountNeverExpire', Mandatory = $true)] [Parameter(ParameterSetName = 'uAccountNeverExpire', Mandatory = $true)] [switch]$AccountNeverExpire, [Alias('ResultLimit', 'Limit')] [ValidateRange(1, 1000)] [int]$SizeLimit = 100, [Alias('RunAs')] [pscredential] [System.Management.Automation.Credential()] $Credential = [pscredential]::Empty, [Alias('Domain')] [ValidateScript( { if ($_ -match '^(?:(?!-)[A-Za-z0-9-]{1,63}(?<!-)\.)+[A-Za-z]{2,6}$') { $true } else { throw "DomainName must be FQDN. Ex: contoso.locale - Hostname like '$_' is not working" } })] [String]$DomainName, [Alias('DomainDN', 'SearchRoot', 'SearchBase')] [String]$DomainDistinguishedName = $(([adsisearcher]'').Searchroot.path), [Switch]$NoResultLimit ) $Search = New-Object -TypeName System.DirectoryServices.DirectorySearcher -ErrorAction 'Stop' if ($PSBoundParameters['DomainName']) { $DomainDistinguishedName = "LDAP://DC=$($DomainName.replace('.', ',DC='))" Write-Verbose -Message "Current Domain: $DomainDistinguishedName" } elseif ($PSBoundParameters['DomainDistinguishedName']) { if ($DomainDistinguishedName -notlike 'LDAP://*') { $DomainDistinguishedName = "LDAP://$DomainDistinguishedName" } Write-Verbose -Message "Different Domain specified: $DomainDistinguishedName" } $Search.SearchRoot = $DomainDistinguishedName if ($PSBoundParameters['Credential']) { $Cred = New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList $DomainDistinguishedName, $($Credential.UserName), $($Credential.GetNetworkCredential().password) $Search.SearchRoot = $Cred } write-verbose -Message ('ParameterSetName : {0}' -f $PSCmdlet.ParameterSetName) if ($PSBoundParameters['Computers']) { $type = 'computer' } else { $type = 'user' } switch -wildcard ($PSCmdlet.ParameterSetName) { '?AccountNeverLogged' { #Never logged and must change password and not disabled $Search.Filter = "(&(objectCategory=$type)(objectClass=$type)(lastLogon=0)(!lastLogonTimestamp=*)(!userAccountControl:1.2.840.113556.1.4.803:=2))" break } '?AccountNeverLoggedChangePassword' { #Never logged and must change password and not disabled $Search.Filter = "(&(objectCategory=$type)(objectClass=$type)(pwdLastSet=0)(lastLogon=0)(!lastlogontime‌​stamp=*)(!userAccountControl:1.2.840.113556.1.4.803:=2))" break } '?AccountNeverLoggedPasswordNeverExpire' { #Never loged and password never expire and not disabled $Search.Filter = "(&(objectCategory=$type)(objectClass=$type)(userAccountControl:1.2.840.113556.1.4.803:=65536)(lastLogon=0)(!lastlogontime‌​stamp=*)(!userAccountControl:1.2.840.113556.1.4.803:=2))" break } '?AccountDisabled' { #Disabled $Search.Filter = "(&(objectCategory=$type)(objectClass=$type)(userAccountControl:1.2.840.113556.1.4.803:=2))" break } '?PasswordNeverExpires' { #Password never expire and not disabled $Search.Filter = "(&(objectCategory=$type)(objectClass=$type)(userAccountControl:1.2.840.113556.1.4.803:=65536)(!userAccountControl:1.2.840.113556.1.4.803:=2))" break } '?AccountExpired' { #Account expired and not disabled $date = (Get-Date).ToFileTime() $Search.Filter = "(&(objectCategory=$type)(objectClass=$type)(accountExpires<=$date)(!accountExpires=0)(!userAccountControl:1.2.840.113556.1.4.803:=2))" break } '?AccountExpiring' { #Account expiring in x days and not disabled #Attention : Account set to expire on 22/05/2017, attribute is set to 23/05/2017 00:00 or 22:00 write-verbose -Message "Show accounts expiring between now and $Days day(s)" $Now = Get-Date $start = $Now.ToFileTime() $end = ($Now.Adddays($Days)).ToFileTime() $Search.Filter = "(&(objectCategory=$type)(objectClass=$type)(accountExpires>=$start)(accountExpires<=$end)(!userAccountControl:1.2.840.113556.1.4.803:=2))" break } '?AccountInactive' { #Account Inactive and not disabled #Returns all accounts that have been inactive for more than X days. write-verbose -Message "Show inactive accounts for more than $Days day(s)" $Now = Get-Date $start = ($Now.Adddays( - $Days)).ToFileTime() $Search.Filter = "(&(objectCategory=$type)(objectClass=$type)(lastLogonTimestamp<=$start)(!userAccountControl:1.2.840.113556.1.4.803:=2))" break } '?PasswordExpired' { #PASSWORD Expired and account not disabled #Rule : User must be connected at least one time to be in the result $Search.Filter = "(&(objectCategory=$type)(objectClass=$type)(pwdLastSet=0)(!(userAccountControl:1.2.840.113556.1.4.803:=65536)(!userAccountControl:1.2.840.113556.1.4.803:=2))(|(lastLogon>=1)(lastLogonTimestamp>=1)))" break } '?AccountNeverExpire' { #Account never expire and account not disabled $Search.Filter = "(&(objectCategory=$type)(objectClass=$type)(accountExpires=0)(!userAccountControl:1.2.840.113556.1.4.803:=2))" break } DEFAULT { write-verbose -Message 'unknown ParameterSetName' return } } if (-not$PSBoundParameters['NoResultLimit']) { Write-warning -Message "Result is limited to $SizeLimit entries, specify a specific number (1-1000) on the parameter SizeLimit or use -NoResultLimit switch to remove the limit" $Search.SizeLimit = $SizeLimit } else { Write-Verbose -Message 'Use NoResultLimit switch, all objects will be returned. no limit' $Search.PageSize = 10000 } $Search.FindAll() } function Set-ADSIUser { <# .SYNOPSIS This function modifies an account identified by its display name, sam account name or distinguished name. .DESCRIPTION This function modifies an account identified by its display name, sam account name or distinguished name. .PARAMETER Identity Specify the Identity of the accounts to modify. The Identity can either be (in order of resolution attempt): A SAM account name An object SID A distinguished name .PARAMETER Country Specify the country name. This parameter sets the co property of a user. .PARAMETER Description Specify the description. This parameter sets the description property of a user. .PARAMETER DisplayName Specify the display name. This parameter sets the DisplayName property of a user. .PARAMETER Location Specify the location name. This parameter sets the l property of a user. .PARAMETER Mail Specify the mail address. This parameter sets the mail property of a user. .PARAMETER Manager Specify the manager. This parameter sets the manager property of a user. The manager must be specified as a SAM account name. .PARAMETER PostalCode Specify the postal code name. This parameter sets the postalCode property of a user. .PARAMETER SamAccountName Specify the Sam account name. This parameter sets the sAMAccountName property of a user. .PARAMETER UserPrincipalName Specify the UserPrincipalName. This parameter sets the UserPrincipalName property of a user. .PARAMETER HomeDrive Specify the HomeDrive. This parameter sets the HomeDrive property of a user. This must be a single letter (aka 'U'). This is the drive you want the HomeDirectory to show up as .PARAMETER HomeDirectory Specify the HomeDirectory. This parameter sets the HomeDirectory property of a user. This is the directory you want to map to. .PARAMETER TelephoneNumber Specify the Telephone number .PARAMETER DomainName Specify the Domain Distinguished name .PARAMETER Credential Specify alternative Credential .EXAMPLE Set-ADSIUSer -Identity micky -UserPrincipalName micky@contoso.com -confirm:$false -SamAccountName mickyballadelli Changes the UPN and SAM account name of an account without confirmation popup .EXAMPLE Set-ADSIUSer -identity micky -Country France Changes the Country value of the account micky .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High', DefaultParameterSetName = 'Default')] param ( [Parameter(Mandatory = $true)] [String]$Identity, [Parameter(Mandatory = $false)] [string]$Country, [Parameter(Mandatory = $false)] [string]$Description, [Parameter(Mandatory = $false)] [string]$DisplayName, [Parameter(Mandatory = $false)] [string]$Location, [Parameter(Mandatory = $false)] [string]$Mail, [Parameter(Mandatory = $false)] [string]$Manager, [Parameter(Mandatory = $false)] [string]$PostalCode, [Parameter(Mandatory = $false)] [String]$SamAccountName, [Parameter(Mandatory = $false)] [String]$TelephoneNumber, [Parameter(Mandatory = $false)] [string]$UserPrincipalName, [Parameter(Mandatory = $false)] [Parameter(Mandatory = $true, ParameterSetName = "HomeDriveHomeDirectory")] [string]$HomeDrive, [Parameter(Mandatory = $false)] [Parameter(Mandatory = $true, ParameterSetName = "HomeDriveHomeDirectory")] [string]$HomeDirectory, [Alias("Domain", "DomainDN")] [String]$DomainName = $(([adsisearcher]"").Searchroot.path), [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ ContextType = "Domain" } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } $Context = New-ADSIPrincipalContext @ContextSplatting } process { try { $DirectoryEntryParams = $ContextSplatting $DirectoryEntryParams.remove('ContextType') $DirectoryEntry = New-ADSIDirectoryEntry @DirectoryEntryParams # Principal Searcher $Search = new-object -TypeName System.DirectoryServices.DirectorySearcher $Search.SizeLimit = 2 $Search.SearchRoot = $DirectoryEntry # Resolve the Object $Search.filter = "(&(objectCategory=person)(objectClass=User)(samaccountname=$Identity))" $user = $Search.FindAll() if ($user.Count -eq 0) { $Search.filter = "(&(objectCategory=person)(objectClass=User)(objectsid=$Identity))" $user = $Search.FindAll() } if ($user.Count -eq 0) { $Search.filter = "(&(objectCategory=person)(objectClass=User)(distinguishedname=$Identity))" $user = $Search.FindAll() } if ($user.Count -eq 0) { $Search.filter = "(&(objectCategory=person)(objectClass=User)(UserPrincipalName=$Identity))" $user = $Search.FindAll() } if ($user.Count -eq 1) { $Account = $user.Properties.samaccountname -as [string] $adspath = $($user.Properties.adspath -as [string]) -as [ADSI] # Country if ($Country -ne '') { Write-Verbose -Message "[$($Account)] Setting Country value to : $Country" if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Set Country of account $account to $Country")) { if ($PSBoundParameters.ContainsKey('WhatIf')) { Write-Verbose -Message "WhatIf: Setting Country of account $account to $Country" -Verbose:$true } else { $adspath.Put("co", $Country) $adspath.SetInfo() } } } # Description if ($Description -ne '') { Write-Verbose -Message "[$($Account)] Setting Description value to : $Description" if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Set Description of account $account to $Description")) { if ($PSBoundParameters.ContainsKey('WhatIf')) { Write-Verbose -Message "WhatIf: Setting Description of account $account to $Description" -Verbose:$true } else { $Adspath.Put("description", $Description) $Adspath.SetInfo() } } } # DisplayName if ($DisplayName -ne '') { Write-Verbose -Message "[$($Account)] Setting Country value to : $DisplayName" if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Set DisplayName of account $account to $DisplayName")) { if ($PSBoundParameters.ContainsKey('WhatIf')) { Write-Verbose -Message "WhatIf: Setting DisplayName of account $account to $DisplayName" -Verbose:$true } else { $Adspath.Put("displayName", $DisplayName) $Adspath.SetInfo() } } } # Location if ($Location -ne '') { Write-Verbose -Message "[$($Account)] Setting Location value to : $Location" if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Set Location of account $account to $Location")) { if ($PSBoundParameters.ContainsKey('WhatIf')) { Write-Verbose -Message "WhatIf: Setting Location of account $account to $Location" -Verbose:$true } else { $Adspath.Put("l", $Location) $Adspath.SetInfo() } } } if ($Mail -ne '') { Write-Verbose -Message "[$($Account)] Setting Mail value to : $Mail" if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Set Mail of account $account to $Mail")) { if ($PSBoundParameters.ContainsKey('WhatIf')) { Write-Verbose -Message "WhatIf: Setting Mail of account $account to $Mail" -Verbose:$true } else { $Adspath.Put("mail", $Mail) $Adspath.SetInfo() } } } # Manager if ($Manager -ne '') { Write-Verbose -Message "[$($Account)] Setting Manager value to : $Manager" if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Set Manager of account $account to $Manager")) { if ($PSBoundParameters.ContainsKey('WhatIf')) { Write-Verbose -Message "WhatIf: Setting Manager of account $account to $Manager" -Verbose:$true } else { $Search.filter = "(&(objectCategory=person)(objectClass=User)(samaccountname=$Manager))" $user = $Search.FindOne() $Adspath.Put("manager", ($user.properties.distinguishedname -as [string])) $Adspath.SetInfo() } } } # PostalCode if ($PostalCode -ne '') { Write-Verbose -Message "[$($Account)] Setting Location value to : $PostalCode" if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Set PostalCode of account $account to $PostalCode")) { if ($PSBoundParameters.ContainsKey('WhatIf')) { Write-Verbose -Message "WhatIf: Setting Location of account $account to $PostalCode" -Verbose:$true } else { $Adspath.Put("postalCode", $PostalCode) $Adspath.SetInfo() } } } # TelephoneNumber if ($TelephoneNumber -ne '') { Write-Verbose -Message "[$($Account)] Setting SamAccountName value to : $TelephoneNumber" if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Set TelephoneNumber of account $account to $TelephoneNumber")) { if ($PSBoundParameters.ContainsKey('WhatIf')) { Write-Verbose -Message "WhatIf: Setting TelephoneNumber of account $account to $TelephoneNumber" -Verbose:$true } else { $Adspath.Put("telephoneNumber", $TelephoneNumber) $Adspath.SetInfo() } } } # SAM Account Name if ($SamAccountName -ne '') { Write-Verbose -Message "[$($Account)] Setting SamAccountName value to : $SamAccountName" if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Set SamAccountName of account $account to $SamAccountName")) { if ($PSBoundParameters.ContainsKey('WhatIf')) { Write-Verbose -Message "WhatIf: Setting SamAccountName of account $account to $SamAccountName" -Verbose:$true } else { $Adspath.Put("sAMAccountName", $SamAccountName) $Adspath.SetInfo() } } } # UserPrincipalName if ($UserPrincipalName -ne '') { Write-Verbose -Message "[$($Account)] Setting UPN value to : $UserPrincipalName" if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Set UPN of account $account to $UserPrincipalName")) { if ($PSBoundParameters.ContainsKey('WhatIf')) { Write-Verbose -Message "WhatIf: Setting UPN of account $account to $UserPrincipalName" -Verbose:$true } else { $Adspath.Put("UserPrincipalName", $UserPrincipalName) $Adspath.SetInfo() } } } # HomeDrive if ($HomeDrive -ne '') { if($HomeDrive.Length -gt 1) { $e = New-Object System.Exception "[Set-AdsiUser] HomeDrive must be a single letter!" throw $e } elseif($HomeDirectory -eq '') { $er = New-Object System.Exception "[Set-AdsiUser] HomeDirectory must be use with HomeDrive! HomeDrive is the drive letter, HomeDirectory is the path." throw $er } else { Write-Verbose -Message "[$($Account)] Setting HomeDrive value to : $HomeDrive and HomeDirectory to : $HomeDirectory" if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Set HomeDrive of account $account to $HomeDrive and HomeDirectory to $HomeDirectory")) { if ($PSBoundParameters.ContainsKey('WhatIf')) { Write-Verbose -Message "WhatIf: Setting HomeDrive of account $account to $HomeDrive and HomeDirectory to $HomeDirectory" -Verbose:$true } else { try { $Adspath.Put("homeDrive", $HomeDrive) $adspath.Put("homeDirectory", $HomeDirectory) $Adspath.SetInfo() } catch { throw $_ } } } } } } elseif ($user.Count -gt 1) { Write-Warning -Message "[Set-ADSIUser] Identity $identity is not unique" } elseif ($Search.FindAll().Count -eq 0) { Write-Warning -Message "[Set-ADSIUser] Account $identity not found" } }#try catch { $pscmdlet.ThrowTerminatingError($_) } }#process end { Write-Verbose -Message "[END] Function Set-ADSIUser End." } } function Set-ADSIUserPassword { <# .SYNOPSIS Function to change a User's password .DESCRIPTION Function to change a User's password .PARAMETER Identity Specifies the Identity .PARAMETER Credential Specifies alternative credential .PARAMETER AccountPassword Specifies the new password. The object needs to be a System.Security.SecureString. You can use something like that: $AccountPassword = (read-host -AsSecureString -Prompt "AccountPassword") .PARAMETER DomainName Specifies the DomainName to query By default it will take the current domain. .EXAMPLE Set-ADSIUserPassword -Identity 'testaccount' -AccountPassword (read-host -AsSecureString -Prompt "AccountPassword") Change the password of the account 'testaccount' to the specified new password .EXAMPLE Set-ADSIUserPassword -Identity 'testaccount' -AccountPassword (read-host -AsSecureString -Prompt "AccountPassword") -Credential (Get-Credential) Change the password of the account 'testaccount' using the credential specified, to the specified new password .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [parameter(Mandatory = $true)] $Identity, [parameter(Mandatory = $true)] [System.Security.SecureString]$AccountPassword, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$DomainName) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } } process { try { if ($pscmdlet.ShouldProcess("$Identity", "Change Account Password")) { (Get-ADSIUser -Identity $Identity @ContextSplatting).SetPassword((New-Object -TypeName PSCredential -ArgumentList "user", $AccountPassword).GetNetworkCredential().Password) } } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Start-ADSIReplicationConsistencyCheck { <# .SYNOPSIS Start-ADSIReplicationConsistencyCheck starts the knowledge consistency checker on a given DC. .DESCRIPTION Start-ADSIReplicationConsistencyCheck connects to an Active Directory Domain Controller and starts the KCC to verify if the replication topology needs to be optimized. .PARAMETER ComputerName Defines the remote computer to connect to. .PARAMETER Credential Defines alternate credentials to use. Use Get-Credential to create proper credentials. .EXAMPLE Start-ADSIReplicationConsistencyCheck -ComputerName dc1.ad.local Connects to remote domain controller dc1.ad.local using current credentials and starts a KCC check. .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding(SupportsShouldProcess = $true)] param ([Parameter(Mandatory = $true)] [string]$ComputerName, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) if ($ComputerName) { if ($Credential) { $context = new-object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList "DirectoryServer", $ComputerName, $Credential.UserName, $Credential.GetNetworkCredential().Password } else { $context = new-object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList "DirectoryServer", $ComputerName } } if ($context) { Write-Verbose -Message "Connecting to $ComputerName" $dc = [System.DirectoryServices.ActiveDirectory.DomainController]::GetDomainController($context) } if ($PSCmdlet.ShouldProcess($dc, "Check Replication Consistency (KCC Check)")) { if ($dc) { $dc.CheckReplicationConsistency() Write-Verbose -Message "KCC Check started on $($dc.name)" } } } function Test-ADSICredential { <# .SYNOPSIS Function to test credential .DESCRIPTION Function to test credential .PARAMETER AccountName Specifies the AccountName to check .PARAMETER AccountPassword Specifies the AccountName's password .PARAMETER Credential Specifies the alternative credential to use. By default it will use the current user windows credentials. .PARAMETER DomainName Specifies the alternative Domain where the user should be created By default it will use the current domain. .EXAMPLE Test-ADCredential -AccountName 'Xavier' -Password 'Wine and Cheese!' .EXAMPLE PS C:\> New-ADSIUser -SamAccountName "fxtest04" -Enabled -AccountPassword (read-host -AsSecureString -Prompt "AccountPassword") -Passthru # You can test the credential using the following function Test-ADSICredential -AccountName "fxtest04" -Password "Password1" .OUTPUTS System.Boolean .NOTES https://github.com/lazywinadmin/ADSIPS #> [OutputType('System.Boolean')] [CmdletBinding()] param ( [Parameter(Mandatory)] [Alias("UserName")] [string]$AccountName, [Parameter(Mandatory)] [System.Security.SecureString]$AccountPassword, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$DomainName) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ ContextType = "Domain" } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } $Context = New-ADSIPrincipalContext @ContextSplatting } process { try { Write-Verbose -Message "[Test-ADSICredential][PROCESS] Validating $AccountName Credential against $($Context.ConnectedServer)" $Context.ValidateCredentials($AccountName, (New-Object -TypeName PSCredential -ArgumentList "user", $AccountPassword).GetNetworkCredential().Password) } catch { $pscmdlet.ThrowTerminatingError($_) } } } function Test-ADSIUserIsGroupMember { <# .SYNOPSIS This function will check if a domain user is member of a domain group .DESCRIPTION This function will check if a domain user is member of a domain group .PARAMETER GroupSamAccountName Specifies the Group to query .PARAMETER UserSamAccountName Specifies the user account .EXAMPLE Test-ADSIUserIsGroupMember -GroupSamAccountName TestGroup -UserSamAccountName Fxcat This will return $true or $false depending if the user Fxcat is member of TestGroup .NOTES https://github.com/lazywinadmin/ADSIPS #> param ( $GroupSamAccountName, $UserSamAccountName ) $UserInfo = [ADSI]"$((Get-ADSIUser -SamAccountName $UserSamAccountName).AdsPath)" $GroupInfo = [ADSI]"$((Get-ADSIGroup -SamAccountName $GroupSamAccountName).AdsPath)" #([ADSI]$GroupInfo.ADsPath).IsMember([ADSI]($UserInfo.AdsPath)) $GroupInfo.IsMember($UserInfo.ADsPath) } function Test-ADSIUserIsLockedOut { <# .SYNOPSIS Function to test if a User is LockedOut .DESCRIPTION Function to test if a User is LockedOut .PARAMETER Identity Specifies the Identity .PARAMETER Credential Specifies alternative credential .EXAMPLE Test-ADSIUserIsLockedOut -Identity 'testaccount' .EXAMPLE Test-ADSIUserIsLockedOut -Identity 'testaccount' -Credential (Get-Credential) .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] [OutputType('System.Boolean')] param ( [Parameter(Mandatory = $true)] [string]$Identity, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) process { (Get-ADSIUser @PSBoundParameters).IsAccountLockedOut() } } function Unlock-ADSIUser { <# .SYNOPSIS Function to Unlock a User in Active Directory .DESCRIPTION Function to Unlock a User in Active Directory .PARAMETER Identity Specifies the Identity .PARAMETER Credential Specifies alternative credential .EXAMPLE Unlock-ADSIUser -Identity 'testaccount' .EXAMPLE Unlock-ADSIUser -Identity 'testaccount' -Credential (Get-Credential) .PARAMETER DomainName Specifies the alternative Domain where the user should be created By default it will use the current domain. .NOTES https://github.com/lazywinadmin/ADSIPS #> [CmdletBinding()] param ([Parameter(Mandatory)] [string]$Identity, [Alias("RunAs")] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty, [String]$DomainName) begin { Add-Type -AssemblyName System.DirectoryServices.AccountManagement # Create Context splatting $ContextSplatting = @{ } if ($PSBoundParameters['Credential']) { $ContextSplatting.Credential = $Credential } if ($PSBoundParameters['DomainName']) { $ContextSplatting.DomainName = $DomainName } } process { (Get-ADSIUser -Identity $Identity @ContextSplatting).UnlockAccount() } } # Try to add necessary assembly during module import - fixes issue where params rely on types within this assembly # If this assembly was not loaded prior to running Get-ADSIGroup, for example, you were not able to use that function # If adding this assembly fails, we still allow the user to import the module, but we show them a helpful warning TRY { Add-Type -AssemblyName System.DirectoryServices.AccountManagement } CATCH { Write-Warning "[AdsiPS] Unable to add assembly 'System.DirectoryServices.AccountManagement'.`r`nPlease manually add this assembly into your session or you may encounter issues! `r`n`r`nRun the following command: 'Add-Type -AssemblyName System.DirectoryServices.AccountManagement'" } |