Hey, Scripting Guy! How Can I Use Windows PowerShell to Determine the Owner of a File?

Hey, Scripting Guy! How Can I Use Windows PowerShell to Determine the Owner of a File?

Rate This
  • Comments 8
Hey, Scripting Guy! Question

Hey, Scripting Guy! Is it possible to determine the owner of a file using Windows PowerShell?
-- GF

SpacerHey, Scripting Guy! AnswerScript Center

Hey, GF. Well, today is April 15th, which, in the US, can mean only one thing: it’s time to celebrate the birthday of Italian mathematician Pietro Antonio Cataldi, best known for discovering the sixth and seventh Mersenne primes. Pietro, who developed the first notation for continued fractions, was born on this day in 1552. Happy birthday, Pietro!

Coincidentally, April 15th is also Tax Day in the US, the last day on which Americans can submit their income tax returns for the previous year. Needless to say, for many Americans April 15th is a very stressful day. For other Americans, however, April 15th isn’t the least bit stressful; that’s because the US has a long history of people who believe that the government has no right to collect income taxes and therefore decide not to pay their taxes. For example, in 1997 actor Wesley Snipes (recently convicted on three counts of failure to pay income tax) reported an income of $19,238,192. Not only did Wesley decline to pay any taxes on that income, he actually demanded a refund of $7,360,755. Interestingly enough, his own lawyers termed his positions on income tax “kooky,” “crazy” and “dead wrong.”

Which, coincidentally enough, are the exact same phrases that were sprinkled throughout the mid-year performance review of the Scripting Guy who writes this column.

Oh, and did we mention that Wesley Snipes was recently convicted on three counts of failure to pay income tax? That’s usually what happens to people who decline to pay their taxes or file a tax return.

As it turns out, the Scripting Guy who writes this column isn’t stressing out today, either; that’s because he submitted his tax return well in advance of today’s deadline. (On Sunday, April 13th, to be exact.) Admittedly, that might sound like he was cutting it a little close. He wasn’t concerned, however, because he knew he could complete his tax return in less than hour; needless to say, it doesn’t take him anywhere near as long to count his money as it takes Wesley Snipes to count his.

And no, that’s not because the Scripting Guy who writes this column is a really fast counter.

Best of all, getting his taxes done early turned out to have multiple benefits for the Scripting Guy who writes this column. For one thing, submitting his tax return helped him avoid going to prison for income tax evasion; that’s usually a plus. For another, filing early also gave him time to figure out how to determine the owner of a file (or folder) using Windows PowerShell.

Although, in all honesty, he didn’t need all that much time to do that, either:

Get-Acl C:\Scripts\Test.txt

Believe it or not, that’s the entire script; all we have to do to determine the owner of a file is call the Get-Acl cmdlet, passing Get-Acl the path to the file in question. In turn, Get-Acl will report back information similar to this:

Directory: Microsoft.PowerShell.Core\FileSystem::C:\Scripts

Path                          Owner                         Access
----                          -----                         ------
Test.txt                      FABRIKAM\kenmyer              BUILTIN\Administrators Allow  FullCo...

Not bad, huh? If all you care about is the name of the owner then pipe the results to the Select-Object cmdlet, like so:

Get-Acl C:\Scripts\Test.txt | Select-Object Owner

That will give you information similar to this:

Owner
-----
FABRIKAM\kenmyer

Or, if you’d like to see the complete security descriptor, pipe the output to the Format-List cmdlet:

Get-Acl C:\Scripts\Test.txt | Format-List
Path   : Microsoft.PowerShell.Core\FileSystem::C:\Scripts\Test.txt
Owner  : FABRIKAM\kenmyer
Group  : FABRIKAM\Domain Users
Access : BUILTIN\Administrators Allow  FullControl
         NT AUTHORITY\SYSTEM Allow  FullControl
         FABRIKAM\kenmyer Allow  FullControl
         BUILTIN\Users Allow  ReadAndExecute, Synchronize
