Update on 28 October 2019: This issue is finally resolved in pull request #10909. (The last modified date is kept unchanged since this is not something super exciting.)
The issue is submitted to PowerShell repository as issue #6743.
Clear-RecycleBin
is a cmdlet that clears your recycle bin. Internally, it callsSHEmptyRecycleBin
function. It has been malfunctioning for a long time: when you run the cmdlet for the first time in a PowerShell session withForce
switch on, it produces anErrorRecord
. Further investigation shows that it is detecting error status ofSHEmptyRecycleBin
the wrong way. To make things worse,SHEmptyRecycleBin
is really bad at error handling.
If you open PowerShell, and type Clear-RecycleBin -Force
, you will see the following error:
Clear-RecycleBin : The system cannot find the path specified
At line:1 char:1
+ Clear-RecycleBin -Force
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (RecycleBin:String) [Clear-RecycleBin], Win32Exception
+ FullyQualifiedErrorId : FailedToClearRecycleBin,Microsoft.PowerShell.Commands.ClearRecycleBinCommand
You recycle bin is emptied despite an ErrorRecord
is produced. Interestingly, if you repeat the same command a second time in the same session, no error will be written. Moreover, if, when you are running the cmdlet for the first time in a PowerShell session, instead of switching on Force
, you manually confirm the operation, no ErrorRecord
will be written. This problem has been there for long. What’s wrong with Clear-RecycleBin
?
Now that PowerShell is open source (a rather earlier ‘now’, and by the way, China’s law allows users to study how a piece of software is designed [clause 22 of this document], so presumably you could have used ILSpy or other things to inspect the source code), we can have a look at how this cmdlet is implemented. Let’s come to this method. On line 222, the method calls SHEmptyRecycleBin
shell function, and then retrieves Win32 error code with Marshal.GetLastWin32Error
method. Moreover, the comment explains the three possible cases of success:
- The last error code is
0
, which is the default success code. - The last error code is
203
, which means the recycle bin is already emptied. - The last error code is
18
, which means there are no more files in the given recycle bin.
However, according to the documentation of SHEmptyRecycleBin
function (Windows) on MSDN, the API returns HRESULT
and there’s no indication on using SetLastError
to indicate error status. Now we may explain the strange behaviour of Force
switch and subsequent calls. It could be that ShouldProcess
calls some Win32 API that Set
sLastError
, and the error code was mistaken for that set by SHEmptyRecycleBin
.
Now let’s see how SHEmptyRecycleBin
returns its error status. The documentation says S_OK
is returned when the operation succeeds, but does not specify or list common error codes the function might return. In my tests, if the recycle bin is already empty, the call returns E_UNEXPECTED
(unexpected/catastrophic failure). Well, guess you’re not expected to clear an empty recycle bin, do you? In my humble opinion, returning E_UNEXPECTED
is simply unacceptable when the shell API could have detected the specific error.
Perhaps Clear-RecycleBin
was written when SHEmptyRecycleBin
was using SetLastError
? I said that in the GitHub issue, but I now know that this isn’t possible. According to documentation of Clear-RecycleBin
, it was introduced in PowerShell 5.0, which comes with Windows 10 RTM, and I believe the documentation for SHEmptyRecycleBin
has not changed since then. Perhaps it’s a documentation issue and SHEmptyRecycleBin
does call SetLastError
? Even if that were true, the implementation of Clear-RecycleBin
is a big mess. If you reflect the declaration of NativeMethod.SHEmptyRecycleBin
, you will see that the DllImportAttribute
does not set SetLastError
boolean property to true
, which means Marshal.GetLastWin32Error
will never return the error code set by SHEmptyRecycleBin
, if it were ever set. Whether an ErrorRecord
was written doesn’t depend on the call to SHEmptyRecycleBin
, but some random leftover of other calls!
Microsoft, you’ve got to have quality assurance and code review.
Sidenote I wish Raymond Chen could write a blog entry on SHEmptyRecycleBin
if there’s something interesting to add. He’s an expert of Windows shell programming. However, his suggestion box is currently closed and there’s no prescribed way to make a suggestion (though I could have sent him an email, but that would be too impolite), so I can only make wishes.
Please enable JavaScript to view the comments powered by Disqus.