高手,对MS有严重催残倾向对INPRISE有明显爱癖的朋友请进:《是CreateFile()不对,还是我不对?》 By 3H(200分)

3

3h

Unregistered / Unconfirmed
GUEST, unregistred user!
&lt;strong&gt;&lt;font color="Blue"&gt;声明:以下均在DELPHI4中经历。&lt;/font&gt;<br>&lt;font color="red"&gt;<br>原委:&lt;/font&gt;&lt;/strong&gt;<br>&nbsp; &nbsp; 因为需要得到某一目录的打开句柄(皆为使用SetFileTime<br>函数可以使用...),花了狠久时间翻了好页帮助文件之后,终<br>于发现CreateFile()函数可以打开目录并获得句柄。<br>&nbsp; &nbsp; 大家看帮助文件,应该没问题吧:<br>&nbsp; &nbsp; (来自文件../Borland Shared/MSHelp/win32.hlp)<br>The CreateFile function creates or opens the <br>following objects and returns a handle that<br>can be used to access the object: <br>&nbsp; Files <br>&nbsp; pipes <br>&nbsp; mailslots <br>&nbsp; communications resources <br>&nbsp; disk devices (Windows NT only)<br>&nbsp; consoles <br>&nbsp; directories (open only)<br>&nbsp; ***********************<br>虽然是OPEN ONLY,也将就了,反正是取得其句柄即可。于是:<br>&lt;font color="Blue"&gt;<br>procedure TForm1.Button1Click(Sender: TObject);<br>Const<br>&nbsp; &nbsp;FileName = 'e:/123'; &nbsp; &nbsp;//这是一个已存在的目录<br>Var<br>&nbsp; &nbsp;q : THandle;<br>begin<br>&nbsp; &nbsp;try<br>&nbsp; &nbsp; &nbsp; Q := CreateFile( FileName+#0,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GENERIC_WRITE,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; OPEN_ALWAYS ,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FILE_ATTRIBUTE_NORMAL,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0);<br>&nbsp; &nbsp; &nbsp; ShowMessage(IntToStr(Q)); &nbsp; //看看它究竟是多少<br>&nbsp; &nbsp; &nbsp; if Q = INVALID_HANDLE_VALUE then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ShowMessageBox(FileName + ' open error.');<br>&nbsp; &nbsp;finally<br>&nbsp; &nbsp; &nbsp; CloseHandle(Q);<br>&nbsp; &nbsp;end;<br>end;<br>&lt;/font&gt;<br>没想到得到的Q=4294967295,也就是-1,结果当然是显示<br>“打开错误”了。大家不妨看看函数的定义原型:<br>&lt;font color="Teal"&gt;HANDLE CreateFile(<br>&nbsp; LPCTSTR lpFileName,<br> // pointer to name of the file <br>&nbsp; DWORD dwDesiredAccess,<br> // access (read-write) mode <br> // 按要求设置为GENERIC_WRITE<br>&nbsp; DWORD dwShareMode,<br> // share mode<br> // 没什么好共享的<br>&nbsp; LPSECURITY_ATTRIBUTES lpSecurityAttributes, <br> // pointer to security attributes<br> // 没什么安全要求(95/98)所以忽略了<br>&nbsp; DWORD dwCreationDistribution, <br> // how to create <br> // 已存在的,就用OPEN_ALWAYS<br>&nbsp; DWORD dwFlagsAndAttributes,<br> // file attributes<br> // 来个一般属性罢:FILE_ATTRIBUTE_NORMAL<br>&nbsp; HANDLE hTemplateFile<br> // handle to file with attributes to copy<br> // 95/98明文禁止使用,不得已,用0.<br>&nbsp; );&lt;/font&gt;<br>返回值有两种情况:<br> 成功为句柄.<br> 失败为INVALID_HANDLE_VALUE (=-1).<br>很不幸,此例的结果属于后者。<br>至于详细的帮助大家可看看开始菜单中<br>Borland Delphi 4<br>&nbsp; /Help<br>&nbsp; &nbsp; /MS SDK Help Files<br>&nbsp; &nbsp; &nbsp; /Win32 Programmer's Reference<br>&nbsp; &nbsp; &nbsp; &nbsp; -&gt; CreateFile<br>的描述,算是比较详细了。<br>&lt;font color="red"&gt;&lt;strong&gt;<br>不过我不明白的是,如果将上面的FileName换成一个文件,<br>就能返回成功的句柄,只要是目录,此功能就会失败!<br>究竟是什么原因?是我在程序中参数有错误?还是......<br>MS的帮助文件有错误?它的函数没有支持这样的功能?<br>&lt;/strong&gt;<br>请求大家解答,<br>特别是高手们,<br>对MS有严重催残倾向对DELPHI有明显爱癖的朋友们。&lt;/font&gt;
 
