我一直试图让Powershell或批处理脚本在完成后删除包含所有脚本的文件夹。
最初,我尝试过Remove-Item -Path "C:\Tool" -Recurse -Force
,如果以脚本形式运行C:\Tool
之外的位置,则没有问题。当从其中的脚本运行时,它将抱怨文件正在使用中。
经过一番研究,我发现&cmd.exe /c rd /s /q "C:\Tool"
的效果要好得多,但是即使我关闭了GUI,该命令也不会删除正在使用的img文件/文件夹。
从USB驱动器启动时,上述两个命令都能完美运行。
以前,我在temp文件夹中创建了第二个脚本,该脚本将删除所有文件,然后删除其自身。我正在寻找一种新的方法来简化我正在研究的新设计。我希望脚本可以从C:\Tool
或USB驱动器中运行。
控制流程如下:
1)脚本加载所有功能
2)显示GUI(包含img)
3)按下按钮
4)GUI已关闭
5)包含脚本的文件夹被删除
步骤5是我已经说明的问题。尝试执行的命令和命令的变体都不能删除所有文件。
我希望第5步能够正常工作,无论是否从GUI上的按钮调用了命令,它都作为脚本的一部分自动运行,还是其他位置(如USB)的脚本调用它来删除文件夹{{1} }
答案 0 :(得分:0)
我们不知道如何显示GUI,但是,假设您使用的是 PowerShell 代码构建的WinForms GUI,您的问题可能是GUI的构造方式代码从您以后要删除的文件夹中的文件中加载图像。
值得注意的是,如果您使用类似这样的内容:
[Bitmap]::new(<file-path>)
[System.Drawing.Image]::FromFile(<file-path>)
指定的文件显然在PowerShell会话的其余部分保持打开状态,您将无法删除该文件夹。
解决方案是在内存中创建一个 new 图像实例,以复制从文件中加载的图像,然后处置从文件加载的图片中的em> ,它释放了对基础文件的锁定,如this [C#] answer所示。
下面是一个最小的脚本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()