Fix "Monitoring" not detecting all file changes issue
This patch adds an active monitor to detect changes on files since Windows isn't honoring FILE_NOTIFY_CHANGE_SIZE or FILE_NOTIFY_CHANGE_LAST_WRITE on ReadDirectoryChangesW correctly if the file writer keep it opened. This solution is based on GNU tail for Windows does. It does it at static void tail_forever (struct File_spec *f, int nfiles, double sleep_interval) on tail.c. Fix #3142, fix #4955, fix #4527, close #7969
This commit is contained in:
parent
e309ec23ec
commit
66893f980f
@ -35,6 +35,7 @@
|
||||
#include "VerticalFileSwitcher.h"
|
||||
#include "functionListPanel.h"
|
||||
#include "ReadDirectoryChanges.h"
|
||||
#include "ReadFileChanges.h"
|
||||
#include <tchar.h>
|
||||
#include <unordered_set>
|
||||
|
||||
@ -60,13 +61,16 @@ DWORD WINAPI Notepad_plus::monitorFileOnChange(void * params)
|
||||
CReadDirectoryChanges changes;
|
||||
changes.AddDirectory(folderToMonitor, true, dwNotificationFlags);
|
||||
|
||||
CReadFileChanges fChanges;
|
||||
fChanges.AddFile(fullFileName, FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE);
|
||||
|
||||
HANDLE changeHandles[] = { buf->getMonitoringEvent(), changes.GetWaitHandle() };
|
||||
|
||||
bool toBeContinued = true;
|
||||
|
||||
while (toBeContinued)
|
||||
{
|
||||
DWORD waitStatus = ::WaitForMultipleObjects(_countof(changeHandles), changeHandles, FALSE, INFINITE);
|
||||
DWORD waitStatus = ::WaitForMultipleObjects(_countof(changeHandles), changeHandles, FALSE, 250);
|
||||
switch (waitStatus)
|
||||
{
|
||||
case WAIT_OBJECT_0 + 0:
|
||||
@ -102,7 +106,11 @@ DWORD WINAPI Notepad_plus::monitorFileOnChange(void * params)
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WAIT_TIMEOUT:
|
||||
if (fChanges.DetectChanges()) {
|
||||
::PostMessage(h, NPPM_INTERNAL_RELOADSCROLLTOEND, reinterpret_cast<WPARAM>(buf), 0);
|
||||
}
|
||||
break;
|
||||
case WAIT_IO_COMPLETION:
|
||||
// Nothing to do.
|
||||
break;
|
||||
@ -112,6 +120,7 @@ DWORD WINAPI Notepad_plus::monitorFileOnChange(void * params)
|
||||
// Just for sample purposes. The destructor will
|
||||
// call Terminate() automatically.
|
||||
changes.Terminate();
|
||||
fChanges.Terminate();
|
||||
delete monitorInfo;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -0,0 +1,47 @@
|
||||
#include "ReadFileChanges.h"
|
||||
|
||||
|
||||
|
||||
CReadFileChanges::CReadFileChanges()
|
||||
{
|
||||
_szFile = NULL;
|
||||
_dwNotifyFilter = 0;
|
||||
}
|
||||
|
||||
|
||||
CReadFileChanges::~CReadFileChanges()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BOOL CReadFileChanges::DetectChanges() {
|
||||
|
||||
WIN32_FILE_ATTRIBUTE_DATA fInfo;
|
||||
BOOL rValue = FALSE;
|
||||
::GetFileAttributesEx(_szFile, GetFileExInfoStandard, &fInfo);
|
||||
|
||||
if ((_dwNotifyFilter & FILE_NOTIFY_CHANGE_SIZE) && (fInfo.nFileSizeHigh != _lastFileInfo.nFileSizeHigh || fInfo.nFileSizeLow != _lastFileInfo.nFileSizeLow)) {
|
||||
rValue = TRUE;
|
||||
}
|
||||
|
||||
if ((_dwNotifyFilter & FILE_NOTIFY_CHANGE_LAST_WRITE) && (fInfo.ftLastWriteTime.dwHighDateTime != _lastFileInfo.ftLastWriteTime.dwHighDateTime || fInfo.ftLastWriteTime.dwLowDateTime != _lastFileInfo.ftLastWriteTime.dwLowDateTime)) {
|
||||
rValue = TRUE;
|
||||
}
|
||||
|
||||
_lastFileInfo = fInfo;
|
||||
return rValue;
|
||||
}
|
||||
|
||||
void CReadFileChanges::AddFile(LPCTSTR szFile, DWORD dwNotifyFilter)
|
||||
{
|
||||
_szFile = szFile;
|
||||
_dwNotifyFilter = dwNotifyFilter;
|
||||
::GetFileAttributesEx(szFile, GetFileExInfoStandard, &_lastFileInfo);
|
||||
}
|
||||
|
||||
|
||||
void CReadFileChanges::Terminate()
|
||||
{
|
||||
_szFile = NULL;
|
||||
_dwNotifyFilter = 0;
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef VC_EXTRALEAN
|
||||
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
|
||||
#endif
|
||||
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
class CReadFileChanges
|
||||
{
|
||||
public:
|
||||
CReadFileChanges();
|
||||
~CReadFileChanges();
|
||||
void AddFile(LPCTSTR szDirectory, DWORD dwNotifyFilter);
|
||||
BOOL DetectChanges();
|
||||
void Terminate();
|
||||
|
||||
private:
|
||||
LPCTSTR _szFile;
|
||||
DWORD _dwNotifyFilter;
|
||||
WIN32_FILE_ATTRIBUTE_DATA _lastFileInfo;
|
||||
|
||||
};
|
||||
|
@ -394,6 +394,7 @@ copy ..\src\contextMenu.xml ..\bin64\contextMenu.xml
|
||||
<ClCompile Include="..\src\WinControls\FileBrowser\fileBrowser.cpp" />
|
||||
<ClCompile Include="..\src\WinControls\ReadDirectoryChanges\ReadDirectoryChanges.cpp" />
|
||||
<ClCompile Include="..\src\WinControls\ReadDirectoryChanges\ReadDirectoryChangesPrivate.cpp" />
|
||||
<ClCompile Include="..\src\WinControls\ReadDirectoryChanges\ReadFileChanges.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="..\src\icons\allChars_off.ico" />
|
||||
@ -673,6 +674,8 @@ copy ..\src\contextMenu.xml ..\bin64\contextMenu.xml
|
||||
<ClInclude Include="..\src\WinControls\ReadDirectoryChanges\ReadDirectoryChanges.h" />
|
||||
<ClInclude Include="..\src\WinControls\ReadDirectoryChanges\ReadDirectoryChangesPrivate.h" />
|
||||
<ClInclude Include="..\src\WinControls\ReadDirectoryChanges\ThreadSafeQueue.h" />
|
||||
<ClInclude Include="..\src\WinControls\ReadDirectoryChanges\ReadFileChanges.h" />
|
||||
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Manifest Include="..\src\notepad++.exe.manifest" />
|
||||
|
Loading…
Reference in New Issue
Block a user