6 Replies - 1866 Views - Last Post: 07 November 2016 - 11:38 AM Rate Topic: -----

#1 Dreamfall   User is offline

  • D.I.C Head

Reputation: 2
  • View blog
  • Posts: 137
  • Joined: 26-January 15

Count files in the directory and subfolders of system ?

Posted 05 November 2016 - 11:37 AM

Hi guys, I can get the size of the system folders with subfolders, but can not get the full number of files of the scanned system folder, with the classic final error "System.UnauthorizedAccessException"....

Try
            Dim Dir_Info As DirectoryInfo = New DirectoryInfo("C:\Users")
            Dim Folder_Info As DirectoryInfo
            Dim Total_Size As Double

            For Each Folder_Info In Dir_Info.GetDirectories()
                Total_Size += GetFolderSize(Folder_Info.FullName, True)
                Label1.Text = Format_Size(Total_Size.ToString)
            Next

            Dim Files_Count As Integer = 0
            For Each File As String In Directory.EnumerateFiles(Dir_Info.FullName, "*", SearchOption.AllDirectories)
                Files_Count += 1
                Label2.Text = Files_Count
            Next
        Catch ex As Exception
            MsgBox(ex.Message)
            Exit Try
        End Try



I hope to resolve or find any solution for the reading of the number of files in the system folders....Thankss

This post has been edited by Dreamfall: 05 November 2016 - 11:40 AM


Is This A Good Question/Topic? 0
  • +

Replies To: Count files in the directory and subfolders of system ?

#2 IronRazer   User is offline

  • Custom Control Freak
  • member icon

Reputation: 1498
  • View blog
  • Posts: 3,796
  • Joined: 01-February 13

Re: Count files in the directory and subfolders of system ?

Posted 06 November 2016 - 09:49 AM

There are going to be system folders that you are just not going to be able to access even if your app is ran with administrator privileges. It would be a BIG security risk if any app that was ran with admin privileges could access these files and folders.

About the closest you are going to get to counting all the files that are in the base folder and all the sub folders within it is to run your app with admin privileges and use a recursive method with some error handling so that you can ignore the folders that you do not have access to even with admin privileges.

If you run the app without admin privileges it will not give you the same file count as it will when it is run with admin privileges. However, as i said already, even with admin privileges, it will still not be able to access all the system folders/files so, even then you will not get the real count.

Example of the difference of file counts for the example below with my testing:
35918 files found without admin privileges
36722 files found with admin privileges

Here is a simple example you can try in a new form project with 1 Button and 1 Label added to the form.
Public Class Form1
    Private FileCount As Integer = 0

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        'reset the class scoped variables we use to count the files and sub folders
        FileCount = 0

        Label1.Text = "Counting Files..."
        Label1.Refresh() 'this just forces the label to update its text before entering the long running blocking GetFileCount sub.

        'You will want to call the GetFileCount sub inside a Try/Catch because, if the Folder that you pass to it is a protected
        'folder, it will throw an exception that is will not be taken care of in the GetFileCount sub.
        Try
            'Call the recursive GetFileCount sub and pass the Folder path that you want to find a total file count from.
            'The second parameter indicates that the files inside the Folder path have not been counted. See comments in the sub.
            GetFileCount("C:\Users", False)
        Catch ex As Exception
            MessageBox.Show("The base directory is a protected system folder. The files and folders inside it are not accessable.")
        End Try

        Label1.Text = "Files Counted: " & FileCount.ToString
    End Sub


    Private Sub GetFileCount(BaseFolder As String, BaseFolderFilesCounted As Boolean)

        'iterate through just the Top Directories of the Base Folder.
        For Each di As IO.DirectoryInfo In New IO.DirectoryInfo(BaseFolder).GetDirectories
            On Error Resume Next 'as much as i HATE using the ON Error methods, it is the easiest way in this case to catch the Exceptions and stop the app from crashing.

            'if the BaseFolderFilesCounted is False when you call this sub, this will count the files in the base folder and then set it to True
            'so that they are only counted once. If it is True, the files in the base folder will not be counted again.
            If Not BaseFolderFilesCounted Then
                FileCount += IO.Directory.GetFiles(BaseFolder).Length 'add the file count of the base folder to the FileCount
                BaseFolderFilesCounted = True
            End If

            FileCount += IO.Directory.GetFiles(di.FullName).Length 'add the file count of the files in the current sub folder being iterated through to the FileCount

            'call the GetFileCount sub to continue the recursion through the sub folders of the current sub folder. The second parameter is True because,
            'if it made it to here, the base folder`s files have already been counted.
            GetFileCount(di.FullName, True)
        Next
    End Sub

