modification to the powershell script is needed to get list of folder owners for shared folders

I was wondering if it is possible to  modify the inventory script below to capture the owner value as well. A lot of folders I get "Access Denied" error even though the account that I used to run it is a Domain Admin. I want to capture the owners for those folders that get "Access Denied". FYI. I tried also manually accessing some folders with my Domain Admin account and not only the Full Access is missing but I dont have READ access. I need to document those folders that I don't have access and need to fix. Thank you very much!

# Include only folders from the root path
Get-ChildItem "C:\installs" -Recurse | ?{ $_.PsIsContainer } | %{
  $Path = $_.FullName

  (Get-Acl $Path).Access | Select-Object `
    @{n='Path';e={ $Path }}, IdentityReference, AccessControlType, `
    InheritanceFlags, PropagationFlags, FileSystemRights, IsInherited
} | Export-CSV "Permissions.csv"
creative555Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Randy DownsOWNERCommented:
Maybe you could incorporate this. They create a function that you call.

function Get-FolderOwner {
    param(
        [string] $Path = ".",
        [int] $RecurseDepth = 1
    )

    $RecurseDepth--

    Get-ChildItem $Path -Directory | ForEach-Object {
        # Get-Acl throws terminating errors, so we need to wrap it in
        # a ForEach-Object block; included -ErrorAction Stop out of habit
        try {
            $Owner = $_ | Get-Acl -ErrorAction Stop | select -exp Owner
        }
        catch {
            $Owner = "Error: {0}" -f $_.Exception.Message
        }

        [PSCustomObject] @{
            Path = $_.FullName
            Owner = $Owner
        }

        if ($RecurseDepth -gt 0) {
            Get-FolderOwner -Path $_.FullName -RecurseDepth $RecurseDepth
        }
    }
}

Open in new window


Call Function:
Get-FolderOwner c:\temp -RecurseDepth 3 | Export-Csv C:\temp\FolderOwner.csv

Open in new window

0
creative555Author Commented:
oh thanks.

Where do I put this line to export it to csv?
Get-FolderOwner c:\temp -RecurseDepth 3 | Export-Csv C:\temp\FolderOwner.csv
0
Randy DownsOWNERCommented:
You could run it separately from the other script or just add it to the bottom. Keep in mind that you have to define the function in the script too.
0
ON-DEMAND: 10 Easy Ways to Lose a Password

Learn about the methods that hackers use to lift real, working credentials from even the most security-savvy employees in this on-demand webinar. We cover the importance of multi-factor authentication and how these solutions can better protect your business!

creative555Author Commented:
hm. not sure how do I define the function.....Could you please help.
0
Randy DownsOWNERCommented:
The 1st set of code creates the function = "Get-FolderOwner". It has to be defined before you call it so it's best to list all functions 1st in your script.

Functions may the code easier to read & they are reusable. In this case, "Get-FolderOwner" runs all the code we previously defined.

If you want to run this as stand alone, try the following code. You may want to create the output file ("C:\temp\FolderOwner.csv") 1st

function Get-FolderOwner {
    param(
        [string] $Path = ".",
        [int] $RecurseDepth = 1
    )

    $RecurseDepth--

    Get-ChildItem $Path -Directory | ForEach-Object {
        # Get-Acl throws terminating errors, so we need to wrap it in
        # a ForEach-Object block; included -ErrorAction Stop out of habit
        try {
            $Owner = $_ | Get-Acl -ErrorAction Stop | select -exp Owner
        }
        catch {
            $Owner = "Error: {0}" -f $_.Exception.Message
        }

        [PSCustomObject] @{
            Path = $_.FullName
            Owner = $Owner
        }

        if ($RecurseDepth -gt 0) {
            Get-FolderOwner -Path $_.FullName -RecurseDepth $RecurseDepth
        }
    }
}

Get-FolderOwner c:\temp -RecurseDepth 3 | Export-Csv C:\temp\FolderOwner.csv

