├── src
├── DiskUsage.snk
├── DiskUsage
│ ├── Images
│ │ ├── App.ico
│ │ ├── App16.png
│ │ ├── App32.png
│ │ ├── App48.pdn
│ │ ├── App48.png
│ │ ├── Drive.bmp
│ │ ├── Files.bmp
│ │ ├── Cancel.bmp
│ │ ├── Refresh.bmp
│ │ ├── ChoosePath.bmp
│ │ ├── FileSearch.gif
│ │ ├── OpenFolder.bmp
│ │ └── OpenFolder2.bmp
│ ├── Enumerations.cs
│ ├── Properties
│ │ ├── PublishProfiles
│ │ │ ├── Framework.pubxml
│ │ │ └── Core.pubxml
│ │ ├── Resources.Designer.cs
│ │ └── Resources.resx
│ ├── Program.cs
│ ├── DiskUsage.csproj
│ ├── NativeMethods.cs
│ ├── ExtendedFileAttributes.cs
│ ├── DirectoryData.cs
│ ├── MainForm.Designer.cs
│ ├── MainForm.cs
│ └── MainForm.resx
├── DiskUsage.ruleset
└── Directory.Build.props
├── Build.cmd
├── .editorconfig
├── .github
└── workflows
│ └── build.yml
├── README.md
├── LICENSE
├── DiskUsage.sln
├── .gitattributes
├── eng
└── build.ps1
└── .gitignore
/src/DiskUsage.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/menees/DiskUsage/HEAD/src/DiskUsage.snk
--------------------------------------------------------------------------------
/src/DiskUsage/Images/App.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/menees/DiskUsage/HEAD/src/DiskUsage/Images/App.ico
--------------------------------------------------------------------------------
/src/DiskUsage/Images/App16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/menees/DiskUsage/HEAD/src/DiskUsage/Images/App16.png
--------------------------------------------------------------------------------
/src/DiskUsage/Images/App32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/menees/DiskUsage/HEAD/src/DiskUsage/Images/App32.png
--------------------------------------------------------------------------------
/src/DiskUsage/Images/App48.pdn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/menees/DiskUsage/HEAD/src/DiskUsage/Images/App48.pdn
--------------------------------------------------------------------------------
/src/DiskUsage/Images/App48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/menees/DiskUsage/HEAD/src/DiskUsage/Images/App48.png
--------------------------------------------------------------------------------
/src/DiskUsage/Images/Drive.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/menees/DiskUsage/HEAD/src/DiskUsage/Images/Drive.bmp
--------------------------------------------------------------------------------
/src/DiskUsage/Images/Files.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/menees/DiskUsage/HEAD/src/DiskUsage/Images/Files.bmp
--------------------------------------------------------------------------------
/src/DiskUsage/Images/Cancel.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/menees/DiskUsage/HEAD/src/DiskUsage/Images/Cancel.bmp
--------------------------------------------------------------------------------
/src/DiskUsage/Images/Refresh.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/menees/DiskUsage/HEAD/src/DiskUsage/Images/Refresh.bmp
--------------------------------------------------------------------------------
/src/DiskUsage/Images/ChoosePath.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/menees/DiskUsage/HEAD/src/DiskUsage/Images/ChoosePath.bmp
--------------------------------------------------------------------------------
/src/DiskUsage/Images/FileSearch.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/menees/DiskUsage/HEAD/src/DiskUsage/Images/FileSearch.gif
--------------------------------------------------------------------------------
/src/DiskUsage/Images/OpenFolder.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/menees/DiskUsage/HEAD/src/DiskUsage/Images/OpenFolder.bmp
--------------------------------------------------------------------------------
/src/DiskUsage/Images/OpenFolder2.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/menees/DiskUsage/HEAD/src/DiskUsage/Images/OpenFolder2.bmp
--------------------------------------------------------------------------------
/Build.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | REM Inspired by https://github.com/dotnet/roslyn/blob/master/Build.cmd
3 | powershell -ExecutionPolicy ByPass -NoProfile -command "& """%~dp0eng\build.ps1""" %*"
--------------------------------------------------------------------------------
/src/DiskUsage/Enumerations.cs:
--------------------------------------------------------------------------------
1 | namespace DiskUsage
2 | {
3 | #region Using Directives
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Diagnostics;
8 | using System.Linq;
9 | using System.Text;
10 |
11 | #endregion
12 |
13 | #region public DirectoryDataType
14 |
15 | public enum DirectoryDataType
16 | {
17 | Unknown = 0,
18 | Directory = 1,
19 | Files = 2,
20 | Error = 3,
21 | }
22 |
23 | #endregion
24 | }
25 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # To learn more about .editorconfig see https://aka.ms/editorconfigdocs
2 | root = true
3 |
4 | # All files
5 | [*]
6 | indent_style = tab
7 |
8 | # IDE0063: Use simple 'using' statement
9 | csharp_prefer_simple_using_statement = false:silent
10 |
11 | # IDE0057: Use range operator
12 | csharp_style_prefer_range_operator = true:silent
13 |
14 | # IDE0066: Convert switch statement to expression
15 | csharp_style_prefer_switch_expression = false:silent
16 |
17 | csharp_using_directive_placement = inside_namespace
--------------------------------------------------------------------------------
/src/DiskUsage/Properties/PublishProfiles/Framework.pubxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | FileSystem
6 | Release
7 | Any CPU
8 | net48
9 | ..\..\artifacts\Framework
10 |
11 |
--------------------------------------------------------------------------------
/src/DiskUsage/Properties/PublishProfiles/Core.pubxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | FileSystem
6 | Release
7 | Any CPU
8 | net6.0-windows
9 | ..\..\artifacts\Core
10 | false
11 |
12 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: windows build
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | jobs:
10 | build:
11 | runs-on: windows-2022
12 |
13 | steps:
14 | - uses: actions/checkout@v4.1.5
15 |
16 | - name: Setup .NET
17 | uses: actions/setup-dotnet@v4.0.0
18 | with:
19 | dotnet-version: 6.0.x
20 |
21 | - name: Build everything
22 | run: |
23 | & .\eng\build.ps1 -build $true
24 |
25 | - name: Test artifact publishing
26 | run: |
27 | & .\eng\build.ps1 -build $false -publish $true
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # Disk Usage
4 |
5 | This program calculates and displays the total space used for a directory, its files, and all of its subdirectories. I wrote it in 2003 because I didn't like any of the free ones I found on the net, and I wasn't about to spend money for a little utility like this. DiskUsage doesn't require an installer, so it's easy to run on any modern Windows system.
6 |
7 | This software is charityware. If you like it and use it, I ask that you donate something to the charity of your choice. I'll never know if you follow this policy, but the good karma from following it will be well worth your investment.
8 |
9 | 
--------------------------------------------------------------------------------
/src/DiskUsage/Program.cs:
--------------------------------------------------------------------------------
1 | namespace DiskUsage
2 | {
3 | #region Using Directives
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 | using Menees.Windows.Forms;
11 |
12 | #endregion
13 |
14 | internal static class Program
15 | {
16 | #region Main Entry Point
17 |
18 | ///
19 | /// The main entry point for the application.
20 | ///
21 | [STAThread]
22 | private static void Main()
23 | {
24 | WindowsUtility.InitializeApplication("Disk Usage", null);
25 |
26 | using (MainForm frmMain = new())
27 | {
28 | Application.Idle += new EventHandler(frmMain.OnIdle);
29 | Application.Run(frmMain);
30 | }
31 | }
32 |
33 | #endregion
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/DiskUsage/DiskUsage.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | true
6 | Images\App.ico
7 | true
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | Designer
19 | ResXFileCodeGenerator
20 | Resources.Designer.cs
21 |
22 |
23 | True
24 | True
25 | Resources.resx
26 |
27 |
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Bill Menees
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/DiskUsage.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29920.165
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DiskUsage", "src\DiskUsage\DiskUsage.csproj", "{8CB2A984-B953-432E-852F-119583A3B5DA}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{51D062F0-37C6-4D52-BF7D-C2A3B09B506A}"
9 | ProjectSection(SolutionItems) = preProject
10 | .editorconfig = .editorconfig
11 | README.md = README.md
12 | EndProjectSection
13 | EndProject
14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Src", "Src", "{8E699365-A7DB-4821-AEBE-DBBAD91AA3C8}"
15 | ProjectSection(SolutionItems) = preProject
16 | src\Directory.Build.props = src\Directory.Build.props
17 | src\DiskUsage.ruleset = src\DiskUsage.ruleset
18 | EndProjectSection
19 | EndProject
20 | Global
21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
22 | Debug|Any CPU = Debug|Any CPU
23 | Release|Any CPU = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
26 | {8CB2A984-B953-432E-852F-119583A3B5DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {8CB2A984-B953-432E-852F-119583A3B5DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {8CB2A984-B953-432E-852F-119583A3B5DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {8CB2A984-B953-432E-852F-119583A3B5DA}.Release|Any CPU.Build.0 = Release|Any CPU
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | GlobalSection(ExtensibilityGlobals) = postSolution
35 | SolutionGuid = {FF3FE384-1672-4CA0-A9EC-736E42C553BE}
36 | EndGlobalSection
37 | EndGlobal
38 |
--------------------------------------------------------------------------------
/src/DiskUsage/NativeMethods.cs:
--------------------------------------------------------------------------------
1 | namespace DiskUsage
2 | {
3 | #region Using Directives
4 |
5 | using System.ComponentModel;
6 | using System.IO;
7 | using System.Runtime.InteropServices;
8 | using System.Security;
9 |
10 | #endregion
11 |
12 | internal static class NativeMethods
13 | {
14 | #region Private Data Members
15 |
16 | // Value from https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfilesize
17 | private const uint INVALID_FILE_SIZE = 0xFFFFFFFF;
18 |
19 | // From winerror.h
20 | private const int NO_ERROR = 0;
21 |
22 | #endregion
23 |
24 | #region Public Methods
25 |
26 | public static long GetCompressedFileSize(string fileName)
27 | {
28 | uint lowSize = GetCompressedFileSize(fileName, out uint highSize);
29 | if (lowSize == INVALID_FILE_SIZE)
30 | {
31 | int error = Marshal.GetLastWin32Error();
32 | if (error != NO_ERROR)
33 | {
34 | throw new Win32Exception(error, $"Unable to get compressed file size for \"{fileName}\".");
35 | }
36 | }
37 |
38 | const int UInt32Bits = 32;
39 | long result = ((long)highSize << UInt32Bits) | lowSize;
40 | return result;
41 | }
42 |
43 | public static uint GetDiskClusterSize(DirectoryInfo directory)
44 | {
45 | DirectoryInfo root = directory.Root;
46 | string rootPath = root.FullName;
47 | if (!rootPath.EndsWith(Path.DirectorySeparatorChar.ToString()))
48 | {
49 | rootPath += Path.DirectorySeparatorChar;
50 | }
51 |
52 | if (!GetDiskFreeSpace(rootPath, out uint sectorsPerCluster, out uint bytesPerSector, out _, out _))
53 | {
54 | int error = Marshal.GetLastWin32Error();
55 | throw new Win32Exception(error, $"Unable to get cluster size for \"{rootPath}\".");
56 | }
57 |
58 | uint result = bytesPerSector * sectorsPerCluster;
59 | return result;
60 | }
61 |
62 | #endregion
63 |
64 | #region Private Methods
65 |
66 | [DllImport("kernel32.dll", SetLastError = true, PreserveSig = true, CharSet = CharSet.Unicode)]
67 | private static extern uint GetCompressedFileSize(
68 | string lpFileName,
69 | out uint lpFileSizeHigh);
70 |
71 | [DllImport("kernel32.dll", SetLastError = true, PreserveSig = true, CharSet = CharSet.Unicode)]
72 | [return: MarshalAs(UnmanagedType.Bool)]
73 | private static extern bool GetDiskFreeSpace(
74 | string lpRootPathName,
75 | out uint lpSectorsPerCluster,
76 | out uint lpBytesPerSector,
77 | out uint lpNumberOfFreeClusters,
78 | out uint lpTotalNumberOfClusters);
79 |
80 | #endregion
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/eng/build.ps1:
--------------------------------------------------------------------------------
1 | param(
2 | [bool] $build = $true,
3 | [string[]] $configurations = @('Debug', 'Release'),
4 | [bool] $publish = $false,
5 | [string] $msBuildVerbosity = 'minimal'
6 | )
7 |
8 | Set-StrictMode -Version Latest
9 | $ErrorActionPreference = "Stop"
10 |
11 | $scriptPath = [IO.Path]::GetDirectoryName($MyInvocation.MyCommand.Definition)
12 | $repoPath = Resolve-Path (Join-Path $scriptPath '..')
13 | $slnPath = Get-ChildItem -Path $repoPath -Filter *.sln
14 | $productName = [IO.Path]::GetFileNameWithoutExtension($slnPath)
15 |
16 | function GetXmlPropertyValue($fileName, $propertyName)
17 | {
18 | $result = Get-Content $fileName |`
19 | Where-Object {$_ -like "*<$propertyName>*$propertyName>*"} |`
20 | ForEach-Object {$_.Replace("<$propertyName>", '').Replace("$propertyName>", '').Trim()}
21 | return $result
22 | }
23 |
24 | if ($build)
25 | {
26 | foreach ($configuration in $configurations)
27 | {
28 | dotnet build $slnPath /p:Configuration=$configuration /v:$msBuildVerbosity /nologo
29 | }
30 | }
31 |
32 | if ($publish)
33 | {
34 | $version = GetXmlPropertyValue "$repoPath\src\Directory.Build.props" 'Version'
35 | $published = $false
36 | if ($version)
37 | {
38 | $artifactsPath = "$repoPath\artifacts"
39 | if (Test-Path $artifactsPath)
40 | {
41 | Remove-Item -Recurse -Force $artifactsPath
42 | }
43 |
44 | $ignore = mkdir $artifactsPath
45 | if ($ignore) { } # For PSUseDeclaredVarsMoreThanAssignments
46 |
47 | foreach ($configuration in $configurations)
48 | {
49 | if ($configuration -like '*Release*')
50 | {
51 | Write-Host "Publishing version $version $configuration profiles to $artifactsPath"
52 | $profiles = @(Get-ChildItem -r "$repoPath\src\**\Properties\PublishProfiles\*.pubxml")
53 | foreach ($profile in $profiles)
54 | {
55 | $profileName = [IO.Path]::GetFileNameWithoutExtension($profile)
56 | Write-Host "Publishing $profileName"
57 |
58 | # The Publish target in "C:\Program Files\dotnet\sdk\3.1.101\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.CrossTargeting.targets"
59 | # throws an exception if the .csproj uses . We have to override that and force a specific instead.
60 | $targetFramework = GetXmlPropertyValue $profile 'TargetFramework'
61 | dotnet publish $slnPath /t:Publish /p:PublishProfile=$profileName /p:TargetFramework=$targetFramework /v:$msBuildVerbosity /nologo /p:Configuration=$configuration
62 |
63 | Remove-Item "$artifactsPath\$profileName\*.pdb"
64 |
65 | Compress-Archive -Path "$artifactsPath\$profileName\*" -DestinationPath "$artifactsPath\$productName-Portable-$version-$profileName.zip"
66 | $published = $true
67 | }
68 | }
69 | }
70 | }
71 |
72 | if ($published)
73 | {
74 | Write-Host "`n`n****** REMEMBER TO ADD A GITHUB RELEASE! ******"
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/DiskUsage.ruleset:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/src/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | en-US
4 | en
5 | Bill Menees
6 | http://www.menees.com
7 | MIT
8 | git
9 | https://github.com/menees/DiskUsage
10 | Off
11 | true
12 | latest
13 | Copyright © 2003-$([System.DateTime]::UtcNow.ToString(`yyyy`)) Bill Menees
14 |
15 |
16 | net48;net6.0-windows
17 |
18 | $(MSBuildThisFileDirectory)
19 | $(RepoSrcFolder)DiskUsage.ruleset
20 | $(RepoSrcFolder)DiskUsage.snk
21 | true
22 | enable
23 | true
24 | false
25 | <_SkipUpgradeNetAnalyzersNuGetWarning>true
26 |
27 |
28 | 3.5.0
29 |
30 |
31 |
32 | DEBUG;TRACE
33 | true
34 |
35 |
36 |
37 | $([System.DateTime]::UtcNow.ToString(`yyyy-MM-dd 00:00:00Z`))
38 |
39 |
40 |
41 | TRACE
42 |
43 |
44 | $([System.DateTime]::UtcNow.ToString(`yyyy-MM-dd HH:mm:ssZ`))
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | all
54 | runtime; build; native; contentfiles; analyzers; buildtransitive
55 |
56 |
57 | all
58 | runtime; build; native; contentfiles; analyzers; buildtransitive
59 |
60 |
61 | all
62 | runtime; build; native; contentfiles; analyzers; buildtransitive
63 |
64 |
65 | all
66 | runtime; build; native; contentfiles; analyzers; buildtransitive
67 |
68 |
69 |
--------------------------------------------------------------------------------
/src/DiskUsage/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace DiskUsage.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DiskUsage.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized resource of type System.Drawing.Bitmap.
65 | ///
66 | internal static System.Drawing.Bitmap Cancel {
67 | get {
68 | object obj = ResourceManager.GetObject("Cancel", resourceCulture);
69 | return ((System.Drawing.Bitmap)(obj));
70 | }
71 | }
72 |
73 | ///
74 | /// Looks up a localized resource of type System.Drawing.Bitmap.
75 | ///
76 | internal static System.Drawing.Bitmap ChoosePath {
77 | get {
78 | object obj = ResourceManager.GetObject("ChoosePath", resourceCulture);
79 | return ((System.Drawing.Bitmap)(obj));
80 | }
81 | }
82 |
83 | ///
84 | /// Looks up a localized resource of type System.Drawing.Bitmap.
85 | ///
86 | internal static System.Drawing.Bitmap Drive {
87 | get {
88 | object obj = ResourceManager.GetObject("Drive", resourceCulture);
89 | return ((System.Drawing.Bitmap)(obj));
90 | }
91 | }
92 |
93 | ///
94 | /// Looks up a localized resource of type System.Drawing.Bitmap.
95 | ///
96 | internal static System.Drawing.Bitmap FileSearch {
97 | get {
98 | object obj = ResourceManager.GetObject("FileSearch", resourceCulture);
99 | return ((System.Drawing.Bitmap)(obj));
100 | }
101 | }
102 |
103 | ///
104 | /// Looks up a localized resource of type System.Drawing.Bitmap.
105 | ///
106 | internal static System.Drawing.Bitmap OpenFolder {
107 | get {
108 | object obj = ResourceManager.GetObject("OpenFolder", resourceCulture);
109 | return ((System.Drawing.Bitmap)(obj));
110 | }
111 | }
112 |
113 | ///
114 | /// Looks up a localized resource of type System.Drawing.Bitmap.
115 | ///
116 | internal static System.Drawing.Bitmap OpenFolder2 {
117 | get {
118 | object obj = ResourceManager.GetObject("OpenFolder2", resourceCulture);
119 | return ((System.Drawing.Bitmap)(obj));
120 | }
121 | }
122 |
123 | ///
124 | /// Looks up a localized resource of type System.Drawing.Bitmap.
125 | ///
126 | internal static System.Drawing.Bitmap Refresh {
127 | get {
128 | object obj = ResourceManager.GetObject("Refresh", resourceCulture);
129 | return ((System.Drawing.Bitmap)(obj));
130 | }
131 | }
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Dd]ebugPublic/
19 | [Rr]elease/
20 | [Rr]eleases/
21 | x64/
22 | x86/
23 | [Aa][Rr][Mm]/
24 | [Aa][Rr][Mm]64/
25 | bld/
26 | [Bb]in/
27 | [Oo]bj/
28 | [Ll]og/
29 |
30 | # Visual Studio (Code) cache/options directory
31 | .vs/
32 | .vscode/
33 | # Uncomment if you have tasks that create the project's static files in wwwroot
34 | #wwwroot/
35 |
36 | # Visual Studio 2017 auto generated files
37 | Generated\ Files/
38 |
39 | # MSTest test Results
40 | [Tt]est[Rr]esult*/
41 | [Bb]uild[Ll]og.*
42 |
43 | # NUNIT
44 | *.VisualState.xml
45 | TestResult.xml
46 |
47 | # Build Results of an ATL Project
48 | [Dd]ebugPS/
49 | [Rr]eleasePS/
50 | dlldata.c
51 |
52 | # Benchmark Results
53 | BenchmarkDotNet.Artifacts/
54 |
55 | # .NET Core
56 | project.lock.json
57 | project.fragment.lock.json
58 | artifacts/
59 |
60 | # StyleCop
61 | StyleCopReport.xml
62 |
63 | # Files built by Visual Studio
64 | *_i.c
65 | *_p.c
66 | *_h.h
67 | *.ilk
68 | *.meta
69 | *.obj
70 | *.iobj
71 | *.pch
72 | *.pdb
73 | *.ipdb
74 | *.pgc
75 | *.pgd
76 | *.rsp
77 | *.sbr
78 | *.tlb
79 | *.tli
80 | *.tlh
81 | *.tmp
82 | *.tmp_proj
83 | *_wpftmp.csproj
84 | *.log
85 | *.vspscc
86 | *.vssscc
87 | .builds
88 | *.pidb
89 | *.svclog
90 | *.scc
91 |
92 | # Chutzpah Test files
93 | _Chutzpah*
94 |
95 | # Visual C++ cache files
96 | ipch/
97 | *.aps
98 | *.ncb
99 | *.opendb
100 | *.opensdf
101 | *.sdf
102 | *.cachefile
103 | *.VC.db
104 | *.VC.VC.opendb
105 |
106 | # Visual Studio profiler
107 | *.psess
108 | *.vsp
109 | *.vspx
110 | *.sap
111 |
112 | # Visual Studio Trace Files
113 | *.e2e
114 |
115 | # TFS 2012 Local Workspace
116 | $tf/
117 |
118 | # Guidance Automation Toolkit
119 | *.gpState
120 |
121 | # ReSharper is a .NET coding add-in
122 | _ReSharper*/
123 | *.[Rr]e[Ss]harper
124 | *.DotSettings.user
125 |
126 | # JustCode is a .NET coding add-in
127 | .JustCode
128 |
129 | # TeamCity is a build add-in
130 | _TeamCity*
131 |
132 | # DotCover is a Code Coverage Tool
133 | *.dotCover
134 |
135 | # AxoCover is a Code Coverage Tool
136 | .axoCover/*
137 | !.axoCover/settings.json
138 |
139 | # Visual Studio code coverage results
140 | *.coverage
141 | *.coveragexml
142 |
143 | # NCrunch
144 | _NCrunch_*
145 | .*crunch*.local.xml
146 | nCrunchTemp_*
147 |
148 | # MightyMoose
149 | *.mm.*
150 | AutoTest.Net/
151 |
152 | # Web workbench (sass)
153 | .sass-cache/
154 |
155 | # Installshield output folder
156 | [Ee]xpress/
157 |
158 | # DocProject is a documentation generator add-in
159 | DocProject/buildhelp/
160 | DocProject/Help/*.HxT
161 | DocProject/Help/*.HxC
162 | DocProject/Help/*.hhc
163 | DocProject/Help/*.hhk
164 | DocProject/Help/*.hhp
165 | DocProject/Help/Html2
166 | DocProject/Help/html
167 |
168 | # Click-Once directory
169 | publish/
170 |
171 | # Publish Web Output
172 | *.[Pp]ublish.xml
173 | *.azurePubxml
174 | # Note: Comment the next line if you want to checkin your web deploy settings,
175 | # but database connection strings (with potential passwords) will be unencrypted
176 | # *.pubxml
177 | *.publishproj
178 |
179 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
180 | # checkin your Azure Web App publish settings, but sensitive information contained
181 | # in these scripts will be unencrypted
182 | PublishScripts/
183 |
184 | # NuGet Packages
185 | *.nupkg
186 | # The packages folder can be ignored because of Package Restore
187 | **/[Pp]ackages/*
188 | # except build/, which is used as an MSBuild target.
189 | !**/[Pp]ackages/build/
190 | # Uncomment if necessary however generally it will be regenerated when needed
191 | #!**/[Pp]ackages/repositories.config
192 | # NuGet v3's project.json files produces more ignorable files
193 | *.nuget.props
194 | *.nuget.targets
195 |
196 | # Microsoft Azure Build Output
197 | csx/
198 | *.build.csdef
199 |
200 | # Microsoft Azure Emulator
201 | ecf/
202 | rcf/
203 |
204 | # Windows Store app package directories and files
205 | AppPackages/
206 | BundleArtifacts/
207 | Package.StoreAssociation.xml
208 | _pkginfo.txt
209 | *.appx
210 |
211 | # Visual Studio cache files
212 | # files ending in .cache can be ignored
213 | *.[Cc]ache
214 | # but keep track of directories ending in .cache
215 | !?*.[Cc]ache/
216 |
217 | # Others
218 | ClientBin/
219 | ~$*
220 | *~
221 | *.dbmdl
222 | *.dbproj.schemaview
223 | *.jfm
224 | *.pfx
225 | *.publishsettings
226 | orleans.codegen.cs
227 |
228 | # Including strong name files can present a security risk
229 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
230 | #*.snk
231 |
232 | # Since there are multiple workflows, uncomment next line to ignore bower_components
233 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
234 | #bower_components/
235 |
236 | # RIA/Silverlight projects
237 | Generated_Code/
238 |
239 | # Backup & report files from converting an old project file
240 | # to a newer Visual Studio version. Backup files are not needed,
241 | # because we have git ;-)
242 | _UpgradeReport_Files/
243 | Backup*/
244 | UpgradeLog*.XML
245 | UpgradeLog*.htm
246 | ServiceFabricBackup/
247 | *.rptproj.bak
248 |
249 | # SQL Server files
250 | *.mdf
251 | *.ldf
252 | *.ndf
253 |
254 | # Business Intelligence projects
255 | *.rdl.data
256 | *.bim.layout
257 | *.bim_*.settings
258 | *.rptproj.rsuser
259 | *- Backup*.rdl
260 |
261 | # Microsoft Fakes
262 | FakesAssemblies/
263 |
264 | # GhostDoc plugin setting file
265 | *.GhostDoc.xml
266 |
267 | # Node.js Tools for Visual Studio
268 | .ntvs_analysis.dat
269 | node_modules/
270 |
271 | # Visual Studio 6 build log
272 | *.plg
273 |
274 | # Visual Studio 6 workspace options file
275 | *.opt
276 |
277 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
278 | *.vbw
279 |
280 | # Visual Studio LightSwitch build output
281 | **/*.HTMLClient/GeneratedArtifacts
282 | **/*.DesktopClient/GeneratedArtifacts
283 | **/*.DesktopClient/ModelManifest.xml
284 | **/*.Server/GeneratedArtifacts
285 | **/*.Server/ModelManifest.xml
286 | _Pvt_Extensions
287 |
288 | # Paket dependency manager
289 | .paket/paket.exe
290 | paket-files/
291 |
292 | # FAKE - F# Make
293 | .fake/
294 |
295 | # JetBrains Rider
296 | .idea/
297 | *.sln.iml
298 |
299 | # CodeRush personal settings
300 | .cr/personal
301 |
302 | # Python Tools for Visual Studio (PTVS)
303 | __pycache__/
304 | *.pyc
305 |
306 | # Cake - Uncomment if you are using it
307 | # tools/**
308 | # !tools/packages.config
309 |
310 | # Tabs Studio
311 | *.tss
312 |
313 | # Telerik's JustMock configuration file
314 | *.jmconfig
315 |
316 | # BizTalk build output
317 | *.btp.cs
318 | *.btm.cs
319 | *.odx.cs
320 | *.xsd.cs
321 |
322 | # OpenCover UI analysis results
323 | OpenCover/
324 |
325 | # Azure Stream Analytics local run output
326 | ASALocalRun/
327 |
328 | # MSBuild Binary and Structured Log
329 | *.binlog
330 |
331 | # NVidia Nsight GPU debugger configuration file
332 | *.nvuser
333 |
334 | # MFractors (Xamarin productivity tool) working folder
335 | .mfractor/
336 |
337 | # Local History for Visual Studio
338 | .localhistory/
339 |
340 | # BeatPulse healthcheck temp database
341 | healthchecksdb
--------------------------------------------------------------------------------
/src/DiskUsage/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | ..\images\cancel.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
123 |
124 |
125 | ..\images\choosepath.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
126 |
127 |
128 | ..\images\drive.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
129 |
130 |
131 | ..\images\filesearch.gif;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
132 |
133 |
134 | ..\images\openfolder.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
135 |
136 |
137 | ..\images\openfolder2.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
138 |
139 |
140 | ..\images\refresh.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
141 |
142 |
--------------------------------------------------------------------------------
/src/DiskUsage/ExtendedFileAttributes.cs:
--------------------------------------------------------------------------------
1 | namespace DiskUsage;
2 |
3 | #region Using Directives
4 |
5 | using System.IO;
6 |
7 | #endregion
8 |
9 | #region public ExtendedFileAttributes
10 |
11 | ///
12 | /// Extends .NET's enum with more attributes defined by Win32.
13 | ///
14 | ///
15 | /// This list of attribute names and values comes from:
16 | /// https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants.
17 | ///
18 | /// The result of .NET's property can be cast to
19 | /// to access the newer attributes as enum
20 | /// members.
21 | ///
22 | public enum ExtendedFileAttributes
23 | {
24 | ///
25 | /// A file that is read-only. Applications can read the file, but cannot write to it or delete it.
26 | /// This attribute is not honored on directories. For more information, see You cannot view or
27 | /// change the Read-only or the System attributes of folders in Windows Server 2003,
28 | /// in Windows XP, in Windows Vista or in Windows 7.
29 | ///
30 | ///
31 | /// 0x1
32 | ///
33 | ReadOnly = 1,
34 |
35 | ///
36 | /// The file or directory is hidden. It is not included in an ordinary directory listing.
37 | ///
38 | ///
39 | /// 0x2
40 | ///
41 | Hidden = 2,
42 |
43 | ///
44 | /// A file or directory that the operating system uses a part of, or uses exclusively.
45 | ///
46 | ///
47 | /// 0x4
48 | ///
49 | System = 4,
50 |
51 | ///
52 | /// The handle that identifies a directory.
53 | ///
54 | ///
55 | /// 0x10
56 | ///
57 | Directory = 16,
58 |
59 | ///
60 | /// A file or directory that is an archive file or directory. Applications typically use this attribute to mark files for backup or removal .
61 | ///
62 | ///
63 | /// 0x20
64 | ///
65 | Archive = 32,
66 |
67 | ///
68 | /// This value is reserved for system use.
69 | ///
70 | ///
71 | /// 0x40
72 | ///
73 | Device = 64,
74 |
75 | ///
76 | /// A file that does not have other attributes set. This attribute is valid only when used alone.
77 | ///
78 | ///
79 | /// 0x80
80 | ///
81 | Normal = 128,
82 |
83 | ///
84 | /// A file that is being used for temporary storage. File systems avoid writing data back to mass storage
85 | /// if sufficient cache memory is available, because typically, an application deletes a temporary file after
86 | /// the handle is closed. In that scenario, the system can entirely avoid writing the data. Otherwise, the
87 | /// data is written after the handle is closed.
88 | ///
89 | ///
90 | /// 0x100
91 | ///
92 | Temporary = 256,
93 |
94 | ///
95 | /// A file that is a sparse file.
96 | ///
97 | ///
98 | /// 0x200
99 | ///
100 | SparseFile = 512,
101 |
102 | ///
103 | /// A file or directory that has an associated reparse point, or a file that is a symbolic link.
104 | ///
105 | ///
106 | /// 0x400
107 | ///
108 | ReparsePoint = 1024,
109 |
110 | ///
111 | /// A file or directory that is compressed. For a file, all of the data in the file is compressed. For a directory,
112 | /// compression is the default for newly created files and subdirectories.
113 | ///
114 | ///
115 | /// 0x800
116 | ///
117 | Compressed = 2048,
118 |
119 | ///
120 | /// The data of a file is not available immediately. This attribute indicates that the file data is physically
121 | /// moved to offline storage. This attribute is used by Remote Storage, which is the hierarchical storage
122 | /// management software. Applications should not arbitrarily change this attribute.
123 | ///
124 | ///
125 | /// 0x1000
126 | ///
127 | Offline = 4096,
128 |
129 | ///
130 | /// The file or directory is not to be indexed by the content indexing service.
131 | ///
132 | ///
133 | /// 0x2000
134 | ///
135 | NotContentIndexed = 8192,
136 |
137 | ///
138 | /// A file or directory that is encrypted. For a file, all data streams in the file are encrypted. For a directory,
139 | /// encryption is the default for newly created files and subdirectories.
140 | ///
141 | ///
142 | /// 0x4000
143 | ///
144 | Encrypted = 16384,
145 |
146 | ///
147 | /// The directory or user data stream is configured with integrity (only supported on ReFS volumes). It is not
148 | /// included in an ordinary directory listing. The integrity setting persists with the file if it's renamed. If a file
149 | /// is copied the destination file will have integrity set if either the source file or destination directory have integrity set.
150 | ///
151 | ///
152 | /// 0x8000
153 | ///
154 | /// Windows Server 2008 R2, Windows 7, Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP:
155 | /// This flag is not supported until Windows Server 2012.
156 | ///
157 | IntegrityStream = 32768,
158 |
159 | ///
160 | /// This value is reserved for system use.
161 | ///
162 | ///
163 | /// 0x10000
164 | ///
165 | Virtual = 65536,
166 |
167 | ///
168 | /// The user data stream not to be read by the background data integrity scanner (AKA scrubber). When set on a
169 | /// directory it only provides inheritance. This flag is only supported on Storage Spaces and ReFS volumes. It is not
170 | /// included in an ordinary directory listing.
171 | ///
172 | ///
173 | /// 0x20000
174 | ///
175 | /// Windows Server 2008 R2, Windows 7, Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP:
176 | /// This flag is not supported until Windows 8 and Windows Server 2012.
177 | ///
178 | NoScrubData = 131072,
179 |
180 | ///
181 | /// This attribute only appears in directory enumeration classes (FILE_DIRECTORY_INFORMATION,
182 | /// FILE_BOTH_DIR_INFORMATION, etc.). When this attribute is set, it means that the file or directory has no physical
183 | /// representation on the local system; the item is virtual. Opening the item will be more expensive than normal, e.g.,
184 | /// it will cause at least some of it to be fetched from a remote store.
185 | ///
186 | ///
187 | /// 0x40000
188 | ///
189 | RecallOnOpen = 262144,
190 |
191 | ///
192 | /// This attribute indicates user intent that the file or directory should be kept fully present locally even when not
193 | /// being actively accessed. This attribute is for use with hierarchical storage management software.
194 | ///
195 | ///
196 | /// 0x80000
197 | ///
198 | Pinned = 524288,
199 |
200 | ///
201 | /// This attribute indicates that the file or directory should not be kept fully present locally except when being
202 | /// actively accessed. This attribute is for use with hierarchical storage management software.
203 | ///
204 | ///
205 | /// 0x100000
206 | ///
207 | Unpinned = 1048576,
208 |
209 | ///
210 | /// When this attribute is set, it means that the file or directory is not fully present locally. For a file that means
211 | /// that not all of its data is on local storage (e.g. it may be sparse with some data still in remote storage). For
212 | /// a directory it means that some of the directory contents are being virtualized from another location. Reading
213 | /// the file / enumerating the directory will be more expensive than normal, e.g. it will cause at least some of the
214 | /// file/directory content to be fetched from a remote store. Only kernel-mode callers can set this bit.
215 | ///
216 | ///
217 | /// 0x400000
218 | ///
219 | RecallOnDataAccess = 4194304,
220 | }
221 |
222 | #endregion
223 |
--------------------------------------------------------------------------------
/src/DiskUsage/DirectoryData.cs:
--------------------------------------------------------------------------------
1 | namespace DiskUsage
2 | {
3 | #region Using Directives
4 |
5 | using System;
6 | using System.Collections;
7 | using System.Collections.Generic;
8 | using System.ComponentModel;
9 | using System.Diagnostics;
10 | using System.Diagnostics.CodeAnalysis;
11 | using System.IO;
12 | using System.Runtime.InteropServices;
13 | using System.Threading;
14 | using System.Threading.Tasks;
15 | using System.Windows.Forms;
16 | using Menees;
17 | using Menees.Windows.Forms;
18 | using Microsoft.Research.CommunityTechnologies.Treemap;
19 |
20 | #endregion
21 |
22 | public class DirectoryData
23 | {
24 | #region Private Data Members
25 |
26 | private const double BytesPerMegabyte = 1048576.0;
27 |
28 | private readonly DirectoryInfo? directoryInfo;
29 | private readonly object resourceLock = new();
30 | private readonly uint clusterSize;
31 | private long size;
32 | private long fileCount;
33 | private long folderCount;
34 | private string? name;
35 | private string? fullName;
36 | private DirectoryData[] subData;
37 | private Node treeMapNode = new(string.Empty, 0, 0);
38 |
39 | #endregion
40 |
41 | #region Constructors
42 |
43 | public DirectoryData(DirectoryInfo directoryInfo, BackgroundWorker worker)
44 | : this(directoryInfo, worker, true, NativeMethods.GetDiskClusterSize(directoryInfo))
45 | {
46 | }
47 |
48 | public DirectoryData(string name, string fullName, long size, long fileCount)
49 | {
50 | this.DataType = DirectoryDataType.Files;
51 | this.treeMapNode.Tag = this;
52 |
53 | this.SetName(name, fullName);
54 | this.SetSize(size);
55 | this.fileCount = fileCount;
56 | this.subData = CollectionUtility.EmptyArray();
57 | this.PullNodes();
58 | }
59 |
60 | public DirectoryData(string error)
61 | {
62 | this.DataType = DirectoryDataType.Error;
63 | this.treeMapNode.Tag = this;
64 |
65 | this.SetName(error, error);
66 | this.SetSize(0);
67 | this.subData = CollectionUtility.EmptyArray();
68 | this.PullNodes();
69 | }
70 |
71 | private DirectoryData(DirectoryInfo directoryInfo, BackgroundWorker? worker, bool reportProgress, uint clusterSize)
72 | {
73 | this.DataType = DirectoryDataType.Directory;
74 | this.treeMapNode.Tag = this;
75 |
76 | this.directoryInfo = directoryInfo;
77 | this.SetName(this.directoryInfo.Name, this.directoryInfo.FullName);
78 | this.subData = CollectionUtility.EmptyArray();
79 | this.clusterSize = clusterSize;
80 | this.Refresh(worker, reportProgress);
81 | }
82 |
83 | #endregion
84 |
85 | #region Public Members
86 |
87 | public long Size => this.size;
88 |
89 | public double SizeInMegabytes => this.size / BytesPerMegabyte;
90 |
91 | public long FileCount => this.fileCount;
92 |
93 | public long FolderCount => this.folderCount;
94 |
95 | public string Name => this.name!;
96 |
97 | public string FullName => this.fullName!;
98 |
99 | public DirectoryDataType DataType { get; private set; } = DirectoryDataType.Directory;
100 |
101 | public ICollection SubData => this.subData;
102 |
103 | public Node TreeMapNode => this.treeMapNode;
104 |
105 | public void Refresh(BackgroundWorker worker)
106 | {
107 | this.Refresh(worker, true);
108 | }
109 |
110 | public void AdjustStats(long sizeAdjustment, long fileCountAdjustment, long folderCountAdjustment)
111 | {
112 | this.AdjustStats(sizeAdjustment, fileCountAdjustment, folderCountAdjustment, true);
113 | }
114 |
115 | public void Explore(IWin32Window owner)
116 | {
117 | if (this.directoryInfo != null)
118 | {
119 | WindowsUtility.ShellExecute(owner, this.directoryInfo.FullName);
120 | }
121 | }
122 |
123 | public DirectoryData Clone()
124 | {
125 | DirectoryData result = (DirectoryData)this.MemberwiseClone();
126 | return result;
127 | }
128 |
129 | #endregion
130 |
131 | #region Private Methods
132 |
133 | private static void AddErrorData(List subDataList, string prefix, string message)
134 | {
135 | subDataList.Add(new DirectoryData(prefix + message));
136 | }
137 |
138 | private static bool CheckCanceled(BackgroundWorker? worker)
139 | {
140 | bool result = false;
141 |
142 | if (worker != null)
143 | {
144 | result = worker.CancellationPending;
145 | }
146 |
147 | return result;
148 | }
149 |
150 | private void Refresh(BackgroundWorker? worker, bool reportProgress)
151 | {
152 | if (this.directoryInfo != null)
153 | {
154 | // Recreate the tree map node so we can update its Nodes collection.
155 | if (this.treeMapNode.Nodes.Count > 0)
156 | {
157 | this.RecreateTreeMapNode(false);
158 | }
159 |
160 | this.SetSize(0);
161 | this.fileCount = 0;
162 | this.folderCount = 0;
163 |
164 | List subDataList = new();
165 |
166 | this.CalculateFileSizes(subDataList);
167 | if (!CheckCanceled(worker))
168 | {
169 | if (reportProgress)
170 | {
171 | this.CalculateDirectorySizesWithProgress(subDataList, worker);
172 | }
173 | else
174 | {
175 | this.CalculateDirectorySizesParallel(subDataList, worker);
176 | }
177 |
178 | if (!CheckCanceled(worker))
179 | {
180 | this.subData = new DirectoryData[subDataList.Count];
181 | subDataList.CopyTo(this.subData);
182 |
183 | // I'm doing Y - X so the sort will always be in descending order.
184 | // I'm using Sign rather than an int cast because these sizes are
185 | // 64-bit integers so an int cast would truncate and lose data
186 | // when the sizes were > 2GB (which happens with directories).
187 | Array.Sort(this.subData, (x, y) => Math.Sign(y.Size - x.Size));
188 |
189 | this.PopulateTreeMapSubNodes();
190 | }
191 | }
192 | }
193 | }
194 |
195 | private void PopulateTreeMapSubNodes()
196 | {
197 | foreach (DirectoryData data in this.subData)
198 | {
199 | if (data.DataType != DirectoryDataType.Error)
200 | {
201 | this.treeMapNode.Nodes.Add(data.TreeMapNode);
202 | }
203 | }
204 |
205 | this.PullNodes();
206 | }
207 |
208 | private void RecreateTreeMapNode(bool addChildNodes)
209 | {
210 | this.treeMapNode = new Node(
211 | this.treeMapNode.Text,
212 | this.treeMapNode.SizeMetric,
213 | this.treeMapNode.ColorMetric,
214 | this.treeMapNode.Tag,
215 | this.treeMapNode.ToolTip);
216 |
217 | if (addChildNodes)
218 | {
219 | this.PopulateTreeMapSubNodes();
220 | }
221 | }
222 |
223 | [Conditional("DEBUG")]
224 | private void PullNodes()
225 | {
226 | // Debug builds will assert if you don't pull the Nodes
227 | // collection. So I'll just call a debug-only method
228 | // here on the Nodes collection.
229 | if (this.subData.Length == 0)
230 | {
231 | this.treeMapNode.Nodes.AssertValid();
232 | }
233 | }
234 |
235 | [SuppressMessage(
236 | "Microsoft.Design",
237 | "CA1031:DoNotCatchGeneralExceptionTypes",
238 | Justification = "I don't want an error in one node to stop the whole process.")]
239 | private void CalculateFileSizes(List subDataList)
240 | {
241 | try
242 | {
243 | int fileCount = 0;
244 | long fileSize = 0;
245 | Parallel.ForEach(
246 | this.directoryInfo!.EnumerateFiles(),
247 | info =>
248 | {
249 | long sizeOnDisk = this.GetSizeOnDisk(info);
250 | Interlocked.Add(ref fileSize, sizeOnDisk);
251 | Interlocked.Increment(ref fileCount);
252 | });
253 |
254 | this.AdjustStats(fileSize, fileCount, 0, false);
255 |
256 | // Only add a [Files] node if we found some files (even 0 byte files).
257 | if (fileCount > 0)
258 | {
259 | // Add a faux node for files
260 | const string FilesNodeName = "[Files]";
261 | DirectoryData data = new(FilesNodeName, Path.Combine(this.directoryInfo.FullName, FilesNodeName), fileSize, fileCount);
262 | subDataList.Add(data);
263 | }
264 | }
265 | catch (Exception ex)
266 | {
267 | AddErrorData(subDataList, "File Error: ", ex.Message);
268 | }
269 | }
270 |
271 | [SuppressMessage(
272 | "Microsoft.Design",
273 | "CA1031:DoNotCatchGeneralExceptionTypes",
274 | Justification = "I don't want an error in one node to stop the whole process.")]
275 | private void CalculateDirectorySizesWithProgress(List subDataList, BackgroundWorker? worker)
276 | {
277 | try
278 | {
279 | DirectoryInfo[] directories = this.directoryInfo!.GetDirectories();
280 |
281 | // Since we're reporting the directory names as our progress, let's do them in alphabetical order.
282 | Array.Sort(directories, (x, y) => string.Compare(x.Name, y.Name, true));
283 |
284 | int numDirectories = directories.Length;
285 | for (int i = 0; i < numDirectories; i++)
286 | {
287 | DirectoryInfo info = directories[i];
288 |
289 | if (CheckCanceled(worker))
290 | {
291 | worker = null;
292 | break;
293 | }
294 |
295 | if (worker != null)
296 | {
297 | int percentage = (int)Math.Round((100.0 * i) / numDirectories);
298 | worker.ReportProgress(percentage, info.FullName);
299 | Debug.WriteLine(string.Format("{0}% - {1}", percentage, info.FullName));
300 | }
301 |
302 | this.CalculateDirectorySize(subDataList, worker, info);
303 | }
304 |
305 | if (worker != null)
306 | {
307 | worker.ReportProgress(100, string.Empty);
308 | }
309 | }
310 | catch (Exception ex)
311 | {
312 | AddErrorData(subDataList, "Directory Error: ", ex.Message);
313 | }
314 | }
315 |
316 | [SuppressMessage(
317 | "Microsoft.Design",
318 | "CA1031:DoNotCatchGeneralExceptionTypes",
319 | Justification = "I don't want an error in one node to stop the whole process.")]
320 | private void CalculateDirectorySizesParallel(List subDataList, BackgroundWorker? worker)
321 | {
322 | try
323 | {
324 | Parallel.ForEach(
325 | this.directoryInfo!.EnumerateDirectories(),
326 | info =>
327 | {
328 | if (!CheckCanceled(worker))
329 | {
330 | this.CalculateDirectorySize(subDataList, worker, info);
331 | }
332 | });
333 | }
334 | catch (Exception ex)
335 | {
336 | AddErrorData(subDataList, "Directory Error: ", ex.Message);
337 | }
338 | }
339 |
340 | private void CalculateDirectorySize(List subDataList, BackgroundWorker? worker, DirectoryInfo info)
341 | {
342 | // Never report progress for sub-directories. It adds too much blocking, which makes things take forever.
343 | // Add 1 to the folder count to account for the current directory.
344 | DirectoryData data = new(info, worker, false, this.clusterSize);
345 | this.AdjustStats(data.Size, data.FileCount, 1 + data.FolderCount, false);
346 | lock (subDataList)
347 | {
348 | subDataList.Add(data);
349 | }
350 | }
351 |
352 | private void SetSize(long size)
353 | {
354 | this.size = size;
355 |
356 | // Sizes must be positive numbers for the tree map control
357 | long treeMapSize = Math.Max(size, 1);
358 | this.treeMapNode.SizeMetric = treeMapSize;
359 |
360 | switch (this.DataType)
361 | {
362 | case DirectoryDataType.Directory:
363 | case DirectoryDataType.Files:
364 | // We also have to set the color metric, so base it on the log of the
365 | // size. 100KB has log 5 and 1GB has log 9, so we'll subtract
366 | // 5 and then get the percentage from 0 to 4.
367 | const int LowestLog = 5;
368 | const int HighestLog = 9;
369 | double log = Math.Max(LowestLog, Math.Log10(treeMapSize));
370 | double metric = ((log - LowestLog) / (HighestLog - LowestLog)) * 100;
371 | if (this.DataType == DirectoryDataType.Files)
372 | {
373 | metric = -metric;
374 | }
375 |
376 | this.treeMapNode.ColorMetric = (float)metric;
377 | break;
378 |
379 | default:
380 | // Use the default Window color for Error or Unknown.
381 | this.treeMapNode.ColorMetric = 0;
382 | break;
383 | }
384 |
385 | this.UpdateToolTip();
386 | }
387 |
388 | private void SetName(string name, string fullName)
389 | {
390 | this.name = name;
391 | this.fullName = fullName;
392 | this.treeMapNode.Text = name;
393 | this.UpdateToolTip();
394 | }
395 |
396 | private void UpdateToolTip()
397 | {
398 | switch (this.DataType)
399 | {
400 | case DirectoryDataType.Directory:
401 | case DirectoryDataType.Files:
402 | this.treeMapNode.ToolTip = string.Format("{0}: {1:N1} MB", this.fullName ?? this.name, this.SizeInMegabytes);
403 | break;
404 |
405 | case DirectoryDataType.Error:
406 | this.treeMapNode.ToolTip = this.Name;
407 | break;
408 | }
409 | }
410 |
411 | private void AdjustStats(long sizeAdjustment, long fileCountAdjustment, long folderCountAdjustment, bool recreateNode)
412 | {
413 | // If multiple threads are calculating sub-directory sizes, then the parent directory size
414 | // can be adjusted simultaneously. We need to lock on some member to ensure the size
415 | // is safely adjusted along with all dependent info (e.g., tree map size).
416 | lock (this.resourceLock)
417 | {
418 | this.SetSize(this.size + sizeAdjustment);
419 | }
420 |
421 | if (fileCountAdjustment != 0)
422 | {
423 | Interlocked.Add(ref this.fileCount, fileCountAdjustment);
424 | }
425 |
426 | if (folderCountAdjustment != 0)
427 | {
428 | Interlocked.Add(ref this.folderCount, folderCountAdjustment);
429 | }
430 |
431 | if (recreateNode)
432 | {
433 | this.RecreateTreeMapNode(true);
434 | }
435 | }
436 |
437 | private long GetSizeOnDisk(FileInfo info)
438 | {
439 | long result;
440 |
441 | ExtendedFileAttributes attributes = (ExtendedFileAttributes)info.Attributes;
442 | if (!attributes.HasFlag(ExtendedFileAttributes.Pinned)
443 | && (attributes.HasFlag(ExtendedFileAttributes.RecallOnDataAccess)
444 | || attributes.HasFlag(ExtendedFileAttributes.RecallOnOpen)
445 | || attributes.HasFlag(ExtendedFileAttributes.Unpinned)))
446 | {
447 | // If an on-demand/virtual file isn't available locally (e.g., a non-downloaded OneDrive file), then treat it as size 0.
448 | result = 0;
449 | }
450 | else
451 | {
452 | if (attributes.HasFlag(ExtendedFileAttributes.Compressed))
453 | {
454 | result = NativeMethods.GetCompressedFileSize(info.FullName);
455 | }
456 | else
457 | {
458 | result = info.Length;
459 | }
460 |
461 | // Round up to the next full cluster size to report "size on disk" instead of just "file size".
462 | // https://stackoverflow.com/a/3751135/1882616
463 | result = ((result + this.clusterSize - 1) / this.clusterSize) * this.clusterSize;
464 | }
465 |
466 | return result;
467 | }
468 |
469 | #endregion
470 | }
471 | }
472 |
--------------------------------------------------------------------------------
/src/DiskUsage/MainForm.Designer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.Collections;
4 | using System.ComponentModel;
5 | using System.Windows.Forms;
6 | using System.Data;
7 | using Menees.Windows.Forms;
8 | using System.IO;
9 | using System.Text;
10 | using Microsoft.Research.CommunityTechnologies.Treemap;
11 | using System.Reflection;
12 | using Menees;
13 |
14 | namespace DiskUsage
15 | {
16 | public partial class MainForm : ExtendedForm
17 | {
18 | private Menees.Windows.Forms.FormSaver FormSave;
19 | private BackgroundWorker MainWorker;
20 | private BackgroundWorker RefreshWorker;
21 | private RecentItemList RecentPaths;
22 | private System.Windows.Forms.TreeView Tree;
23 | private System.Windows.Forms.ImageList Images;
24 | private MenuStrip Menustrip;
25 | private ToolStripMenuItem mnuFile;
26 | private ToolStripMenuItem mnuDrives;
27 | private ToolStripMenuItem mnuChoosePath;
28 | private ToolStripSeparator toolStripMenuItem2;
29 | private ToolStripMenuItem mnuRefreshBranch;
30 | private ToolStripMenuItem mnuOpenFolder;
31 | private ToolStripSeparator toolStripMenuItem3;
32 | private ToolStripMenuItem mnuExit;
33 | private ToolStripMenuItem mnuHelp;
34 | private ToolStripMenuItem mnuAbout;
35 | private ContextMenuStrip TreeCtxMenu;
36 | private ToolStripMenuItem mnuRefreshBranch2;
37 | private ToolStripMenuItem mnuOpenFolder2;
38 | private StatusStrip Status;
39 | private ToolStripStatusLabel lblStatus;
40 | private ToolStripProgressBar Progress;
41 | private ToolStripMenuItem mnuCancel;
42 | private System.ComponentModel.IContainer components;
43 | private ToolStripStatusLabel lblProgressImage;
44 | private SplitContainer Splitter;
45 | private TreemapControl Map;
46 | private ToolStripMenuItem mnuRecentPaths;
47 | private ToolStripSeparator toolStripMenuItem4;
48 | private SplitContainer DetailSplitter;
49 | private WebBrowser Browser;
50 | private Panel BrowserPanel;
51 |
52 | ///
53 | /// Clean up any resources being used.
54 | ///
55 | protected override void Dispose( bool disposing )
56 | {
57 | if( disposing )
58 | {
59 | if (components != null)
60 | {
61 | components.Dispose();
62 | }
63 | }
64 | base.Dispose( disposing );
65 | }
66 |
67 | #region Windows Form Designer generated code
68 | ///
69 | /// Required method for Designer support - do not modify
70 | /// the contents of this method with the code editor.
71 | ///
72 | private void InitializeComponent()
73 | {
74 | this.components = new System.ComponentModel.Container();
75 | System.Windows.Forms.ToolStripMenuItem mnuDummyDrive;
76 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
77 | this.Tree = new System.Windows.Forms.TreeView();
78 | this.TreeCtxMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
79 | this.mnuRefreshBranch2 = new System.Windows.Forms.ToolStripMenuItem();
80 | this.mnuOpenFolder2 = new System.Windows.Forms.ToolStripMenuItem();
81 | this.Images = new System.Windows.Forms.ImageList(this.components);
82 | this.FormSave = new Menees.Windows.Forms.FormSaver(this.components);
83 | this.Menustrip = new System.Windows.Forms.MenuStrip();
84 | this.mnuFile = new System.Windows.Forms.ToolStripMenuItem();
85 | this.mnuDrives = new System.Windows.Forms.ToolStripMenuItem();
86 | this.mnuChoosePath = new System.Windows.Forms.ToolStripMenuItem();
87 | this.mnuRecentPaths = new System.Windows.Forms.ToolStripMenuItem();
88 | this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripSeparator();
89 | this.mnuCancel = new System.Windows.Forms.ToolStripMenuItem();
90 | this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator();
91 | this.mnuRefreshBranch = new System.Windows.Forms.ToolStripMenuItem();
92 | this.mnuOpenFolder = new System.Windows.Forms.ToolStripMenuItem();
93 | this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripSeparator();
94 | this.mnuExit = new System.Windows.Forms.ToolStripMenuItem();
95 | this.mnuHelp = new System.Windows.Forms.ToolStripMenuItem();
96 | this.mnuAbout = new System.Windows.Forms.ToolStripMenuItem();
97 | this.Status = new System.Windows.Forms.StatusStrip();
98 | this.lblStatus = new System.Windows.Forms.ToolStripStatusLabel();
99 | this.lblProgressImage = new System.Windows.Forms.ToolStripStatusLabel();
100 | this.Progress = new System.Windows.Forms.ToolStripProgressBar();
101 | this.MainWorker = new System.ComponentModel.BackgroundWorker();
102 | this.RefreshWorker = new System.ComponentModel.BackgroundWorker();
103 | this.Splitter = new System.Windows.Forms.SplitContainer();
104 | this.DetailSplitter = new System.Windows.Forms.SplitContainer();
105 | this.Map = new Microsoft.Research.CommunityTechnologies.Treemap.TreemapControl();
106 | this.BrowserPanel = new System.Windows.Forms.Panel();
107 | this.Browser = new System.Windows.Forms.WebBrowser();
108 | this.RecentPaths = new Menees.Windows.Forms.RecentItemList(this.components);
109 | mnuDummyDrive = new System.Windows.Forms.ToolStripMenuItem();
110 | this.TreeCtxMenu.SuspendLayout();
111 | this.Menustrip.SuspendLayout();
112 | this.Status.SuspendLayout();
113 | ((System.ComponentModel.ISupportInitialize)(this.Splitter)).BeginInit();
114 | this.Splitter.Panel1.SuspendLayout();
115 | this.Splitter.Panel2.SuspendLayout();
116 | this.Splitter.SuspendLayout();
117 | ((System.ComponentModel.ISupportInitialize)(this.DetailSplitter)).BeginInit();
118 | this.DetailSplitter.Panel1.SuspendLayout();
119 | this.DetailSplitter.Panel2.SuspendLayout();
120 | this.DetailSplitter.SuspendLayout();
121 | this.BrowserPanel.SuspendLayout();
122 | this.SuspendLayout();
123 | //
124 | // mnuDummyDrive
125 | //
126 | mnuDummyDrive.Enabled = false;
127 | mnuDummyDrive.Name = "mnuDummyDrive";
128 | mnuDummyDrive.Size = new System.Drawing.Size(133, 22);
129 | mnuDummyDrive.Text = "";
130 | //
131 | // Tree
132 | //
133 | this.Tree.ContextMenuStrip = this.TreeCtxMenu;
134 | this.Tree.Dock = System.Windows.Forms.DockStyle.Fill;
135 | this.Tree.HideSelection = false;
136 | this.Tree.ImageIndex = 0;
137 | this.Tree.ImageList = this.Images;
138 | this.Tree.Location = new System.Drawing.Point(0, 0);
139 | this.Tree.Name = "Tree";
140 | this.Tree.SelectedImageIndex = 0;
141 | this.Tree.Size = new System.Drawing.Size(213, 388);
142 | this.Tree.TabIndex = 0;
143 | this.Tree.BeforeCollapse += new System.Windows.Forms.TreeViewCancelEventHandler(this.Tree_BeforeCollapse);
144 | this.Tree.BeforeExpand += new System.Windows.Forms.TreeViewCancelEventHandler(this.Tree_BeforeExpand);
145 | this.Tree.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.Tree_AfterSelect);
146 | this.Tree.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Tree_MouseDown);
147 | //
148 | // TreeCtxMenu
149 | //
150 | this.TreeCtxMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
151 | this.mnuRefreshBranch2,
152 | this.mnuOpenFolder2});
153 | this.TreeCtxMenu.Name = "TreeCtxMenu";
154 | this.TreeCtxMenu.Size = new System.Drawing.Size(154, 48);
155 | //
156 | // mnuRefreshBranch2
157 | //
158 | this.mnuRefreshBranch2.Image = global::DiskUsage.Properties.Resources.Refresh;
159 | this.mnuRefreshBranch2.ImageTransparentColor = System.Drawing.Color.Fuchsia;
160 | this.mnuRefreshBranch2.Name = "mnuRefreshBranch2";
161 | this.mnuRefreshBranch2.Size = new System.Drawing.Size(153, 22);
162 | this.mnuRefreshBranch2.Text = "&Refresh Branch";
163 | this.mnuRefreshBranch2.Click += new System.EventHandler(this.RefreshBranch_Click);
164 | //
165 | // mnuOpenFolder2
166 | //
167 | this.mnuOpenFolder2.Image = global::DiskUsage.Properties.Resources.OpenFolder2;
168 | this.mnuOpenFolder2.ImageTransparentColor = System.Drawing.Color.Fuchsia;
169 | this.mnuOpenFolder2.Name = "mnuOpenFolder2";
170 | this.mnuOpenFolder2.Size = new System.Drawing.Size(153, 22);
171 | this.mnuOpenFolder2.Text = "&Open Folder";
172 | this.mnuOpenFolder2.Click += new System.EventHandler(this.OpenFolder_Click);
173 | //
174 | // Images
175 | //
176 | this.Images.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("Images.ImageStream")));
177 | this.Images.TransparentColor = System.Drawing.Color.Magenta;
178 | this.Images.Images.SetKeyName(0, "Error.bmp");
179 | this.Images.Images.SetKeyName(1, "Files.bmp");
180 | this.Images.Images.SetKeyName(2, "OpenFolder2.bmp");
181 | //
182 | // FormSave
183 | //
184 | this.FormSave.ContainerControl = this;
185 | this.FormSave.SettingsNodeName = "Form Save";
186 | //
187 | // Menustrip
188 | //
189 | this.Menustrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
190 | this.mnuFile,
191 | this.mnuHelp});
192 | this.Menustrip.Location = new System.Drawing.Point(0, 0);
193 | this.Menustrip.Name = "Menustrip";
194 | this.Menustrip.Size = new System.Drawing.Size(542, 24);
195 | this.Menustrip.TabIndex = 1;
196 | this.Menustrip.Text = "menuStrip1";
197 | //
198 | // mnuFile
199 | //
200 | this.mnuFile.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
201 | this.mnuDrives,
202 | this.mnuChoosePath,
203 | this.mnuRecentPaths,
204 | this.toolStripMenuItem4,
205 | this.mnuCancel,
206 | this.toolStripMenuItem2,
207 | this.mnuRefreshBranch,
208 | this.mnuOpenFolder,
209 | this.toolStripMenuItem3,
210 | this.mnuExit});
211 | this.mnuFile.Name = "mnuFile";
212 | this.mnuFile.Size = new System.Drawing.Size(37, 20);
213 | this.mnuFile.Text = "&File";
214 | //
215 | // mnuDrives
216 | //
217 | this.mnuDrives.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
218 | mnuDummyDrive});
219 | this.mnuDrives.Name = "mnuDrives";
220 | this.mnuDrives.Size = new System.Drawing.Size(193, 22);
221 | this.mnuDrives.Text = "&Drives";
222 | this.mnuDrives.DropDownOpening += new System.EventHandler(this.Drives_DropDownOpening);
223 | //
224 | // mnuChoosePath
225 | //
226 | this.mnuChoosePath.Image = global::DiskUsage.Properties.Resources.ChoosePath;
227 | this.mnuChoosePath.ImageTransparentColor = System.Drawing.Color.Fuchsia;
228 | this.mnuChoosePath.Name = "mnuChoosePath";
229 | this.mnuChoosePath.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.N)));
230 | this.mnuChoosePath.Size = new System.Drawing.Size(193, 22);
231 | this.mnuChoosePath.Text = "Choose &Path...";
232 | this.mnuChoosePath.Click += new System.EventHandler(this.ChoosePath_Click);
233 | //
234 | // mnuRecentPaths
235 | //
236 | this.mnuRecentPaths.Name = "mnuRecentPaths";
237 | this.mnuRecentPaths.Size = new System.Drawing.Size(193, 22);
238 | this.mnuRecentPaths.Text = "R&ecent Paths";
239 | //
240 | // toolStripMenuItem4
241 | //
242 | this.toolStripMenuItem4.Name = "toolStripMenuItem4";
243 | this.toolStripMenuItem4.Size = new System.Drawing.Size(190, 6);
244 | //
245 | // mnuCancel
246 | //
247 | this.mnuCancel.Image = global::DiskUsage.Properties.Resources.Cancel;
248 | this.mnuCancel.ImageTransparentColor = System.Drawing.Color.Fuchsia;
249 | this.mnuCancel.Name = "mnuCancel";
250 | this.mnuCancel.Size = new System.Drawing.Size(193, 22);
251 | this.mnuCancel.Text = "&Cancel";
252 | this.mnuCancel.Click += new System.EventHandler(this.Cancel_Click);
253 | //
254 | // toolStripMenuItem2
255 | //
256 | this.toolStripMenuItem2.Name = "toolStripMenuItem2";
257 | this.toolStripMenuItem2.Size = new System.Drawing.Size(190, 6);
258 | //
259 | // mnuRefreshBranch
260 | //
261 | this.mnuRefreshBranch.Image = global::DiskUsage.Properties.Resources.Refresh;
262 | this.mnuRefreshBranch.ImageTransparentColor = System.Drawing.Color.Fuchsia;
263 | this.mnuRefreshBranch.Name = "mnuRefreshBranch";
264 | this.mnuRefreshBranch.ShortcutKeys = System.Windows.Forms.Keys.F5;
265 | this.mnuRefreshBranch.Size = new System.Drawing.Size(193, 22);
266 | this.mnuRefreshBranch.Text = "&Refresh Branch";
267 | this.mnuRefreshBranch.Click += new System.EventHandler(this.RefreshBranch_Click);
268 | //
269 | // mnuOpenFolder
270 | //
271 | this.mnuOpenFolder.Image = global::DiskUsage.Properties.Resources.OpenFolder2;
272 | this.mnuOpenFolder.ImageTransparentColor = System.Drawing.Color.Fuchsia;
273 | this.mnuOpenFolder.Name = "mnuOpenFolder";
274 | this.mnuOpenFolder.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O)));
275 | this.mnuOpenFolder.Size = new System.Drawing.Size(193, 22);
276 | this.mnuOpenFolder.Text = "&Open Folder";
277 | this.mnuOpenFolder.Click += new System.EventHandler(this.OpenFolder_Click);
278 | //
279 | // toolStripMenuItem3
280 | //
281 | this.toolStripMenuItem3.Name = "toolStripMenuItem3";
282 | this.toolStripMenuItem3.Size = new System.Drawing.Size(190, 6);
283 | //
284 | // mnuExit
285 | //
286 | this.mnuExit.Name = "mnuExit";
287 | this.mnuExit.Size = new System.Drawing.Size(193, 22);
288 | this.mnuExit.Text = "E&xit";
289 | this.mnuExit.Click += new System.EventHandler(this.Exit_Click);
290 | //
291 | // mnuHelp
292 | //
293 | this.mnuHelp.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
294 | this.mnuAbout});
295 | this.mnuHelp.Name = "mnuHelp";
296 | this.mnuHelp.Size = new System.Drawing.Size(44, 20);
297 | this.mnuHelp.Text = "&Help";
298 | //
299 | // mnuAbout
300 | //
301 | this.mnuAbout.Name = "mnuAbout";
302 | this.mnuAbout.Size = new System.Drawing.Size(180, 22);
303 | this.mnuAbout.Text = "&About...";
304 | this.mnuAbout.Click += new System.EventHandler(this.About_Click);
305 | //
306 | // Status
307 | //
308 | this.Status.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
309 | this.lblStatus,
310 | this.lblProgressImage,
311 | this.Progress});
312 | this.Status.Location = new System.Drawing.Point(0, 412);
313 | this.Status.Name = "Status";
314 | this.Status.Size = new System.Drawing.Size(542, 22);
315 | this.Status.TabIndex = 2;
316 | //
317 | // lblStatus
318 | //
319 | this.lblStatus.Name = "lblStatus";
320 | this.lblStatus.Size = new System.Drawing.Size(527, 17);
321 | this.lblStatus.Spring = true;
322 | this.lblStatus.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
323 | //
324 | // lblProgressImage
325 | //
326 | this.lblProgressImage.AutoSize = false;
327 | this.lblProgressImage.Image = global::DiskUsage.Properties.Resources.FileSearch;
328 | this.lblProgressImage.Name = "lblProgressImage";
329 | this.lblProgressImage.Size = new System.Drawing.Size(30, 17);
330 | this.lblProgressImage.Visible = false;
331 | //
332 | // Progress
333 | //
334 | this.Progress.Name = "Progress";
335 | this.Progress.Size = new System.Drawing.Size(200, 16);
336 | this.Progress.Visible = false;
337 | //
338 | // MainWorker
339 | //
340 | this.MainWorker.WorkerReportsProgress = true;
341 | this.MainWorker.WorkerSupportsCancellation = true;
342 | this.MainWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(this.MainWorker_DoWork);
343 | this.MainWorker.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.Worker_ProgressChanged);
344 | this.MainWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.MainWorker_RunWorkerCompleted);
345 | //
346 | // RefreshWorker
347 | //
348 | this.RefreshWorker.WorkerReportsProgress = true;
349 | this.RefreshWorker.WorkerSupportsCancellation = true;
350 | this.RefreshWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(this.RefreshWorker_DoWork);
351 | this.RefreshWorker.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.Worker_ProgressChanged);
352 | this.RefreshWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.RefreshWorker_RunWorkerCompleted);
353 | //
354 | // Splitter
355 | //
356 | this.Splitter.Dock = System.Windows.Forms.DockStyle.Fill;
357 | this.Splitter.Location = new System.Drawing.Point(0, 24);
358 | this.Splitter.Name = "Splitter";
359 | //
360 | // Splitter.Panel1
361 | //
362 | this.Splitter.Panel1.Controls.Add(this.Tree);
363 | //
364 | // Splitter.Panel2
365 | //
366 | this.Splitter.Panel2.Controls.Add(this.DetailSplitter);
367 | this.Splitter.Size = new System.Drawing.Size(542, 388);
368 | this.Splitter.SplitterDistance = 213;
369 | this.Splitter.TabIndex = 0;
370 | //
371 | // DetailSplitter
372 | //
373 | this.DetailSplitter.Dock = System.Windows.Forms.DockStyle.Fill;
374 | this.DetailSplitter.Location = new System.Drawing.Point(0, 0);
375 | this.DetailSplitter.Name = "DetailSplitter";
376 | this.DetailSplitter.Orientation = System.Windows.Forms.Orientation.Horizontal;
377 | //
378 | // DetailSplitter.Panel1
379 | //
380 | this.DetailSplitter.Panel1.Controls.Add(this.Map);
381 | //
382 | // DetailSplitter.Panel2
383 | //
384 | this.DetailSplitter.Panel2.Controls.Add(this.BrowserPanel);
385 | this.DetailSplitter.Size = new System.Drawing.Size(325, 388);
386 | this.DetailSplitter.SplitterDistance = 194;
387 | this.DetailSplitter.TabIndex = 0;
388 | //
389 | // Map
390 | //
391 | this.Map.AllowDrag = false;
392 | this.Map.BorderColor = System.Drawing.SystemColors.WindowFrame;
393 | this.Map.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
394 | this.Map.DiscreteNegativeColors = 20;
395 | this.Map.DiscretePositiveColors = 20;
396 | this.Map.Dock = System.Windows.Forms.DockStyle.Fill;
397 | this.Map.EmptySpaceLocation = Microsoft.Research.CommunityTechnologies.Treemap.EmptySpaceLocation.DeterminedByLayoutAlgorithm;
398 | this.Map.FontFamily = "Arial";
399 | this.Map.FontSolidColor = System.Drawing.Color.Black;
400 | this.Map.IsZoomable = false;
401 | this.Map.LayoutAlgorithm = Microsoft.Research.CommunityTechnologies.Treemap.LayoutAlgorithm.BottomWeightedSquarified;
402 | this.Map.Location = new System.Drawing.Point(0, 0);
403 | this.Map.MaxColor = System.Drawing.Color.DeepSkyBlue;
404 | this.Map.MaxColorMetric = 100F;
405 | this.Map.MinColor = System.Drawing.Color.ForestGreen;
406 | this.Map.MinColorMetric = -100F;
407 | this.Map.Name = "Map";
408 | this.Map.NodeColorAlgorithm = Microsoft.Research.CommunityTechnologies.Treemap.NodeColorAlgorithm.UseColorMetric;
409 | this.Map.NodeLevelsWithText = Microsoft.Research.CommunityTechnologies.Treemap.NodeLevelsWithText.All;
410 | this.Map.PaddingDecrementPerLevelPx = 1;
411 | this.Map.PaddingPx = 5;
412 | this.Map.PenWidthDecrementPerLevelPx = 1;
413 | this.Map.PenWidthPx = 3;
414 | this.Map.SelectedBackColor = System.Drawing.SystemColors.Highlight;
415 | this.Map.SelectedFontColor = System.Drawing.SystemColors.HighlightText;
416 | this.Map.ShowToolTips = true;
417 | this.Map.Size = new System.Drawing.Size(325, 194);
418 | this.Map.TabIndex = 0;
419 | this.Map.TextLocation = Microsoft.Research.CommunityTechnologies.Treemap.TextLocation.Top;
420 | this.Map.NodeDoubleClick += new Microsoft.Research.CommunityTechnologies.Treemap.TreemapControl.NodeEventHandler(this.Map_NodeDoubleClick);
421 | this.Map.SelectedNodeChanged += new System.EventHandler(this.Map_SelectedNodeChanged);
422 | //
423 | // BrowserPanel
424 | //
425 | this.BrowserPanel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
426 | this.BrowserPanel.Controls.Add(this.Browser);
427 | this.BrowserPanel.Dock = System.Windows.Forms.DockStyle.Fill;
428 | this.BrowserPanel.Location = new System.Drawing.Point(0, 0);
429 | this.BrowserPanel.Name = "BrowserPanel";
430 | this.BrowserPanel.Size = new System.Drawing.Size(325, 190);
431 | this.BrowserPanel.TabIndex = 0;
432 | //
433 | // Browser
434 | //
435 | this.Browser.AllowWebBrowserDrop = false;
436 | this.Browser.Dock = System.Windows.Forms.DockStyle.Fill;
437 | this.Browser.Location = new System.Drawing.Point(0, 0);
438 | this.Browser.MinimumSize = new System.Drawing.Size(20, 20);
439 | this.Browser.Name = "Browser";
440 | this.Browser.ScriptErrorsSuppressed = true;
441 | this.Browser.Size = new System.Drawing.Size(321, 186);
442 | this.Browser.TabIndex = 0;
443 | this.Browser.WebBrowserShortcutsEnabled = false;
444 | //
445 | // RecentPaths
446 | //
447 | this.RecentPaths.FormSaver = this.FormSave;
448 | this.RecentPaths.Items = new string[0];
449 | this.RecentPaths.MenuItem = this.mnuRecentPaths;
450 | this.RecentPaths.SettingsNodeName = "Recent Paths";
451 | this.RecentPaths.ItemClick += new System.EventHandler(this.RecentPaths_ItemClick);
452 | //
453 | // MainForm
454 | //
455 | this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
456 | this.ClientSize = new System.Drawing.Size(542, 434);
457 | this.Controls.Add(this.Splitter);
458 | this.Controls.Add(this.Menustrip);
459 | this.Controls.Add(this.Status);
460 | this.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
461 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
462 | this.MainMenuStrip = this.Menustrip;
463 | this.Name = "MainForm";
464 | this.Text = "Disk Usage";
465 | this.TreeCtxMenu.ResumeLayout(false);
466 | this.Menustrip.ResumeLayout(false);
467 | this.Menustrip.PerformLayout();
468 | this.Status.ResumeLayout(false);
469 | this.Status.PerformLayout();
470 | this.Splitter.Panel1.ResumeLayout(false);
471 | this.Splitter.Panel2.ResumeLayout(false);
472 | ((System.ComponentModel.ISupportInitialize)(this.Splitter)).EndInit();
473 | this.Splitter.ResumeLayout(false);
474 | this.DetailSplitter.Panel1.ResumeLayout(false);
475 | this.DetailSplitter.Panel2.ResumeLayout(false);
476 | ((System.ComponentModel.ISupportInitialize)(this.DetailSplitter)).EndInit();
477 | this.DetailSplitter.ResumeLayout(false);
478 | this.BrowserPanel.ResumeLayout(false);
479 | this.ResumeLayout(false);
480 | this.PerformLayout();
481 |
482 | }
483 | #endregion
484 | }
485 | }
486 |
487 |
--------------------------------------------------------------------------------
/src/DiskUsage/MainForm.cs:
--------------------------------------------------------------------------------
1 | namespace DiskUsage
2 | {
3 | #region Using Directives
4 |
5 | using System;
6 | using System.Collections;
7 | using System.ComponentModel;
8 | using System.Data;
9 | using System.Diagnostics;
10 | using System.Diagnostics.CodeAnalysis;
11 | using System.Drawing;
12 | using System.IO;
13 | using System.Reflection;
14 | using System.Runtime.InteropServices;
15 | using System.Text;
16 | using System.Windows.Forms;
17 | using Menees;
18 | using Menees.Shell;
19 | using Menees.Windows.Forms;
20 | using Microsoft.Research.CommunityTechnologies.Treemap;
21 |
22 | #endregion
23 |
24 | public partial class MainForm
25 | {
26 | #region Private Data Members
27 |
28 | private const int ErrorImageIndex = 0;
29 | private const int FilesImageIndex = 1;
30 | private const int FolderImageIndex = 2;
31 |
32 | private Stopwatch? stopwatch;
33 |
34 | #endregion
35 |
36 | #region Constructors
37 |
38 | public MainForm()
39 | {
40 | this.InitializeComponent();
41 |
42 | // Get the OS's closed folder icon if possible.
43 | Icon? icon = null;
44 | ShellUtility.GetFileTypeInfo("Folder", false, IconOptions.Small | IconOptions.Folder, hIcon => icon = (Icon)Icon.FromHandle(hIcon).Clone());
45 | if (icon != null)
46 | {
47 | using (Image folderImage = icon.ToBitmap())
48 | {
49 | this.Images.Images[FolderImageIndex] = folderImage;
50 | }
51 | }
52 | }
53 |
54 | #endregion
55 |
56 | #region Internal Methods
57 |
58 | [SuppressMessage(
59 | "Microsoft.Design",
60 | "CA1031:DoNotCatchGeneralExceptionTypes",
61 | Justification = "Windows Forms doesn't automatically handle errors in OnIdle event handlers.")]
62 | internal void OnIdle(object? sender, EventArgs e)
63 | {
64 | try
65 | {
66 | bool scanning = this.MainWorker.IsBusy || this.RefreshWorker.IsBusy;
67 | this.mnuDrives.Enabled = !scanning;
68 | this.mnuChoosePath.Enabled = !scanning;
69 | this.mnuRecentPaths.Enabled = !scanning;
70 | this.mnuCancel.Enabled = scanning && !this.MainWorker.CancellationPending && !this.RefreshWorker.CancellationPending;
71 |
72 | bool directorySelected = !scanning && IsNodeADirectory(this.Tree.SelectedNode);
73 |
74 | this.mnuRefreshBranch.Enabled = directorySelected;
75 | this.mnuRefreshBranch2.Enabled = directorySelected;
76 | this.mnuOpenFolder.Enabled = directorySelected;
77 | this.mnuOpenFolder2.Enabled = directorySelected;
78 |
79 | this.Progress.Visible = scanning;
80 | this.lblProgressImage.Visible = scanning;
81 | this.Tree.Enabled = !scanning;
82 | }
83 | catch (Exception ex)
84 | {
85 | // We must explicitly call this because Application.Idle
86 | // doesn't run inside the normal ThreadException protection
87 | // that the Application provides for the main message pump.
88 | Application.OnThreadException(ex);
89 | }
90 | }
91 |
92 | #endregion
93 |
94 | #region Private Methods
95 |
96 | private static void AddDirectoryNode(TreeNodeCollection parentNodes, DirectoryData data)
97 | {
98 | TreeNode node = new();
99 |
100 | node.Tag = data;
101 | node.ImageIndex = GetImageForData(data);
102 | node.SelectedImageIndex = node.ImageIndex;
103 | node.Name = data.Name; // Map_NodeDoubleClick needs this so Nodes.IndexOfKey will work.
104 | SetNodeText(node, data);
105 |
106 | parentNodes.Add(node);
107 |
108 | if (data.SubData.Count > 0)
109 | {
110 | node.Nodes.Add(new DummyNode());
111 | }
112 | }
113 |
114 | private static int GetImageForData(DirectoryData data)
115 | {
116 | int result;
117 |
118 | switch (data.DataType)
119 | {
120 | case DirectoryDataType.Directory:
121 | result = FolderImageIndex;
122 | break;
123 |
124 | case DirectoryDataType.Files:
125 | result = FilesImageIndex;
126 | break;
127 |
128 | default:
129 | result = ErrorImageIndex; // Error or Unknown
130 | break;
131 | }
132 |
133 | return result;
134 | }
135 |
136 | private static void SetNodeText(TreeNode node, DirectoryData data)
137 | {
138 | node.Text = string.Format("{0}: {1:N1} MB", data.Name, data.SizeInMegabytes);
139 | }
140 |
141 | private static DirectoryData GetDataForNode(TreeNode node) => (DirectoryData)node.Tag;
142 |
143 | private static DirectoryData GetDataForNode(Node node) => (DirectoryData)node.Tag;
144 |
145 | private static string GetSuffix(double value) => Math.Round(value, 2) == 1 ? string.Empty : "s";
146 |
147 | private static bool IsNodeADirectory(TreeNode node)
148 | {
149 | bool result = false;
150 |
151 | if (node != null)
152 | {
153 | DirectoryData data = GetDataForNode(node);
154 | result = data.DataType == DirectoryDataType.Directory;
155 | }
156 |
157 | return result;
158 | }
159 |
160 | private static void SetDirectoryNodeImage(TreeNode node)
161 | {
162 | if (IsNodeADirectory(node))
163 | {
164 | DirectoryData data = GetDataForNode(node);
165 | int imageIndex = GetImageForData(data);
166 | node.ImageIndex = imageIndex;
167 | node.SelectedImageIndex = node.ImageIndex;
168 | }
169 | }
170 |
171 | private static string FormatLongUnits(long value, string unit)
172 | {
173 | StringBuilder sb = new();
174 | sb.AppendFormat("{0:N0}", value);
175 | sb.Append(' ').Append(unit);
176 | if (value != 1)
177 | {
178 | sb.Append('s');
179 | }
180 |
181 | return sb.ToString();
182 | }
183 |
184 | private void Exit_Click(object sender, System.EventArgs e)
185 | {
186 | this.Close();
187 | }
188 |
189 | private void ChoosePath_Click(object sender, System.EventArgs e)
190 | {
191 | string? selectedPath = WindowsUtility.SelectFolder(this, "Select a directory or drive:", null);
192 | if (selectedPath.IsNotEmpty())
193 | {
194 | this.PopulateTree(selectedPath);
195 | }
196 | }
197 |
198 | private void PopulateTree(string directoryName)
199 | {
200 | using (new WaitCursor(this))
201 | {
202 | this.Tree.BeginUpdate();
203 | this.Map.BeginUpdate();
204 | try
205 | {
206 | this.Tree.Nodes.Clear();
207 | this.Map.Clear();
208 | this.ClearFolderView();
209 | }
210 | finally
211 | {
212 | this.Tree.EndUpdate();
213 | this.Map.EndUpdate();
214 | }
215 |
216 | this.Text = "Disk Usage - " + directoryName;
217 | this.UpdateStatusBar("Scanning");
218 | this.stopwatch = Stopwatch.StartNew();
219 | this.Progress.Value = 0;
220 | this.RecentPaths.Add(directoryName);
221 | this.MainWorker.RunWorkerAsync(directoryName);
222 | }
223 | }
224 |
225 | private void UpdateStatusBar(TimeSpan totalTime)
226 | {
227 | const int SecondsPerMinute = 60;
228 | double seconds = totalTime.TotalSeconds;
229 | if (seconds >= SecondsPerMinute)
230 | {
231 | int minutes = ((int)seconds) / SecondsPerMinute;
232 | double remainingSeconds = seconds - (minutes * SecondsPerMinute);
233 | this.UpdateStatusBar(string.Format(
234 | "Total Time: {0} minute{1} {2:F2} second{3}",
235 | minutes,
236 | GetSuffix(minutes),
237 | remainingSeconds,
238 | GetSuffix(remainingSeconds)));
239 | }
240 | else
241 | {
242 | this.UpdateStatusBar(string.Format("Total Time: {0:F2} second{1}", seconds, GetSuffix(seconds)));
243 | }
244 | }
245 |
246 | private void UpdateStatusBar(string? message)
247 | {
248 | this.lblStatus.Text = message;
249 | }
250 |
251 | private void UpdateStatusBar(TreeNode selectedNode)
252 | {
253 | if (selectedNode != null)
254 | {
255 | DirectoryData selectedData = GetDataForNode(selectedNode);
256 | this.UpdateStatusBar(selectedData);
257 | }
258 | else
259 | {
260 | this.UpdateStatusBar(string.Empty);
261 | }
262 | }
263 |
264 | private void UpdateStatusBar(DirectoryData selectedData)
265 | {
266 | string message = string.Empty;
267 |
268 | if (selectedData != null)
269 | {
270 | switch (selectedData.DataType)
271 | {
272 | case DirectoryDataType.Directory:
273 | case DirectoryDataType.Files:
274 | DirectoryData rootData = GetDataForNode(this.Tree.Nodes[0]);
275 | double percentage = rootData.Size != 0 ? selectedData.Size / (double)rootData.Size : 0;
276 | message = string.Format(
277 | "{0:F2}% of total space usage. {1}. {2}. {3}.",
278 | 100 * percentage,
279 | FormatLongUnits(selectedData.Size, "byte"),
280 | FormatLongUnits(selectedData.FileCount, "file"),
281 | FormatLongUnits(selectedData.FolderCount, "folder"));
282 | break;
283 | }
284 | }
285 |
286 | this.UpdateStatusBar(message);
287 | }
288 |
289 | private void Tree_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
290 | {
291 | if (e.Node != null)
292 | {
293 | this.UpdateStatusBar(e.Node);
294 | this.UpdateMap(e.Node);
295 | this.UpdateFolderView(e.Node);
296 | }
297 | }
298 |
299 | private void UpdateMap(TreeNode treeNode)
300 | {
301 | using (new WaitCursor(this))
302 | {
303 | DirectoryData data = GetDataForNode(treeNode);
304 | this.Map.BeginUpdate();
305 | try
306 | {
307 | this.Map.Clear();
308 | this.Map.Nodes.Add(data.TreeMapNode);
309 | }
310 | finally
311 | {
312 | this.Map.EndUpdate();
313 | }
314 | }
315 | }
316 |
317 | private void RefreshBranch_Click(object sender, System.EventArgs e)
318 | {
319 | TreeNode selectedNode = this.Tree.SelectedNode;
320 | if (selectedNode != null)
321 | {
322 | // Force it to collapse first since we're populating the tree on-demand.
323 | selectedNode.Collapse();
324 |
325 | // Do the refresh asynchronously. Make a copy of the data now, so we can
326 | // adjust the stats all the way up the tree later.
327 | DirectoryData selectedData = GetDataForNode(selectedNode);
328 | DirectoryData selectedDataClone = selectedData.Clone();
329 | this.Progress.Value = 0;
330 | this.RefreshWorker.RunWorkerAsync(Tuple.Create(selectedNode, selectedData, selectedDataClone));
331 | }
332 | }
333 |
334 | private void OpenFolder_Click(object sender, System.EventArgs e)
335 | {
336 | TreeNode selectedNode = this.Tree.SelectedNode;
337 | if (selectedNode != null)
338 | {
339 | DirectoryData selectedData = GetDataForNode(selectedNode);
340 | if (selectedData.DataType == DirectoryDataType.Directory)
341 | {
342 | selectedData.Explore(this);
343 | }
344 | }
345 | }
346 |
347 | private void Tree_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
348 | {
349 | TreeNode node = this.Tree.GetNodeAt(e.X, e.Y);
350 | if (node != null)
351 | {
352 | TreeNode previouslySelectedNode = this.Tree.SelectedNode;
353 | this.Tree.SelectedNode = node;
354 |
355 | // If the user re-clicks the same node, then we need to resync the
356 | // Folder View because they probably drilled down through it and now
357 | // want to go back to the folder selected in the tree.
358 | if (previouslySelectedNode == node)
359 | {
360 | this.UpdateFolderView(node);
361 | }
362 | }
363 |
364 | // Force OnIdle to fire here because a right-click will popup a
365 | // menu before OnIdle gets a chance to enable/disable the items.
366 | this.OnIdle(sender, e);
367 | }
368 |
369 | #pragma warning disable CC0091 // Use static method. Designer likes instance event handlers.
370 | private void Tree_BeforeExpand(object sender, System.Windows.Forms.TreeViewCancelEventArgs e)
371 | #pragma warning restore CC0091 // Use static method
372 | {
373 | if (e.Node != null)
374 | {
375 | TreeNode node = e.Node;
376 |
377 | SetDirectoryNodeImage(node);
378 |
379 | if (node.FirstNode is DummyNode)
380 | {
381 | node.Nodes.Clear();
382 |
383 | DirectoryData data = GetDataForNode(node);
384 | foreach (DirectoryData childData in data.SubData)
385 | {
386 | AddDirectoryNode(node.Nodes, childData);
387 | }
388 | }
389 | }
390 | }
391 |
392 | #pragma warning disable CC0091 // Use static method. Designer likes instance event handlers.
393 | private void Tree_BeforeCollapse(object sender, System.Windows.Forms.TreeViewCancelEventArgs e)
394 | #pragma warning restore CC0091 // Use static method
395 | {
396 | if (e.Node != null)
397 | {
398 | SetDirectoryNodeImage(e.Node);
399 | }
400 | }
401 |
402 | private void About_Click(object sender, System.EventArgs e)
403 | {
404 | WindowsUtility.ShowAboutBox(this, Assembly.GetExecutingAssembly());
405 | }
406 |
407 | private void Drive_Click(object? sender, EventArgs e)
408 | {
409 | ToolStripMenuItem? mi = (ToolStripMenuItem?)sender;
410 | if (mi != null)
411 | {
412 | DriveInfo drive = (DriveInfo)mi.Tag;
413 | this.PopulateTree(drive.RootDirectory.FullName);
414 | }
415 | }
416 |
417 | #pragma warning disable CC0091 // Use static method. Designer likes instance event handlers.
418 | private void MainWorker_DoWork(object sender, DoWorkEventArgs e)
419 | #pragma warning restore CC0091 // Use static method
420 | {
421 | string? directoryName = (string?)e.Argument;
422 | if (directoryName.IsNotEmpty())
423 | {
424 | DirectoryInfo dirInfo = new(directoryName);
425 |
426 | // This does all the directory walking and sizing.
427 | BackgroundWorker bw = (BackgroundWorker)sender;
428 | DirectoryData data = new(dirInfo, bw);
429 |
430 | e.Result = data;
431 | e.Cancel = bw.CancellationPending;
432 | }
433 | }
434 |
435 | private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
436 | {
437 | this.Progress.Value = e.ProgressPercentage;
438 | string? directory = (string?)e.UserState;
439 | this.UpdateStatusBar(directory);
440 | }
441 |
442 | private void MainWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
443 | {
444 | using (new WaitCursor(this))
445 | {
446 | this.Tree.BeginUpdate();
447 | this.Map.BeginUpdate();
448 | try
449 | {
450 | DirectoryData? data;
451 | if (e.Error != null)
452 | {
453 | data = new DirectoryData(e.Error.Message);
454 | }
455 | else if (e.Cancelled)
456 | {
457 | data = new DirectoryData("Cancelled");
458 | }
459 | else
460 | {
461 | data = (DirectoryData?)e.Result ?? new DirectoryData("Empty");
462 | }
463 |
464 | // This populates the root of the tree.
465 | AddDirectoryNode(this.Tree.Nodes, data);
466 |
467 | // Select the first tree node so the map will update.
468 | if (this.Tree.SelectedNode == null)
469 | {
470 | this.Tree.SelectedNode = this.Tree.Nodes[0];
471 |
472 | // Expand it since that's almost always desired too.
473 | this.Tree.SelectedNode.Expand();
474 | }
475 |
476 | // Show the total time it took.
477 | if (this.stopwatch != null)
478 | {
479 | this.stopwatch.Stop();
480 | this.UpdateStatusBar(this.stopwatch.Elapsed);
481 | }
482 | }
483 | finally
484 | {
485 | this.Tree.EndUpdate();
486 | this.Map.EndUpdate();
487 | }
488 | }
489 | }
490 |
491 | private void Cancel_Click(object? sender, EventArgs e)
492 | {
493 | if (this.MainWorker.IsBusy && !this.MainWorker.CancellationPending)
494 | {
495 | this.MainWorker.CancelAsync();
496 | }
497 | else if (this.RefreshWorker.IsBusy && !this.RefreshWorker.CancellationPending)
498 | {
499 | this.RefreshWorker.CancelAsync();
500 | }
501 |
502 | this.UpdateStatusBar("Cancelling...");
503 | }
504 |
505 | #pragma warning disable CC0091 // Use static method. Designer likes instance event handlers.
506 | private void RefreshWorker_DoWork(object sender, DoWorkEventArgs e)
507 | #pragma warning restore CC0091 // Use static method
508 | {
509 | e.Result = e.Argument;
510 |
511 | var selection = (Tuple?)e.Argument;
512 | if (selection != null)
513 | {
514 | DirectoryData selectedData = selection.Item2;
515 |
516 | BackgroundWorker bw = (BackgroundWorker)sender;
517 | selectedData.Refresh(bw);
518 |
519 | e.Cancel = bw.CancellationPending;
520 | }
521 | }
522 |
523 | private void RefreshWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
524 | {
525 | using (new WaitCursor(this))
526 | {
527 | this.Tree.BeginUpdate();
528 | this.Map.BeginUpdate();
529 | try
530 | {
531 | if (e.Error != null || e.Cancelled)
532 | {
533 | TreeNode selectedNode = this.Tree.SelectedNode;
534 | TreeNodeCollection nodes;
535 | if (selectedNode != null)
536 | {
537 | nodes = selectedNode.Nodes;
538 | }
539 | else
540 | {
541 | nodes = this.Tree.Nodes;
542 | }
543 |
544 | nodes.Clear();
545 | string message = e.Error != null ? e.Error.Message : "Cancelled";
546 | DirectoryData data = new(message);
547 | AddDirectoryNode(nodes, data);
548 | this.UpdateStatusBar(message);
549 | }
550 | else if (e.Result is Tuple selection)
551 | {
552 | TreeNode selectedNode = selection.Item1;
553 | DirectoryData selectedData = selection.Item2;
554 | DirectoryData oldData = selection.Item3;
555 |
556 | SetNodeText(selectedNode, selectedData);
557 |
558 | // The nodes will have to be rebuilt below it.
559 | selectedNode.Nodes.Clear();
560 | if (selectedData.SubData.Count > 0)
561 | {
562 | selectedNode.Nodes.Add(new DummyNode());
563 | }
564 |
565 | // Recalculate the stats for everything above it.
566 | TreeNode parentNode = selectedNode.Parent;
567 | long sizeAdjustment = selectedData.Size - oldData.Size;
568 | long fileCountAdjustment = selectedData.FileCount - oldData.FileCount;
569 | long folderCountAdjustment = selectedData.FolderCount - oldData.FolderCount;
570 | while (parentNode != null)
571 | {
572 | DirectoryData parentData = GetDataForNode(parentNode);
573 | parentData.AdjustStats(sizeAdjustment, fileCountAdjustment, folderCountAdjustment);
574 | SetNodeText(parentNode, parentData);
575 | parentNode = parentNode.Parent;
576 | }
577 |
578 | // Refresh the treemap
579 | this.UpdateMap(selectedNode);
580 |
581 | // Refresh the status bar
582 | this.UpdateStatusBar(selectedNode);
583 |
584 | // Expand it if it's the root node since that's almost always desired too.
585 | if (selectedNode == this.Tree.Nodes[0])
586 | {
587 | selectedNode.Expand();
588 | }
589 | }
590 | }
591 | finally
592 | {
593 | this.Tree.EndUpdate();
594 | this.Map.EndUpdate();
595 | }
596 | }
597 | }
598 |
599 | private void Map_SelectedNodeChanged(object? sender, EventArgs e)
600 | {
601 | Node node = this.Map.SelectedNode;
602 | if (node != null)
603 | {
604 | this.UpdateStatusBar(GetDataForNode(node));
605 | }
606 | else
607 | {
608 | this.UpdateStatusBar(string.Empty);
609 | }
610 | }
611 |
612 | private void Drives_DropDownOpening(object? sender, EventArgs e)
613 | {
614 | using (new WaitCursor(this))
615 | {
616 | this.mnuDrives.DropDownItems.Clear();
617 |
618 | foreach (DriveInfo drive in DriveInfo.GetDrives())
619 | {
620 | if (drive.IsReady)
621 | {
622 | long totalSize = drive.TotalSize;
623 | double percentFree = totalSize == 0 ? 0.0 : 100 * ((double)drive.TotalFreeSpace) / totalSize;
624 | string text = string.Format(
625 | "{0} - \"{1}\" - {2} - {3:##0.0}% free",
626 | drive.Name,
627 | drive.VolumeLabel,
628 | drive.DriveType,
629 | percentFree);
630 | ToolStripMenuItem mi = new(text, DiskUsage.Properties.Resources.Drive, this.Drive_Click)
631 | {
632 | ImageTransparentColor = Color.Magenta,
633 | Tag = drive,
634 | };
635 | this.mnuDrives.DropDownItems.Add(mi);
636 | }
637 | }
638 | }
639 | }
640 |
641 | private void RecentPaths_ItemClick(object sender, RecentItemClickEventArgs e)
642 | {
643 | this.PopulateTree(e.Item);
644 | }
645 |
646 | private void Map_NodeDoubleClick(object sender, NodeEventArgs e)
647 | {
648 | // Because the tree auto-populates as its nodes are expanded,
649 | // we have to drill down one level at a time by parsing the path.
650 | // We can't assume that a given Treemap.Node will already have
651 | // an associated TreeViewNode.
652 | Node node = e.Node;
653 | if (node != null && this.Tree.Nodes.Count > 0)
654 | {
655 | TreeNode rootTreeNode = this.Tree.Nodes[0];
656 | DirectoryData rootData = GetDataForNode(rootTreeNode);
657 |
658 | DirectoryData data = GetDataForNode(node);
659 | if (data != null && rootData != null)
660 | {
661 | string fullName = data.FullName;
662 | string rootFullName = rootData.FullName;
663 | if (!string.IsNullOrEmpty(fullName) && !string.IsNullOrEmpty(rootFullName) &&
664 | fullName.StartsWith(rootFullName, StringComparison.CurrentCultureIgnoreCase))
665 | {
666 | // Remove the root path first.
667 | fullName = fullName.Remove(0, rootFullName.Length);
668 |
669 | // Now get the remaining path parts, so we can find their tree nodes.
670 | string[] parts = fullName.Split(new char[] { Path.DirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);
671 |
672 | TreeNode? currentNode = rootTreeNode;
673 | foreach (var partName in parts)
674 | {
675 | currentNode.Expand();
676 | int childIndex = currentNode.Nodes.IndexOfKey(partName);
677 | if (childIndex >= 0)
678 | {
679 | currentNode = currentNode.Nodes[childIndex];
680 | }
681 | else
682 | {
683 | currentNode = null;
684 | break;
685 | }
686 | }
687 |
688 | if (currentNode != null)
689 | {
690 | this.Tree.SelectedNode = currentNode;
691 | }
692 | }
693 | }
694 | }
695 | }
696 |
697 | private void UpdateFolderView(TreeNode treeNode)
698 | {
699 | using (new WaitCursor(this))
700 | {
701 | DirectoryData data = GetDataForNode(treeNode);
702 | string? directory = null;
703 | bool clearView = false;
704 | switch (data.DataType)
705 | {
706 | case DirectoryDataType.Directory:
707 | directory = data.FullName;
708 | break;
709 | case DirectoryDataType.Files:
710 | // Show the directory where the files are located.
711 | directory = Path.GetDirectoryName(data.FullName);
712 | break;
713 | case DirectoryDataType.Error:
714 | clearView = true;
715 | break;
716 | }
717 |
718 | if (!string.IsNullOrEmpty(directory))
719 | {
720 | // Make sure the directory is accessible for navigation. Otherwise, the
721 | // WebBrowser control pops up a modal error dialog.
722 | if (Directory.Exists(directory))
723 | {
724 | try
725 | {
726 | // See if we can read anything in the directory (by looking for a GUID filename that should never exist).
727 | // This throws an exception if we can't read from the folder.
728 | Directory.GetFiles(directory, "4322F6AF-27BA-419C-AB4D-5FF8862B338C", SearchOption.TopDirectoryOnly);
729 |
730 | // When arrowing down quickly between tree nodes, the browser may not finish navigating to one folder
731 | // before the next navigation request comes in (since it navigates asynchronously from the UI thread).
732 | // To prevent a COMException from being thrown, we'll request that any pending navigation stop first.
733 | this.Browser.Stop();
734 | this.Browser.Navigate(new Uri(directory, UriKind.Absolute), false);
735 | }
736 | catch (COMException)
737 | {
738 | clearView = true;
739 | }
740 | catch (UnauthorizedAccessException)
741 | {
742 | clearView = true;
743 | }
744 | }
745 | else
746 | {
747 | clearView = true;
748 | }
749 | }
750 |
751 | if (clearView)
752 | {
753 | this.ClearFolderView();
754 | }
755 | }
756 | }
757 |
758 | private void ClearFolderView()
759 | {
760 | try
761 | {
762 | this.Browser.Stop();
763 | this.Browser.Url = null;
764 | }
765 | #pragma warning disable CC0004 // Catch block cannot be empty
766 | catch (COMException)
767 | {
768 | // There's nothing we can do here. This occurs if the browser is still navigating to the previous URI and can't stop.
769 | }
770 | #pragma warning restore CC0004 // Catch block cannot be empty
771 | }
772 |
773 | #endregion
774 |
775 | #region Private Types
776 |
777 | private class DummyNode : TreeNode
778 | {
779 | }
780 |
781 | #endregion
782 | }
783 | }
784 |
--------------------------------------------------------------------------------
/src/DiskUsage/MainForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | False
122 |
123 |
124 | 320, 17
125 |
126 |
127 | 124, 17
128 |
129 |
130 |
131 | AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
132 | LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
133 | ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABu
134 | EQAAAk1TRnQBSQFMAgEBAwEAAUABAAFAAQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA
135 | AwABEAMAAQEBAAEgBgABEFIAAbcBogGTAf8BWwFBAS0B/wFbAUEBLQH/AVsBQQEtAf8BWwFBAS0B/wFb
136 | AUEBLQH/AVsBQQEtAf8BWwFBAS0B/wFbAUEBLQH/AVsBQQEtAf8BWwFBAS0B/xwAAeoB9QH3Af8BuAHh
137 | AeoB/wF1AcgB2gH/AUQBswHMAf8BWwGvAcQB/wGsAc8B2gH/AeUB8QH1Af9sAAHPAdgB8gH/AVIBagG5
138 | Af8BGwE1AZMB/wETASgBbwH/AQwBIgFmAf8BCwEmAXcB/wFBAVcBpAH/Ac8B2AHyAf8QAAG3AaIBkwX/
139 | AbcBogGTAf8BtwGiAZMB/wG3AaIBkwH/AbcBogGTAf8BtwGiAZMB/wG3AaIBkwH/AbcBogGTAf8BtwGi
140 | AZMB/wFbAUEBLQH/GAABjQHWAeYB/wFWAcMB2QH/AVQBwAHWAf8BVQG/AdYB/wFXAb8B1gH/ATsBrwHK
141 | Af8BQgGmAcEB/wFNAbgB1AH/AVUBwAHXAf8BVAG/AdcB/wFTAb4B1gH/AWkBxwHbAf8BswHgAeoB/1AA
142 | AeYB6gH4Af8BdwGUAdQB/wEmAUUBqwH/ARQBOQG4Af8BBAE0AdAB/wEAATEB4QH/AQABLgHbAf8BAAEr
143 | AbwB/wEAASIBlgH/AQMBHQF0Af8BXgFxAbIB/wHmAeoB+AH/CAABtwGiAZMF/wG3AaIBkwH/AVsBQQEt
144 | Af8BWwFBAS0B/wFbAUEBLQH/AVsBQQEtAf8BWwFBAS0B/wFbAUEBLQH/AVsBQQEtAf8BWwFBAS0B/wFb
145 | AUEBLQH/AVsBQQEtAf8QAAFjAc4B4QH/AYAB1AHkAf8BbgHOAeAB/wFmAckB3QH/AV4BxAHaAf8BOwGv
146 | AcoB/wE6AaYBwwH/AUUBuAHXAf8BRQHBAd4B/wFFAcEB3gH/AUUBwQHeAf8BRwHBAd0B/wFqAccB2wH/
147 | UAABiAGcAdsB/wEzAVIBugH/ARQBRAHdAf8BAQE7AfoB/wEAATkB+QH/AT8BawH6Af8BPgFpAfYB/wEA
148 | ATAB7AH/AQABLgHjAf8BAAEnAbUB/wEAARwBdQH/AV8BcQGyAf8IAAG3AaIBkwX/AbcBogGTBf8BtwGi
149 | AZMB/wG3AaIBkwH/AbcBogGTAf8BtwGiAZMB/wG3AaIBkwH/AbcBogGTAf8BtwGiAZMB/wG3AaIBkwH/
150 | AVsBQQEtAf8QAAFnAdEB5AH/AYkB2wHoAf8BgAHUAeQB/wFuAc4B4AH/AWYByQHdAf8BOwGvAcoB/wE8
151 | AagBxAH/AUUBuAHXAf8BRQHBAd4B/wFFAcEB3gH/AUUBwQHeAf8B0wGlAUAB/wFUAb8B1wH/TAABzwHY
152 | AfIB/wFIAWMBxgH/ASYBUgHjAf8BFQFKAf0B/wESAUgB/QH/AU4BdwH8Af8D/gH/A/4B/wFRAYAB+gH/
153 | AQABMwHvAf8BAAEvAeQB/wEAAScBtgH/AQMBHQFzAf8BzwHYAfIB/wQAAbcBogGTBf8BtwGiAZMF/wG3
154 | AaIBkwH/AVsBQQEtAf8BWwFBAS0B/wFbAUEBLQH/AVsBQQEtAf8BWwFBAS0B/wFbAUEBLQH/AVsBQQEt
155 | Af8BWwFBAS0B/wFbAUEBLQH/AVsBQQEtAf8IAAFsAdQB5wH/AZIB4QHsAf8BiQHbAegB/wGAAdQB5AH/
156 | AW4BzgHgAf8BPAGwAcoB/wFAAakBxAH/AUkBugHYAf8BSQHDAd8B/wFFAcEB3gH/AUUBwQHeAf8B3QG5
157 | AVQB/wFVAcAB2AH/TAABpwG2AeUB/wFFAWgB2QH/ASQBVwL/ASUBWQL/ASUBVwL/AVsBiQH+Af8D/gH/
158 | A/4B/wFIAXEB+wH/AQABNwH5Af8BAAEyAe4B/wEAAS4B5AH/AQEBIgGWAf8BQQFXAaQB/wQAAboBpQGW
159 | Bf8BtwGiAZMF/wG3AaIBkwX/AbcBogGTAf8BtwGiAZMB/wG3AaIBkwH/AbcBogGTAf8BtwGiAZMB/wG3
160 | AaIBkwH/AbcBogGTAf8BtwGiAZMB/wFbAUEBLQH/CAABcAHYAekB/wGbAecB8AH/AZIB4QHsAf8BiQHb
161 | AegB/wGAAdQB5AH/AT4BsgHMAf8BRQGsAcYB/wFNAbwB2QH/AVIBxwHhAf8BTQHFAeAB/wFJAcMB3wH/
162 | A+wB/wFXAcEB2QH/TAABaAGIAdUB/wFDAWoB7gH/ATcBZQL/ATkBZwL/ATYBZQL/ATEBYgL/AWIBjgL/
163 | AVoBhwH+Af8BEwFKAfwB/wEFAUAB+wH/AQABNQH4Af8BAAExAeoB/wEAASsBvQH/AQwBJgF3Af8EAAG+
164 | AakBmgX/AbcBogGTBf8BtwGiAZMJ/wH8AfoB+QH/AfcB8QHuAf8B8QHnAeEB/wHsAd0B1QH/AeYB0wHJ
165 | Af8B4QHKAb0B/wG3AaIBkwH/AVsBQQEtAf8IAAF0AdsB7AH/AaMB7AH0Af8BmwHnAfAB/wGSAeEB7AH/
166 | AYkB2wHoAf8BQQG0Ac4B/wFLAa8ByAH/AVMBvwHaAf8BXQHNAeQB/wFXAcoB4wH/AVIBxwHhAf8D7AH/
167 | AVkBwgHaAf9MAAGBAZQB0QH/AUkBcAH7Af8BSgF0Av8BTQF3Av8BSgF0Av8BVgGFAv8D/gH/A/4B/wE1
168 | AWUB/QH/ARABSAH7Af8BAgE9AfkB/wEAATMB8wH/AQABLgHdAf8BDAEiAWYB/wQAAcwBtgGnBf8BugGl
169 | AZYF/wG3AaIBkwn/A/4B/wH6AfcB9QH/AfUB7QHpAf8B7wHjAdwB/wHqAdkB0QH/AeQBzwHEAf8BtwGi
170 | AZMB/wFbAUEBLQH/CAABgQHeAe4B/wGqAfEB9wH/AaMB7AH0Af8BmwHnAfAB/wGSAeEB7AH/AUUBtwHQ
171 | Af8BUgGyAckB/wFaAcIB3AH/AWoB0wHoAf8BZAHQAeYB/wFdAc0B5AH/A+wB/wFaAcMB2wH/TAABigGb
172 | AdQB/wFYAYYB+wH/AV0BigL/AWABjgL/AV4BjAL/AZUBrwL/A/4B/wP+Af8BcQGaAv8BGQFPAf0B/wEJ
173 | AUEB+wH/AQABNgH4Af8BAAExAeIB/wETASkBbgH/BAAB0QG7AasF/wG+AakBmgX/AbcBogGTDf8B/QH8
174 | AfsB/wH4AfMB8AH/AfIB6QHjAf8B7QHfAdgB/wHnAdUBywH/AbcBogGTAf8BWwFBAS0B/wgAAYQB4AHw
175 | Af8BsAH1AfkB/wGqAfEB9wH/AaMB7AH0Af8BxgHxAfYB/wFJAboB0gH/AVgBtgHLAf8BYAHGAd4B/wGC
176 | AdoB7AH/AXEB1wHqAf8BagHTAegB/wFkAdAB5gH/AVwBxQHcAf9MAAGKAZ4B3AH/AXEBlgHyAf8BcAGa
177 | Av8BdAGcAv8BcQGZAv8BsQHEAv8D/gH/A/4B/wGiAbgB/gH/ASABVAH+Af8BDwFHAfsB/wEAATkB+AH/
178 | AQQBMwHQAf8BGwE2AZMB/wQAAdUBvwGvBf8BzAG2AacF/wG6AaUBlhH/AfsB+AH3Af8B9gHvAesB/wHw
179 | AeUB3wH/AesB2wHTAf8BtwGiAZMB/wFbAUEBLQH/CAABiAHjAfIB/wG0AfcB+wH/AbAB9QH5Af8BqgHx
180 | AfcB/wHoAfoB/AH/AU0BvQHUAf8BXwG5Ac0B/wFnAckB4AH/AZAB4gHwAf8BiQHeAe4B/wGCAdoB7AH/
181 | AWYBzAHiAf8BpAHcAeoB/0wAAacBtgHlAf8BjQGiAeUB/wGHAaUC/wGNAagC/wGIAaMC/wHFAdMB/gH/
182 | A/4B/wP+Af8BtQHHAf4B/wEkAVcC/wETAUoB/AH/AQEBOwH6Af8BFAE5AbgB/wFcAXIBugH/BAAB2AHC
183 | AbIF/wHRAbsBqwX/Ab4BqQGaEf8B/gH9AfwB/wH5AfUB8gH/AfQB6wHmAf8B7gHhAdoB/wG3AaIBkwH/
184 | AVsBQQEtAf8IAAGKAeUB8wH/AbQB9wH7Af8BtAH3AfsB/wGwAfUB+QH/AfQB/QH+Af8BUQHAAdcB/wFl
185 | AbwBzgH/AW0BzAHhAf8BngHpAfMB/wGXAeUB8gH/AZAB4gHwAf8BYgHJAd8B/1AAAc8B2AHyAf8BlwGn
186 | Ad0B/wGUAaoB8QH/AZkBsgL/AY0BqAL/AakBvgL/A/4B/wP+Af8BgwGhAv8BJgFaAv8BFAFLAf0B/wEU
187 | AUQB3AH/ASYBRAGsAf8BzwHYAfIB/wQAAdgBwgGyAf8B2AHCAbIB/wHVAb8BrwX/AcwBtgGnGf8B/QH8
188 | AfsB/wG3AaIBkwH/AbcBogGTAf8BXAFCAS4B/wgAAY0B5gH1Af8BtAH3AfsB/wG0AfcB+wH/AbQB9wH7
189 | Af8B/AP/AVYBxAHaAf8BawG+AdAB/wF0Ac8B4wH/AawB7wH3Af8BpQHsAfUB/wGeAekB8wH/AWUBygHh
190 | Af9UAAG0AcIB7AH/AZsBqgHdAf8BlQGrAfEB/wGHAaUC/wFwAZoC/wFcAYsC/wFKAXQC/wE3AWUC/wEl
191 | AVkC/wEmAVIB4wH/ATIBUQG7Af8BbQGMAdQB/xAAAdgBwgGyBf8B0QG7AasZ/wG3AaIBkwH/AVwBQgEu
192 | Af8BXAFCAS4B/wFcAUIBLgH/CAABjQHnAfUB/wG0AfcB+wH/AbQB9wH7Af8BtAH3AfsF/wFbAcgB3QH/
193 | AW8BwAHRAf8BgQHSAeUB/wG3AfQB+gH/AbEB8gH5Af8BrAHvAfcB/wFnAcwB4gH/VAAB5gHqAfgB/wG0
194 | AcIB7AH/AZcBpwHdAf8BjQGjAeUB/wFxAZYB8gH/AVgBhgH7Af8BSAFyAfsB/wFEAWsB7gH/AUUBaAHY
195 | Af8BSAFjAcYB/wF2AZUB3AH/AeYB6gH4Af8QAAHYAcIBsgH/AdgBwgGyAf8B1QG/Aa8Z/wG5AaQBlQH/
196 | AdQBxQG6Af8BXAFCAS4B/wHhAdUBzQH/CAABjQHnAfUB/wG0AfcB+wH/AbQB9wH7Af8B/AP/AfwD/wFg
197 | AcsB4AH/AXYBxgHVAf8BrgHuAfYB/wG/AfkB/AH/AbsB9wH7Af8BtwH0AfoB/wFpAc0B5AH/XAABzAHY
198 | Af4B/wGdAa0B4AH/AYoBngHcAf8BigGbAdQB/wGBAZQB0QH/AWgBiQHVAf8BXAFyAboB/wFcAXIBugH/
199 | IAAB2AHCAbIZ/wHAAasBnAH/AVwBQgEuAf8B4gHWAc0B/wwAAY0B5wH1Af8BsQH2AfsB/wHpAfsB/QH/
200 | AZkB6gH0Af8BhwHfAe0B/wFwAc0B3AH/AbwB9QH6Af8BwgH6Af0B/wHCAfoB/QH/AcIB+gH9Af8BtgH0
201 | AfkB/wGGAdUB6AH/nAAB2AHCAbIB/wHYAcIBsgH/AdgBwgGyAf8B2AHCAbIB/wHYAcIBsgH/AdQBvgGu
202 | Af8BzwG5AakB/wHJAbMBpAH/AeIB1gHNAf8QAAGuAewB9wH/AY4B5wH1Af8BjQHkAfQB/wGJAeAB8gH/
203 | AYgB3gHxAf8BiQHdAfEB/wGGAdsB7wH/AYMB2QHuAf8BgAHXAewB/wF0AdUB6gH/AYoB2AHrAf8BvgHn
204 | AfIB/0wAAUIBTQE+BwABPgMAASgDAAFAAwABEAMAAQEBAAEBBQABgBcAA/8BAAL/AQABHwHAAX8CAAHw
205 | AQ8BAAEfAYABAwIAAcABAwEAAQcBgAEDAgABwAEDAQABBwGAAQMCAAGAAQEBAAEBAYABAwIAAYABAQEA
206 | AQEBgAEDAgABgAEBAQABAQGAAQMCAAGAAQEBAAEBAYABAwIAAYABAQEAAQEBgAEDAgABgAEBAQABAQGA
207 | AQMCAAGAAQEBAAEBAYABBwIAAYABAQEAAQEBgAEHAgABwAEDAcABAQGAAQcCAAHAAQMBwAEBAYABBwIA
208 | AfABDwHwAQMBgAEHAgAC/wHwAQcBgAEHAgAL
209 |
210 |
211 |
212 | 215, 17
213 |
214 |
215 | 17, 17
216 |
217 |
218 | 444, 17
219 |
220 |
221 |
222 |
223 | AAABAAMAMDAAAAEAIACoJQAANgAAACAgAAABACAAqBAAAN4lAAAQEAAAAQAgAGgEAACGNgAAKAAAADAA
224 | AABgAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
225 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
226 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
227 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
228 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
229 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
230 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
231 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
232 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
233 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
234 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
235 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAA
236 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
237 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
238 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAIAAAADAAAAA4AAAANAAAACgAA
239 | AAcAAAAEAAAAAgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
240 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
241 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABwAAABkAAAAqAAAAPQAA
242 | AEQAAAA7AAAAKwAAAB0AAAAYAAAAEwAAAA0AAAAIAAAABQAAAAIAAAABAAAAAAAAAAAAAAAAAAAAAAAA
243 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
244 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAOAAAAJQAA
245 | AEMAAACDaGho1nZ2duJ2d3bopJ+g5nZ0c7sgHh59AAAATgAAADsAAAAmAAAAFwAAABAAAAAMAAAABwAA
246 | AAQAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
247 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACAAA
248 | ABsAAAAzAAAAYhcXF7p1dXX7hoeG/4iIiP+FhYX/lZWT/5qWlv/GwMD/ycPD/peUlPBxbm7MKygoigIA
249 | AWAAAABDAAAALgAAABoAAAATAAAADQAAAAkAAAAFAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
250 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
251 | AAMAAAARAAAAKQAAAEgAAACLQ0ND5Xx8fP+wsLD/iYmJ/2tqav8fHx//RWhR/32Cfv98fHz/npub/8C4
252 | uP/Pxsb/zcjI/8jBwf+gnp77eXh43CQlJYUAAABiAAAASgAAACwAAAAXAAAAEAAAAAsAAAAHAAAAAwAA
253 | AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
254 | AAAAAAAAAAAABwAAABkAAAA2AAAAZBgYGLpoaGj+iYmJ/4SEhP+SkpL/gYGA/1JSUv8AAAD/C7lN/xyE
255 | Q/+tpaj/qaam/5uZmf+GhYX/fHt7/7OwsP/NxMT/0snJ/9DKyv/Evr7/nZqa+3JxcdYiIiOGAAAAXgAA
256 | AEAAAAAhAAAAEwAAAA4AAAAHAAAABAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
257 | AAAAAAAAAAAAAAAAAAMAAAAPAAAAJAAAAEYAAACNRkZG5oCAgP+Li4v/fn5+/3V1df+Ghob/e3t8/1JR
258 | Uf8AAAD/E8dW/xWHP/+6rrL/vba2/8O9vP/NxMT/uLOz/7Gtrf+empr/hISE/35+fv+0sbD/xb29/9XN
259 | zf/Qysr/w729/5uXl/deXl6uERAQaQAAAEIAAAAoAAAADwAAAAcAAAAEAAAAAQAAAAAAAAAAAAAAAAAA
260 | AAAAAAAAAAAAAAAAAAAAAAABAAAACAAAABwAAAA2AAAAZiIiIsRxcXH/i4uL/4ODg/92dnb/dXV1/4KC
261 | gv+hoaH/fn19/1VUU/8AAAD/DN9a/xiKQv+0qq7/v7q6/8a+vv/OxcX/1c3O/93S0v/j2Nj/6d7e/8W9
262 | vf+2srH/mpmZ/4KBgf+IiIj/ubW1/9LJyf/Rycn/z8nJ/7GsrP6Mioy4X19fbQAAAB0AAAACAAAAAgAA
263 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAOAAAAKAAAAEgAAACSTExM6IKCgv+Li4v/fX19/3Z2
264 | dv99fX3/jIyM/5+fn//Lzc3/fHt7/4iFhf8hHSH/AO1U/x2GQ/+6r7L/wbu7/8fAwP/Rx8f/2M/P/97U
265 | 1P/l29v/7N/f/+/k5P/y5ub/9Ojo/9XNzP/LxMT/rqqq/5aUlP99fHz/o6Gh/8G5uf/Tycn/0cnJ/7q2
266 | tvgiIiJOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABwAAABgAAAAxAAAAZSEhIcJxcXH+jIyM/4SE
267 | hP95eXn/e3t7/4eHh/+ampr/r6+v/8PDw//j4+P/k5OT/4KAgP+RjY7/YXFk/y+JT//AuLr/wby7/8rB
268 | w//Sysr/2dDQ/9/V1f/m3Nz/7eLh//Dk5P/z5+f/9Ojo//To6P/06Oj/8OXl/+3i4v/LxcX/ube3/6Oh
269 | of+NjIz/jY2N/764uP+8uLjmubS0YgAAAAAAAAAAAAAAAAAAAAMAAAANAAAAIwAAAEIAAACIS0tL5oaG
270 | hv+MjIz/f39//3t7e/+Dg4P/lJSU/6mpqf+9vb3/zc3N/9nZ2f/p6en/3Nzc/3Jycf+Bf3//kJeR/6Sx
271 | pv/Ev77/0srK/9TNy//Yz8//3dLS/+LX1//n3d3/7uPi//Hl5f/z6Of/9Ojo//To6P/z6Oj/7+Xl/+zh
272 | 4f/l3Nz/39fX/9jS0f/Tzs7/z8rK/4KCgv+Zl5f6wbu76QAAAAAAAAAAAAAABwAAABkAAAAzAAAAaSAg
273 | IL5ubm78jo6O/4eHh/9+fn7/gYGB/5CQkP+lpaX/u7u7/8rKyv/X19f/4+Pj/+fn5//c3Nz/1NTU/8HB
274 | w/+XmJj/i4yK/4ODgv+Dg4P/ko+P/66qqv/KxcX/4tjY//Ln6P/26en/9Ojo//Tn6P/06Oj/9Ojo//To
275 | 6P/y5+f/7uTk/+jf3//j29v/3dXU/9jR0f/Szcv/z8rK/6akpP+VlJT/ycLC4wAAAAIAAAALAAAAIwAA
276 | AEcAAACWVVVV74yMjP+QkJD/goKC/4CAgP+MjIz/n5+f/7W1tf/IyMj/1dXV/+Li4v/o6Oj/4uLi/83N
277 | zf+9vb3/urq6/7y8vP/BwcH/yMjK/7a2tv+tra3/mZmZ/3l5ef9ubm7/gX9//5yZmf+yrq//0cnI/+ni
278 | 4f/79PP/+vf1//ry8P/37Ov/8OTj/+je3v/i2Nn/29PT/9XQz//Qy8v/zcbH/7u2tv+EhIT/ycLC5gAA
279 | AA0AAAAkAAAASB4eHrp9fX3/kpKS/4qKiv+BgYH/iYmJ/5ubm/+wsLD/w8PD/9HR0f/f39//5+fn/+Tk
280 | 5P/R0dH/v7+//7q6uv+6urv/tLS0/6+vr/+1tbX/wMHB/8XFxv/Iysr/0NHR/9LT1P/Dw8T/r7Cw/52e
281 | nv+JiIn/goCA/5CNjf+loaH/uLO0/8i/wP/c0NH/6d/g//Dm5//u5ub/5Nzd/9vU1P/Szc3/zcfH/726
282 | u/+CgoL/ycLC5gAAABkAAAAtAAAAd5GRkf+YmJj/h4eH/4aGhv+Tk5P/qamp/76+vv/Ozs7/29vb/+Xl
283 | 5f/k5eX/09PT/7+/v/+2trb/tLS1/7W1tf+2trb/uLi6/7q7u/++vb7/v7+//8HBw//ExMX/xcXG/8jK
284 | y//P0NH/09XX/9zd3v/j5OX/2dvc/8TFxv+zs7X/jo+P/4ODg/9/f37/jYqK/5uamf+koqT/p6Sk/66s
285 | rP++u7v/xsHD/6Shof+Dg4P/ycLC4wAAABcAAAAcNDQ0nLKysv+Ojo7/jo6O/6Ghof+2trb/yMjI/9fX
286 | 1//j4+P/5eXl/9PU1P+6urr/rKur/6mmpf+sqaf/s6+s/7u0sf/BvLX/ysO9/9nQy//o39n/7+fi/+/o
287 | 4v/s5N7/49zY/9zX0//V0s//0s/O/9DPz//T09T/2dze/+Tl5//p7e//8fP0//Hz9P/j5eb/z9DR/8jJ
288 | yv+ys7P/mpqb/5aWl/+NjY3/k5OT/5eXl/+lpaXsy8PDowAAAAoAAAAFXV1dr7S0tP+ioqL/tLS0/8bG
289 | xv/U1NT/4uLi/+Xm5v/R0dH/p6am/42Liv+Ni4f/nZqV/66rp/+4tLP/wL27/8XBwP/Kx8X/zcvI/9HP
290 | zv/X1NP/2djX/97c2f/h3tz/49/e/+Th3v/k4d3/4t3b/9vX0//Ry8f/x8PB/8fGxv/Y2dz/5ujs/+7w
291 | 8v/z9Pj/9vn7//f5+//y9vf/6Ons//Hx8f/R0tP/s7Oz/q+vr/i/v79vAAAAAAAAAAMAAAAAa2trrsvL
292 | y//Dw8P/0dHR/97e3v/m5ub/3d7e/76+vv+GhoT/f359/6KhoP+7urj/xMTD/8fIyP/Kysr/y8vL/83N
293 | zf/Oz8//z9DQ/8fHx/+pqaj/nZub/6+vr//Nzs7/4eHh/+Xl5f/o6On/7e7u//Dw8P/w7+//7Ojn/9vY
294 | 1P/Nysj/3t/f/+/x8//y9Pf/8/b4//Dy9P/Lzc7/tLW1/6+vr/y1tbXJtra2YsTExAIAAAAAAAAAAAAA
295 | AAEAAAAAXl5enObm5v/c3Nz/5eXl/+Hh4f/Pz8//wMDB/6ysrP+WlZb/vb2+/8vLy//Ky8r/y8vL/83N
296 | zf/Pz8//0tLS/9TU1P/X2Nf/ycfG/45tXP+VTij/l0sj/3ROOv+QjYv/3Nzb//Dw8P/y8vL/9vT0//j4
297 | 9//5+vn/+/v7//v7+//39vf/8fLy//Hz9v/d3uH/v8DB/6yurv6zs7TWtra2eby8vA0AAAAAAAAAAAAA
298 | AAAAAAAAAAAAAAAAAAAAAAAAKiYmYPHx8f/k5eX/0tLS/8HBwf+8vb3/vL29/72+vv/BwcP/zs7O/9DP
299 | z//R0dH/09PT/9XV1f/Z2dn/3Nzc/9/e3//j4uP/vpuH/7RfNP+4VR//ylwh/9lhIv93UD3/yMjI//f3
300 | 9//6+vr/+/v7//v7+//7+/v/+/v7//v7+//n5+f/xcbG/a6urvyysrLhs7OzjLW1tRsAAAAAAAAAAAAA
301 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASmBgEamrq9Wvr6/qtLS0+ry8vP/Bw8P/xcbG/8bG
302 | x//Gx8j/ysrL/9HR0v/X19f/3Nzc/9/h4f/k5OP/5ubm/+zp6f/t7e3/yKKN/6JaNP+nTR7/t1Qf/8pc
303 | If+TTyz/x8fH//r6+v/7+/v/+/v7//v7+//u7u7/zs7P/7CwsPqvsLDrsbGxlq+vrx8AAAAAAAAAAAAA
304 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAq6urA6urq2aqqqqaqampzKqq
305 | qvWqqqr1q6ur7rCwsPG5ubn6xMTF/87Pz//V19f/2dvc/9zd3v/f4eL/4+Tl/+fn6P/s7e3/z7Ok/7mN
306 | df+aSiD/p04f/7xZJP+PYEf/4eLj//f5+v/v8PL/0dHS/7S1tfeurq72sLCwq66urjQAAAAAAAAAAAAA
307 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
308 | AAAAAAAAAAAAAAAAAACrq6sYq6urRaqqqnipqamsqqqq3aurq/6srKzzsLCx6ri4uOzBw8T0z9DS++Hj
309 | 5P/c3t//mpOP/8Spmf/PrZz/yJuC/653W/+spKH/1tfY/7q7u/isrKz5r6+vva6urk0AAAAAAAAAAAAA
310 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
311 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACrq6snq6urVKur
312 | q4Krq6uxq6ur3aurq92rq6v/ubm5/8TCwfm+sqz6vLCq+7q4t/mvr7D2r6+v0a6urmGrq6sJAAAAAAAA
313 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
314 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
315 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACrq6thqKiog4WDgrpua2rIbmtqyGRiX6V3d3ddAAAAAQAA
316 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
317 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
318 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjUkhLZ1TLPKeSR34oksd+HY6
319 | HOYIBAQ/AAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
320 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
321 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlUwmNcyU
322 | dv/NXSL/5WYj/51IHfUNCAVdAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
323 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
324 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
325 | AAAAAAAAl1QlG82cgfzJYy3/3WMj/89eIv83HA6rAAAAMgAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
326 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
327 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
328 | AAAAAAAAAAAAAAAAAAAAAAAA//8AAcCOc9DTimP/014i/+FkI/+sTx35JxULmgAAADQAAAAHAAAAAAAA
329 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
330 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
331 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKJfOVjhvan/zWs4/9ZgIv/hZSP/rk8e+jMb
332 | DakEBAA+AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
333 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
334 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0fl+N5sGs/9Fw
335 | Pf/VYCL/3WMi/75WIP03Hg6uAAAANQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
336 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
337 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
338 | AAAAAAABsXZXfeXBrf7ScT7/0l4i/9liIv+tTx77IxMKjgAAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
339 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
340 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
341 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK90U33ju6X/ymEq/89dIv/WYCL/dDgY4wcDA0gAAAAEAAAAAAAA
342 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
343 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
344 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH9/AAK+i23R0H9U/8VaIP/KXCL/r1Eg/iMS
345 | DHsAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
346 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
347 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAWAAAABQAAAAAAAAAAAAAAAAAAAACpaEif0INa/79Y
348 | IP/CWSD/vVcg/zodEJ4AAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
349 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
350 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH9XQ5o4JR6VBwMDRQAAAB0AAAAMAAAACAwM
351 | ABSsakXOxGY0/75XIP+9ViD/u1Yg/0MiEqIAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
352 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
353 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMOPdee0bEf+ek843kgu
354 | IqkzIReBOCQYfnlGK8fBbkP/vFso/7pUH/+5VB//sFEf/zodD4IAAAAHAAAAAAAAAAAAAAAAAAAAAAAA
355 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
356 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM2n
357 | kubLgVr/x3ZL/8B0S/+1bUb/tGpD/8FsP/++Zzj/vGIz/7leL/+3WCb/nFIq+BwQCD4AAAABAAAAAAAA
358 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
359 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
360 | AAAAAAAAAAAAAM+rmObQjWr/yn5U/8p7UP/Id03/xXRJ/8JwRf+/bD//vGg5/7lkNv/BdEv/dkEmlwAA
361 | AAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
362 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
363 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAMalkK3lyr3/47ii/9ecff/QjGj/zINb/8mAWv/LhmL/zpFw/8aN
364 | bfycYECWFRUADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
365 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
366 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqqVQOyg2lGwZiBncuolNHNqZbqzaaQ7sqg
367 | iejBknvPqXBSmIpQMTkAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
368 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
369 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
370 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
371 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
372 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
373 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
374 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
375 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
376 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
377 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
378 | AAAAAAAAAAAAAP////////IE////////8gT////////yBP//+P////IE///AD///8gT//wAA///yBP/+
379 | AAAP//IE//gAAAH/8gT/8AAAAB/yBP/gAAAAA/IE/4AAAAAA8gT+AAAAAADyBPwAAAAAAfIE8AAAAAAA
380 | 8gTgAAAAAADyBMAAAAAAAPIEAAAAAAAA8gQAAAAAAADyBAAAAAAAAPIEAAAAAAAA8gQAAAAAAAHyBEAA
381 | AAAAA/IEQAAAAAAf8gTAAAAAAP/yBMAAAAAH//IEwAAAAD//8gT+AAAB///yBP/4AAf///IE///gH///
382 | 8gT///Af///yBP//8B////IE///wD///8gT///AH///yBP//+AP///IE///8Af//8gT///wB///yBP//
383 | /wD///IE////AP//8gT//8eA///yBP//wAD///IE///AAP//8gT//8AA///yBP//wAH///IE///AA///
384 | 8gT//8AH///yBP////////IE////////8gT////////yBCgAAAAgAAAAQAAAAAEAIAAAAAAAAAAAAAAA
385 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
386 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
387 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
388 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
389 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
390 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIAAAADAAAAAwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
391 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
392 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAWAAAAKgAAADAAAAAiAAAAFAAAAA4AAAAIAAAABAAA
393 | AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
394 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAALAAAAKxISEmxkZGTReXl56ZqXl+pyb221UExMckI+
395 | PlEhISEuAAAAGwAAAA8AAAAHAAAAAwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
396 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAGwAAAEswMDCtdnZ274uMi/9jY2P/W25h/4uM
397 | iv+opKT/s6ys9qumptyfmprGcnJypxYWFlkAAAA5AAAAGwAAAAwAAAAGAAAAAgAAAAAAAAAAAAAAAAAA
398 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACgAAAC0UFBRxSEhI2IODg/+Ghob/g4OC/zc3
399 | N/8KnEH/TJBl/62oqf+cmpr/iIaG/7m0tP/Fvb3/wr29/6ikpPx4dXXHRkREfj4+PlIUFBQlAAAAEwAA
400 | AAcAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAABsAAABKNTU1r3BwcPKAgID/eXl5/4aG
401 | hv+CgYH/ODc3/wyzSv9MlGb/vba3/8jAwP/MxMX/zsXF/8jBwf+wq6v/q6en/56cnP+4s7P/vLW19K+q
402 | qtGUkJCtY2NjVwAAAA8AAAACAAAAAAAAAAAAAAAAAAAAAQAAAAsAAAAtExMTdFBQUOCEhIT/f39//3x8
403 | fP+Pj4//s7S0/42Njf9raGn/FrxR/1SVav/Aubr/y8PD/9fOzv/h19f/69/f//Dl5f/06Oj/18/O/724
404 | uP+cmZn/oqCg/8C4uP/Gv7//qaamyYODgx8AAAAAAAAAAAAAAAQAAAAXAAAARjc3N65zc3Pxg4OD/39/
405 | f/+Kior/pKSk/8DAwP/Z2dn/ysrK/3x7e/+BiYL/lKya/8vExP/Sysr/29HR/+PY2P/t4uH/8ebl//To
406 | 6P/06Oj/8Obm/+fd3f/Uzs7/w76+/7m2tv+amJj7urW1xQAAAAEAAAAKAAAALBcXF3VOTk7aiIiI/4SE
407 | hP+FhYX/nZ2d/7y8vP/S0tL/4eHh/9/f3//R0dH/tbW2/5eXlv+Li4r/kpCQ/6ypqf/Oxsb/5tzc/+7i
408 | 4v/z5+j/9erq//Tp6f/v5eT/5t3d/97W1f/Wz8//z8rK/6KgoP+/ubnoAAAADwAAADY4ODiseXl59YmJ
409 | if+Hh4f/mJiY/7S0tP/Nzc3/39/f/+Dg4P/Nzc3/v7+//7e3t/+1tbX/wcLC/8DAwf++v7//sLCx/6Gh
410 | of+bmpr/m5iY/7Swr//MyMf/3dPT/+rf4P/s4+P/49rb/9bR0P/OyMj/qaen/7y3t+oAAAAfCQkJb5aW
411 | lv+Li4v/j4+P/6urq//Hx8f/29vb/+Dh4f/Pz8//ubm4/7SztP+3trX/urm6/8HAv//HxcT/ycjJ/8rJ
412 | yf/Nzs7/0tPV/9zd3v/a3N3/xcbH/6Olpf+TlJT/l5WV/6Sjo/+lo6P/rqys/7y4uv+Zl5f+vbe33gAA
413 | AA5OTk6Pq6ur/6Wlpf+/v7//19fX/93e3v/AwMD/oqCf/6GfnP+vrKn/ure1/8O/vf/LyMT/19LQ/+Dc
414 | 2v/k4Nz/497c/+Hd2v/d2df/1dLQ/87My//V1df/6Ort/+/w8v/q7O7/5Obn/9DS1P/Ly8v/q6ur/qmp
415 | qdrBurpHAAAAAmlpaY/Nzc3/0tLS/+Dg4P/a29v/qqqq/4mJiP+wr67/xMTD/8nKyv/MzMz/z8/P/87P
416 | z/+2rqr/npCJ/6+rqf/b29v/6Ojo/+7u7v/x8fH/7+zr/9za1//f39//7/Hz/+vu8P/a3N39t7i467Gx
417 | scW0tLRg////AQAAAAAAAAAAQT8/Yenq6v/a2tr/ycnJ/76/v/+2trf/xcXF/87Ozv/Q0ND/09PT/9jY
418 | 2P/d3N3/x7On/6leN/+3ViL/pV45/8G9uv/29vb/+fj4//r6+v/7+/v/9vb2/9fX2P7DxMX3ubu7vK6x
419 | sVyxsbEuqqqqAwAAAAAAAAAAAAAAAAAAAABVVVUMqqysy7Gxse+6u7v9wMHB/MPDxP3IyMn/09PT/9vb
420 | 2//g4eH/5eXl/+zq6v/PsaD/pls0/7JSH/+2WCf/wrey//n6+v/19fX/6urq/s7Oz/OwsLDSsLCwibS0
421 | tBEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wGsrKwoqKioQampqVeqqqp5ra2trbKy
422 | suO3uLj8vb6+8sbHyPTT1db84uTl/7Wpo/+/mYT/vYNk/614XP/Qzs3/ysvM+729vtqysrJ0r6+vPaqq
423 | qgwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
424 | AAAAAAAAAAAAAKKiogurq6tAqqqqeaqqqrKqqqrHtbW16bezsfCypqHyr6ys5q2trbatra04////AQAA
425 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
426 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKKioguchXVDlFw+4pNTMuhoQS6jNjY2DgAA
427 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
428 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJVKJSnMg1z/4GQj/4xB
429 | GcgQCAgfAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
430 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAn18fCMmK
431 | aunVZSr/w1gf9D8fDokAAAAaAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
432 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
433 | AAAAAAAAxZV5gNKCWfzYYyX/vVQf/EcjD5UJCQAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
434 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
435 | AAAAAAAAAAAAAAAAAACvf18Qy5uBlNqSbP/VYiX/u1Uf9T4fDYMAAAANAAAAAAAAAAAAAAAAAAAAAAAA
436 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
437 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyZZ8mM1yQv7QXSL/jkMb6w0JBDcAAAABAAAAAAAA
438 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
439 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAFAAAAAAAAAACxdFY7zIBX8sJZIP+6ViD/MRgOZwAA
440 | AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
441 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfVVBpz0mHGsnFhAtLRsSHJFZN2nAZDT4vVYg/7pV
442 | IP8/IBBtAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
443 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADIknXus2xH9p9gP96bXDrUsmM5871h
444 | Mf+5WSj/plIl+ywWDTkAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
445 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM+ii+jPimX/y39W/8d3
446 | Tf/Cckf/v29D/7tsQvmITC+SAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
447 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAy6mXVNCo
448 | kbTOoYnmzJt+88iTduq8gmPAsHVVYmo/KgwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
449 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
450 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
451 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
452 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
453 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////8H///+AH//+AAH//AAAP/AAAAfgA
454 | AADgAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAB4AAAH+AAAH//wAP///wP///+B////gP///8
455 | D////Af///8D///zA///8AP///AD///wB///8A////////////8oAAAAEAAAACAAAAABACAAAAAAAAAA
456 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
457 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAABEAAAAXAAAACQAA
458 | AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBgYGEpra2vQcHVy9o2K
459 | itWUj4+jeHZ2bAwMDCkAAAALAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAABAAAAG0FBQZN0dHT3hYWF/yBf
460 | N/+BoYv/s66u/8K7u/+xra3/mJWV25mUlJxzc3NNAAAABQAAAAAAAAAHGxsbSmNjY9WCgoL/nZ2d/8DA
461 | wP9ngnD/na+g/9PLy//m3Nv/8ubm/+PZ2f/Dvb3/vLe3/6ejo7cAAAAURkZGlXx8fPeVlZX/w8PD/9nZ
462 | 2f/Hx8j/s7O0/6mpqf+rqan/vbe3/9rS0v/r4OD/5dzd/9LNzP+sqKj2KysrQZ2dnf+1tbX/0tLS/7q6
463 | uP+0srH/wb27/9PPzf/a19X/2NbV/9bV1f/P0NL/yMnK/8HCw/+1tLT/qaamwlVVVTDa2tr/z9DQ/6ys
464 | rP/GxsX/0NHR/9LOy/+qdVn/tJ6S//Lx8v/29vb/5eXk/9XX2O/CwsSZsrKyPwAAAAB/f38Cq6urgbW1
465 | tbC6urrhyMnJ+9fY2fvY0Mz/tHRR/7mOeP/d3d72zMzMp7GxsUyqqqoDAAAAAAAAAAAAAAAAAAAAAAAA
466 | AAAAAAAAAAAAAKOjow6oqKg7raimcJ9+bOaPg32MqqqqDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
467 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAI1UHAnRdkb5jEAYpQAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
468 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzZR1fNNtN/58OhWYAAAABAAAAAAAAAAAAAAAAAAA
469 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAADJhF6ovFYf/CMRCysAAAAAAAAAAAAA
470 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKJtUsqGUTWKtGI32bVWI/42HgwqAAAAAAAA
471 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADRooe4zI5s9sN/W+ysaUR+AAAAAQAA
472 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
473 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//rEH4P6xB8AOsQcAArEGAAKxBAACsQQAArEEAAaxBAAesQfA/
474 | rEH8P6xB/h+sQf0frEH8H6xB/B+sQf//rEE=
475 |
476 |
477 |
478 | 529, 17
479 |
480 |
481 | 648, 17
482 |
483 |
484 | 780, 17
485 |
486 |
--------------------------------------------------------------------------------