End Class



As a side note, calling the GetFileCount sub will block the app from responding until the recursive sub has finished. This may be a few seconds or a few minutes depending on the directory you pass to the sub and other things like the speed of your processor and weather or not another process is busy and tying up the processor.

So, you may want to work out a different method, so that you can do this in a separate background thread rather than in the UI thread so that your app stays responsive while it is counting the files.

EDIT: I threw together an example that uses a separate Background thread to count the files.

This can be tested in a form with 1 Button and 1 Label added to the form.
Imports System.Threading
Imports System.IO

Public Class Form1
    Private Worker As Thread = Nothing
    Private FileCount As Integer = 0

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        Dim TheBaseFolder As String = "C:\Users"

        If Worker Is Nothing OrElse Not Worker.IsAlive Then 'make sure the WorkerThread is not already running before starting it
            Try
                If IsAccessableFolder(TheBaseFolder) Then 'make sure the base folder is not a protected system folder before starting the thread.

                    FileCount = 0 'reset the class scoped FileCount back to 0
                    Worker = New Thread(AddressOf WorkerThread) 'create a new thread
                    Worker.IsBackground = True 'tell the thread to run in the background

                    'being you can only pass a single Object type to the thread when it is started, and we want to pass 2 different types of arguments to it,
                    'a String and a Boolean, we need to create an Object type array that contains both arguments and pass that array to the thread.
                    Dim TheArguments() As Object = {TheBaseFolder, False}
                    Worker.Start(TheArguments)
                Else
                    MessageBox.Show("The base folder is a protected system folder and can not be accessed.")
                End If
            Catch ex As Exception
                MessageBox.Show(ex.ToString)
            End Try
        End If
    End Sub

    Private Function IsAccessableFolder(FolderPath As String) As Boolean
        Dim safe As Boolean = True
        Try
            Dim di() As DirectoryInfo = New DirectoryInfo(FolderPath).GetDirectories 'if this throws an exception, then the folder is not accessable.
        Catch ex As Exception
            safe = False
        End Try
        Return safe
    End Function

    Private Sub WorkerThread(StartArgs As Object)
        Dim args() As Object = CType(StartArgs, Object()) 'cast the StartArgs object back to an array of object types
        Dim BaseFolder As String = args(0).ToString 'convert the 1st array object to a String type
        Dim BaseFolderFilesCounted As Boolean = CBool(args(1)) 'convert the 2nd array object to a Boolean type

        'iterate through just the Top Directories of the Base Folder.
        For Each di As DirectoryInfo In New DirectoryInfo(BaseFolder).GetDirectories
            On Error Resume Next 'as much as i HATE using the ON Error methods, it is the easiest way in this case to catch the Exceptions and stop the app from crashing.

            'if the BaseFolderFilesCounted is False when you call this sub, this will count the files in the base folder and then set it to True
            'so that they are only counted once. If it is True, the files in the base folder will not be counted again.
            If Not BaseFolderFilesCounted Then
                FileCount += Directory.GetFiles(BaseFolder).Length 'add the file count of the base folder to the FileCount
                BaseFolderFilesCounted = True
            End If

            FileCount += IO.Directory.GetFiles(di.FullName).Length 'add the file count of the files in the current sub folder being iterated through to the FileCount

            UpdateFileCount() 'call the UpdateFileCount sub on the UI thread from this thread

            'call the GetFileCount sub to continue the recursion through the sub folders of the current sub folder. The second parameter is True because,
            'if it made it to here, the base folder`s files have already been counted. Again, we need to pass the 2 arguments as an Object array.
            WorkerThread(New Object() {di.FullName, True})
        Next
    End Sub

    'see these 2 links for information on making safe calls to controls across threads
    'http://www.vbforums.com/showthread.php?498387-Accessing-Controls-from-Worker-Threads
    'https://msdn.microsoft.com/en-us/library/ms171728%28v=vs.110%29.aspx

    Private Sub UpdateFileCount()
        If Label1.InvokeRequired Then
            Label1.Invoke(New MethodInvoker(AddressOf UpdateFileCount))
        Else
            Label1.Text = FileCount.ToString
        End If
    End Sub
