Link to home
Start Free TrialLog in
Avatar of Jason Paradis
Jason ParadisFlag for United States of America

asked on

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?
ASKER CERTIFIED SOLUTION
Avatar of it_saige
it_saige
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Jason Paradis

ASKER

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!
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.
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-
It worked great, thanks! I wish I could re-open this post and give you assisted solution to your second answer.
No worries.

-saige-