i made this script to find all windows 10 machines which are not placed in the right OU, there is no action taken at this point - but i would like to move them once they had been found, we have over 30 country's and data centers so i would like to keep the OU string in the arrays, to keep the code to a minimal - how would one perform a move in this script? i could use some pointers.
$Script:OUBase = "OU=Countries,OU=Global,DC=internal"
Import-Module ActiveDirectory
$CountryDataCenter =
#(
[pscustomobject]#{Country="UK";DataCenter="CEN1"},
[pscustomobject]#{Country="UK";DataCenter="CEN2"}
)
Function GetWin10MachineAccounts($Country, $DataCenter){
#Build OUstring
$OUStringTarget = "*OU=Windows 10,OU=Computers,OU=" + $DataCenter + ",OU=" + $Country + "," + $Script:OUBase
$OUStringSource = "OU=Computers,OU=" + $DataCenter + ",OU=" + $Country + "," + $Script:OUBase
$countPC = ($Win10Computeraccounts).count
Write-Host "OU to search - " $OUStringSource -ForegroundColor Yellow
$Win10ComputerAccounts = Get-ADComputer -SearchBase $OUStringSource -Filter {(enabled -eq "true") -and (OperatingSystem -like "*Windows 10*")} -properties * | where {$_.DistinguishedName -notlike "$OUStringTarget"} | select CN -expandproperty Name
Return $Win10Computeraccounts
}
############### Main Script ##########################
##create empty array for use later
$DataArray = #()
ForEach ($Country in $CountryDataCenter)
{
$Win10Computeraccounts = GetWin10MachineAccounts $Country.Country $Country.DataCenter
$countPC = $Win10Computeraccounts.count
if(!$Win10Computeraccounts) {
write-host "No Windows 10 Computers are found in the container" $Country.Country $Country.DataCenter
}
foreach ($Computer in $Win10Computeraccounts){
Write-Host $Computer -ForegroundColor Red
#Store Data in foreach array
$DataArray += (Get-ADComputer $Computer )
Write-Host "$countPC" "Computers found in" $Country.Country $Country.DataCenter -ForegroundColor Green
}
}
$DataArray | Export-Csv "C:\log.csv" -Force
Use the Move-ADObject cmdlet:
foreach($Country in $CountryDataCenter)
{
$OUStringTarget = "OU=Windows 10,OU=Computers,OU={0},OU={1},{2}" -f $Country.DataCenter,$Country.Country,$Script:OUBase
$Win10Computeraccounts = GetWin10MachineAccounts $Country.Country $Country.DataCenter
foreach ($Computer in $Win10Computeraccounts){
Move-ADObject -Identity $Computer -TargetPath $OUStringTarget
}
}
Related
Need help to catch the error. Whenever my network connection is unstable my get-ad script will be terminated.
$ScriptDir = Split-Path $script:MyInvocation.MyCommand.Path
$Date = Get-Date -Format yyyy_MM_dd_THHmm
Start-Transcript -Path "$ScriptDir\Logs.log" -Append
$List = Import-Csv "$ScriptDir\Accounts.csv"
$TotalCount = $List.Length
$CurrentCount = 0
Write-Host 'Total Count: '$TotalCount
ForEach ($user in $List) {
# Retrieve UserSamAccountName and ADGroup
$Groups = $User.Group
$UserSam = $User.SamAccountName
# Retrieve SamAccountName and ADGroup
$ADUser = Get-ADUser -Filter "SamAccountName -eq '$UserSam'" | Select-Object SamAccountName
$ADGroups = Get-ADGroup -Filter * | Select-Object Name
# User does not exist in AD
if ($ADUser -eq $null) {
Write-Host "$UserSam does not exist in AD" -ForegroundColor DarkCyan
Continue
}
# User does not have a group specified in CSV file
if ($Groups -eq $null) {
Write-Host "$UserSam has no group specified in CSV file" -ForegroundColor Yellow
Continue
}
# Retrieve AD user group membership
$ExistingGroups = Get-ADPrincipalGroupMembership $UserSam | Select-Object Name
foreach ($Group in $Groups.Split(';')) {
# Group does not exist in AD
if ($ADGroups.Name -notcontains $Group) {
Write-Host "$Group group does not exist in AD" -ForegroundColor Gray
Continue
}
# User already member of group
if ($ExistingGroups.Name -eq $Group) {
Write-Host "$UserSam already exists in group $Group." -ForeGroundColor Yellow
}
else {
# User not a member of group
Write-Host "User $UserSam doesn't exists in $Group AD group" -ForegroundColor Red
}
}
$CurrentCount++
$Percentage = [math]::Round($CurrentCount/$TotalCount*100)
Write-Progress -Activity "Building report in progress" -Status "$Percentage% Complete" -PercentComplete $Percentage
}
Stop-Transcript
Write-Output 'Script complete.'
OUTPUT ERROR
Get-ADUser : Unable to find a default server with Active Directory Web Services running.
At C:\Users\JVERE05\Desktop\Powershell\Powershell\CheckIfExist\08_08.ps1:22 char:11
+ $ADUser = Get-ADUser -Filter "SamAccountName -eq '$UserSam'" | Select ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (:) [Get-ADUser], ADServerDownException
+ FullyQualifiedErrorId : ActiveDirectoryServer:1355,Microsoft.ActiveDirectory.Management.Commands.GetADUser
The fully qualified type name is Microsoft.ActiveDirectory.Management.ADServerDownException:
try {
Get-ADUser ... -ErrorAction Stop
}
catch [Microsoft.ActiveDirectory.Management.ADServerDownException] {
<# AD Server is down #>
}
catch {
<# Something else went wrong #>
}
Goal: Use a script to add 3 workstations to all users.
Problem: Receiving error thats says variable's format is invalid. $finalworkstations.gettype() brings up null-valued expression.
Receive an error:
Set-ADUser : The format of the specified computer name is invalid
At \\pathwaystuff\file.ps1:37 char:9
+ Set-ADUser $logonname -LogonWorkstations $finalworkstations
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (tester:ADUser) [Set-ADUser], ADException
+ FullyQualifiedErrorId : ActiveDirectoryServer:1210,Microsoft.ActiveDirectory.Management.Commands.SetADUser
Here's the script I have now.
$list = Get-ADUser -filter {LogonWorkstations -like "*"} -properties name, LogonWorkstations | select name, logonworkstations
$logonname = "someone"
Function addspecificLogon {
param (
$logonname
)
$wrklist = Import-Csv "\\pathwaystuff\anotherplace\file.csv"
$Workstations = (Get-Aduser $logonname ` -Properties LogonWorkstations).LogonWorkstations
$workstations += ",work1, work2, work3"
#CONVERT WORKSTATION LIST TO AN ARRAY TO ALLOW FOR BETTER MANIPULATION OF DATA
$Workarray = $Workstations.Split(",")
#ERROR-CHECKING MEASURE: ELIMINATE DUPLICATE WORKSTATION NAMES
$Workarray = $Workarray | Sort-Object | Get-Unique
#CONVERTING ARRAY BACK TO STRING TO SET IN AD WORKSTATIONS (NEEDS TO BE A SPECIFIC STRING FORMAT TO ADD TO AD WORKSTATION)
$finalworkstations = ''
foreach ($work in $Workarray) {
$finalworkstations += ", $($work)"
}
Set-ADUser $logonname -LogonWorkstations $finalworkstations
$finalworkstations
}
addspecificLogon($logonname)
Get-ADUser -identity $logonname -properties * | select logonworkstations
Found a solution. That proved a lot simpler overall. Don't know exactly why but manipulating an array as long as possible helped.
function workstations{
$userWorkstationListLocation = Read-Host -Prompt "Enter the filepath of the CSV containing the allowed workstations"
if ($userworkstationlistlocation -eq ""){
$userWorkstationList = "empty"
$script:userworkstationlist = $userworkstationList
$script:userworkstationListLocation = $userWorkstationListLocation
} elseif ((test-path -path $userWorkstationListLocation) -eq $false) {
$userWorkstationListLocation = verify($userWorkstationListLocation)
}
$userWorkstations = Import-Csv -Path "$userWorkstationListLocation" | ForEach-Object {$_.userPC}
#CSV REFERENCE LIST FOR DEFAULT LOGON RIGHTS
$defaultWorkstationslist = Import-Csv '\\url\link\of\stations.csv'
foreach ($station in $defaultworkstationslist) {
$userWorkstations += "$($station.Infrastructure)"
}
#CONFIRMING IF NEEDED TO USE CITRIX
$CitrixUser = Read-Host "Will this user need access to Citrix? [Y/N]"
#FUNCTION TO CONFIRM ADD OR SKIP CITRIX LOGON RIGHTS
if ($CitrixUser -eq "Y"){
foreach($station in $defaultworkstationslist){
if ($station.Citrix -eq ""){
continue
} else {
$userWorkstations += "$($station.Citrix)"
}
}
}
#Removing Duplicates
$userworkstations = $userWorkstations | Sort-Object | Get-Unique
#Fixing for blanks
$userWorkstations.where({$_ -ne "" })
#converting to a list Set-AD can use
foreach ($s in $userWorkstations){
$s
if ($s -eq ""){
continue
} else {
$userworkstationlist += "$s,"
}
}
$userworkstationlist
$script:userworkstationListLocation = $userWorkstationListLocation
$script:userworkstationlist = $userworkstationlist
Write-Host "Within function $($userworkstationlist)"
}
We have a master registry within our on premise SharePoint environment, to keep this list accurate, we run a clean up script each day to remove the item within the list registry.
As part of this script, we wish to delete the AD permissions group at the same time.
Our script works when deleting a single site collection, but when multiple are deleted, the script removes the list item, but attempts to delete the same AD group over and over, it doesnt refresh the variables.
Here is part of the script:
Add-PSSnapin *sharepoint* -ErrorAction SilentlyContinue
Import-Module ActiveDirectory
#Adding variables
$siteRequestUrl = "https://contorso/sites/demo"
$siteRequestListTitle = "Registry"
$webAppArray = #()
$listSCArray = #()
$itemsToDeleteArray = #()
$dn = Get-ADDoman | select -ExpandProperty DistinguishedName
$ou = Get-ADOrganizationalUnit ('Ou=SharePoint, OU=Account Groups, OU=Groups,' + $dn)
$ouSDL = Get-ADOrganizationalUnit ('Ou=SharePoint, OU=Resource Groups, OU=Groups,' + $dn)
Start-SPAssignment -Global
$list = (Get-SPSite -Identity $siteRequestUrl).RootWeb.Lists | Where-Object { $_.Title -eq $siteRequestListTitle }
$expectedSCCount = $list.ItemCount
$WebAppSCCount = $list.ParentWeb.Site.WebApplication.Sites
If ($expectedSCCount -ne $webAppSCCount) {
$listItems = $list.Items
foreach ($webAppSC in $list.ParentWeb.Site.WebApplication.Sites) {
$webAppSCArray += $webAppSC.Url
}
foreach ($item in $listItems) {
$li = New-Object Microsoft.SharePoint.SPFieldUrlValue($item["URL_Link"])
$listSCArray += $i.Url.String()
}
$comparison = Compare-Object -ReferenceObject $webAppSCArray -DifferenceObject $listSCArray | where-Object -FilterScript { $_.SiteIndicator -eq '=>' }
foreach ($difference in $comparison) {
foreach ($item in $listItems) {
$i = New-Object Microsoft.SharePoint.SPFieldUrlValue($item["URL_Link"])
If ($i.Url -eq $difference.InputObject) {
$itemsToDeleteArray = + $item
}
}
}
$itemTitle - $itemToDelete.Title.ToString()
$itemTemplate - $itemToDelete["Template"].ToString()
###### Now I move onto the problem, these variables work but do not not refresh if more than one item is being deleted ############
foreach ($itemToDelete in $itemToDeleteArray) {
switch ($itemTemplate) {
"Branch1" {
$managedPath = "BR1"
}
"Branch2" {
$managedPath = "BR2"
}
}
$forceLowerCase = $itemTitle.ToLower()
$siteTitle = $forceLowerCase -replace '\W', '-'
$GroupName = $managedPath + "-" + $siteTitle
$SggGroupName = "SGG_" + $GroupName + "_Members"
$SdlGroupName = "SDL_" + $GroupName + "_Members"
Try {
Get-ADGroup -Filter 'GroupCatergory -eq "Security" -and GroupScope -ne "DomainLocal"' -SearchBase "CN=$SggGroupName,OU=SharePoint,OU=Account Groups,OU=Groups,DC=Contorso" | Remove-ADGroup -Confirm:$false
Get-ADGroup -Filter 'GroupCatergory -eq "Security" -and GroupScope -eq "DomainLocal"' -SearchBase "CN=$SdlGroupName,OU=SharePoint,OU=Resource Groups,OU=Groups,DC=Contorso" | Remove-ADGroup -Confirm:$false
Write-host "AD Groups $SggGroupName and $SdlGroupName deleted" -ForegroundColor -Green
}
Catch { write-host "AD Groups $SggGroupName and $SdlGroupName failed to delete" }
$itemToDelete.Delete()
}
}
Stop-SPAssignment -Global
I'm trying to create a loop that tests the connection to specific computers in the Active Directory. The output is #{name=KY-WH-DT01} when I'm looking for KY-WH-DT01. I'm not sure what I'm doing wrong.
As a workaround, I've pulled the list manually and properly inserted it into the variable as hard code.
function testConnection {
$computers = Get-ADComputer -filter 'Name -like "KY-WH*" -or name -like "KY-SR"' | select name
$pass = 0
$fail = 0
foreach ($computer in $computers) {
$testConnection = Test-Path "\\$computer\C$" -ErrorAction Stop
if ($testConnection -eq $true) {
Write-Host $computer -ForegroundColor Green
$pass = $pass + 1
}
else {
Write-Host $computer -ForegroundColor Red -BackgroundColor Black
$fail = $fail + 1
}
}
Write-Host $null
Write-Host "Passed: $pass | Failed: $fail"
}
testConnection
...
This code should output a list of computer names with colors determining whether the connection test passed or failed by turning them either red or green.
You need to drill down a little bit in your variable.
foreach ($computer in $computers.Name) {
This will do it if you only want the name or the computer and no other variable.
You can also change your initial search to include the -ExpandProperty switch and you will not need to dig down into the property.
$computers = Get-ADComputer -filter 'Name -like "KY-WH*" -or name -like "KY-SR"' | select -ExpandProperty name
Hi I would like to find out where my AD group called BIDEV is located within my AD, as you can see on the pictures below.
It exists, but where is it?
Also, any example of how I could do this using Powershell?
#------------------------------
# first part search for a user
#------------------------------
Clear-Host
$SearchFor = "mmartin"
import-module activedirectory
Write-Host "Searching..."
$all_users_list=Get-ADUser -filter * -properties SamAccountName,sn,GivenName,mail,EmailAddress,LastLogonDate,Country,DistinguishedName,CanonicalName |
select-object SamAccountName,sn,GivenName,mail,EmailAddress,LastLogonDate,Country,DistinguishedName,CanonicalName -ErrorAction silentlycontinue
foreach($u in $all_users_list)
{
if($u.SamAccountName -like "*$SearchFor*")
{
$Output = $u.SamAccountName + " - " + $u.DistinguishedName
Write-Host $Output
}
}
Write-Host "Done"
#that will work
#just put what you want at the top in "SearchFor"
#mmartin my powershell guru - 16-july-2015
#------------------------------
# second part search for a group
#------------------------------
Clear-Host
$SearchFor = "BIDEV"
import-module activedirectory
Write-Host "Searching..."
$all_group_list=Get-ADGroup -filter * -properties * |
select-object * -ErrorAction silentlycontinue
foreach($u in $all_group_list)
{
if($u.SamAccountName -like "*$SearchFor*")
{
$Output = $u.SamAccountName + " - " + $u.DistinguishedName
Write-Host $Output
}
}
Write-Host "Done"