Category Archives: Windows 2008

Modifying data folder permissions with Powershell

If you are doing a migration from one domain to another, you may need to change groups (old groups for new groups!). We did trying playing around with SID History, but with limited success.

With this script, you need to give it a CSV file containing a list of the groups that you want swapped (two columns, oldgroup & newgroup, in a file called groups.csv), and you will also need to edit the variables for in the script for your domain names.

There is a $removeoldgroup variable. If this is set to true, the old group is replaced. If it set to false, it is left. The script also checks to see if a particaular ACL entry is inherited. This is important because otherwise, you can get duplicate entries on the ACL (although no necessarily visible from the GUI, or having any effect in normal user use, it isn’t very clean).

Finally, as we had several areas where “Administrators” had been removed, the script will also add them back in if they are missing.

There are three files that are created by the script.
“Before Permission Changes.txt” – This will contain a list of folders and ACL’s before any processing is done.
“After Permission Changes.txt” – This will contain a list of folders and ACL’s once the processing is complete.
“folders done.txt” – This will contain a list of all folders that have been modified, as well as the date/time.

A few things to note.
1) It will fail to handle long paths (260 or more characters). You will need to create a share further down the tree in order to successfully process those. I looked at other ways around this, but didn’t find one which appealed.
2) I ran this from my Windows7 workstation against the server using UNC paths. I did test this on the server itself (Windows Server 2008, not R2), and it didn’t work as I expected with the subfolders. I don’t know if this is to do with an older version of Powershell, or an older version of .NET…
2) Test, test, test. I spent the best part of a week testing this in different scenarios, including reversing things to put the old groups back. Still, we have 140,000 folders and and problems would be a potential nightmare to solve. If you have more folders, do more testing 🙂

$destinationpath = "\\server1\share1"
$oldDomain = "EMEA"
$newDomain = "IPRUK"

$removeoldgroup = $false

"Job started at " + (Get-Date) `
	| Out-File "folders Done.txt" -Append
	
#Build a list of folders
$folders = Get-childitem $destinationpath -recurse `
	| where {$_.mode -like "d----"} 

#Get the ACL's and store in a txt file for future review.
$folders | Get-Acl `
	| Format-List @{l='Directory';e={($_.PSpath).substring(38)}},`
			accessToString `
			| Out-File -FilePath "Before permission changes.txt"

#Read the groups from a CSV with two columns, oldgroup & newgroup.
$groups = import-csv groups.csv

foreach ($folder in $folders){
	
	$aclaccess = Get-Acl $folder.FullName | select Access -ExpandProperty Access

	Foreach ($group in $groups) {
		$oldgroup = $olddomain + "\" + $group.oldgroup
		$newgroup = $newdomain + "\" + $group.newgroup

		Foreach ($accessright in $aclaccess) {
			[string]$aclIdentity = $accessright.IdentityReference
			If ($oldgroup -eq $aclIdentity) {
				
				#We don't need to change if it is inherited
				If (!$accessright.IsInherited) {
					#We have a match, so grab the full ACL from folder.
					$acl = Get-Acl $folder.fullname
					
					#Build new access rule to add to ACL.
					$FileSystemRights = $accessright.FileSystemRights
					$InheritanceFlags = $accessright.InheritanceFlags
					$PropogationFlags = $accessright.PropagationFlags
					$ACEtype = $accessright.AccessControlType
					$permission = ($newgroup, `
						$Filesystemrights, `
						$InheritanceFlags, `
						$PropogationFlags, `
						$ACEtype)
					$Rule = New-Object `
						System.Security.AccessControl.FileSystemAccessRule $permission
						Try {
							$acl.AddAccessRule($rule)
							}
						Catch {
						$FolderFullName = $folder.FullName
						$Datenow = (Get-Date)
						"$Datenow - $folderfullname, $permission : " + `
							$_ | Out-File "Group Errors.txt" -Append
							}
					#Build rule to remove from ACL.
					If ($removeoldgroup){
						$permission = ($oldgroup, `
							$Filesystemrights, `
							$InheritanceFlags, `
							$PropogationFlags, `
							$ACEtype)
						$Rule = New-Object `
							System.Security.AccessControl.FileSystemAccessRule $permission
						$acl.RemoveAccessRuleAll($Rule)
						}
					
					#Apply new access rule to folder.
					Set-Acl $folder.FullName $acl
					
					#Check for builtin\administrators, add if missing
					$adminright = $acl.access `
						| Where {$_.IdentityReference -eq "BUILTIN\Administrators"}
					If (!$adminright){
						#Build new access rule to add to ACL.
						$FileSystemRights = "FullControl"
						$InheritanceFlags = "ContainerInherit,ObjectInherit"
						$PropogationFlags = "None"
						$ACEtype = "Allow"
						$permission = ("BUILTIN\Administrators", `
							$Filesystemrights, `
							$InheritanceFlags, `
							$PropogationFlags, `
							$ACEtype)
						$Rule = New-Object `
							System.Security.AccessControl.FileSystemAccessRule $permission
						$acl.AddAccessRule($rule)	
						#Apply new access rule to folder.
						Set-Acl $folder.FullName $acl
						}
					}
				}		
			}
		}
	$FolderFullName = $folder.FullName
	"$folderFullName completed at " + (Get-Date) `
		| Out-File "folders Done.txt" -Append
	}
#Final report on permissions.
$folders | Get-Acl `
	| Format-List @{l='Directory';e={($_.PSpath).substring(38)}},`
			accessToString `
			| Out-File -FilePath "After permission changes.txt"
			