Audit  :
Sddl   : O:S-1-5-21-1454471165-1004336348-1606980848-8183G:DUD:AI(A;ID;FA;;;BA)(A;ID;FA;;;SY)
         (A;ID;FA;;;S-1-5-21-1454471165-1004336348-1606980848-8183)(A;ID;0x1200a9;;;BU)

If we had to guess, we’d guess that Wesley Snipes didn’t mean to ignore the April 15th deadline for filing his tax return. He probably just got caught up in the fun and excitement of working with file ownership scripts, and forgot all about paying his taxes.

For example, suppose Wesley wanted to get a list of owners for all the files in the folder C:\Scripts. That’s no problem; after all, the Get-Acl cmdlet does accept wildcard characters:

Get-Acl C:\Scripts\*.*
    Directory: Microsoft.PowerShell.Core\FileSystem::C:\Scripts

Path                          Owner                         Access
----                          -----                         ------
Example.txt                   FABRIKAM\kenmyer              BUILTIN\Administrators Allow  FullCo...
Test.txt                      FABRIKAM\pilarackerman        BUILTIN\Administrators Allow  FullCo...
Trial.txt                     FABRIKAM\kenmyer              BUILTIN\Administrators Allow  FullCo...

Pretty cool, huh? Of course, while Get-Acl does accept wildcard characters, what it doesn’t accept is some sort of –recurse parameter that would enable you to retrieve the owners of all the files located in any subfolders of C:\Scripts. But that’s OK, too; after all, the Get-ChildItem cmdlet does accept the –recurse parameter. That means we can retrieve the file owners for all the files in C:\Scripts and its subfolders by using this command:

Get-ChildItem C:\Scripts -recurse | ForEach-Object {Get-Acl $_.FullName}

There’s nothing particularly complicated about that command, either: we simply use Get-ChildItem and the –recurse parameter to retrieve the collection of files found in C:\Scripts and its subfolders, then pipe that collection to the ForEach-Object cmdlet. In turn, we ask ForEach-Object to run the Get-Acl cmdlet against each and every file in that collection, using the value of the FullName property as Get-Acl’s file path parameter.

Is that going to work? Hey, come on: have you ever known the Scripting Guys to do something that didn’t work?

Well, OK. But the command we showed you will work. Promise.

Who would have guessed that file ownership scripting could be so much fun, eh? In fact, like Wesley Snipes, we’re having such a good time today we thought we’d try one more script. It is pretty cool that you can determine the owner of a file by running a simple little Windows PowerShell script. But you know what would be really cool? It would be really cool if you could take ownership of a file by running a simple little Windows PowerShell script. You know, maybe a script like this one:

$objUser = New-Object System.Security.Principal.NTAccount("fabrikam", "kenmyer")
$objFile = Get-Acl C:\Scripts\Test.txt
$objFile.SetOwner($objUser)
Set-Acl -aclobject $objFile -path C:\Scripts\Test.txt

Much like the Scripting Guy who writes this column’s income for the year 2007, there’s really not much to this script. In line 1 we use the New-Object cmdlet to create an instance of the System.Security.Principal.NTAccount class, a .NET Framework class used to represent a user account. When creating an instance of this class we need to pass two parameters: the name of our domain (fabrikam) and the name of our user account (kenmyer).

Note. That’s a good question, and as far as we know the answer is this: assuming you want to stay out of jail then, yes, you do have to pay income tax in the US. As for your other question, the answer is no: although you can take ownership of a file using Windows PowerShell, we don’t believe that you can give ownership of a file to someone else. To transfer ownership to another user you’ll need to use the Windows Resource Kit utility Subinacl.exe.

As far as we know, anyway.

After we create an instance of the NTAccount class we use the Get-Acl cmdlet to retrieve the security descriptor from the file C:\Scripts\Test.txt; that’s what we do here:

$objFile = Get-Acl C:\Scripts\Test.txt

Once we have the security descriptor we can use the SetOwner method to assign ourselves ownership of the file:

