Самостоятельное удаление папки со скриптами powershell

Я пытался заставить PowerShell или пакетные сценарии удалить папку, содержащую все мои сценарии, когда я закончу. Первоначально я пытался Remove-Item -Path "C:\Tool" -Recurse -Force который работал без проблем, если запустить в качестве сценария для места за пределами C:\Tool, Было бы жаловаться, что файлы использовались при запуске из скрипта внутри. После некоторых исследований я нашел &cmd.exe /c rd /s /q "C:\Tool" это работало намного лучше, но даже если я закрыл графический интерфейс, команда не удаляла используемые файлы / папки img.

Обе вышеперечисленные команды отлично работают при запуске с USB-накопителя.

Ранее я создал второй скрипт во временной папке, который будет удалять все файлы, а затем и сам. Я ищу новый способ сделать это, чтобы упростить новый дизайн, над которым я работаю. Я хочу, чтобы скрипт работал изнутри C:\Tool или с USB-накопителя.

Поток управления таков:
1) Скрипт загружает все функции
2)GUI отображается (который содержит imgs)
3) Кнопка нажата
4)GUI закрыт
5) Папка, содержащая скрипт, удалена

Шаг 5 - моя проблема, как уже объяснено. Не все файлы удаляются ни попытками команд, ни изменениями команд.

Я хочу, чтобы шаг 5 работал независимо от того, была ли вызвана команда с кнопки в графическом интерфейсе, она автоматически запускается как часть сценария или сценарий в другом месте, например через USB, вызывает ее для удаления папки C:\Tool

1 ответ

Мы не знаем особенностей отображения вашего графического интерфейса, но, если вы используете графический интерфейс WinForms, созданный в коде PowerShell, ваша проблема может заключаться в том, как ваш код построения графического интерфейса загружает изображения из файлов в папке, которую вы позже захотите удалять.

В частности, если вы используете что-то вроде:

[Bitmap]::new(<file-path>)
[System.Drawing.Image]::FromFile(<file-path>)

указанный файл, очевидно, остается открытым до конца сеанса PowerShell, и вы не сможете удалить свою папку.

Решение состоит в том, чтобы создать новый экземпляр изображения в памяти, который копирует загруженное из файла изображение, и затем избавиться от загруженного из файла изображения, которое снимает блокировку с базового файла, как продемонстрировано в этом [C#] ответ.

Вот минимальный сценарий, demo.ps1, что демонстрирует подход:

  • Сохраните его в своей временной временной папке.

  • Скопируйте небольшой файл изображения с именем demo.png в ту же папку.

  • Затем вызвать его как <temp-folder>/demo -SelfDestruct увидеть это в действии; необходимость указать
    -SelfDescript Это мера предосторожности, учитывая, что случайный вызов уничтожит всю папку, в которой находится сценарий.

demo.ps1:

param([switch] $SelfDestruct)

# Load the WinForms assembly.
Add-Type -AssemblyName System.Windows.Forms    

# Create the form.
$form = New-Object system.Windows.Forms.Form -Property @{
    ClientSize = New-Object System.Drawing.Point 400,100
    Text       = "Dialog"
}    

# Add a PictureBox control that loads its image from 'demo.png'
$form.Controls.Add((New-Object System.Windows.Forms.PictureBox  -Property @{
Image = & { 
    # Load the image from file in the same folder as a script into
    # a temporary variable.
    $tmpImg = [System.Drawing.Image]::FromFile((Join-Path $PSScriptRoot 'demo.png')) 
    # Create an in-memory copy of the image. 
    New-Object System.Drawing.Bitmap $tmpImg
    # Dispose of the from-file image, which releases the file.
    $tmpImg.Dispose()
}
Location = New-Object System.Drawing.Point 10, 10
}))


# Show the form and wait for the use to close it.
$null = $form.ShowDialog()

if ($SelfDestruct) { # Remove the running script's entire folder.
  if ("$($PWD.Path)\" -like "$PSScriptRoot\*") {                                                      #"
      Push-Location C:\ # must switch to different dir. before deleting.
  }
  # Remove the entire folder.
  Remove-Item -literalpath $PSScriptRoot -Recurse -Force
  exit
}

Вот вариант, который вызывает удаление по нажатию кнопки, через обработчик событий:

param([switch] $SelfDestruct)

Add-Type -AssemblyName System.Windows.Forms

function remove-OwnFolder {
    # If the current dir. is in the subtree of the folder to delete, 
    # we must switch to different dir. before deleting.
    if ("$($PWD.Path)\" -like "$PSScriptRoot\*") {                                                      #"
        Push-Location C:\ 
    }
    # Remove the script's parent folder as a whole.
    Remove-Item -literalpath $PSScriptRoot -Recurse -Force
}

# Create the form.
$form = New-Object system.Windows.Forms.Form -Property @{
    ClientSize = New-Object System.Drawing.Point 400,100
    Text       = "Dialog"
}    

# Add a PictureBox control that loads its image from 'demo.png'
$form.Controls.Add((New-Object System.Windows.Forms.PictureBox  -Property @{
    Image = & { 
        # Load the image from file in the same folder as a script into
        # a temporary variable.
        $tmpImg = [System.Drawing.Image]::FromFile((Join-Path $PSScriptRoot 'demo.png')) 
        # Create an in-memory copy of the image. 
        New-Object System.Drawing.Bitmap $tmpImg
        # Dispose of the from-file image, which releases the file.
        $tmpImg.Dispose()
    }
    Location = New-Object System.Drawing.Point 10, 10
}))


# Add a button that will trigger the self-destruction
$btnSelfDestruct = New-Object system.Windows.Forms.Button -Property @{
    Text              = "Submit"
    Location          = New-Object System.Drawing.Point 160, 60
}
$form.Controls.Add($btnSelfDestruct)

# Add the button-click event handler.
$btnSelfDestruct.Add_Click({
    $form.Close()
    if ($SelfDestruct) {
        remove-OwnFolder
    }
    exit
})

# Show the form and wait for the use to close it.
$null = $form.ShowDialog()
Другие вопросы по тегам