Skip to content

Refactor: support PowerShell 5.1 C# compilation & Pester legacy syntax compliance - #22

Merged
aj1126 merged 30 commits into
mainfrom
async-thread-ingest
Jul 8, 2026
Merged

Refactor: support PowerShell 5.1 C# compilation & Pester legacy syntax compliance#22
aj1126 merged 30 commits into
mainfrom
async-thread-ingest

Conversation

@aj1126

@aj1126 aj1126 commented Jul 8, 2026

Copy link
Copy Markdown
Owner

This PR stabilizes the repository for legacy environments (specifically Windows PowerShell 5.1 and Pester v3.4.0) while preserving code semantics.

Key Changes

  1. C# 5 Compatibility:
    • Refactored C# 6 expression-bodied properties (=>) in AuditEngine (inside src/DriveTools.psm1 and src/DriveTools.Core.cs) to standard C# 5 getters. This prevents compilation failures during module import in PowerShell 5.1.
  2. Pester Legacy Assertions Refactoring:
    • Updated assertion blocks in tests/DriveTools.Tests.ps1 to use non-dashed assertions (e.g. Should Be, Should Not BeNullOrEmpty, Should Not Throw).
    • Refactored pipeline-unpacked collection check FileQueue | Should Not Be $null to a parenthesized boolean check ($null -ne $Engine.FileQueue) | Should Be $true to prevent false failures from pipeline unpacking.
  3. UTF-8 with BOM Encoding:
    • Saved all Unicode-containing script files as UTF-8 with BOM to prevent ANSI parsing corruption in PowerShell 5.1.
  4. Development Guidelines Updated:
    • Documented these compatibility guidelines in .agents/AGENTS.md (Rules 3 and 9).

Resolves Issues

aj1126 added 28 commits June 30, 2026 03:15
…drive for file system activities and store the results in a CSV format. It uses several external modules, such as `WizTree`, `PSDriveTools`, and `SqlServer`. The script processes files asynchronously using multiple PowerShell runspace pools.

Here's a breakdown of what the code does:

1. **Module Imports**:
   ```powershell
   Import-Module WizTree
   Import-Module PSDriveTools
   Import-Module SqlServer
   ```

2. **Drive Audit Fast Function**:
   ```powershell
   function Invoke-DriveAuditFast {
       param (
           [Parameter(Mandatory=$true)]
           $SourcePath,
           [Parameter()]
           $WizTreePath = (Get-PSDrive | Where-Object { $_.ProviderName -eq 'Microsoft.PowerShell.WizTree' } | Select-Object PSProvider, Root) | Select-Object -ExpandProperty Root,
           [Parameter(Mandatory=$true)]
           [System.IO.DirectoryInfo]$TargetDir,
           [Parameter()]
           [Switch]$IncludeHashes,
           [Parameter()]
           [Boolean]$Asynchronous
       )
   ```
   This function takes the source path of the drive to audit, the WizTree executable mapping target reference, the target directory for storing CSV files, an optional parameter to include hash values in the output, and a switch to enable asynchronous processing.

3. **Global Variables**:
   ```powershell
   $dbAvailable = Test-Path 'SQLServer:\'
   $useWiztree = (Test-Path $WizTreePath)
   ```

4. **Output Queue**:
   ```powershell
   $outputQueue = New-Object System.Collections.Generic.Queue
   ```
   This queue is used to store audit results until they are written to a CSV file.

5. **SQL Server Connection and Command Initialization**:
   ```powershell
   if ($dbAvailable) {
       # Code for initializing SQL Server connection and command
   }
   ```

6. **Asyncronous Processing**:
   - The script creates multiple PowerShell runspace pools using the `Start-Process` cmdlet with the `-NoNewWindow`, `-Wait`, and `-RedirectStandardOutput` options.
   - Each runspace pool is used to execute different tasks concurrently.