Open in new window

0
creative555Author Commented:
oh. Awesome!! I made it work. will it get the folders that my account im running doesn't have access??

Path      Owner
C:\installs\ActiveDirectory      BUILTIN\Administrators
C:\installs\PowerGUI      BUILTIN\Administrators
C:\installs\PowerGUI\ActiveDirectory      BUILTIN\Administrators
C:\installs\PowerGUI\AD-Network Admin PowerPack      BUILTIN\Administrators
C:\installs\PowerGUI\AdvancedReporting      BUILTIN\Administrators
C:\installs\Quest_Quest-One-ActiveRoles---Full-Package-zip_690      BUILTIN\Administrators
0
Randy DownsOWNERCommented:
I don't think you will have trouble listing the owner even if you can't set permissions on the folder. Once you know the owners that you have issue with you can compare their memberships to the account you are using.

If you need to recurse more than 3 levels of directories you can change -RecurseDepth x (where is the number of levels you want to recurse):
0
creative555Author Commented:
I tried to run this script for the folders that i get access denied, and I am not able to get owners for those folders....(:
So, this is useful if I would have rights. But my problem is that I need to document the shares that I have users as owners and get access denied.

maybe you can suggest other option of getting some kind of log into csv that tells me the list of shares that I get access denied? Can we add something to this script below? It actually lists shares that get access denied, but I need to export the error log to the csv so that we can take ownerships for those shares.

Thank you
0
creative555Author Commented:
Is it possible to export the log from this script for shares that get access denied? The problem is that the script for owners get access denied too. I checked the permissions and my account that is Domain Admin doens't even have READ rights on those users folders.

# Include only folders from the root path
Get-ChildItem "C:\installs" -Recurse | ?{ $_.PsIsContainer } | %{
  $Path = $_.FullName

  (Get-Acl $Path).Access | Select-Object `
    @{n='Path';e={ $Path }}, IdentityReference, AccessControlType, `
    InheritanceFlags, PropagationFlags, FileSystemRights, IsInherited
} | Export-CSV "Permissions.csv"
0
Randy DownsOWNERCommented:
The easiest solution would be to run the script with Administrator privileges rather than just Domain Administrators. You will like need Administrator privileges to take ownership anyway.
0
creative555Author Commented:
hm My account is in the Local Administrators group on each computer.

Here is the error that I am getting:

PS C:\scripts> .\GET-NTFSpermissionsvOwner.ps1 
Get-ChildItem : Access to the path 'C:\Installs-TEST\test' is denied. 
At C:\scripts\GET-NTFSpermissionsvOwner.ps1:9 char:5 
+     Get-ChildItem $Path -Directory | ForEach-Object { 
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    + CategoryInfo          : PermissionDenied: (C:\Installs-TEST\test:String) [Get-ChildItem], Unauthor 
   izedAccessException 
    + FullyQualifiedErrorId : DirUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemComma 
   nd 
0
creative555Author Commented:
It does show in the powershell the error. Is it possible to add the command to export this in the log file?

C:\Installs-TEST\test' is denied.
0
Randy DownsOWNERCommented:
Try modifying this code.

Replace the try code {$AuthorizedUsers = Get-Content \\ FileServer\HRShare\UserList.txt -ErrorAction Stop} with

{
Get-FolderOwner c:\temp -RecurseDepth 3 | Export-Csv C:\temp\FolderOwner.csv
}

Open in new window


Likewise you probably don't want a restart so you can eliminate this section:
{
    Restart-Computer localhost
}

Open in new window


Ditto for sending an email.

    Send-MailMessage -From ExpensesBot@MyCompany.Com -To WinAdmin@MyCompany.Com -Subject "HR File Read Failed!" -SmtpServer EXCH01.AD.MyCompany.Com -Body "We failed to read file $FailedItem. The error message was $ErrorMessage"

Open in new window


Probably easiest to comment out sections & lines.

Try
{
    $AuthorizedUsers = Get-Content \\ FileServer\HRShare\UserList.txt -ErrorAction Stop
}
Catch [System.OutOfMemoryException]
{
    Restart-Computer localhost
}
Catch
{
    $ErrorMessage = $_.Exception.Message
    $FailedItem = $_.Exception.ItemName
    Send-MailMessage -From ExpensesBot@MyCompany.Com -To WinAdmin@MyCompany.Com -Subject "HR File Read Failed!" -SmtpServer EXCH01.AD.MyCompany.Com -Body "We failed to read file $FailedItem. The error message was $ErrorMessage"
    Break
}
Finally
{
    $Time=Get-Date
    "This script made a read attempt at $Time" | out-file c:\logs\ExpensesScript.log -append
}

Open in new window

0
Randy DownsOWNERCommented:
Hopefully my changes work for you. Note the function is still defined above this code. You probably want to create this file 1st - c:\logs\ExpensesScript.log

The code has a break so it will stop for the error. You may want to comment that out & see if it will continue.

Try
{
    Get-FolderOwner c:\temp -RecurseDepth 3 | Export-Csv C:\temp\FolderOwner.csv

}
Catch [System.OutOfMemoryException]
{
   # Restart-Computer localhost
}
Catch
{
    $ErrorMessage = $_.Exception.Message
    $FailedItem = $_.Exception.ItemName
    # Send-MailMessage -From ExpensesBot@MyCompany.Com -To WinAdmin@MyCompany.Com -Subject "HR File Read Failed!" -SmtpServer EXCH01.AD.MyCompany.Com -Body "We failed to read file $FailedItem. The error message was $ErrorMessage"
    Break
}
Finally
{
    $Time=Get-Date
    "This script made a read attempt at $Time" | out-file c:\logs\ExpensesScript.log -append
}

Open in new window

0
creative555Author Commented:
oh. Could you please post the entire script. I ran the script that you posted last and that doesn't produce the csv file with owners...

thank you so much!
0
Randy DownsOWNERCommented:
function Get-FolderOwner {
    param(
        [string] $Path = ".",
        [int] $RecurseDepth = 1
    )

    $RecurseDepth--

    Get-ChildItem $Path -Directory | ForEach-Object {
        # Get-Acl throws terminating errors, so we need to wrap it in
        # a ForEach-Object block; included -ErrorAction Stop out of habit
        try {
            $Owner = $_ | Get-Acl -ErrorAction Stop | select -exp Owner
        }
        catch {
            $Owner = "Error: {0}" -f $_.Exception.Message
        }

        [PSCustomObject] @{
            Path = $_.FullName
            Owner = $Owner
        }

        if ($RecurseDepth -gt 0) {
            Get-FolderOwner -Path $_.FullName -RecurseDepth $RecurseDepth
        }
    }
}

Try
{
    Get-FolderOwner c:\temp -RecurseDepth 3 | Export-Csv C:\temp\FolderOwner.csv

}
Catch [System.OutOfMemoryException]
{
   # Restart-Computer localhost
}
Catch
{
    $ErrorMessage = $_.Exception.Message
    $FailedItem = $_.Exception.ItemName
    # Send-MailMessage -From ExpensesBot@MyCompany.Com -To WinAdmin@MyCompany.Com -Subject "HR File Read Failed!" -SmtpServer EXCH01.AD.MyCompany.Com -Body "We failed to read file $FailedItem. The error message was $ErrorMessage"
    Break
}
Finally
{
    $Time=Get-Date
    "This script made a read attempt at $Time" | out-file c:\logs\ExpensesScript.log -append
}

          

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
creative555Author Commented:
Excellent!! This worked perfect. I also was able to get owners for even folders I didn't have access.

Quick question regarding recursion option which is now set to 3.
What would be the option to get owners for "ALL Directories but no files"? I don't really know how many subfolders we have, so I would like to capture all folders except files. Can we put recursion to max so it gets all children? What would be a number?
0
Randy DownsOWNERCommented:
You could just set the recursion to a ridiculously high number like 100. Surely that will be enough for any folder & the script quits after the subfolders are exhausted.

Getting subdirectories is a little trickier.

Get-ChildItem -Recurse | ?{ $_.PSIsContainer }

Open in new window


Maybe rewriting this section of the function would do trick:
Get-ChildItem $Path -Directory | ForEach-Object

Open in new window


Perhaps this would work:
Get-ChildItem $Path -Directory | ForEach-Object ?{ $_.PSIsContainer }

Open in new window

0
creative555Author Commented:
oh. is the recursion is not the same as Get-ChildItem ? If i set it to 100 then do I need to modify the script with what you suggested?

If you could please re-post the entire script with the option to get all folders and not files if I need to do more than changing the number to 100

Thank you so much for all your amazing help!!
0
Randy DownsOWNERCommented:
Get-ChildItem returns the subfolders.

You can change the 3 to 100 in the script you tried earlier & that should solve one problem.

I'm not certain the the change for the folders only will work but you can give it a try. I added ?{ $_.PSIsContainer } to the function call.

function Get-FolderOwner {
    param(
        [string] $Path = ".",
        [int] $RecurseDepth = 1
    )

    $RecurseDepth--

    Get-ChildItem $Path -Directory | ForEach-Object ?{ $_.PSIsContainer }{
        # Get-Acl throws terminating errors, so we need to wrap it in
        # a ForEach-Object block; included -ErrorAction Stop out of habit
        try {
            $Owner = $_ | Get-Acl -ErrorAction Stop | select -exp Owner
        }
        catch {
            $Owner = "Error: {0}" -f $_.Exception.Message
        }

        [PSCustomObject] @{
            Path = $_.FullName
            Owner = $Owner
        }

        if ($RecurseDepth -gt 0) {
            Get-FolderOwner -Path $_.FullName -RecurseDepth $RecurseDepth
        }
    }
}

Try
{
    Get-FolderOwner c:\temp -RecurseDepth 3 | Export-Csv C:\temp\FolderOwner.csv

}
Catch [System.OutOfMemoryException]
{
   # Restart-Computer localhost
}
Catch
{
    $ErrorMessage = $_.Exception.Message
    $FailedItem = $_.Exception.ItemName
    # Send-MailMessage -From ExpensesBot@MyCompany.Com -To WinAdmin@MyCompany.Com -Subject "HR File Read Failed!" -SmtpServer EXCH01.AD.MyCompany.Com -Body "We failed to read file $FailedItem. The error message was $ErrorMessage"
    Break
}
Finally
{
    $Time=Get-Date
    "This script made a read attempt at $Time" | out-file c:\logs\ExpensesScript.log -append
}

          

Open in new window

0
creative555Author Commented:
I only now need to change recurse to 100  in line 32? right?
Try
{
    Get-FolderOwner c:\temp -RecurseDepth 100 | Export-Csv C:\temp\FolderOwner.csv
0
creative555Author Commented:
Actually it works perfect with the previous version of script. I changed the recursion from 3 to 5 and it gives me exactly what I need. Also it identified the directory that are not accessible by producing a message "Attempted to perform an unathorized operation.

THank you so much for all your hard work.

Wish I could give you more points. You are amazing.
0
creative555Author Commented:
Thank you so much for all your help! You are a true expert!
0
Randy DownsOWNERCommented:
Thanks. Next time we can split questions into multiple parts if you want to divvy out more points.
0
creative555Author Commented:
Yes. Sounds good!! Will be more than happy to do this since you are providing such a phenomenal service! Thank you again. Script is working perfect and I got amazing reports!

I am opening another thread now to get a script to ping servers and get their IPs with the server name into the csv file. Here is the link
http://www.experts-exchange.com/questions/28698035/Script-is-needed-to-ping-the-servers-by-name-and-output-the-server-names-with-their-IPs-into-csv.html
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Powershell

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.