Загрузка данных
& {
$ErrorActionPreference = 'Stop'
$file = Join-Path $env:ProgramData 'NVIDIA Corporation\Drs\nvAppTimestamps'
$output = $null
$guard = $null
$reader = $null
$temporary = $null
try {
[byte[]]$data = [IO.File]::ReadAllBytes($file)
$end = $data.Length - 1
if ($data.Length -lt 2 -or $data[$end] -ne 1) {
throw 'Неожиданный формат файла. Замена отменена.'
}
$encoding = [Text.UnicodeEncoding]::new($false, $false, $true)
$output = [IO.MemoryStream]::new()
$removed = [Collections.Generic.List[string]]::new()
$output.WriteByte($data[0])
$pos = 1
while ($pos -lt $end) {
if ($pos + 5 -gt $end) {
throw "Неполная запись на смещении $pos."
}
$size = [int]$data[$pos + 3] +
([int]$data[$pos + 4] -shl 8)
$start = $pos + 5
$next = $start + $size + 7
if ($size -lt 2 -or ($size % 2) -ne 0 -or $next -gt $end) {
throw "Некорректная длина записи на смещении $pos."
}
if ($data[$start + $size - 2] -ne 0 -or
$data[$start + $size - 1] -ne 0) {
throw "Не найден конец строки на смещении $pos."
}
$appPath = $encoding.GetString($data, $start, $size - 2)
if ($appPath.IndexOf([char]0) -ge 0) {
throw "Неожиданная структура строки на смещении $pos."
}
# Удаляем только записи, путь которых начинается с D:\
if ($appPath.StartsWith('D:\', [StringComparison]::OrdinalIgnoreCase)) {
$removed.Add($appPath)
}
else {
# Все остальные записи сохраняем без изменений.
$output.Write($data, $pos, $next - $pos)
}
$pos = $next
}
$output.WriteByte(1)
if ($removed.Count -eq 0) {
Write-Host 'Записей D:\ не найдено. Файл не изменён.'
return
}
Write-Host "`nБудут удалены записи из истории NVIDIA:"
$removed | Sort-Object -Unique | ForEach-Object { Write-Host $_ }
Write-Host "`nВсего записей: $($removed.Count)"
if ((Read-Host 'Введи DELETE для удаления БЕЗ резервной копии') -cne 'DELETE') {
Write-Host 'Отмена. Файл не изменён.'
return
}
# Проверяем, что файл не обновился, и блокируем параллельную запись.
$share = [IO.FileShare]::Read -bor [IO.FileShare]::Delete
$guard = [IO.File]::Open(
$file, [IO.FileMode]::Open, [IO.FileAccess]::Read, $share
)
$reader = [IO.BinaryReader]::new($guard)
[byte[]]$current = $reader.ReadBytes($data.Length + 1)
if ([Convert]::ToBase64String($current) -cne
[Convert]::ToBase64String($data)) {
throw 'Файл обновился после просмотра. Замена отменена. Повтори запуск.'
}
# Временный файл содержит результат, а не резервную копию.
$temporary = "$file.$([Guid]::NewGuid().ToString('N')).new"
[IO.File]::WriteAllBytes($temporary, $output.ToArray())
# Настоящий null для строкового параметра: резервная копия отключена.
[IO.File]::Replace(
$temporary,
$file,
[System.Management.Automation.Language.NullString]::Value
)
$temporary = $null
Write-Host "`nГотово. Удалено записей D:\: $($removed.Count)"
Write-Host 'Резервная копия не создавалась.'
}
catch {
Write-Warning ("Ошибка: " + $_.Exception.Message)
if ($temporary -and [IO.File]::Exists($temporary)) {
Write-Host "После ошибки остался временный файл: $temporary"
}
}
finally {
if ($reader) { $reader.Dispose() }
if ($guard) { $guard.Dispose() }
if ($output) { $output.Dispose() }
}
}