7. **File Handling**:
   - For each file, it checks if the file size exceeds 50MB before processing to avoid high I/O overhead.
   - If the file size does not exceed 50MB, it calculates a checksum and stores the result in the CSV file or SQL Server based on the `$Asynchronous` parameter.

8. **Cleanup**:
   - The script ensures that all necessary objects (like writers, connections, and commands) are properly disposed of to free up resources.
   - After processing all files, it collects garbage and waits for finalizers to complete.

This script provides a robust solution for auditing a drive efficiently, handling both file I/O and potentially large file checks. The use of asynchronous processing helps in managing resource usage and speeding up the audit process.
…rove performance through optimized database indexing, memory-safe queue traversal, ultra-high-speed WizTree MFT ingestion, and advanced asynchronous multi-threaded worker runspace pool architecture with backpressure control.
…=================================== Export-ModuleMember -Function *-Drive*, Get-DriveToolsStatus, Set-DriveToolsStatus, Clear-DriveToolsStatus, Write-DriveToolsLog, Get-DriveToolsRootPath -
…dle massive streaming buffer bypass without ISE/VSCode crashes
…riveTools GUI project. The `MainWindow.xaml` contains a simple interface for initializing the drive audit process, displaying various information such as status updates, path details, and an audit progress bar.

The following changes were made:
1. **Window Declaration**: A new `Window` element is added to the XAML file with the specified properties such as title, height, width, and background color.
2. **Grid Layout**: The grid layout for the window is defined to center its content vertically.
3. **StackPanel Container**: A `StackPanel` is used to organize the elements in a vertical stacking manner.
4. **TextBlocks**: Two `TextBlock` elements are added to display "Ready to initialize file systems scan..." and "Target: None" respectively, along with their respective properties such as font weights, sizes, foreground colors, margin, text trimming options, and text alignment.
5. **ProgressBar**: A `ProgressBar` element is added to visually represent the progress of the drive audit process.

This change simplifies the user interface by providing a clear and concise way for users to understand the status of the drive audit operation and interact with it directly from the GUI.
… tasks related to drive management and monitoring, including scheduling, cleanup, prediction, and logging. The script is designed for a Windows application using WPF and is intended for both local and remote drives.

Here's a brief overview of the main functionality:

1. **GUI Interaction**:
   - Users can interact with buttons to perform various operations such as generating tree maps, predicting scan durations, cleaning up drive spaces, and managing scheduled tasks.

2. **Logging**:
   - The script includes logging capabilities to record the progress and outcomes of each operation in a text file.

3. **Task Management**:
   - It allows users to schedule daily maintenance tasks for clean-up operations.

4. **Drive Tools Core UI Layer Initialization**:
   - This section initializes the WPF application and sets up event handlers, including the timer that updates the status bar dynamically based on module logs.

5. **File Paths**:
   - The script handles file paths, particularly for storing log files, setting drive root paths, and scheduling tasks.

6. **Module Loading**:
   - The script loads necessary modules using `Import-Module` to perform specific operations such as `Show-DriveVisualMap` for tree maps, `Invoke-DriveCleanup` for cleanup tasks, and `Show-DriveVolumePerformanceMetricsCalculator` for prediction forecasting.

7. **Status Bar**:
   - A timer is used to update the status bar dynamically based on logs generated by modules.

8. **Error Handling**:
   - Basic error handling is included to manage exceptions that might occur during module execution.

### Key Points of Interest:

- **Event Handlers**: The script uses event handlers like `Add_Click` and `Add_Tick` to respond to user interactions and time-based updates.

- **Module Loading**: The use of `Import-Module` ensures that the necessary modules are available for use in the application.

- **Logging**: The script utilizes functions like `Append-Log` to record messages in a text file, which can be accessed through the log window provided by WPF.

- **Task Management**: Scheduled tasks using `Register-DriveMaintenanceTask` allow users to automate specific operations on a regular basis.

### Example Workflow:

