{"id":50733,"date":"2010-04-07T00:01:00","date_gmt":"2010-04-07T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2010\/04\/07\/hey-scripting-guy-how-can-i-grant-administrator-rights-to-folders-and-then-delete-them\/"},"modified":"2010-04-07T00:01:00","modified_gmt":"2010-04-07T00:01:00","slug":"hey-scripting-guy-how-can-i-grant-administrator-rights-to-folders-and-then-delete-them","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-grant-administrator-rights-to-folders-and-then-delete-them\/","title":{"rendered":"Hey, Scripting Guy! How Can I Grant Administrator Rights to Folders and Then Delete Them?"},"content":{"rendered":"<p><a class=\"addthis_button\" href=\"http:\/\/www.addthis.com\/bookmark.php?v=250&amp;pub=scriptingguys\"><img decoding=\"async\" alt=\"Bookmark and Share\" src=\"http:\/\/s7.addthis.com\/static\/btn\/v2\/lg-share-en.gif\" width=\"125\" height=\"16\"><\/a><\/p>\n<p><img decoding=\"async\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\"><\/p>\n<p class=\"MsoNormal\">Hey Scripting Guy! Our previous network administrator was a slouch. He did not maintain proper backups, never reviewed event logs, and never cleaned up user folders when he deleted users in Active Directory. This last omission is particularly egregious because it has taken a lot of cleanup work to find and delete the user folders. One of the big problems with doing this manually is taking ownership of the folders, granting the Administrator rights to the folders, and then deleting them. It is a real pain. I would love a script that would do this automatically. <\/p>\n<p class=\"MsoNormal\">&#8212; BE<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\"><img decoding=\"async\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\">Hello BE, <\/p>\n<p class=\"MsoNormal\">Microsoft Scripting Guy Ed Wilson here. Things are really getting hectic in Charlotte, North Carolina. The 2010 Scripting Games commence on April 26, and there are lots of last-minute details to take care of. I have been busy talking to the many guest commentators, and have had several interviews with various scripting related podcasts about the Games. I have spoken to several user groups, and even found a little bit of time to write Hey, Scripting Guy! Blog posts. <\/p>\n<p class=\"MsoNormal\">I even found one guest commentator by reviewing submissions to the Official Scripting Guys Forum. Andrew Barnes has been really busy answering questions, and I contacted him and asked him if he would like to be a forum moderator. He was thrilled. I then asked him if he would like to be a guest commentator for the 2010 Scripting Games<span>\u2014<\/span>he was ecstatic. Andrew is from the United Kingdom, and his guest commentary on the games will appear in May when we begin posting the answers. Because I have spent so much time talking to Andrew recently, I went back through some of the pictures I took when I was in Reading teaching a VBScript class a few years. The following photo is one I took in downtown Reading. <\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Photo Ed took in Reading, England\" alt=\"Photo Ed took in Reading, England\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/HSG-04-07-10-01.jpg\"><\/p>\n<p class=\"Fig-Graphic\">BE, I decided to write the Get-ADUserAndRemoveProfileAndHomeDrive.ps1 script for you. In writing the script, I decided to query Active Directory to return the path to the user\u2019s home drive and the user\u2019s profile location. Next the script sets the security on the two folders to allow the Administrator to delete the files and folders, and finally it deletes the files and the folders. I did not add code to delete the user account in Active Directory, because there are dozens of scripts that do that in the Script Repository, and I did not want to clutter up an already complicated script with extra code. The complete Get-ADUserAndRemoveProfileAndHomeDrive.ps1 script is seen here. <\/p>\n<p class=\"CodeBlockScreenedHead\"><strong>Get-ADUserAndRemoveProfileAndHomeDrive.ps1<\/strong><\/p>\n<p class=\"CodeBlockScreened\"><span><font><font face=\"Lucida Sans Typewriter\">$psSession = New-PSSession -ComputerName HyperV -Credential nwtraders\\administrator <\/p>\n<p>Invoke-Command -Session $PSSession -ScriptBlock {<br \/><span>&nbsp; <\/span>$HD=$PD=$null<br \/><span>&nbsp; <\/span>$Filter = &#8220;(&amp;(ObjectCategory=user)(Name=HSG Testuser))&#8221;<br \/><span>&nbsp; <\/span>$Searcher = [adsiSearcher]($Filter)<br \/><span>&nbsp; <\/span>$Searcher.Findall() | <br \/><span>&nbsp;&nbsp;&nbsp; <\/span>ForEach-Object { <br \/><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>$HD = $_.properties.homedirectory <br \/><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>$PD = $_.properties.profilepath<br \/><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>$PD = &#8220;$PD.V2&#8221;<br \/><span>&nbsp;&nbsp; <\/span>} #end foreach-object<br \/>} #end scriptblock<\/p>\n<p>&#8220;Taking ownership of $hd&#8221;<br \/><span>&nbsp; <\/span>Invoke-Command -Session $PSSession -ScriptBlock `<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>{ Invoke-Expression &#8220;takeown \/f $HD \/r \/d y&#8221; } <br \/>&#8220;Taking ownership of $pd&#8221;<br \/><span>&nbsp; <\/span>Invoke-Command -Session $PSSession -ScriptBlock `<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>{ Invoke-Expression &#8220;takeown \/f $PD \/r \/d y&#8221; }<br \/>&#8220;Adding Administrator Rights to $hd&#8221;<br \/><span>&nbsp; <\/span>Invoke-Command -Session $PSSession -ScriptBlock `<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>{ Invoke-Expression &#8220;icacls $HD \/grant administrators:F \/t&#8221; }<br \/>&#8220;Adding Administrator Rights to $PD&#8221;<br \/><span>&nbsp; <\/span>Invoke-Command -Session $PSSession -ScriptBlock `<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>{ Invoke-Expression &#8220;icacls $PD \/grant administrators:F \/t&#8221; }<br \/>&#8220;Removing folder $hd&#8221;<br \/><span>&nbsp; <\/span>Invoke-Command -Session $PSSession -ScriptBlock `<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>{ Invoke-Expression &#8220;Remove-Item -Path $HD -Recurse -Force&#8221; }<br \/>&#8220;Removing Folder $PD&#8221;<br \/><span>&nbsp; <\/span>Invoke-Command -Session $PSSession -ScriptBlock `<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>{ Invoke-Expression &#8220;RD $PD -Recurse -Force&#8221; }<\/p>\n<p>Remove-PSSession -Session $psSession<\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\">BE, the first thing that must be done is to locate the user\u2019s profile path and home directory. These are two items that are often specified when the user account is created. The user profile page in Active Directory Users and Computers is shown in the following image.<\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of user profile page in Active Directory Users and Computers\" alt=\"Image of user profile page in Active Directory Users and Computers\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/HSG-04-07-10-02.jpg\" width=\"434\" height=\"515\"><\/p>\n<p class=\"Fig-Graphic\">To find the corresponding Active Directory Services Interface (ADSI) names, use the ADSI editor shown in the following image because the names used by the ADSI interface are seldom the names that are presented in the dialog box from Active Directory Users and Computers.<\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of ADSI editor\" alt=\"Image of ADSI editor\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/HSG-04-07-10-03.jpg\" width=\"414\" height=\"461\"><a href=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2010\/april\/hey0407\/hsg-04-07-10-03.jpg\"><\/a><\/p>\n<p>If you look up the user\u2019s home drive location and attempt to access it<span>\u2014<\/span>even as a Domain Administrator<span>\u2014<\/span>it is likely that you will not be able to access the user\u2019s home drive on the file server. You might be able to access the files, depending on the settings that were configured for the user home directories. This is seen in the following image.<\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of access limitations based on user home directories' settings\" alt=\"Image of access limitations based on user home directories' settings\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/HSG-04-07-10-04.jpg\" width=\"366\" height=\"169\"><\/p>\n<p class=\"Fig-Graphic\">On a Windows Server 2008 R2 server running Active Directory Domain Services (AD DS), you will not be able to access the user\u2019s profile directory because the Domain Administrator does not have access. This is seen in the following image.<\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of inability to access user's profile directory\" alt=\"Image of inability to access user's profile directory\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/HSG-04-07-10-05.jpg\" width=\"366\" height=\"169\"><\/p>\n<p class=\"Fig-Graphic\">Therefore, it is likely you will not have access to the user\u2019s home drive location, and it is virtually certain you will not have access to the user\u2019s profile directory. When you delete a user from Active Directory Domain Services, their home drive information and their profile information are not deleted. This necessitates a rather cumbersome process of taking ownership of each folder, granting Administrator full control, backing out, and then deleting the folder. If you are attempting to do this manually, it is a real bother, particularly if you have more than one user to clean up after. <\/p>\n<p class=\"MsoNormal\">Because the script will be running against a remote server, create a new <b>PSSession<\/b>. This will allow you to run interactive commands against the remote server that is running Windows PowerShell 2.0. In addition, I used the <b>\u2013credential<\/b> parameter because I want the script to specify the administrator credentials to use in the remote session. When using the <b>credential<\/b> parameter, the dialog box shown in the following image is displayed. <\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of dialog box shown when using credential parameter\" alt=\"Image of dialog box shown when using credential parameter\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/HSG-04-07-10-06.jpg\" width=\"336\" height=\"267\"><\/p>\n<p class=\"Fig-Graphic\">The first thing that needs to be done is to create a remote session on the server containing the user\u2019s profile and home drive. Store the returned session object in the <b>$psSession<\/b> variable, as shown here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">$psSession = New-PSSession -ComputerName HyperV -Credential nwtraders\\administrator <\/font><\/span><\/p>\n<p class=\"MsoNormal\">To run a command on the remote server, use the <b>Invoke-Command<\/b> cmdlet and specify the session to use. The session will be the session that was stored in the <b>$psSession<\/b> variable. The command to execute queries Active Directory for a specific user (HSG Testuser, in this example). It then returns the user\u2019s <b>homedirectory<\/b> and <b>profilepath<\/b>, and stores these values in a couple of variables. On my Windows Server 2008 R2 server, when connecting using a Windows 7 client, the user\u2019s profile path does not exactly match up with what is stored on the file server. The folder has a .V2 extension after the user name. To account for that, I append<b>.V2<\/b> to the end of the user\u2019s profile path. This is shown here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">Invoke-Command -Session $PSSession -ScriptBlock {<br \/><span>&nbsp; <\/span>$HD=$PD=$null<br \/><span>&nbsp; <\/span>$Filter = &#8220;(&amp;(ObjectCategory=user)(Name=HSG Testuser))&#8221;<br \/><span>&nbsp; <\/span>$Searcher = [adsiSearcher]($Filter)<br \/><span>&nbsp; <\/span>$Searcher.Findall() | <br \/><span>&nbsp;&nbsp;&nbsp; <\/span>ForEach-Object { <br \/><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>$HD = $_.properties.homedirectory <br \/><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>$PD = $_.properties.profilepath<br \/><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>$PD = &#8220;$PD.V2&#8221;<br \/><span>&nbsp;&nbsp; <\/span>} #end foreach-object<br \/>} #end scriptblock<\/font><\/span><\/p>\n<p class=\"MsoNormal\">Next the <b>takeown<\/b> utility is used to take ownership of the folders, and to recurse through the subfolders and to take ownership of all the folders. The <b>takeown<\/b> utility is a standard utility included with the operating system. To execute the command on the remote server, use the <b>Invoke-Command<\/b> cmdlet to run the command in the remote session. In the <b>scriptblock<\/b>, use the <b>Invoke-Expression<\/b> cmdlet to execute the <b>takeown<\/b> command. The <b>\/r<\/b> switch tells the command to recurse through subfolders. The <b>\/d<\/b> switch specifies the default answer to prompts when the user does not have the \u201clist folder\u201d permission, which happens when taking ownership of subfolders. A \u201cy\u201d means yes, go ahead and take ownership of the folder. The <b>takeown<\/b> commands are shown here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">&#8220;Taking ownership of $hd&#8221;<br \/><span>&nbsp; <\/span>Invoke-Command -Session $PSSession -ScriptBlock `<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>{ Invoke-Expression &#8220;takeown \/f $HD \/r \/d y&#8221; } <br \/>&#8220;Taking ownership of $pd&#8221;<br \/><span>&nbsp; <\/span>Invoke-Command -Session $PSSession -ScriptBlock `<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>{ Invoke-Expression &#8220;takeown \/f $PD \/r \/d y&#8221; }<\/font><\/span><\/p>\n<p class=\"MsoNormal\">After the <b>takeown<\/b> command has run and taken ownership of the folders, the <b>icacls<\/b> utility is used to grant administrators full control of the folders. The \u201cF\u201d in the command grants administrators full control. The <b>\/t<\/b> parameter for <b>icacls<\/b> tells the command to process all matching files and directories below the specified directory. The two <b>icacls<\/b> commands are shown here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">&#8220;Adding Administrator Rights to $hd&#8221;<br \/><span>&nbsp; <\/span>Invoke-Command -Session $PSSession -ScriptBlock `<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>{ Invoke-Expression &#8220;icacls $HD \/grant administrators:F \/t&#8221; }<br \/>&#8220;Adding Administrator Rights to $PD&#8221;<br \/><span>&nbsp; <\/span>Invoke-Command -Session $PSSession -ScriptBlock `<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>{ Invoke-Expression &#8220;icacls $PD \/grant administrators:F \/t&#8221; }<\/font><\/span><\/p>\n<p class=\"MsoNormal\">After the <b>takeown<\/b> and the <b>icacls<\/b> utilities have been used to grant administrator rights to the folders, the <b>Remove-Item<\/b> cmdlet can be used. The <b>Invoke-Command<\/b> cmdlet is used to execute the <b>Remove-Item<\/b> cmdlet on the remote computer. These two commands are shown here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">&#8220;Removing folder $hd&#8221;<br \/><span>&nbsp; <\/span>Invoke-Command -Session $PSSession -ScriptBlock `<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>{ Invoke-Expression &#8220;Remove-Item -Path $HD -Recurse -Force&#8221; }<br \/>&#8220;Removing Folder $PD&#8221;<br \/><span>&nbsp; <\/span>Invoke-Command -Session $PSSession -ScriptBlock `<br \/><span>&nbsp;&nbsp;&nbsp; <\/span>{ Invoke-Expression &#8220;RD $PD -Recurse -Force&#8221; }<\/font><\/span><\/p>\n<p class=\"MsoNormal\">After the folders have been removed, it is time to end the <b>PSSession<\/b> and to release the resources that the <b>PSSession<\/b> was using. The <b>Remove-PSSession<\/b> cmdlet will also close the connection between the local computer and the remote server. The <b>session<\/b> object would still be stored in the <b>$psSession<\/b> variable, unless we remove the variable by using the <b>Remove-Variable<\/b> cmdlet as shown here:<\/p>\n<p class=\"CodeBlock\"><font face=\"Lucida Sans Typewriter\"><span>Remove-PSSession -Session $psSession<br \/>Remove-Variable \u2013name psSession<\/span><\/font><\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\">BE, that is all there is to using Windows PowerShell to delete remote folders. Potpourri Week will continue tomorrow. <\/p>\n<p class=\"MsoNormal\">If you want to know exactly what we will be looking at tomorrow, follow us on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\"><font face=\"Segoe\">Twitter<\/font><\/a> or <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\"><font face=\"Segoe\">Facebook<\/font><\/a>. If you have any questions, send e-mail to us at <a href=\"mailto:scripter@microsoft.com\" target=\"_blank\"><font face=\"Segoe\">scripter@microsoft.com<\/font><\/a> or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\"><font face=\"Segoe\">Official Scripting Guys Forum<\/font><\/a>. See you tomorrow. Until then, peace.<\/p>\n<p class=\"MsoNormal\"><span>&nbsp;<\/span><\/p>\n<p><b><span>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/span><\/b>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey Scripting Guy! Our previous network administrator was a slouch. He did not maintain proper backups, never reviewed event logs, and never cleaned up user folders when he deleted users in Active Directory. This last omission is particularly egregious because it has taken a lot of cleanup work to find and delete the user folders. [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[7,62,89,3,63,20,45],"class_list":["post-50733","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-active-directory","tag-dacls-and-sacls","tag-resource-ownership","tag-scripting-guy","tag-security","tag-user-accounts","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Hey Scripting Guy! Our previous network administrator was a slouch. He did not maintain proper backups, never reviewed event logs, and never cleaned up user folders when he deleted users in Active Directory. This last omission is particularly egregious because it has taken a lot of cleanup work to find and delete the user folders. [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/50733","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=50733"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/50733\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=50733"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=50733"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=50733"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}