"Job completed at " + (Get-Date) `
	| Out-File "folders Done.txt" -Append

So, this, combined with Finding Long Paths, and the script for modifying USER permissions, means that I have the scripts I wanted to proceed with our domain migration!

Leave a comment

Filed under Microsoft, Powershell, Windows 2008

Using Powershell to change USER home drive permissions

There may be times, say during migration to a new domain where you need to add permissions for users in the new domain. I used the following script, run from my Windows 7 PC using Powershell 3.0, to make the changes.

It uses a csv file with two columns, “olduser”, and “newuser”. Obviously each line has the old user ID and then new one. The script will go through each user in the file, find the folder that has the same name as the user, prompt if it can’t find it, and then add permissions on the folder for the “newuser”.

It will leave the old permissions in place, because you could be doing this during the pilot phase of the process.

Here is the code.


$folderroot = Read-Host "What is the path to USER$"
$csvfile = Read-Host "What is the path to the csvfile"

#Read contents of CSV file.
$users = Import-Csv $csvfile

If ($users) {
	Foreach ($user in $users) {
		#Read line from file, and create expected path to home drive.
		$newID = $user.newuser
		$oldID = $user.olduser
		$folderpath = $folderroot + "\" + $user.olduser
		#Get the ACL for the folder.
		$acl = Get-Acl $folderpath
		#Check that the ACL isn't empty because the expect folder doesn't exist.
		if ($acl -eq $null){
			$altpath = (Read-Host "Folder not found, please enter the folder name manually for $oldID")
			if ($altpath) {
				$folderpath = ($folderroot + "\" + $altpath)
				$acl = Get-Acl $folderpath
				}
			else {
				Write-Host "Sorry, still not found."
				}
			}
		#Build a permission to add to the ACL.	
		$permission = “IPRUK\$newID”,”Modify”,”ContainerInherit,ObjectInherit”,”None”,”Allow”
		$accessrule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
		$acl.SetAccessRule($accessrule)
		$acl | set-acl -path $folderpath
		$timenow = get-date
		Write-Host "Permissions set for $oldID at $timenow"
		$users2 = $users | where {$_.olduser -ne $oldID}
		$users = $users2
		If ($users){
			$users | Export-Csv users.csv -NoTypeInformation
			}
		}
	}


Obviously, you need to be VERY CAREFUL about running this, as it would be a mess to clean up, and this code as it stands, is not production ready. It could really do with a bit more checking built in. It worked for me though 🙂

2 Comments

Filed under Microsoft, Powershell, Windows 2008

Changing NetBIOS over TCP/IP with Powershell

I needed to re-enable netBIOS over TCP/IP on a set of computers after someone disabled it and broke a system. Powershell was obviously the easiest way to do it!

Here is the code:

$servers = "myserver01", "myserver02", "myserver03", "myserver04", "myserver05", "myserver06"
Foreach ($server in $servers){
  $adapter=(gwmi -computer $server win32_networkadapterconfiguration | where {$_.servicename -like "vmxnet*"})
  $adapter.settcpipnetbios(1)
}

A value of 1 for settcpipnetbios enables it, and 2 disables it. 0 is to use the DHCP default (from memory).

1 Comment

Filed under Microsoft, Powershell, Windows 2008

Using Powershell to check for hotfixes

OK, nothing really new here to anyone who has played much with powershell but I gave myself a pat on the back for it.

If you want to check what hotfixes are installed on your machines, you can use the following command:

( get-adcomputer -filter *) | ForEach-Object -process {out-file -filepath c:\hotfixes.txt -append -inputobject (get-hotfix -computer $_.Name)}

Of course that is going to return a pretty long list if you have a lot of machines and/or hotfixes, so if you only wanted to check computers who names start with “server”, you could do:

( get-adcomputer -filter  ‘Name -like “server*”‘) | ForEach-Object -process {out-file -filepath c:\hotfixes.txt -append -inputobject (get-hotfix  -id KB976902 -computer $_.Name)}

And if you only want to check for a specific hotfix on those servers, you could do

( get-adcomputer -filter  ‘Name -like “server*”‘) | ForEach-Object -process {out-file -filepath c:\hotfixes.txt -append -inputobject (get-hotfix  -id KB976902 -computer $_.Name)}

It should of course have some error handling make sure that the ActiveDirectory module is loaded (you can check by running “Get-module -list”).

You do NOT need powershell installed on your target workstations/servers for this to work!

 

Leave a comment

Filed under Powershell, Windows 2008

Getting rid of the hybernate file in Windows 2008

The Hiberfil.sys hidden system file is located in the root folder of the drive where the operating system is installed. The Windows Kernel Power Manager reserves this file when you install Microsoft Windows. The size of this file is approximately equal to the amount of random access memory (RAM) that is installed on the computer.

Click Start, and then type cmd in the Start Search box.
In the search results list, right-click Command Prompt, and then click Run as Administrator.
When you are prompted by User Account Control, click Continue.
At the command prompt, type powercfg.exe /hibernate off, and then press ENTER.
Type exit, and then press ENTER.

http://support.microsoft.com/kb/920730/en-us

Leave a comment

Filed under Microsoft, Windows 2008