1. **User selects a root drive path**.
2. The script initializes the WPF application.
3. Users interact with buttons to trigger different maintenance tasks such as generating tree maps, predicting scan durations, and cleaning up drive spaces.
4. Module logs are generated during these operations.
5. A timer updates the status bar dynamically based on these logs.

This script is designed for both local and remote drives, making it a robust tool for managing file systems in Windows environments.
…mapping for the native thread-safe Async Pipeline Handler.
…ed to manage disk cleanup and analysis tasks for a storage system. It uses the `DriveTools` module to perform various operations such as drive cleanup, visual map generation, prediction of scan duration, and logging.

Here's a breakdown of key components and functionalities:

### 1. Drive Cleanup
The script defines a function `Invoke-DriveCleanup` that takes several parameters:
- `$root`: The root path of the disk to be cleaned.
- `$removeEmptyDirectories`: A boolean indicating whether to remove empty directories.
- `$compressArchives`: A boolean indicating whether to compress archived files.
- `$reportDuplicates`: A boolean indicating whether to report duplicate entries.

The function uses `Import-Module` to load the `DriveTools.Core.StorageProfiler` module, which likely contains necessary functions for disk profiling and analysis.

### 2. Visual Map Generation
The script defines a function `Show-DriveVisualMap` that takes a root path and generates a visual map of the storage tree structure up to a maximum depth of 4 levels.

### 3. Predictive Scan Duration
The script defines a function `PredictScanDuration` that calculates an estimated scan duration based on MFT storage benchmarks.

### 4. Logging and Status Updates
- The script handles status updates from the engine module using `Get-DriveToolsStatus`.
- It logs messages to text boxes for display.
- The `Timer` object is used to periodically check the status of background tasks such as drive cleanup and visual map generation.

### 5. Lifecycle Observer Loop
The script includes a lifecycle observer loop that handles event notifications from the engine module and updates the UI accordingly.

### Example Usage
Here's an example of how you might use this script:

```powershell
# Load the DriveTools module
Import-Module DriveTools.Core.StorageProfiler

# Define the root path for cleanup
$rootPath = "C:\"

# Define settings
$removeEmptyDirs = $true
$compressArchives = $false
$reportDuplicates = $true
$modulePath = "DriveTools.Core.StorageProfiler"

# Run the drive cleanup task
Invoke-AsyncGuiTask -Script { Invoke-DriveCleanup -RootPath $rootPath -RemoveEmptyDirectories:$removeEmptyDirs -CompressArchives:$compressArchives -ReportDuplicates:$reportDuplicates } -ArgumentList @($rootPath, $removeEmptyDirs, $compressArchives, $reportDuplicates, $modulePath)
```

### Important Notes
- The script assumes that the `DriveTools` module is properly installed and configured on your system.
- The logging functionality is rudimentary and can be enhanced with more detailed error handling and logging levels.
- The script uses `InvokeAsyncGuiTask` to run background tasks, which may require a separate process management or thread safety considerations depending on your environment.
…d for managing and optimizing drives. It includes functions to perform audits, resolve duplicate entries, clean up empty directories, compress archives, register maintenance tasks, and handle status logs. The script uses SQL queries to retrieve information from a database and performs various operations based on the input parameters.

Here's a summary of the main functionalities:

1. **Drive Audits**:
   - `Invoke-DriveAuditFast`: Runs an optimized drive audit.
   - `Invoke-DriveAuditSlow`: Performs a slower but more thorough drive audit.

2. **Duplicate Resolution**:
   - `Resolve-DriveDuplicates`: Finds and removes redundant copies of files and directories on the drive.

3. **Directory Cleanup**:
   - `Invoke-DriveCleanup`: Removes empty directories and compresses archives to optimize disk space.

4. **Scheduled Maintenance**:
   - `Register-DriveMaintenanceTask`: Registers a scheduled task that runs the specified maintenance actions daily or hourly.

