Javascript 如何在XULRunner(js ctypes)中使用ReadDirectoryChangesW

Javascript 如何在XULRunner(js ctypes)中使用ReadDirectoryChangesW,javascript,firefox,firefox-addon,xulrunner,jsctypes,Javascript,Firefox,Firefox Addon,Xulrunner,Jsctypes,我正在尝试实现关于异步监视Windows文件系统的。我在ChomeWorker中使用js ctypes作为XULRunner应用程序的一部分,但我认为如果我实现为Firefox附加组件,这将是相同的 作为任务的一部分,我尝试如下声明函数ReadDirectoryChangesW(基于我对js ctypes和的有限知识) 此外(这里没有特别介绍),我已经为FindFirstChangeNotification()和WaitForSingleObject()声明了函数映射,这两个函数似乎工作得很好

我正在尝试实现关于异步监视Windows文件系统的。我在ChomeWorker中使用js ctypes作为XULRunner应用程序的一部分,但我认为如果我实现为Firefox附加组件,这将是相同的

作为任务的一部分,我尝试如下声明函数ReadDirectoryChangesW(基于我对js ctypes和的有限知识)

此外(这里没有特别介绍),我已经为
FindFirstChangeNotification()
WaitForSingleObject()
声明了函数映射,这两个函数似乎工作得很好

我遇到的问题是,当文件系统事件发生时,我不知道应该向lpBuffer参数传递什么,也不知道如何解释结果

<>所有的C++示例都使用了<代码> dWord < /Cord>数组,然后将结果抛出。我的尝试如下:

const DWORD_ARRAY = new ctypes.ArrayType(DWORD);  
var lBuffer = new DWORD_ARRAY(4000);
var lBufferSize = DWORD.size * 4000;
var lBytesOut = new LPDWORD();

ReadDirectoryChangesW(lHandle, lBuffer.address(), lBufferSize, true, WATCH_ALL, lBytesOut)
这似乎每次都会使XULRunner崩溃


有人能建议我应该为lpBuffer参数传递什么和/或如何从
ReadDirectoryChangesW()
获取结果吗?我能在网上找到的是C++的例子,它们并没有很多帮助。谢谢。

这是我在做同样的事情时学到的东西,仍在进行中

  • 您必须创建一个DWORD缓冲区,因此
    var buf=ctypes.ArrayType(DWORD,BUFSIZE)
    ,因为它需要在DWORD边界上对齐,无论这意味着什么
  • 我不知道BUFSIZE应该是什么,但我看过2048和4096,我不知道为什么。我也见过1024*64的BUFSIZE,不知道为什么
  • 然后在成功运行
    ReadDirectoryChangesW
    后,将此缓冲区强制转换为
    文件\u NOTIFY\u INFORMATION
    ,然后读取其内容
  • 仅当您不需要异步时,才将
    null
    传递到最后2个参数,我们需要异步,因此我们将使用
    LPOVERLAPPED
    结构并将其传递到那里
编辑 以下是同步的解决方案:这将成功读取一个事件。如果你有更多的天赋,你必须在下一个进阶和施法之前,在临时增益中移动。安装那个插件,在你的桌面上创建一个新文件夹,它就会登录到浏览器控制台


我正在开发异步版本,但遇到了一些问题。

这里有一个更简洁的解决方案:阅读评论,从中学习很多。对于类型定义

