Stop-Process vs TaskKill

Viewed 2899

I am automating an icon cache refresh, and I am seeing an interesting difference between TaskKill and Stop-Process. In general I prefer using native PowerShell over DOS command line stuff launched from PowerShell, so I would rather use Stop-Process -name:explorer over Start-Process TaskKill "/f /im explorer.exe" -NoNewWindow to stop Explorer.exe so that the DB files are no longer "in use" and can be deleted. However, the former allows Explorer.exe to restart instantly, so the icon DB files I need to delete are still in use and I can't delete them. The latter truly kills Explorer.exe and I have to use Start-Process later. Is there a way to get the TaskKill behavior using Stop-Process, or is this a rare situation where the old school kludge is also the only way that works?

3 Answers

I done some research and you should better end the explorer by sending a message.

With a messaage espacially for this WM_EXITEXPLORER (1460), you can tell the explorer to be closed.

Here my code working for windows 10:

$code = @'
[DllImport("user32.dll", EntryPoint = "PostMessage", CharSet =  CharSet.Unicode)] public static extern IntPtr PostMessage(IntPtr hWnd, int Msg, uint wParam, string lParam);
[DllImport("user32.dll", EntryPoint = "FindWindowW", CharSet = CharSet.Unicode)] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
'@
$myAPI = Add-Type -MemberDefinition $code -Name myAPI -PassThru
$myAPI::PostMessage($myAPI::FindWindow("Shell_TrayWnd", $Null),1460,0,0)

Start-Sleep -Seconds 10

It better to wait for the explorer windows to be closed, maybe I will add that tomorrow. For now 10 second wait should be enough for the explorer.exe to end graceful.

This is completly better than use the kill at all!

By default, Explorer.exe will restart automatically when stopped by Stop-Process. This is handled by a registry DWORD setting AutoRestartShell in key HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon.

You can of course stop that behavior by using

Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name "AutoRestartShell" -Value 0 -Type DWord

If you're on an older PowerShell version that doesn't understand parameter -Type, this should work:

[Microsoft.Win32.Registry]::SetValue("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon","AutoRestartShell",0,[Microsoft.Win32.RegistryValueKind]::DWord)

Then in your code, stop explore process, delete the icon DB files and start process explorer again.

Finish up by resetting the registry value to 1

Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name "AutoRestartShell" -Value 1 -Type DWord

If you just want explorer to stay down long enough for you to delete your files, just add stop-process to a while loop. Like so:

While (1 -eq 1) {
    stop-process -force -name "explorer"
}

You can hit Ctrl+C when you're done to stop the loop.

Related