Jump to content

User Profile Folders


Recommended Posts

In a perfect world, I'd know how to do something really clever - like write a plugin that will go out and identify User Profiles, where their folders live, and the size of those folders.

But, this world is far from perfect...and I'm probably equally as far from clever.

So, I've been working on something that I'd hoped would be a bit quicker, that could get me the data in some capacity, so that later - when I get the time - I could revisit it, retool it, and get it into a more robust/universal state of functionality.

First thought that came to mind: "Powershell, Invoke-Command, authenticating as {User}'s".  This is made somewhat easier by the fact that all of the PC's/Users I'm currently needing this data from are Windows 7, without Folder Redirection.  So, after a slew of failed attempts to get this working on just ONE PC, I set up a Group Policy to ensure that WinRM is running, PSRemoting/WSManCredSSP are Enabled, and set the Allowed IP's to either of the Domain Controllers.

I can't honestly say whether or not that made a difference.

The only difference I've been able to see, so far, has been when I run one command at a time.  Somewhat hard to explain, so I'll try my best:

The following is the "script", at the end of yesterday:

# Ultra-Secure method of Credential-Handling: CSV
# CSV Headers = Location, UserName (w/o domain), Password
$credList = Import-Csv "C:\Users\Public\UsersList.csv"

# Gather a list of all PC's from AD
$PCs = Get-ADComputer -Filter 'operatingsystem -notlike "*server*"'

# Array to store Offline PCs
$offlinePCs = @()

# Array to store Objects with the Gathered Data
$pcReport = @()

ForEach ($pc in $PCs.Name) {
  If (Test-Connection $pc -Count 1 -Quiet) {
    $users = $credList.User
    
    $rootFolders = Get-ChildItem "\\$($pc)\C$\Users" | Where-Object {$_.PSIsContainer -and ($_.Name -in $users)}
    
    ForEach ($root in $rootFolders) {
      $fUser = $credList | Where-Object {$_.User -eq "$($root.Name)"}
      
      $u = "{DOMAIN}\$($fUser.User)"
      $p = "$($fUser.Password)" | ConvertTo-SecureString -AsPlainText -Force
      $c = New-Object System.Management.Automation.PSCredential($u,$p)
      
      $folderInfo = Invoke-Command -ComputerName $pc -Credential $c -ScriptBlock {
        $desktop = (Get-ChildItem -Path ([Environment]::GetFolderPath("Desktop")) -Recurse -Force | Measure-Object -Property Length -Sum).Sum
        $documents = (Get-ChildItem -Path ([Environment]::GetFolderPath("MyDocuments")) -Recurse -Force | Measure-Object -Property Length -Sum).Sum
        $favorites = (Get-ChildItem -Path ([Environment]::GetFolderPath("Favorites")) -Recurese -Force | Measure-Object -Property Length -Sum).Sum
        $music = (Get-ChildItem -Path ([Environment]::GetFolderPath("MyMusic")) -Recurse -Force | Measure-Object -Property Length -Sum).Sum
        $pictures = (Get-ChildItem -Path ([Environment]::GetFolderPath("MyPictures")) -Recurse -Force | Measure-Object -Property Length -Sum).Sum
        $videos = (Get-ChildItem -Path ([Environment]::GetFolderPath("MyVideos")) -Recurse -Force | Measure-Object -Property Length -Sum).Sum
        
        $totalSize = $desktop + $documents + $favorites + $music + $pictures + $videos
        
        $obj = New-Object PSCustomObject
        
        $obj | Add-Member -MemberType NoteProperty -Name "Location" -Value "$($fUser.Location)"
        $obj | Add-Member -MemberType NoteProperty -Name "Computer" -Value $env:COMPUTERNAME
        $obj | Add-Member -MemberType NoteProperty -Name "User" -Value (whoami)
        $obj | Add-Member -MemberType NoteProperty -Name "TotalSize" -Value $totalSize
        $obj | Add-Member -MemberType NoteProperty -Name "Desktop" -Value $desktop
        $obj | Add-Member -MemberType NoteProperty -Name "Documents" -Value $documents
        $obj | Add-Member -MemberType NoteProperty -Name "Favorites" -Value $favorites
        $obj | Add-Member -MemberType NoteProperty -Name "Music" -Value $music
        $obj | Add-Member -MemberType NoteProperty -Name "Pictures" -Value $pictures
        $obj | Add-Member -MemberType NoteProperty -Name "Videos" -Value $videos
        
        $obj
      } -ArgumentList $fUser
      
      $pcReport += $folderInfo
    }
  }
  Else {
    $offlinePCs += $pc
  }
}