var path=OS.Constants.path.desktopDir;//监控路径
var hDirectory=ostypes.API('CreateFile')(路径,ostypes.CONST.FILE_列表_目录| ostypes.CONST.GENERIC_读取,ostypes.CONST.FILE_共享|读取| ostypes.CONST.FILE_共享_写入,null,ostypes.CONST.OPEN_存在,ostypes.CONST.FILE_标志|备份| ostypes.CONST.FILE标志|重叠,null);
console.info('hDirectory:',hDirectory.toString(),uneval(hDirectory));
如果(ctypes.winLastError!=0){//cutils.jscEqual(hDirectory,ostypes.CONST.INVALID_HANDLE_VALUE)){//注释掉了这一点,因为hDirectory返回为'ctypes.voidptr__t(ctypes.UInt64(“0xb18”)`并且我不知道当它返回-1时会是什么,但通过jscEqual返回时会给出“在obj级别上没有targetType.size的中断:”“ctypes.voidptr_t(ctypes.UInt64(“0xb18”))”`
console.error('Failed hDirectory,winLastError:',ctypes.winLastError');
抛出新错误({
名称:“操作系统api错误”,
消息:“未能创建文件”,
});
}
var dummyForSize=ostypes.TYPE.FILE_NOTIFY_INFORMATION.array(1)(;//一次最多接受1个通知(在应用程序中,您应该将其设置为50或更高,因为在一次读取/调用ReadDirectoryChangesW时,可能会报告多个通知)
log('dummyForSize.constructor.size:',dummyForSize.constructor.size');
log('ostypes.TYPE.DWORD.size:',ostypes.TYPE.DWORD.size.);
var dummyForSize_除以_DwordSize=dummyForSize.constructor.size/ostypes.TYPE.DWORD.size;
console.log('dummyForSize.constructor.size/ostypes.TYPE.DWORD.size:'、dummyForSize除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以除以
var temp_buffer=ostypes.TYPE.DWORD.array(Math.ceil(dummyForSize除以DwordSize));
var temp\u buffer\u size=temp\u buffer.constructor.size;//服从.array的长度
console.info('temp\u buffer.constructor.size:',temp\u buffer.constructor.size);//将是Math.ceil(dummyForSize除以\u DwordSize)
var bytes_returned=ostypes.TYPE.DWORD();
var changes_to_watch=ostypes.CONST.FILE_NOTIFY_CHANGE_LAST_WRITE | ostypes.CONST.FILE_NOTIFY_CHANGE_NAME | ostypes.CONST.FILE_NOTIFY_CHANGE_LAST_WRITE | ostypes.CONST.FILE_NOTIFY_CHANGE_文件名| ostypes.CONST.FILE| NOTIFY;
console.error('start-hang');
var rez_RDC=ostypes.API('ReadDirectoryChanges')(hDirectory,temp_buffer.address(),temp_buffer_size,true,changes_to_watch,bytes_returned.address(),null,null);
var CntNotifications=0;
var-cOffset=0;
while(cOffset
我正在努力使异步版本正常工作,但有一个棘手的问题
const DWORD_ARRAY = new ctypes.ArrayType(DWORD);  
var lBuffer = new DWORD_ARRAY(4000);
var lBufferSize = DWORD.size * 4000;
var lBytesOut = new LPDWORD();

ReadDirectoryChangesW(lHandle, lBuffer.address(), lBufferSize, true, WATCH_ALL, lBytesOut)
var path = OS.Constants.Path.desktopDir; // path to monitor

var hDirectory = ostypes.API('CreateFile')(path, ostypes.CONST.FILE_LIST_DIRECTORY | ostypes.CONST.GENERIC_READ, ostypes.CONST.FILE_SHARE_READ | ostypes.CONST.FILE_SHARE_WRITE, null, ostypes.CONST.OPEN_EXISTING, ostypes.CONST.FILE_FLAG_BACKUP_SEMANTICS | ostypes.CONST.FILE_FLAG_OVERLAPPED, null);
console.info('hDirectory:', hDirectory.toString(), uneval(hDirectory));
if (ctypes.winLastError != 0) { //cutils.jscEqual(hDirectory, ostypes.CONST.INVALID_HANDLE_VALUE)) { // commented this out cuz hDirectory is returned as `ctypes.voidptr_t(ctypes.UInt64("0xb18"))` and i dont know what it will be when it returns -1 but the returend when put through jscEqual gives `"breaking as no targetType.size on obj level:" "ctypes.voidptr_t(ctypes.UInt64("0xb18"))"`
    console.error('Failed hDirectory, winLastError:', ctypes.winLastError);
    throw new Error({
        name: 'os-api-error',
        message: 'Failed to CreateFile',
    });
}

var dummyForSize = ostypes.TYPE.FILE_NOTIFY_INFORMATION.array(1)(); // accept max of 1 notifications at once (in application you should set this to like 50 or something higher as its very possible for more then 1 notification to be reported in one read/call to ReadDirectoryChangesW)
console.log('dummyForSize.constructor.size:', dummyForSize.constructor.size);
console.log('ostypes.TYPE.DWORD.size:', ostypes.TYPE.DWORD.size);
var dummyForSize_DIVIDED_BY_DwordSize = dummyForSize.constructor.size / ostypes.TYPE.DWORD.size;

console.log('dummyForSize.constructor.size / ostypes.TYPE.DWORD.size:', dummyForSize_DIVIDED_BY_DwordSize, Math.ceil(dummyForSize_DIVIDED_BY_DwordSize)); // should be whole int but lets round up with Math.ceil just in case

var temp_buffer = ostypes.TYPE.DWORD.array(Math.ceil(dummyForSize_DIVIDED_BY_DwordSize))();
var temp_buffer_size = temp_buffer.constructor.size; // obeys length of .array
console.info('temp_buffer.constructor.size:', temp_buffer.constructor.size); // will be Math.ceil(dummyForSize_DIVIDED_BY_DwordSize)

var bytes_returned = ostypes.TYPE.DWORD();
var changes_to_watch = ostypes.CONST.FILE_NOTIFY_CHANGE_LAST_WRITE | ostypes.CONST.FILE_NOTIFY_CHANGE_FILE_NAME | ostypes.CONST.FILE_NOTIFY_CHANGE_DIR_NAME; //ostypes.TYPE.DWORD(ostypes.CONST.FILE_NOTIFY_CHANGE_LAST_WRITE | ostypes.CONST.FILE_NOTIFY_CHANGE_FILE_NAME | ostypes.CONST.FILE_NOTIFY_CHANGE_DIR_NAME);

console.error('start hang');
var rez_RDC = ostypes.API('ReadDirectoryChanges')(hDirectory, temp_buffer.address(), temp_buffer_size, true, changes_to_watch, bytes_returned.address(), null, null);

var cntNotfications = 0;
var cOffset = 0;
while (cOffset < bytes_returned) {
    cntNotfications++;
    var cNotif = ctypes.cast(temp_buffer.addressOfElement(cOffset), ostypes.TYPE.FILE_NOTIFY_INFORMATION.ptr).contents; // cannot use `temp_buffer[cOffset]` here as this is equivlaent of `temp_buffer.addressOfElement(cOffset).contents` and cast needs a ptr
    console.info('cNotif:', cNotif.toString());
    cOffset += cNotif.NextEntryOffset; // same as doing cNotif.getAddressOfField('NextEntryoffset').contents // also note that .contents getter makes it get a primaive value so DWORD defined as ctypes.unsigned_long will not be returned as expected ctypes.UInt64 it will be primative (due to the .contents getter), so no need to do the typical stuff with a `var blah = ctypes.unsigned_long(10); var number = blah.value.toString();`
}
console.info('total notifications:', cntNotifications);