this is my JNA code here:
import com.sun.jna.*;
import com.sun.jna.platform.win32.*;
import com.sun.jna.ptr.*;
import java.util.Arrays;
import java.util.List;
public class DirectoryMonitor {
public interface Kernel32 extends com.sun.jna.platform.win32.Kernel32 {
Kernel32 INSTANCE = Native.load("kernel32", Kernel32.class);
WinNT.HANDLE CreateFileW(String lpFileName, int dwDesiredAccess, int dwShareMode, WinBase.SECURITY_ATTRIBUTES lpSecurityAttributes,
int dwCreationDisposition, int dwFlagsAndAttributes, WinNT.HANDLE hTemplateFile);
boolean ReadDirectoryChangesW(WinNT.HANDLE hDirectory, FILE_NOTIFY_INFORMATION lpBuffer, int nBufferLength, boolean bWatchSubtree,
int dwNotifyFilter, IntByReference lpBytesReturned, WinBase.OVERLAPPED lpOverlapped,
WinNT.OVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
boolean CloseHandle(WinNT.HANDLE hObject);
}
public static class FILE_NOTIFY_INFORMATION extends Structure {
public int NextEntryOffset;
public int Action;
public int FileNameLength;
public char[] FileName;
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("NextEntryOffset", "Action", "FileNameLength", "FileName");
}
}
public static void main(String[] args) {
String directory = "C:\\temp\\"; // Directory to monitor
int bufferSize = 4096; // Size of the buffer for directory changes
WinNT.HANDLE dirHandle = Kernel32.INSTANCE.CreateFileW(
directory,
WinNT.FILE_LIST_DIRECTORY,
WinNT.FILE_SHARE_READ | WinNT.FILE_SHARE_WRITE | WinNT.FILE_SHARE_DELETE,
null,
WinNT.OPEN_EXISTING,
WinNT.FILE_FLAG_BACKUP_SEMANTICS,
null
);
if (dirHandle == WinNT.INVALID_HANDLE_VALUE) {
System.err.println("Failed to open directory: Error code " + Kernel32.INSTANCE.GetLastError());
return;
}
FILE_NOTIFY_INFORMATION notification = new FILE_NOTIFY_INFORMATION();
IntByReference bytesReturned = new IntByReference();
WinBase.OVERLAPPED overlapped = new WinBase.OVERLAPPED();
boolean result = Kernel32.INSTANCE.ReadDirectoryChangesW(
dirHandle,
notification,
notification.size(),
true,
WinNT.FILE_NOTIFY_CHANGE_LAST_WRITE,
bytesReturned,
overlapped,
null,
null // Pass null for lpCompletionRoutine
);
if (!result) {
System.err.println("ReadDirectoryChangesW failed: Error code " + Kernel32.INSTANCE.GetLastError());
Kernel32.INSTANCE.CloseHandle(dirHandle);
return;
}
try {
while (true) {
if (Kernel32.INSTANCE.ReadDirectoryChangesW(
dirHandle,
notification,
notification.size(),
true,
WinNT.FILE_NOTIFY_CHANGE_LAST_WRITE,
bytesReturned,
overlapped,
null,
null // Pass null for lpCompletionRoutine
)) {
int offset = 0;
while (offset < bytesReturned.getValue()) {
notification.read();
String fileName = new String(notification.FileName, 0, notification.FileNameLength / 2);
switch (notification.Action) {
case WinNT.FILE_ACTION_ADDED:
System.out.println("File added: " + fileName);
break;
case WinNT.FILE_ACTION_REMOVED:
System.out.println("File removed: " + fileName);
break;
case WinNT.FILE_ACTION_MODIFIED:
System.out.println("File modified: " + fileName);
break;
case WinNT.FILE_ACTION_RENAMED_OLD_NAME:
System.out.println("File renamed (old name): " + fileName);
break;
case WinNT.FILE_ACTION_RENAMED_NEW_NAME:
System.out.println("File renamed (new name): " + fileName);
break;
default:
System.out.println("Unknown action for file: " + fileName);
break;
}
offset += notification.NextEntryOffset;
}
} else {
System.err.println("ReadDirectoryChangesW failed: Error code " + Kernel32.INSTANCE.GetLastError());
}
try {
Thread.sleep(1000); // Sleep for 1 second before checking for changes again
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} finally {
Kernel32.INSTANCE.CloseHandle(dirHandle);
}
}
}
and this is my c++ code to do the same
#include <windows.h>
#include <iostream>
#include<string>
int main() {
HANDLE dirHandle;
DWORD dwBytes;
CHAR buffer[1024];
BOOL result;
// Directory to monitor
LPCWSTR directory = L"D:\\";
// Open handle to the directory
dirHandle = CreateFileW(
directory,
FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL
);
if (dirHandle == INVALID_HANDLE_VALUE) {
std::cerr << "Failed to open directory" << std::endl;
return 1;
}
// Monitor changes in the directory
while (true) {
result = ReadDirectoryChangesW(
dirHandle,
buffer,
sizeof(buffer),
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES |
FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_CREATION |
FILE_NOTIFY_CHANGE_SECURITY,
&dwBytes,
NULL,
NULL
);
if (!result) {
std::cerr << "ReadDirectoryChangesW failed" << std::endl;
break;
}
// Parse the buffer to get file change information
FILE_NOTIFY_INFORMATION* fileInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(buffer);
while (fileInfo) {
std::wstring fileName(fileInfo->FileName, fileInfo->FileNameLength / sizeof(WCHAR));
fileName.erase(std::remove(fileName.begin(), fileName.end(), L'\n'), fileName.end());
std::wstring filePath = std::wstring(directory) + L"\\" + fileName;
DWORD fileSize=0;
FILETIME fileModifiedTime;
WIN32_FILE_ATTRIBUTE_DATA fileAttributes;
if (GetFileAttributesEx(filePath.c_str(), GetFileExInfoStandard, &fileAttributes))
{
fileSize = fileAttributes.nFileSizeLow;
fileModifiedTime = fileAttributes.ftLastWriteTime;
}
else
{
std::wcout << L"Error retrieving file attributes for " << fileName << std::endl;
}
FILETIME localFileTime;
FileTimeToLocalFileTime(&fileModifiedTime, &localFileTime);
SYSTEMTIME systemTime;
FileTimeToSystemTime(&localFileTime, &systemTime);
std::wstring fileModificationTimeString = std::to_wstring(systemTime.wYear) + L"/" +
std::to_wstring(systemTime.wMonth) + L"/" +
std::to_wstring(systemTime.wDay) + L" " +
std::to_wstring(systemTime.wHour) + L":" +
std::to_wstring(systemTime.wMinute) + L":" +
std::to_wstring(systemTime.wSecond);
size_t lastBackslashIndex = fileName.find_last_of(L'\\');
if (lastBackslashIndex != std::wstring::npos) {
fileName = fileName.substr(lastBackslashIndex + 1);
}
switch (fileInfo->Action) {
case FILE_ACTION_ADDED:
std::wcout << L"File " << fileName<< L" added. " <<" filepath: "<<filePath<<L" fileSize: "<<fileSize<<L" fileModificationTime: "<< fileModificationTimeString <<std::endl;
break;
case FILE_ACTION_REMOVED:
std::wcout << L"File " << fileName<< L" removed." << " filepath: " << filePath << L" fileSize: " << fileSize << L" fileModificationTime: " << fileModificationTimeString << std::endl;
break;
/* case FILE_ACTION_MODIFIED:
std::wcout << L"File " << fileName<< L" modified." << " filepath: " << filePath << L" fileSize: " << fileSize << L" fileModificationTime: " << fileModificationTimeString << std::endl;
break;*/
case FILE_ACTION_RENAMED_OLD_NAME:
std::wcout << L"File " << fileName<< L" renamed (old name)." << " filepath: " << filePath << L" fileSize: " << fileSize << L" fileModificationTime: " << fileModificationTimeString << std::endl;
break;
case FILE_ACTION_RENAMED_NEW_NAME:
std::wcout << L"File " << fileName<< L" renamed (new name)." << " filepath: " << filePath << L" fileSize: " << fileSize << L" fileModificationTime: " << fileModificationTimeString << std::endl;
break;
default:
std::wcout << L"Unknown action for file "<< fileName<< L"." << " filepath: " << filePath << L" fileSize: " << fileSize << L" fileModificationTime: " << fileModificationTimeString << std::endl;
break;
}
if (fileInfo->NextEntryOffset == 0)
break;
fileInfo = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(reinterpret_cast<LPBYTE>(fileInfo) + fileInfo->NextEntryOffset);
}
}
// Close the directory handle
CloseHandle(dirHandle);
return 0;
}
the c++ code works fine to print when a file is deleted, moved, renamed... just want to do the same using JNA, the JNA code don't seem to work, some errors here
errors are:'ReadDirectoryChangesW(com.sun.jna.platform.win32.WinNT.HANDLE, com.sun.jna.platform.win32.WinNT.FILE_NOTIFY_INFORMATION, int, boolean, int, com.sun.jna.ptr.IntByReference, com.sun.jna.platform.win32.WinBase.OVERLAPPED, ...)' in 'DirectoryMonitor.Kernel32' cannot be applied to '(com.sun.jna.platform.win32.WinNT.HANDLE, DirectoryMonitor.FILE_NOTIFY_INFORMATION, int, boolean, int, com.sun.jna.ptr.IntByReference, com.sun.jna.platform.win32.WinBase.OVERLAPPED, null, null)'
'ReadDirectoryChangesW(com.sun.jna.platform.win32.WinNT.HANDLE, com.sun.jna.platform.win32.WinNT.FILE_NOTIFY_INFORMATION, int, boolean, int, com.sun.jna.ptr.IntByReference, com.sun.jna.platform.win32.WinBase.OVERLAPPED, ...)' in 'DirectoryMonitor.Kernel32' cannot be applied to '(com.sun.jna.platform.win32.WinNT.HANDLE, DirectoryMonitor.FILE_NOTIFY_INFORMATION, int, boolean, int, com.sun.jna.ptr.IntByReference, com.sun.jna.platform.win32.WinBase.OVERLAPPED, null, null)'