老兄,读书虽多,却不认真,<br>Win32 Help文档后面明明写得很清楚啊!<br><br>Directories<br>An application cannot create a directory with CreateFile; it must call CreateDirectory or CreateDirectoryEx to create a directory.<br><br>Windows NT:<br>You can obtain a handle to a directory by setting the FILE_FLAG_BACKUP_SEMANTICS flag. A directory handle can be passed to some Win32 functions in place of a file handle.<br><br>应用程序不能使用CreateFile函数创建目录,必须使用CreateDirectory或CreateDirectoryEx函数<br><br>Windows NT下:<br>可以通过设置FILE_FLAG_BACKUP_SEMANTICS标志获得一个目录的句柄。。。。<br><br>Win32 Help的相关部分(Directory Operations)也有说明如下:<br>Windows NT: You can obtain a handle to a directory by calling the CreateFile function with the FILE_FLAG_BACKUP_SEMANTICS flag set, as follows:<br>hDir = CreateFile (<br>&nbsp; &nbsp; DirName,<br>&nbsp; &nbsp; GENERIC_READ,<br>&nbsp; &nbsp; FILE_SHARE_READ|FILE_SHARE_DELETE,<br>&nbsp; &nbsp; NULL,<br>&nbsp; &nbsp; OPEN_EXISTING,<br>&nbsp; &nbsp; FILE_FLAG_BACKUP_SEMANTICS,<br>&nbsp; &nbsp; NULL<br>);<br><br><br>你的代码错误在于:<br>1、应该用Generic_Read,目录是可以写的吗?<br>2、应该用Open_Existing<br><br>Win95下是否可行我没试过,如果有问题,写信给我。
 
李颖凶:请你认真些,先看清题意:得到一目录的句柄,而非是要创建目录。<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ~~~~~~~~~~~~~~~<br>&nbsp; &nbsp; &nbsp; &nbsp; 你所说的代码错误改过之后在95下也是一样出错,如你真能解决这一问题,<br>&nbsp; &nbsp; &nbsp; &nbsp; 请你再发表些高见!<br>3h兄:不知你要做些什么,得到句柄的确不易,但我用getlasterror返回的值时有<br>&nbsp; &nbsp; 所发现:即如目录不存在与存在error值会有不同,不知对你是否有用,其它的<br>&nbsp; &nbsp; 还得靠你自己了。:)<br>&nbsp; &nbsp;
 
To 李兄:<br>&nbsp; &nbsp; 虽然您有点急了,不过还是很感激,事实上您为了这道题看了HELP文件。<br>&nbsp; &nbsp; 如果有什么进展的话还是希望您继续发表一些高见。<br>&nbsp; &nbsp; 写信太...了,大家都见不到,还是论坛好. :)<br><br>TO menxin:<br>&gt;不知你要做些什么<br>&nbsp; &nbsp; 看来你对题意也是没有怎么详细注意。哈哈哈<br>&nbsp; &nbsp; 只是为了使用SetFileTime()函数,试图用它修改目录的时间。<br>&gt;但我用getlasterror返回的值时有所发现:<br>&gt;即如目录不存在与存在error值会有不同,不知对你是否有用,<br>&nbsp; &nbsp; 当然有用。不过我试图用另一个函数将getlasterror结果转化成<br>&nbsp; &nbsp; 字串时有问题,因此无法知道它是什么错。老兄可有办法?<br><br>&nbsp; &nbsp; 题目的出处是,我要改变某个目录的建立时间,找来找去只有<br>SetFileTime()函数可用,但它必须是用 GENERIC_WRITE 打开的对象,<br>因此我想到用CreateFile来打开它,并取得句柄。实际是我觉得也只有<br>用这个办法才能取得它的句柄,并且我认为只要这个是正确是操作就一<br>定能够正常进行[SetFileTime()]。这样说,只是一贯以来,文件和目录<br>都是同等待遇的,君不见用 FindFirst() FindNext() FindClose()<br>对文件和目录都是一视同仁的吗?<br>&nbsp; &nbsp; 故有此问。<br>&nbsp; &nbsp; 希望高手们勇跃作答。&lt;font color="red"&gt;200分........&lt;/font&gt;
 
