Windows Event Viewer holds a lock on my EXE file

2019-04-28 17:53发布

I'm curious about something. I'm developing a Windows service and log all the diagnostic events into the Windows Event Log. So when the service is running I open the Event Viewer (from Administrative tools) to view the results of my service's operation.

This works great except for the moment when I need to uninstall my program (again, for the testing purposes.) For some weird reason the Event Viewer holds a lock on the .exe image file for my service so the uninstaller fails to delete it with the error code ERROR_SHARING_VIOLATION:

The process cannot access the file because it is being used by another process.

This happens only on Vista and later OS and seems not to be an issue on XP.

Any idea how to make Event Viewer release the file lock? (I'm asking about programmatic approach. I can obviously close it manually, but that's not what I'm after.)

2条回答
萌系小妹纸
2楼-- · 2019-04-28 18:31

I just met same problem. The DLL was locked by svchost.exe process (Windows Audio, DHCP Client, Windows Event Log, TCP/IP NetBIOS Helper, Security Center, Task Scheduler)

Solution: close Event Viewer! :)

查看更多
男人必须洒脱
3楼-- · 2019-04-28 18:39

There's a less known feature introduced in Vista called Restart Manager that can help you release file locks via a user-mode code. Since you tagged it as C++, based on this article here's a small code sample to do that:

#include <RestartManager.h>
#pragma comment(lib ,"Rstrtmgr.lib")

BOOL ReleaseFileLock(LPCTSTR pFilePath)
{
    BOOL bResult = FALSE;

    DWORD dwSession;
    WCHAR szSessionKey[CCH_RM_SESSION_KEY+1] = { 0 };
    DWORD dwError = RmStartSession(&dwSession, 0, szSessionKey);
    if (dwError == ERROR_SUCCESS) 
    {
        dwError = RmRegisterResources(dwSession, 1, &pFilePath,
            0, NULL, 0, NULL);
        if (dwError == ERROR_SUCCESS) 
        {
            UINT nProcInfoNeeded = 0;
            UINT nProcInfo = 0;
            RM_PROCESS_INFO rgpi[1];
            DWORD dwReason;

            dwError = RmGetList(dwSession, &nProcInfoNeeded,
                &nProcInfo, rgpi, &dwReason);
            if (dwError == ERROR_SUCCESS ||
                dwError == ERROR_MORE_DATA) 
            {
                if(nProcInfoNeeded > 0)
                {
                    //If current process does not have enough privileges to close one of
                    //the "offending" processes, you'll get ERROR_FAIL_NOACTION_REBOOT
                    dwError = RmShutdown(dwSession, RmForceShutdown, NULL);
                    if (dwError == ERROR_SUCCESS)
                    {
                        bResult = TRUE;
                    }
                }
                else
                    bResult = TRUE;
            }
        }
    }

    RmEndSession(dwSession);

    SetLastError(dwError);
    return bResult;
}
查看更多
登录 后发表回答