带有脚本电源外壳的自删除文件夹



我一直在尝试让 powershell 或批处理脚本在完成后删除包含我所有脚本的文件夹。 最初我尝试Remove-Item -Path "C:Tool" -Recurse -Force如果作为脚本运行C:Tool以外的位置,则没有问题。它会抱怨从其中的脚本运行时文件正在使用中。 经过一些研究,我发现&cmd.exe /c rd /s /q "C:Tool"效果更好,但即使我关闭了 GUI,该命令也不会删除正在使用的 img 文件/文件夹。

从 USB 驱动器启动时,上述两个命令都能完美运行。

以前,我在临时文件夹中创建了第二个脚本,该脚本将删除所有文件,然后删除其自身。我正在寻找一种新的方法来简化我正在从事的新设计。我希望脚本在C:Tool或 USB 驱动器中工作。

控制流如下:
1(脚本加载所有函数
2(显示 GUI(包含图像(
3(按钮被按下
4(图形用户界面已关闭
5(删除包含脚本的文件夹

如前所述,第 5 步是我的问题。并非所有文件都会通过尝试的命令和命令的变体删除。

我希望步骤 5 正常工作,无论命令是从 GUI 上的按钮调用的,它作为脚本的一部分自动运行,还是另一个位置(例如 USB (中的脚本调用它以删除文件夹C:Tool

我们不知道 GUI 显示方式的细节,但是,假设你使用的是在 PowerShell代码中构造的 WinForms GUI,你的问题可能是 GUI 构造代码如何从稍后要删除的文件夹中的文件加载图像。

值得注意的是,如果您使用以下内容:

[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()

最新更新