I have problems when running a powershell script in Scheduled Tasks. It gets stuck in Running, even though the Transcript has logged out the last row "Done!" and it also looks like it has done exactly what i want it to. What am I missing?
When running it from Run in Windows it also seems fine: powershell -file "D:\_temp\copy_bat\copy_one_reprint_folder.ps1"
Seetings in Task Scheduler is:
Run with full priviliges
Run weither user is logged on or not
Action, start program powershell.exe
-file "D:\_temp\copy_bat\copy_one_reprint_folder.ps1"
Please see code below if needed.
# PowerShell RePRINT copy first folder, sorted on lastModified
function timestamp
{
$ts = Get-Date -format s
return $ts
}
$fromDirectory = "D:\_temp\copy_bat"
$toDirectory = "D:\_temp\in_dummy"
$extractGUIDdir = ""
$docTypeDir = ""
# Logging
#########
$ErrorActionPreference="SilentlyContinue"
Stop-Transcript | out-null
$ErrorActionPreference = "Continue"
Start-Transcript -path $fromDirectory\copy_one_reprint_folder.log.txt -append
###########
Write-Host ""
Write-Host (timestamp) "Copy RePRINT extract started"
Write-Host (timestamp) "============================"
Get-ChildItem -path $fromDirectory | ?{ $_.PSIsContainer } | Sort-Object CreationTime | `
Where-Object {$_.name -ne "_copied"} | `
Select-Object -first 1 | `
Foreach-Object{
Write-Host (timestamp) $_.name
$extractGUIDdir = $_.FullName
Get-ChildItem -path $extractGUIDdir | ?{ $_.PSIsContainer } | Where-Object {$_.Name -match "Purchase Order \(-999999997\)" -or $_.Name -match "Logistics documents \(-1000000000\)" -or $_.Name -match "Specifications \(-999999998\)"} | `
Foreach-Object{
Write-Host (timestamp) " " $_.Name
}
Write-Host ""
Write-Host "These folders (document types), were also found but will not be included"
Get-ChildItem -path $extractGUIDdir -Exclude "Logistics documents (-1000000000)", "Purchase Order (-999999997)", "Specifications (-999999998)" | ?{ $_.PSIsContainer } | `
Foreach-Object{
Write-Host (timestamp) " - " $_.name
}
Write-Host ""
Get-ChildItem -path $extractGUIDdir | ?{ $_.PSIsContainer } | Where-Object {$_.Name -match "Purchase Order \(-999999997\)" -or $_.Name -match "Logistics documents \(-1000000000\)" -or $_.Name -match "Specifications \(-999999998\)"} | `
Foreach-Object{
$temp_name = $_.FullName
Write-Host (timestamp) "copying files from " $_.FullName
Write-Host (timestamp) " to " $toDirectory
#Copy-Item ($_.FullName)\*.* $toDirectory
Write-Host (timestamp) " copying meta-files..."
Copy-Item $temp_name\*.meta $toDirectory -Filter *.meta
Write-Host (timestamp) " copying pdf-files..."
Copy-Item $temp_name\*.pdf $toDirectory -Filter *.pdf
if(Test-Path $temp_name\*.* -Exclude *.meta, *.pdf)
{
Write-Host (timestamp) " WARNING/ERROR not all documents have been moved. Only PDFs was moved!"
Write-Host (timestamp) " Check folder for other document-types."
}
}
Move-Item $extractGUIDdir $fromDirectory\_copied
}
Write-Host (timestamp) " DONE!"
# Stop logging
Stop-Transcript
It is solved.
It works, stupid me did not press F5(update) in task scheduler to update the status of the task in the gui.
Actually I was quite certain I did this, but apparently not.
Related
I am trying to create a PowerShell script to fetch the root folder's name where in their subdirectories files with error names are present with today's date. Below is the sample code I have tried so far to pick the folder names.
Root Log folder - C:\Errorlogs, contains many other application log level folders.
$targetDir="C:\Errorlogs"
Get-ChildItem $targetDir -Recurse -ErrorAction SilentlyContinue -Force -Filter "*Error*"|
where {([datetime]::now.Date -eq $_.lastwritetime.Date)} |
select FullName
I have tried the above code; however, it's giving me the whole path as result, whereas I only need the folder name.
Result - C:\Errorlogs\AsyncCreateUsersAPIProcessor\202302\04\Error.txt
Required - AsyncCreateUsersAPIProcessor
Use string LastIndexOf and SubString
$rootPath = "C:\Temp\Errorlogs"
$date = [DateTime]::Now.ToString("yyyyMM\\\\dd")
$pattern = '\\(?<folder>\w+)\\' + $date + '\\Error.*$'
$files = Get-ChildItem -Path $rootPath -Recurse | Select-Object -Property Fullname | Where-Object {$_.Fullname -Match $pattern}
foreach($file in $files)
{
$file.Fullname -match $pattern
Write-Host "folder = " $Matches.folder
}
Looks like you can do it just with splitting the path using \ as delimiter then picking the 3rd token (2nd index of an array):
$targetDir = "C:\Errorlogs"
Get-ChildItem $targetDir -Recurse -ErrorAction SilentlyContinue -Force -Filter "*Error*" |
Where-Object { [datetime]::Now.Date -eq $_.LastWriteTime.Date } |
Select-Object #{ N='Name'; E={ $_.FullName.Split('\')[2] }}
Another option if you want 2 levels up in the folder hierarchy is to query the .Directory property of the file then the .Parent property of the parent folder (2 times or as many times as needed):
$targetDir = "C:\Errorlogs"
Get-ChildItem $targetDir -Recurse -ErrorAction SilentlyContinue -Force -Filter "*Error*" |
Where-Object { [datetime]::Now.Date -eq $_.LastWriteTime.Date } |
Select-Object #{ N='Name'; E={ $_.Directory.Parent.Parent.Name }}
As long as the subfolders inside the folder you are after all have numeric-only names, you can loop backwards to get at the first non-numeric foldername and output that.
$targetDir = "C:\Errorlogs"
Get-ChildItem -Path $targetDir -File -Filter "*Error*" -Recurse -Force -ErrorAction SilentlyContinue |
Where-Object { [datetime]::Now.Date -eq $_.LastWriteTime.Date } | ForEach-Object {
$parentDir = $_.Directory
while ($parentDir.Name -match '^\d+$') { $parentDir = $parentDir.Parent }
$parentDir.Name
}
That way, even a path C:\Errorlogs\AsyncCreateUsersAPIProcessor\202302\02\04\1234\567\Error.txt would produce folder name AsyncCreateUsersAPIProcessor
I am working on a Windows Server File Security project, and need the explicit ACL permissions for our " O:" and all of the subfolders. I am wanting to export it to an CSV for easy formatting. I am looking for a Powershell script that can list the folder name and the Security Group or User that has access to that folder.
$rootpath = "O:\ADSMO"
$outfile = "ExplicitACLs.txt"
New-Variable acl
$Report = #"
Explicit permissions on folders under parent $rootpath.
"#
$Report | out-file -Encoding ASCII -FilePath $outfile
Get-ChildItem -Recurse $rootpath -Exclude "*.*" | Where-Object {$_.PSisContainer } | ForEach-Object {
$acl = Get-Acl -Path $_.FullName
$access = $acl.access
if ( $access | Where-Object { $_.IsInherited -eq $False }) {
Add-Content -Path $outfile $_
$access | Where-Object { $_.IsInherited -eq $False } | ForEach-Object {
$i = $_.IdentityReference
$t = "`t"
$r = $_.FileSystemRights
$c = "$i"+"$t"+"$t"+"$t"+"$r"
Add-Content -Path $outfile $c
}
Add-Content -Path $outfile ""
}
Clear-Variable acl
Clear-Variable access
}
Add-Content -Path $outfile ""
Seems like you're trying to build a CSV manually, which is definitely not recommended. You can use Export-Csv to export your report to CSV. From what I'm seeing, your code could be simplified to this:
Get-ChildItem O:\ADSMO -Directory -Recurse | ForEach-Object {
foreach($access in (Get-Acl $_.FullName).Access) {
# if `IsInherited = $true` go to next iteration
if($access.IsInherited) { continue }
[pscustomobject]#{
FolderName = $_.Name
FolderPath = $_.FullName
IdentityReference = $access.IdentityReference
FileSystemRights = $access.FileSystemRights
}
}
} | Export-Csv 'C:\path\to\acls.csv' -NoTypeInformation
I'm trying to exclude two drives from a file search. I'm getting an error when running the code: "Get-ChildItem : Access to the path 'C:\Windows\system32\LogFiles...'". The search shouldn't touch C. Help!! What am I doing wrong? Code attached.
$Drives = Get-PSDrive -PSProvider FileSystem | where { -not ('c','u' -eq $_.name) }
$FS='(.*18)\.FOO'
$FPath=#(foreach($Drive in $drives) {
Get-ChildItem -Path $Drive.Root -Recurse | Where-Object {$_.Name -match $FS} -ErrorAction SilentlyContinue | %{$_.Name}
})
I think you are looking for
Get-PSDrive -PSProvider FileSystem |
Where-Object {"c","u" -notcontains $_.name} |
ForEach-Object{
Get-ChildItem -Path $_.Root -Recurse |
Where-Object {$_.Name -match '(.*18)\.FOO'} -ErrorAction SilentlyContinue |
select Name
}
Seems based on your comments you are still getting the error. Lets trouble shoot it a bit. Lets output the drive that it really seems to error on.
Get-PSDrive -PSProvider FileSystem |
Where-Object {"c","u" -notcontains $_.name} |
ForEach-Object{
$Drive = $_.Name
try{
Get-ChildItem -Path $_.Root -Recurse |
Where-Object {$_.Name -match '(.*18)\.FOO'} -ErrorAction SilentlyContinue |
Select Name
}catch{
#{
Drive = $Drive
}
}
}
I want to search all drives using PowerShell on windows machine to get the list of all files along with their extensions -
Based on desired extension we pass in it like - *.mp3 or
Fetch all files with multiple extensions like - *.txt, *.mp3 etc.
I tried below script but its giving only information from where we are running it. But I want to scan whole machine.
Get-ChildItem -Path .\ -Filter ***.doc** -Recurse -File| Sort-Object Length -Descending | ForEach-Object { $_.BaseName }
Checkout the Get-PSDrive cmdlet. It returns a list of drives, and you can specify just disk drives with the -PSProvider FileSystem parameter:
foreach ( $drive in $(Get-PSDrive -PSProvider FileSystem) ) {
Get-ChildItem -Path $drive.Root -Filter ***.doc** -Recurse -File |
Sort-Object Length -Descending |
ForEach-Object { $_.BaseName }
}
Didn't test that but you get the idea.
Using -Include on Get-ChildItem will allow you to specify a list of extensions. The -ErrorAction will cause it to skip drives that are not available such as an unmounted CD drive.
Get-PSDrive -PSProvider FileSystem |
ForEach-Object {
Get-ChildItem -Path $_.Root -Recurse -Include '*.doc*', '*.txt' -ErrorAction SilentlyContinue |
ForEach-Object { $_.Name }
} |
ForEach-Object {[PSCustomObject]#{HashCode = $_.GetHashCode(); FullName = $_.FullName}}
} |
Export-Csv -Path $TempFile -NoTypeInformation -Encoding ASCII
Update:
Here is a better way. It will prevent unknown extensions from getting into the mix such as "Microsoft.NET.Sdk.Publish.Docker.targets."
$ExtensionList = #('.txt', '.doc', '.docx', '.mp3')
$TempFile = Join-Path -path $Env:TEMP -ChildPath "$($pid.ToString()).tmp"
Get-PSDrive -PSProvider FileSystem |
ForEach-Object {
Get-ChildItem -Path $_.Root -Recurse -ErrorAction SilentlyContinue |
Where-Object { $ExtensionList -contains $_.Extension } |
ForEach-Object {
[PSCustomObject]#{
HashCode = $_.GetHashCode();
DirectoryName = $_.DirectoryName
Name = $_.Name
}
}
} |
Export-Csv -Path $TempFile -Delimiter ';' -NoTypeInformation -Encoding ASCII
Write-Host "The temp file is $TempFile"
This is more than what the original question asked, but if you are going to go through the trouble of listing all your files, I suggest getting the filehash as well so you can determine if you have duplicates. A simple file name search will not detect if the same file has been saved with a different name. Adding to what #lit (https://stackoverflow.com/users/447901/lit) has posted:
$ExtensionList = #('.txt', '.doc', '.docx', '.mp3')
Get-PSDrive -PSProvider FileSystem |
ForEach-Object {
Get-ChildItem -Path $_.Root -Recurse -ErrorAction SilentlyContinue |
Where-Object { $ExtensionList -eq $_.Extension } |
## ForEach-Object { $_.Name, $_.FullName, $_.GetHashCode() }
Select-Object #{Name="Name";Expression={$_.Name}}, #{Name="Hash";Expression={$_.GetHashCode()}}, #{Name="FullName";Expression={$_.FullName}} |
Export-Csv -Path C:\Temp\testing.csv -NoTypeInformation -Append
}
The addition of the file hash will allow you to see if you have duplicates and the full name will allow you to see where they are located.
I am trying to configure a new RDS gateway server through Powershell (for automatic setup after EC2 creation). The issue I'm running into right now is setting up a default or otherwise CAP and RAP. Everything else seems to work just fine, and if I go through the server dialogs and point and click my way to doing the CAP/RAP wizard, it all works. Until I do so, those policies don't exist (not even a default).
The code I'm using, which I sourced from blog posts on technet about the subject, is this:
new-item -Force -Credential $AdminCredentials -path RDS:\GatewayServer\CAP -Name DomainAdmin-CAP -UserGroups “$AdminGroupName#$NetBiosDomainName" -AuthMethod 1
new-item -Force -Credential $AdminCredentials -path RDS:\GatewayServer\CAP -Name DomainUser-CAP -UserGroups “$UserGroupName#$NetBiosDomainName" -AuthMethod 1
new-item -Force -Credential $AdminCredentials -path RDS:\GatewayServer\RAP -Name DomainAdmin-RAP -UserGroups “$AdminGroupName#$NetBiosDomainName" -ComputerGroupType 2
new-item -Force -Credential $AdminCredentials -path RDS:\GatewayServer\RAP -Name DomainUser-RAP -UserGroups “$UserGroupName#$NetBiosdomainName" -ComputerGroupType 2
Again, everything else works and the system is 100% and useable once I RDP in to the server and set these up manually, so my only issue is this automation step. The error I'm getting when I run my script is this:
new-item : Access to the object at RDS:\GatewayServer\CAP\DomainAdmin-CAP is denied for the cmdlet
New-Item.The supplied value is not valid, or you do not have
sufficient permissions. At line:89 char:1
+ new-item -Force -Credential $AdminCredentials -path RDS:\GatewayServe ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (:) [New-Item], AccessViolationException
+ FullyQualifiedErrorId : PermissionDenied,Microsoft.PowerShell.Commands.NewItemCommand
Edit: Things I have tried based on suggestions and frustration:
I have made all " characters uniform after someone pointed out they were actually not the same thing on the front and rear of my -UserGroup variable strings - No error change.
I have tried $NetBiosDomainName as the simple one word NetBIOS version (DOMAIN) as well as the full domain (domain.company.com) - No error change.
I have tried changing the "$AdministratorsGroupName#$NetBiosDomainName" string out for $AdminGroup (= $AdministratorsGroupName + "#" + $NetBiosDomainName") to simplify the input to the -UserGroups parameter - No error change
I have run this script as both the domain admin and local administrator account - No error change
I was able to use the following script to configure a Remote Access Gateway on a non-domain Windows 2019/2016 server. This includes a CAP, a RAP, and a ManagedComputerGroup.
Install-WindowsFeature -Name "RDS-Gateway" -IncludeAllSubFeature -IncludeManagementTools > $null
Import-Module -Name RemoteDesktopServices
#=============User Modifiable=============#
$GroupName="SG_RemoteUsers#$env:COMPUTERNAME"
# No Restrictions
#$GroupName="Users#BUILTIN"
$ManagedComputers="RDG_RDCBComputers"
# Managed Computer Groups
$MCGComputers=#($env:COMPUTERNAME,"<target machines>")
$MCGs=#(#{Name="RDG_RDCBComputers";Desc="All RDCB Computers in the deployment";Computers=$MCGComputers})
# Connection Authorization Policies
$CAPs=#(#{Name="RDG_CAP_AllUsers";UserGroups=$GroupName;AuthMethod=1;Status=1})
# Resrouce Authorization Policies
$RAPs=#(#{Name="RDG_AllComputers";UserGroups=$GroupName;ComputerGroupType=2;ComputerGroup=$null})
# If you already have a certificate, skip this part.
<#region Certificate
$FilePath="C:\temp\export.cer"
$SelfSigned=New-SelfSignedCertificate -CertStoreLocation "Cert:\LocalMachine\My" -DnsName $env:COMPUTERNAME -FriendlyName $env:COMPUTERNAME -KeyAlgorithm "RSA" -HashAlgorithm "SHA256" -KeyDescription "RDG Key" -KeyLength 4096 -KeyUsage KeyEncipherment,DataEncipherment -KeyUsageProperty All
$CertPassword=ConvertTo-SecureString -String “password” -Force –AsPlainText
Export-PfxCertificate -Cert $SelfSigned.PSPath -FilePath $FilePath -Password $CertPassword > $null
Import-PfxCertificate -CertStoreLocation "Cert:\LocalMachine\Root" -FilePath $FilePath -Password $CertPassword > $null
Remove-Item -Path $FilePath
$Certificate=$SelfSigned
#endregion
#>
$Certificate=Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object { $_.Thumbprint -eq "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" } | Sort-Object -Property NotAfter -Descending | Select-Object -Last 1
#=============Do not modify=============#
$CAPPath="RDS:\GatewayServer\CAP"
$RAPPath="RDS:\GatewayServer\RAP"
$MCGPath="RDS:\GatewayServer\GatewayManagedComputerGroups"
#=============Script=============#
# Add the certificate to RDS
Set-Item -Path "RDS:\GatewayServer\SSLCertificate\Thumbprint" -Value $Certificate.Thumbprint
try { Get-LocalGroup -Name $GroupName -ErrorAction Stop > $null }
catch { New-LocalGroup -Name $GroupName > $null }
try { Get-LocalGroupMember -Group $GroupName -Member "<user that should have access>" -ErrorAction Stop > $null }
catch { Add-LocalGroupMember -Group $GroupName -Member "<user that should have access>" > $null }
# Remove existing items (must be done in the order of CAP and/or RAP first, then GatewayManagedComputerGroups
$CAPs | ForEach-Object { if (Test-Path -Path "$CAPPath\$($_.Name)") { Remove-Item -Path "$CAPPath\$($_.Name)" -Recurse } }
$RAPs | ForEach-Object { if (Test-Path -Path "$RAPPath\$($_.Name)") { Remove-Item -Path "$RAPPath\$($_.Name)" -Recurse } }
$MCGs | ForEach-Object { if (Test-Path -Path "$MCGPath\$($_.Name)") { Remove-Item -Path "$MCGPath\$($_.Name)" -Recurse } }
$MCGs | ForEach-Object { New-Item -Path $MCGPath -Name $_.Name -Description $_.Desc -Computers $_.Computers > $null }
$CAPs | ForEach-Object { New-Item -Path $CAPPath -Name $_.Name -UserGroups $_.UserGroups -AuthMethod $_.AuthMethod -Status $_.Status > $null }
$RAPs | ForEach-Object { New-Item -Path $RAPPath -Name $_.Name -UserGroups $_.UserGroups -ComputerGroupType $_.ComputerGroupType > $null }
# Stop redirection of Serial Ports
$CAPs | ForEach-Object { Set-Item -Path "$CAPPath\$($_.Name)\DeviceRedirection\SerialPorts" -Value 0 }
Restart-Service -Name "TSGateway"
This script, which shares a significant portion of the previous, is what I used to configure the same on a server that is a member of an AD domain. It's not the only way to do it, but hopefully it will give you a head start.
There is a portion of this script that creates the necessary AD group.
The only part that's missing is that the certificate must be placed in the Trusted Root store on the PC from which you want to connect.
Install-WindowsFeature -Name "RDS-Gateway" -IncludeAllSubFeature -IncludeManagementTools > $null
Import-Module -Name RemoteDesktopServices
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
#=============User Modifiable=============#
$GroupName="SG_RemoteUsers"
$ManagedComputers="RDG_RDCBComputers"
# Managed Computer Groups
$MCGComputers=#($env:COMPUTERNAME,"<target machines>")
$MCGs=#(#{Name=$ManagedComputers;Desc="All RDCB Computers in the deployment";Computers=$MCGComputers})
# Connection Authorization Policies
$CAPs=#(#{Name="RDG_CAP_AllUsers";UserGroups="$GroupName#$env:USERDOMAIN";AuthMethod=1;Status=1})
# Resrouce Authorization Policies
$RAPs=#(#{Name="RDG_AllDomainComputers";UserGroups="$GroupName#$env:USERDOMAIN";ComputerGroupType=1;ComputerGroup="Domain Computers#$env:USERDOMAIN"},
#{Name="RDG_RDConnectionBrokers";UserGroups="Domain Users#$env:USERDOMAIN";ComputerGroupType=0;ComputerGroup=$ManagedComputers})
# If you already have a certificate, skip this part.
<#region Certificate
$FilePath="C:\temp\export.cer"
$SelfSigned=New-SelfSignedCertificate -CertStoreLocation "Cert:\LocalMachine\My" -DnsName "$env:COMPUTERNAME.$env:USERDNSDOMAIN" -FriendlyName $env:COMPUTERNAME -KeyAlgorithm "RSA" -HashAlgorithm "SHA256" -KeyDescription "RDG Key" -KeyLength 4096 -KeyUsage KeyEncipherment,DataEncipherment -KeyUsageProperty All
$CertPassword=ConvertTo-SecureString -String “password” -Force –AsPlainText
Export-PfxCertificate -Cert $SelfSigned.PSPath -FilePath $FilePath -Password $CertPassword > $null
Import-PfxCertificate -CertStoreLocation "Cert:\LocalMachine\Root" -FilePath $FilePath -Password $CertPassword > $null
Remove-Item -Path $FilePath
$Certificate=$SelfSigned
#endregion
#>
$Certificate=Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object { $_.Thumbprint -eq "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" } | Sort-Object -Property NotAfter -Descending | Select-Object -Last 1
#=============Do not modify=============#
$CAPPath="RDS:\GatewayServer\CAP"
$RAPPath="RDS:\GatewayServer\RAP"
$MCGPath="RDS:\GatewayServer\GatewayManagedComputerGroups"
#=============Script=============#
# Add the certificate to RDS
Set-Item -Path "RDS:\GatewayServer\SSLCertificate\Thumbprint" -Value $Certificate.Thumbprint
$ADGroup=[System.DirectoryServices.DirectorySearcher]::new("(&(objectCategory=Group)(samAccountName=$GroupName))").FindOne()
if ($ADGroup -ne $null) {
$ADGroup=$ADGroup.GetDirectoryEntry()
$Parent=[System.DirectoryServices.DirectoryEntry]::new($ADGroup.Parent)
$Parent.Children.Remove($ADGroup)
$Parent.CommitChanges()
$Parent.Close()
}
$ADGroup=[System.DirectoryServices.AccountManagement.GroupPrincipal]::new([System.DirectoryServices.AccountManagement.PrincipalContext]::new([System.DirectoryServices.AccountManagement.ContextType]::Domain),$GroupName)
$ADGroup.Description="Remote Gateway Users Group"
$ADGroup.GroupScope=[System.DirectoryServices.AccountManagement.GroupScope]::Global
$ADGroup.IsSecurityGroup=$true
$Member=[System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity([System.DirectoryServices.AccountManagement.PrincipalContext]::new([System.DirectoryServices.AccountManagement.ContextType]::Domain),"Administrator")
$ADGroup.Members.Add($Member)
$Member=[System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity([System.DirectoryServices.AccountManagement.PrincipalContext]::new([System.DirectoryServices.AccountManagement.ContextType]::Domain),"admin_jeberhardt")
$ADGroup.Members.Add($Member)
$ADGroup.DisplayName=$ADGroup.SamAccountName
$ADGroup.Save()
$OU=[System.DirectoryServices.DirectoryEntry]::new("LDAP://$($ADGroup.DistinguishedName)")
$NewOU=[System.DirectoryServices.DirectoryEntry]::new("LDAP://OU=<target OU>,DC=<domain name>,DC=com")
$OU.MoveTo($NewOU)
$OU.CommitChanges()
$OU.Close()
$NewOU.Close()
# Remove existing items (must be done in the order of CAP and/or RAP first, then GatewayManagedComputerGroups
$CAPs | ForEach-Object { if (Test-Path -Path "$CAPPath\$($_.Name)") { Write-Verbose "Removing $($_.Name)"; Remove-Item -Path "$CAPPath\$($_.Name)" -Recurse } }
$RAPs | ForEach-Object { if (Test-Path -Path "$RAPPath\$($_.Name)") { Write-Verbose "Removing $($_.Name)"; Remove-Item -Path "$RAPPath\$($_.Name)" -Recurse } }
$MCGs | ForEach-Object { if (Test-Path -Path "$MCGPath\$($_.Name)") { Write-Verbose "Removing $($_.Name)"; Remove-Item -Path "$MCGPath\$($_.Name)" -Recurse } }
$MCGs | ForEach-Object { Write-Verbose "Creating $($_.Name)"; New-Item -Path $MCGPath -Name $_.Name -Description $_.Desc -Computers $_.Computers > $null }
$CAPs | ForEach-Object { Write-Verbose "Creating $($_.Name)"; New-Item -Path $CAPPath -Name $_.Name -UserGroups $_.UserGroups -AuthMethod $_.AuthMethod -Status $_.Status > $null }
$RAPs | ForEach-Object { Write-Verbose "Creating $($_.Name)"; New-Item -Path $RAPPath -Name $_.Name -UserGroups $_.UserGroups -ComputerGroup $_.ComputerGroup -ComputerGroupType $_.ComputerGroupType > $null }
# Stop redirection of Serial Ports
$CAPs | ForEach-Object { Set-Item -Path "$CAPPath\$($_.Name)\DeviceRedirection\SerialPorts" -Value 0 }
Restart-Service -Name "TSGateway"