5. **Status Logging**:
   - `Write-DriveToolsLog`: Writes log messages based on the provided level.
   - `Get-DriveToolsStatus`: Retrieves the status of the module operations.

6. **Module Functions**:
   - The script exports all drive-related functions, including utility functions like `Get-DriveToolsRootPath`.

7. **SQL Query for Duplicate Report Index Sets**:
   - The script includes a function to generate index sets for duplicate report generation from the database, which is used by `Invoke-DriveCleanup`.

The module is designed to be flexible and can be customized based on specific requirements. It uses SQL queries to interact with the underlying database and performs operations that involve file system management and data analysis.
…managing and analyzing drive-related data. It includes various features such as resolving duplicate drives, cleaning up storage, generating visual maps, predicting scan durations, and clearing log files. The script uses classes, methods, and objects to handle different tasks.

Here's a breakdown of some key aspects:

### 1. Engine Module Management
- **Importing Modules**: The script imports necessary modules before executing any operations.
- **Command Execution**: It executes commands specified by the user with arguments and handles output based on the operation performed (e.g., `Resolve-DriveDuplicates`, `Invoke-DriveCleanup`).

### 2. Status Update
- **Status TextBox**: A status textbox updates in real-time to reflect the current operation or task.
- **Custom Status Text**: The script supports custom status messages that can be updated dynamically.
- **Logging Flags**: It maintains flags to control the verbosity of logging and detailed status display.

### 3. Background Process Handling
- **DispatcherTimer**: A timer is used to periodically update the status textbox.
- **Engine Context**: The engine context manages various objects related to background tasks, such as PowerShell sessions and output collection.

### 4. UI Components
- **Buttons**: Various buttons are added to the user interface for different operations (e.g., `BtnDupes`, `BtnCleanup`, `BtnMap`, `BtnPredict`).
- **TextBox**: A textbox for displaying detailed logs or predicted scan durations.
- **CheckBox**: A checkbox for toggling detailed status display.

### 5. Error Handling
The script includes error handling to manage exceptions that may occur during operations, ensuring the application's robustness.

### 6. Script Structure
The script is organized into multiple functions and classes, each responsible for a specific aspect of the functionality. This modular design enhances readability and maintainability.

### 7. Dependencies
- **Requires**: The script includes dependencies such as `Import-Module`, `Resolve-DriveDuplicates`, and others that need to be installed on the system before running.

This script is designed to provide a comprehensive set of tools for managing drive-related data, making it useful for administrators and professionals working with file systems.
Add explicit `this.` prefix to member assignments in C# AuditEngine constructor for clarity. Rename $lastWrite to $time in PowerShell for better semantics. Fix indentation inconsistencies throughout Update-DriveHashCache function. Add clarifying comment about queue compilation bug fix.
@aj1126 aj1126 self-assigned this Jul 8, 2026
@aj1126 aj1126 added the bug Something isn't working label Jul 8, 2026
@aj1126 aj1126 added documentation Improvements or additions to documentation enhancement New feature or request labels Jul 8, 2026
Comment thread public/Start-DTAuditGui.ps1 Outdated

$WorkerBlock = { param([DriveTools.Core.AuditEngine]$EngineInstance) $EngineInstance.StartConsumerWorker() }

