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

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?
LVL 1
Jason ParadisIT Operations SpecialistAsked:
Who is Participating?
 
it_saigeConnect With a Mentor DeveloperCommented:
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-
1
 
Jason ParadisIT Operations SpecialistAuthor 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!
0
 
Jason ParadisIT Operations SpecialistAuthor 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.
0
Cloud Class® Course: Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

 
it_saigeDeveloperCommented:
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-
1
 
Jason ParadisIT Operations SpecialistAuthor Commented:
It worked great, thanks! I wish I could re-open this post and give you assisted solution to your second answer.
0
 
it_saigeDeveloperCommented:
No worries.

-saige-
0
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.

All Courses

From novice to tech pro — start learning today.