The script to run used to be simply, just pin a given folder to windows quick access, like what this answer doing pintohome.
$o = new-object -com shell.application
$o.Namespace('c:\My Folder').Self.InvokeVerb("pintohome")
It works well for years, but after some window upgrade, i found it will get fully stucked on windows version 10.0.19045
, ps version 5.1.19041.5007
.
Then i tried using Start-Job
and Wait-Job
to stop it after a timeout like this:
$job = Start-Job -ScriptBlock {
$o = new-object -com shell.application
$o.Namespace('c:\My Folder').Self.InvokeVerb("pintohome")
}
if (Wait-Job -Job $job -Timeout 3) {
Write-Output "The folder has been pinned successfully."
} else {
Stop-Job -Job $job
Write-Error "The operation took too long to run and has been stopped."
}
Remove-Job -Job $job
But it still stucked and even ctrl+c
will not be able to stop it, i have to close the powershell window to stop.
I have tried capture the error like this and still get stucked and no output.
cmd.exe /c powershell.exe D:\scripts\test.ps1 1>D:\scripts\log.txt 2>&1
According to this discussion Pin and Unpin from Quick Access using PowerShell, it may takes a long time to run it. But i found it will not stopped even after 10 minutes.
So how can i stop it after a timeout and is it failed because windows have done some restrictions?
put the script into a process can correctly timeout the running script, like this:
$OutputEncoding = [Console]::OutputEncoding = [System.Text.Encoding]::UTF8;
$currentPath = $PSScriptRoot
$scriptBlock = {
param($scriptPath)
$shell = New-Object -ComObject Shell.Application
$shell.Namespace($scriptPath).Self.InvokeVerb("'pintohome'")
}.ToString()
$arguments = "-Command & {$scriptBlock} -scriptPath '$currentPath'"
$process = Start-Process powershell -ArgumentList $arguments -NoNewWindow -PassThru
$timeout = 5
if (-not $process.WaitForExit($timeout * 1000)) {
try {
$process.Kill()
Write-Error "Process execution timed out (${timeout}s), forcefully terminated"
exit 1
}
catch {
Write-Error "Error occurred while terminating process: $_"
exit 1
}
}