Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions functions/microwin/Force-CleanupMountDirectory.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
function Force-CleanupMountDirectory {
<#
.SYNOPSIS
Forces cleanup of a mount directory by closing processes that have files open

.DESCRIPTION
This function attempts to clean up a mount directory by unloading registry hives,
releasing file handles, and removing readonly attributes.

.PARAMETER MountPath
The path to the mount directory to clean up

.PARAMETER TimeoutSeconds
Maximum time to wait for processes to close (default: 30 seconds)
#>
param(
[Parameter(Mandatory = $true)]
[string]$MountPath,

[int]$TimeoutSeconds = 30
)

try {
# Attempt to unload any registry hives that might still be loaded
$hiveNames = @("HKLM\zCOMPONENTS", "HKLM\zDEFAULT", "HKLM\zNTUSER", "HKLM\zSOFTWARE", "HKLM\zSYSTEM")
foreach ($hiveName in $hiveNames) {
try {
$null = reg query $hiveName 2>$null
if ($LASTEXITCODE -eq 0) {
# Registry hive is loaded, try to unload it with retries
while ($true) {
reg unload $hiveName 2>$null
if ($LASTEXITCODE -eq 0) {
break
}
Start-Sleep -Milliseconds 100
}
}
} catch {
# Hive not loaded or error checking - continue
}
}

# Force garbage collection to release any PowerShell file handles
Invoke-GarbageCollection -WaitSeconds 2

# Try to set the mount directory and its contents to not readonly
try {
if (Test-Path "$MountPath") {
& attrib -R "$MountPath\*" /S /D 2>$null
}
} catch {
# Ignore attrib errors
}

# Restart Windows Search service if it's running (helps release file handles)
try {
$searchService = Get-Service -Name "WSearch" -ErrorAction SilentlyContinue
if ($searchService -and $searchService.Status -eq "Running") {
Stop-Service -Name "WSearch" -Force -ErrorAction SilentlyContinue
Start-Sleep -Seconds 1
Start-Service -Name "WSearch" -ErrorAction SilentlyContinue
}
} catch {
# Ignore service restart errors
}

# Final cleanup
Invoke-GarbageCollection

return $true

} catch {
return $false
}
}
103 changes: 103 additions & 0 deletions functions/microwin/Get-ProcessesUsingPath.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
function Get-ProcessesUsingPath {
<#
.SYNOPSIS
Identifies processes that may be using files in a specific path

.DESCRIPTION
This function attempts to identify processes that have files open in the specified path,
which can help diagnose unmount issues.

.PARAMETER Path
The path to check for process usage

.EXAMPLE
Get-ProcessesUsingPath -Path "F:\Scratch"
#>
param(
[Parameter(Mandatory = $true)]
[string]$Path
)

Write-Host "Checking for processes using path: $Path" -ForegroundColor Cyan

$foundProcesses = @()

try {
# Method 1: Check process modules and loaded files
$allProcesses = Get-Process -ErrorAction SilentlyContinue
foreach ($process in $allProcesses) {
try {
if ($process.ProcessName -match "^(System|Registry|Idle)$") {
continue
}

# Check process modules
try {
$modules = $process.Modules
} catch {
$modules = $null
}
if ($modules) {
foreach ($module in $modules) {
if ($module.FileName -and $module.FileName.StartsWith($Path, [System.StringComparison]::OrdinalIgnoreCase)) {
$foundProcesses += @{
ProcessName = $process.ProcessName
PID = $process.Id
File = $module.FileName
Method = "Module"
}
break
}
}
}

# Check working directory
try {
$startInfo = $process.StartInfo
if ($startInfo -and $startInfo.WorkingDirectory -and $startInfo.WorkingDirectory.StartsWith($Path, [System.StringComparison]::OrdinalIgnoreCase)) {
$foundProcesses += @{
ProcessName = $process.ProcessName
PID = $process.Id
File = $startInfo.WorkingDirectory
Method = "WorkingDirectory"
}
}
} catch {
# Ignore access denied
}

} catch {
# Ignore processes we can't access
continue
}
}

# Method 2: Check common interfering processes
$suspiciousProcesses = Get-Process -ErrorAction SilentlyContinue | Where-Object {
$_.ProcessName -match "SearchIndexer|SearchProtocolHost|SearchFilterHost|MsMpEng|NisSrv|avp|avgnt|avast|mcshield|explorer"
}

if ($suspiciousProcesses) {
Write-Host "`nPotentially interfering processes (may not be directly using the path):" -ForegroundColor Yellow
foreach ($proc in $suspiciousProcesses) {
Write-Host " - $($proc.ProcessName) (PID: $($proc.Id))" -ForegroundColor Yellow
}
}

# Display results
if ($foundProcesses.Count -gt 0) {
Write-Host "`nProcesses found using path:" -ForegroundColor Red
foreach ($proc in $foundProcesses) {
Write-Host " - $($proc.ProcessName) (PID: $($proc.PID)) - $($proc.File) [$($proc.Method)]" -ForegroundColor Red
}
} else {
Write-Host "No processes found directly using the specified path." -ForegroundColor Green
}

return $foundProcesses

} catch {
Write-Host "Error checking processes: $($_.Exception.Message)" -ForegroundColor Red
return @()
}
}
Loading
Loading