End Class


Was This Post Helpful? 1
  • +
  • -

#3 Dreamfall   User is offline

  • D.I.C Head

Reputation: 2
  • View blog
  • Posts: 137
  • Joined: 26-January 15

Re: Count files in the directory and subfolders of system ?

Posted 06 November 2016 - 03:18 PM

Hey Razer Thanks, as always you find a solution to all... :smile2:/>/>/>/>/>/>
Well I have solved this way fast, but the count of files and the size of the scanned folder has a marked difference compared to the properties of windows.. :sad3:/>/>/>/>/>/>

Public WithEvents Start_Scann As New BackgroundWorker

    Private Sub Button12_Click(sender As Object, e As EventArgs) Handles Button12.Click
        Console.Beep()
        'Me.Start_Scann.WorkerSupportsCancellation = True
        If Not Start_Scann.IsBusy Then Start_Scann.RunWorkerAsync()
    End Sub

    Private Sub Start_Scann_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles Start_Scann.DoWork
        Control.CheckForIllegalCrossThreadCalls = False
        Dim Dir_Info As DirectoryInfo = New DirectoryInfo(TextBox5.Text)
        'Dim SubFolder_Info As DirectoryInfo
        Dim Size_Info As Double = 0
        Try
            For Each SubFolder_Info In Dir_Info.GetDirectories()
                Size_Info += GetFolderSize(SubFolder_Info.FullName, True)
                Label1.Text = Format_Size(Size_Info)
            Next
            GetFileCount(Dir_Info.FullName, False)
        Catch ex As Exception
            Exit Try
        End Try
    End Sub

    Function GetFolderSize(ByVal DirPath As String, Optional IncludeSubFolders As Boolean = True) As Long
        Dim Size_Info As Long
        Dim File_Info As FileInfo
        Dim Dir_Info As DirectoryInfo = New DirectoryInfo(DirPath)
        Dim SubFolder_Info As DirectoryInfo
        Try
            For Each File_Info In Dir_Info.GetFiles()
                Size_Info += File_Info.Length
            Next
            If (IncludeSubFolders) = True Then
                For Each SubFolder_Info In Dir_Info.GetDirectories()
                    Size_Info += GetFolderSize(SubFolder_Info.FullName)
                Next
            End If
        Catch Ex As Exception
            Return Size_Info
            Exit Function
        End Try
        Return Size_Info
    End Function

    Dim FileCounter As Integer = 0
    Private Sub GetFileCount(BaseFolder As String, BaseFolderFilesCounted As Boolean)
        For Each Files As IO.DirectoryInfo In New IO.DirectoryInfo(BaseFolder).GetDirectories
            On Error Resume Next
            If (BaseFolderFilesCounted) = False Then
                FileCounter += IO.Directory.GetFiles(BaseFolder).Length
                BaseFolderFilesCounted = True
            End If
            FileCounter += IO.Directory.GetFiles(Files.FullName).Length
            GetFileCount(Files.FullName, True)
            Label2.Text = FileCounter.ToString("N0") & " File(s)"
        Next
    End Sub

    Function Format_Size(ByVal Output_Size As Double) As String
        If Output_Size < 0 Then
            Return Output_Size.ToString
        ElseIf Output_Size < 1024 Then
            Return String.Format("{0:N0} B", Output_Size)
        ElseIf Output_Size < 1048576 Then
            Return String.Format("{0:N1} KB", Output_Size / 1024)
        ElseIf Output_Size < 1073741824 Then
            Return String.Format("{0:N2} MB", Output_Size / 1048576)
        Else
            Return String.Format("{0:N2} GB", Output_Size / 1073741824)
        End If
    End Function



Launched in normal mode :

Posted Image

Launched in Admin mode :

Posted Image

And that's what I should get, yet without success.... :huh2:/>/>

Posted Image

As you can see a clear difference both in size and in number of Files ... ://> :no:/>
Was This Post Helpful? 0
  • +
  • -

#4 IronRazer   User is offline

  • Custom Control Freak
  • member icon

Reputation: 1498
  • View blog
  • Posts: 3,796
  • Joined: 01-February 13

Re: Count files in the directory and subfolders of system ?