for ($i = 0; $i < $LogicalCores; $i++) {

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to improve compatibility with legacy Windows PowerShell 5.1 / older Pester syntax while also expanding the module’s runtime capabilities (inline C# compilation, new async hashing paths, and new/updated WPF GUI entry points).

Changes:

  • Refactors/extends DriveTools’ inline Add-Type C# payload and adds new -Asynchronous switches for hashing-heavy workflows.
  • Reworks the Pester test suite structure and assertion syntax, plus adds deeper module-state and mock-path validations.
  • Introduces/updates WPF UI assets and GUI execution model (new XAML window + async GUI task runner), and documents compatibility guidelines.

Reviewed changes

Copilot reviewed 7 out of 9 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
tests/DriveTools.Tests.ps1 Replaces and expands the Pester suite setup/teardown and assertions for legacy compatibility verification.
src/UI/MainWindow.xaml Adds a new WPF window definition used by the audit GUI flow.
src/DriveTools.psm1 Adds/updates inline C# compilation and introduces async hashing paths and various refactors for PS 5.1 compatibility.
src/DriveTools.GUI.ps1 Reworks the GUI execution model to use an async pipeline runner with cancellation/progress UI elements.
src/DriveTools.Core.cs Adds a file named .cs that currently contains PowerShell module content (tooling/build implications).
public/Start-DTAuditGui.ps1 Adds a public WPF-based audit GUI launcher that loads the new XAML and spins up worker runspaces.
.agents/AGENTS.md Updates contributor guidelines for Pester legacy assertions and PS 5.1 inline C# constraints.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/DriveTools.psm1
Comment thread src/DriveTools.psm1
Comment on lines +548 to 552
$dateStr = $fields[3]
$time = $dateStr
if ([DateTime]::TryParse($dateStr, [ref]$parsedDate)) {
$lastWrite = $parsedDate.ToString('o')
$time = $parsedDate.ToString('o')
}
Comment thread src/DriveTools.psm1
Comment on lines +945 to 949
$dateStr = $fields[3]
$time = $dateStr
if ([DateTime]::TryParse($dateStr, [ref]$parsedDate)) {
if ([DateTime]::TryParse($dateStr, [ref]$parsedDate)) {
$time = $parsedDate.ToString('o')
}
Comment thread src/DriveTools.psm1
Comment on lines +496 to +502
if ([System.IO.File]::Exists($item.Path)) {
$stream = New-Object System.IO.FileStream($item.Path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite, 4194304)
$hashBytes = $sha.ComputeHash($stream)
$stream.Close()
$stream.Dispose()
$item.Hash = [System.BitConverter]::ToString($hashBytes).Replace("-", "")
} else { $item.Hash = "" }
Comment thread src/DriveTools.psm1
Comment on lines +897 to +903
if ([System.IO.File]::Exists($item.Path)) {
$stream = New-Object System.IO.FileStream($item.Path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite, 4194304)
$hashBytes = $sha.ComputeHash($stream)
$stream.Close()
$stream.Dispose()
$item.Hash = [System.BitConverter]::ToString($hashBytes).Replace("-", "")
} else { $item.Hash = "" }
Comment thread src/DriveTools.GUI.ps1 Outdated
Comment on lines +345 to +346
try {
[void]$PowerShellInstance.BeginInvoke($outputCollection)
Comment on lines +9 to +13
# 1. Instantiate the WPF window from file
$XamlPath = Join-Path $PSScriptRoot "..\src\UI\MainWindow.xaml"
[xml]$XamlContent = Get-Content -Raw -Path $XamlPath
$Reader = [System.Xml.XmlNodeReader]::new($XamlContent)
$Window = [System.Windows.Markup.XamlReader]::Load($Reader)
Comment on lines +1 to +7
function Start-DTAuditGui {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)] [string]$ScanPath,
[Parameter(Mandatory = $true)] [string]$CsvLogPath,
[int]$QueueLimit = 10000
)
Comment thread src/DriveTools.Core.cs Outdated
Comment on lines +1 to +5
#Requires -Version 5.1
<#
.SYNOPSIS
DriveTools — Complete drive auditing, categorization, refinement, and maintenance toolkit.
.DESCRIPTION
Comment thread tests/DriveTools.Tests.ps1 Outdated
Comment on lines +8 to +9
.NOTES
Optimized for Pester v5.7+ and Windows PowerShell 5.1 execution constraints.
Copilot finished work on behalf of aj1126 July 8, 2026 13:23
@aj1126
aj1126 merged commit 2d56b8a into main Jul 8, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

4 participants