This failed continuously, despite the fact that if I broke up the script and ran one command at a time on just one PC - it returned the value.  But, when I tried to put all the values into one object, and return that - PowerShell started throwing up WinRM errors, Access is Denied errors (on folders that it shouldn't even have been looking at), etc.

So, this morning, I figured I'd take advantage of the only approach I'd had any success with.  Rather than one script block on the Remote PC, it invokes each command, separately, and then collects/manages the values in the Session that runs it.

$credList = Import-Csv "C:\Users\Public\UsersList.csv"

$PCs = (Get-ADComputer -Filter 'operatingsystem -notlike "*server*")

$offlinePCs = @()

$pcReport = @()

ForEach ($pc in $PCs.Name) {
  If (Test-Connection "$($pc)" -Count 1 -Quiet) {
    $users = $credList .User

    $rootFolders = Get-ChildItem "\\$($pc)\C$\Users" | Where-Object {$_.PSIsContainer -and ($_.Name -in $users)}

    ForEach ($root in $rootFolders) {
      $fUser = $credList | Where-Object {$_.User -eq "$($root.Name)"}
      
      $u = "{DOMAIN}\$($fUser.User)"
      $p = "$($fUser.Password)" | ConvertTo-SecureString -AsPlainText -Force
      $c = New-Object System.Management.Automation.PSCredential($u,$p)

      $desktop = Invoke-Command -ComputerName $pc -Credential $c -ScriptBlock { (Get-ChildItem -Path ([Environment]::GetFolderPath("Desktop")) -Recurse -Force | Measure-Object -Property Length -Sum).Sum }
      $documents = Invoke-Command -ComputerName $pc -Credential $c -ScriptBlock { (Get-ChildItem -Path ([Environment]::GetFolderPath("MyDocuments")) -Recurse -Force | Measure-Object -Property Length -Sum).Sum }
      $favorites = Invoke-Command -ComputerName $pc -Credential $c -ScriptBlock { (Get-ChildItem -Path ([Environment]::GetFolderPath("Folders")) -Recurse -Force | Measure-Object -Property Length -Sum).Sum }
      $music = Invoke-Command -ComputerName $pc -Credential $c -ScriptBlock { (Get-ChildItem -Path ([Environment]::GetFolderPath("MyMusic")) -Recurse -Force | Measure-Object -Property Length -Sum).Sum }
      $pictures = Invoke-Command -ComputerName $pc -Credential $c -ScriptBlock { (Get-ChildItem -Path ([Environment]::GetFolderPath("MyPictures")) -Recurse -Force | Measure-Object -Property Length -Sum).Sum }
      $videos = Invoke-Command -ComputerName $pc -Credential $c -ScriptBlock { (Get-ChildItem -Path ([Environment]::GetFolderPath("MyVideos")) -Recurse -Force | Measure-Object -Property Length -Sum).Sum }

      $totalSize = $desktop + $documents + $favorites + $music + $pictures + $videos

      $obj = [PSCustomObject]@{
        'Location' = "$($fUser.Location)"
        'Computer' = "$($pc)"
        'User' = "$($pc)"
        'TotalSize' = $totalSize
        'Desktop' = $desktop
        'Documents' = $documents
        'Favorites' = $favorites
        'Music' = $music
        'Pictures' = $pictures
        'Videos' = $videos
      }

      $pcReport += $obj
    }
  }
  Else {
    $offlinePCs += $pc
  }
}

And that's returning nothing.  Except a couple of errors with 'Test-Connection' that say Provider not found.

So, if I run the following - I get a result:

Invoke-Command -ComputerName $pc -Credential $c -ScriptBlock { (Get-ChildItem -Path ([Environment]::GetFolderPath("MyDocuments")) -Recurse -Force | Measure-Object -Property Length -Sum).Sum }

But, for whatever reason, when I loop through, and run multiple commands - I get errors.

I've tried doing it from the Server, using "\\$($PC)\C$\Users" - but access enumeration prevents me from seeing into the User Profile Folders.

I've also tried Mapping a PSDrive, using the User's credentials, but still get 'Access Denied' on the "My Music", "My Pictures", and "My Videos" folders that live inside the "Documents" folder.  (The "Music", "Pictures", and "Videos" folders that are outside of the "Documents" folder do not have issues).

Anyone know of either a) what I'm missing here?  or b) a better approach? Google's not been kind to me, and I think I'm too focused on the forest to see the trees, at the moment.

 

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...