Posted 06 November 2016 - 04:04 PM

Have you tried not counting the hidden files and folders? I am not sure if the folder properties include them or not but, that could be the reason you get more in your app than is shown in the folder`s properties.

Just as an example, you can use the Attributes property of a DirectoryInfo or a FileInfo as you are iterating through the folders and files to check if they are Hidden folders or files.
        'di is a DirectoryInfo of the current directory that you are iterating through
        If Not (di.Attributes And IO.FileAttributes.Hidden) = IO.FileAttributes.Hidden Then
            FolderCount += 1
        End If

        'fi is a FileInfo of the files you are iterating through
        If Not (fi.Attributes And IO.FileAttributes.Hidden) = IO.FileAttributes.Hidden Then
            FileCount += 1
        End If


Was This Post Helpful? 0
  • +
  • -

#5 IronRazer   User is offline

  • Custom Control Freak
  • member icon

Reputation: 1498
  • View blog
  • Posts: 3,796
  • Joined: 01-February 13

Re: Count files in the directory and subfolders of system ?

Posted 06 November 2016 - 05:00 PM

Hmmm... well i messed around with it a little but, i am not sure as though eliminating Hidden and or System files and folders is going to help. It reports to few or to many whichever way i seem to arrange it. Although, as i said before, it could be because there are files and folders that you are just not going to be able to access and count. The Properties window is part of the system and is more than likely able to access those files and folders.

If i come across a solution at some point, i will let you know. It may require digging deeper into the system than managed .Net methods can do. 8)
Was This Post Helpful? 1
  • +
  • -

#6 Dreamfall   User is offline

  • D.I.C Head

Reputation: 2
  • View blog
  • Posts: 137
  • Joined: 26-January 15

Re: Count files in the directory and subfolders of system ?

Posted 07 November 2016 - 03:07 AM

Nasty Cooow, I'm messed up, write code for data about the number of files, number sub/folders and folders size, it is a snap, but control of the system data folders is a real headache. :/
Was This Post Helpful? 0
  • +
  • -

#7 Dreamfall   User is offline

  • D.I.C Head

Reputation: 2
  • View blog
  • Posts: 137
  • Joined: 26-January 15

Re: Count files in the directory and subfolders of system ?

Posted 07 November 2016 - 11:38 AM

Hi Razer actually is as you say, you always right about everything.:-)
I have tested and scanned the size of the system folders and not, and I arrived at this result, adding the attributes for files and directories, giving a false value when scanning, with the result of the same size windows.

Function GetFolderSize(ByVal DirPath As String, Optional IncludeSubFolders As Boolean = True) As Long
        Dim Size_Info As Long
        Dim File_Info As FileInfo
        Dim Dir_Info As DirectoryInfo = New DirectoryInfo(DirPath)
        Dim SubFolder_Info As DirectoryInfo
        Size_Info = 0
        Try
            For Each File_Info In Dir_Info.GetFiles()
                'Protected System/Hidden Files
                If ((File_Info.Attributes And IO.FileAttributes.System) = IO.FileAttributes.System) = False Then
                    Size_Info += File_Info.Length
                ElseIf ((File_Info.Attributes And IO.FileAttributes.Hidden) = IO.FileAttributes.Hidden) = False Then
                    Size_Info += File_Info.Length
                End If
            Next
            If (IncludeSubFolders) = True Then
                For Each SubFolder_Info In Dir_Info.GetDirectories()
                    'Protected System/Hidden Dir
                    If ((SubFolder_Info.Attributes And IO.FileAttributes.System) = IO.FileAttributes.System) = False Then
                        Size_Info += GetFolderSize(SubFolder_Info.FullName)
                    ElseIf ((SubFolder_Info.Attributes And IO.FileAttributes.Hidden) = IO.FileAttributes.Hidden) = False Then
                        Size_Info += GetFolderSize(SubFolder_Info.FullName)
                   End If
                Next
            End If
        Catch Ex As Exception
            Return Size_Info
            Exit Function
        End Try
        Return Size_Info
    End Function



Posted Image

I was unable to fix the count of files. :-(

Razer wanted to ask you one last favor logically when you have time, you could enter your first example on the counting of the total of files even the total folders size, always in a separate background thread, I can not see in way correct the scroll of the total size, as it happens during scanning the scroll so increasing the count of files.
Thankss.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1