权威消息, 来自微软的MSDN:<br>Window 95/98不支持用 CreateFile 来打开一个目录, 在95/98下只能用FindFirstFile.<br><br>Const<br>&nbsp; FileName = 'C:/Tools'; //这是一个已存在的目录<br>Var<br>&nbsp; q : THandle;<br>&nbsp; FindData: TWin32FindData;<br>begin<br>&nbsp; try<br>&nbsp; &nbsp; Q := FindFirstFile(PChar(FileName), FindData);<br>&nbsp; &nbsp; ...
 
但SetFileTime()函数需要的是用 GENERIC_WRITE 打开的句柄,<br>这个能行吗?
 
我看此问题不会轻易解决。:(
 
It seems a bit hard :)<br>Red, blue, Green, Black... So much colors<br>let me see....
 
hehe, CJ, can you... :)
 
3h, here is a way to show lastError message:<br>var ErrMsg: string<br>begin<br>&nbsp; &nbsp; FormatMessage(<br>&nbsp; &nbsp; &nbsp; FORMAT_MESSAGE_ALLOCATE_BUFFER or<br>&nbsp; &nbsp; &nbsp; FORMAT_MESSAGE_FROM_SYSTEM, //needed for GetLastError<br>&nbsp; &nbsp; &nbsp; 0,<br>&nbsp; &nbsp; &nbsp; GetLastError, //call GetLastError<br>&nbsp; &nbsp; &nbsp; Lang_Neutral,<br>&nbsp; &nbsp; &nbsp; @ErrMsg, //a string variable Error message string<br>&nbsp; &nbsp; &nbsp; 0, //max size of buffer<br>&nbsp; &nbsp; &nbsp; nil);<br>&nbsp; &nbsp; &nbsp; showMessage(ErrMsg);<br>end;
 
我不过把帮助多翻译了一句,就被指为不理解题意,<br><br>不白之冤啊!!!!<br>
 
我用了,看来还是要取得那个通用的写打开句柄才行
 
经我的实验,WINZIP也不能恢复目录的时间,所以<br>可能不能在现阶段的Win32API上实现你要求的功<br>能.如果有哪个压缩软件可以实现(要求是32位的),<br>应该就有办法.
 
取得已经存在的目录句柄而非创建,为什么要用create
 
to lhz:<br>其实WINZIP在展开时应该只是简单的建一个目录,<br>而不是“展开”原有的目录,我认识是这样。<br><br>to LSS:<br>我觉得除些好象没有什么别的方法可取得打开目录时的句柄。<br>老兄可有什么良策?
 
你的问题还没有解决,看来只得找找未公开的 win api 了。
 
看来用API应该没什么希望。<br><br>我想用直接磁盘读写,读文件分配表,得到某一个文件夹的位置,然后写进此位置。<br>不过应该对 FAT16 和 FAT32 十分熟识。<br>高手们发表一下意见如何?
 
FILE_ATTRIBUTE_NORMAL ??<br>这个属性对吗?<br>dos下文件有个attribute位指明是否目录(忘了哪一位了). 进入95/NT时代难道取消了?
 
to Another_eYes:<br>&nbsp; &nbsp;你没注意看题了。<br>&nbsp; &nbsp;我想要的是打开目录的句柄,好让它也能进行修改。
 
我的理解 FILE_ATTRIBUTE_NORMAL表明没有特殊属性(不是目录)<br>所以createfile把您的目录名当成一个文件请求, 而且您设置了OPEN_AWAYS, 在不存在<br>CREATE_NEW时当然无法打开了(如果您没有一个同时叫e:/123的文件的话)
 
顶部