This one had me stumped for a while, and I even asked on Twitter with a large amount of replies (thanks everyone who did!) but none that I could get to work, or that weren’t overly complicated requiring the compiling of code.
It’s easy locally to find out what files are open, and here’s a great article covering several free ways: https://www.winhelponline.com/blog/find-process-locked-file-openfiles-utility/
None of those worked remotely for me in a Windows 10 environment – but I thought Handle from the SysInternals Suite would be the best bet. Running locally, it did exactly what I wanted – a giant list of every file open, and say what process had it open (like WinWord.exe).
Using PSExec with Handle however, causes it to forever wait for something. On the remote PC, it definitely launches handle.exe and handle64.exe, but they have no activity. I thought it might be the EULA prompt getting stuck somewhere, but there’s a registry setting that will autoaccept that prompt, and putting that in place didn’t help (but I did check locally and it was skipping the EULA agree prompt. Thanks to this blog post explaining the reg key required https://peter.hahndorf.eu/blog/post/2010/03/07/WorkAroundSysinternalsLicensePopups which was:
reg.exe ADD HKCU\Software\Sysinternals /v EulaAccepted /t REG_DWORD /d 1 /f
I added this to the remote machine under both the user logged on to the remote device, and the user I was connecting as, with no luck.
After a bunch of Googling and trying solutions, I ended up finding this thread on stackoverflow. One of the answers with 0 votes (which can be easily overlooked) was a PowerShell script, invoking the command remotely, from a user called A.D – thank you A.D!
I’ve barely modified it for my purposes, but if this helps you please go vote his post up on stackoverflow (I did but don’t have enough rep for it to show):
$computerName = 'computername' $stringtoCheck = 'test' # String you want to search for, can be blank by removing text between '' quotes $pathtoHandle = 'c:\temp\handle.exe' #location of handle.exe on the remote server. Invoke-command -ComputerName $computerName -Scriptblock { param( [string]$handles, [string]$stringToCheck ) "$handles /accepteula $stringToCheck" | Invoke-Expression } -ArgumentList $pathtoHandle,$stringtoCheck
The script requires handle.exe to be on the remote computer under C:\Temp, and that of course you have admin rights to the remote PC with the account this script is being run. Beyond that, it’ll show back all open files that match the variable set in $stringtocheck across any of the results – it could be the path, the process that has the file open etc.
Why would you want to do this remotely at all? You might be troubleshooting something to do with open files and not want to interrupt the user. You might have a reason to see what files the user has open, or maybe it’s a locked PC and the user left.
Hope this helps others as it was a much harder task to accomplish than I assumed.