$objFile.SetOwner($objUser)

Well, sort of. What the SetOwner method does is assign ownership to the virtual copy of the security descriptor that we retrieved using Get-Acl. To take ownership of the actual file itself we need to use the following Set-Acl command:

Set-Acl -aclobject $objFile -path C:\Scripts\Test.txt

That should give you ownership of the file.

Give these scripts a try, GF; with any luck they should help you with your management of files and file owners. As for the Scripting Guy who writes this column, he’s going to take the rest of the day off; after all, it is Pietro Antonio Cataldi’s birthday, you know.

Note. Why isn’t Pietro’s birthday a national holiday in the US? Beats us; after all, the man did hold the record for the largest known prime number for 184 years, until Leonhard Euler came along in 1772 and discovered that 231 - 1 was the eighth Mersenne prime. The largest known Mersenne prime number as of this writing is 232,582,657−1, which – by yet another amazing coincidence – is also the amount of money the Scripting Guy who writes this column requested as an income tax refund for the year 2007. We’ll let you know how that goes.

Leave a Comment
  • Please add 4 and 2 and type the answer here:
  • Post
  • Does this same approach work for granting ownership to a group?

  • Take a common case for sysadmin - user leaves, but you can't delete his/her home folder, even when using an elevated command prompt on the server hosting the home folder volume. Usually a permissions or long file/pathname problem. Trying to get the ACLs with:

    Get-ChildItem E:\{problem folder} -recurse | ForEach-Object {Get-Acl $_.FullName} | Format-List

    will fail, if you don't have permission to read the ACL of one or more of the child objects - you will get red lines starting:

    Get-Acl: Attempted to perform an unauthorized operation.

    You need to get the file/folder name:

    Get-ChildItem E:\{problem folder} -recurse

    by itself should list all the children, even if these files (or folders) are hidden system files (i.e. have hs attributes set - which is often the case when you hit a problem deleting a folder).

    Then, if you try running the script as above on one of the problem files, the Get-Acl line will throw a similar error. So back to Windows Explorer (view hidden & system files; properties > security - take ownership, close; reopen properties, give yourself permissions, then delete).

  • Some things still better in the old fashioned command prompt! On Server 2003 and later:

    takeown /F "{problem folder}\*" /R

    will give you ownership quickly!

  • @Nathan there is a set-acl Windows PowerShell cmdlet

    @WestNab I agree, I love using the takeown command. It works well. I have described using the tool in other Hey Scripting Guy blog articles. In fact, I wrote about the exact scenario you describe.

  • ScriptingGuy1 you are hilarious, I'm sad I just now found your blog posts!

  • I am wondering if you know a way to set remote file ownership with Powershell. I didn't find a way to do it, as you can see in my last blog post (www.happysysadm.com/.../how-to-remotely-modify-windows-acl.html) but I might very well have missed something... I hope you can help.

    Anyways your blog rocks!!!

  • @Carlo:

    # set the owner on a file on a remote system.

    $acl=get-acl \\SYSTEM01\test\test.log

    $owner=[System.Security.Principal.NTAccount]'MYDOMIAN\user01'

    $acl.SetOwner($owner)

    set-acl -Path \\omega2\test\test.log -AclObject $acl

  • @jrv

    Thanks for the code. Anyway it doesn't work on my system, probably because the user I want to declare as owner of the remote file is a remote local user, not a domain user.

    When I run the code:

    $full_username = "$remote_hostname" + "\" + "$remote_username"

    $owner=[System.Security.Principal.NTAccount]$full_username

    $acl.SetOwner($owner)

    set-acl -Path $path -AclObject $acl

    I get the follwoing translation error:

    Exception calling "SetOwner" with "1" argument(s): "Some or all identity references could not be translated."

    I am pretty sure the problem is due to the Powershell trying to resolve the SID for $remote_username locally and not remotely. Am I wrong?

    Any suggestion?

Page 1 of 1 (8 items)