Preventing access/bypassing junction folders when calculating folder sizes in userprofile folders

Jason Paradis
Jason Paradis used Ask the Experts™
on
I am attempting to write a program that displays the full folder sizes of a specific group of folders. Right now it's only set up for the userprofile "Documents" folder.

Here is my code:

Imports System
Imports System.IO

Public Class BackupperForm
    Dim TotalSize As Long = 0
    Public Function GetDirSize(RootFolder As String) As Long
        Dim FolderInfo = New IO.DirectoryInfo(RootFolder)
        For Each File In FolderInfo.GetFiles : TotalSize += File.Length
        Next
        For Each SubFolderInfo In FolderInfo.GetDirectories : GetDirSize(SubFolderInfo.FullName)
        Next
        Return TotalSize
    End Function

    Private Sub calButton_Click(sender As Object, e As EventArgs) Handles calButton.Click
        TotalSize = 0 'Reset the counter
        Dim TheSize As Long = GetDirSize(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) & "\Documents\")
        MsgBox(FormatNumber(TheSize, 0) & " Bytes" & vbCr & _
               FormatNumber(TheSize / 1024, 1) & " Kilobytes" & vbCr & _
               FormatNumber(TheSize / 1024 / 1024, 1) & " Megabytes" & vbCr & _
               FormatNumber(TheSize / 1024 / 1024 / 1024, 1) & " Gigabytes")
    End Sub
End Class

Open in new window


Every time it runs, it obtains the correct directory but when it tries to access the junction folders (My Music, My Pictures, My Videos, etc.) under "Documents" I get an Unauthorized Access error, as I should. Junction folders are not accessible by design. However, I cannot figure out how to bypass those folders when trying to get the size so an exception doesn't get thrown.

Can anyone assist?
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Commented:
Use a Try...Catch, e.g. -
Imports System.IO

Module Module1

    Sub Main()
        Dim TheSize As Long = String.Format("{0}\Documents\", Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)).GetDirectorySize()
        Console.WriteLine(FormatNumber(TheSize, 0) & " Bytes" & vbCr &
               FormatNumber(TheSize / 1024, 1) & " Kilobytes" & vbCr &
               FormatNumber(TheSize / 1024 / 1024, 1) & " Megabytes" & vbCr &
               FormatNumber(TheSize / 1024 / 1024 / 1024, 1) & " Gigabytes")
        Console.ReadLine()
    End Sub
End Module

Module Extensions
    <System.Runtime.CompilerServices.Extension>
    Function GetDirectorySize(folder As String) As Long
        Return New DirectoryInfo(folder).GetDirectorySize().Sum()
    End Function

    <System.Runtime.CompilerServices.Extension>
    Iterator Function GetDirectorySize(folder As DirectoryInfo) As IEnumerable(Of Long)
        For Each [file] In folder.EnumerateFiles
            Try
                Yield [file].Length
            Catch ex As Exception
            End Try
        Next
        For Each [child] In folder.EnumerateDirectories
            Try
                Yield [child].GetDirectorySize().Sum()
            Catch ex As Exception
            End Try
        Next
    End Function
End Module

Open in new window


-saige-
Jason ParadisIT Operations Specialist

Author

Commented:
That worked perfectly. After I added a call in my click event it did exactly what it's supposed to do. Thank you very much!
Jason ParadisIT Operations Specialist

Author

Commented:
I don't mean to open this again because you helped immensely, however I'm having the exact same problem on a different event.

My.Computer.FileSystem.CopyDirectory(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) & "\Documents\", "\\destination\users\" & (Environment.UserName) & "\Documents\", True)
        My.Computer.FileSystem.CopyDirectory(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) & "\Downloads\", "\\destination\users\" & (Environment.UserName) & "\Downloads\", True)
        My.Computer.FileSystem.CopyDirectory(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) & "\My Pictures\", "\\destination\users\" & (Environment.UserName) & "\My Pictures\", True)
        My.Computer.FileSystem.CopyDirectory(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) & "\Contacts\", "\\destination\users\" & (Environment.UserName) & "\Contacts\", True)
        My.Computer.FileSystem.CopyDirectory(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) & "\Desktop\", "\\destination\users\" & (Environment.UserName) & "\Desktop\", True)
        My.Computer.FileSystem.CopyDirectory(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) & "\Favorites\", "\\destination\users\" & (Environment.UserName) & "\Favorites\", True)
        My.Computer.FileSystem.CopyDirectory(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) & "\My Videos\", "\\destination\users\" & (Environment.UserName) & "\My Videos\", True)

Open in new window


When the button is clicked I get an error regarding those junction folders again. I tried creating my own module and module extension to complete failure. Please bear with me as I am a very amateur programmer as you can tell by my code.

I assume a module and module extension need to be created for this event. However, I cannot figure out how to structure the extension code to work with my code above.

I would have created a new question but it seemed futile.

Thank you.
Become a Microsoft Certified Solutions Expert

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

Commented:
Probably the best way to handle this then is to Create your own CopyDirectory extension method which passes the parameters required for the .NET implementation of CopyDirectory you want to use.  Within that method, you would surround the method call with a Try...Catch statement; e.g. -
Imports System.IO

Module Module1

    Sub Main()
        Dim folders = New String() {"Documents", "Downloads", "My Pictures", "Contacts", "Desktop", "Favorites", "My Videos"}
        Dim sourcePath As String = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)
        Dim targetPath As String = String.Format("\\destination\users\{0}", Environment.UserName)
        Dim size As Long = Path.Combine(sourcePath, folders(0)).GetDirectorySize()
        Console.WriteLine("{1} Bytes{0}{2} Kilobytes{0}{3} Megabytes{0}{4} Gigabytes", vbCrLf, FormatNumber(size, 0), FormatNumber(size / 1024, 1), FormatNumber(size / 1024 / 1024, 1), FormatNumber(size / 1024 / 1024 / 1024, 1))
        For Each folder In folders
            If Path.Combine(sourcePath, folder).CopyDirectory(Path.Combine(targetPath, folder), True) Then
                Console.WriteLine("Successfully copied; {0} to; {1}", Path.Combine(sourcePath, folder), Path.Combine(targetPath, folder))
            Else
                Console.WriteLine("Copy failed for; {0} to; {1}", Path.Combine(sourcePath, folder), Path.Combine(targetPath, folder))
            End If
        Next
        Console.ReadLine()
    End Sub
End Module

Module Extensions
    <System.Runtime.CompilerServices.Extension>
    Function CopyDirectory(source As String, target As String, overwrite As Boolean) As Boolean
        Dim result As Boolean = False
        Try
            My.Computer.FileSystem.CopyDirectory(source, target, overwrite)
            result = True
        Catch ex As Exception
            result = False
        End Try
        Return result
    End Function

    <System.Runtime.CompilerServices.Extension>
    Function GetDirectorySize(folder As String) As Long
        Return New DirectoryInfo(folder).GetDirectorySize().Sum()
    End Function

    <System.Runtime.CompilerServices.Extension>
    Iterator Function GetDirectorySize(folder As DirectoryInfo) As IEnumerable(Of Long)
        For Each [file] In folder.EnumerateFiles
            Try
                Yield [file].Length
            Catch ex As Exception
            End Try
        Next
        For Each [child] In folder.EnumerateDirectories
            Try
                Yield [child].GetDirectorySize().Sum()
            Catch ex As Exception
            End Try
        Next
    End Function
End Module

Open in new window


-saige-
Jason ParadisIT Operations Specialist

Author

Commented:
It worked great, thanks! I wish I could re-open this post and give you assisted solution to your second answer.

Commented:
No worries.

-saige-

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial