关于拷贝独占文件的问题(NTFS格式已经可以,Fat32不行)
实现的功能是: 拷贝当前因为独占而造成锁定的文件已经解决的: 如果一个文件放到NTFS分区下,使用某个程序锁定后,再使用该程序拷贝,完全没有问题
需要解决的: 如果这个文件在FAT32分区下,使用某个程序锁定后,再使用该程序拷贝,虽然可以拷贝,大小也相同,但是拷贝
的数据都是错误的,先将 代码公布如下(NTFS)的,寻求高手可以将FAT32下的功能实现
界面上放置两个文本框和一个按钮
--------------------编程问答-------------------- 此代码不管当前的文件是否是独占,可以用access打开一个mdb(以独占的方式),然后用这段代码再去拷贝那个已经打开的mdb文件,完全没有问题,关键是fat的分区,其实我是怀疑这个函数 GetFileClusters 中 lngOutSize = 32 + (lngFileSize \ lngClusterSize) * 16
Private Declare Function DeviceIoControl Lib "kernel32" (ByVal hDevice As Long, ByVal dwIoControlCode As Long, lpInBuffer As Any, ByVal nInBufferSize As Long, lpOutBuffer As Any, ByVal nOutBufferSize As Long, lpBytesReturned As Long, lpOverlapped As Any) As Long
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As Any) As Long
Private Declare Function SetFilePointer Lib "kernel32" (ByVal hFile As Long, ByVal lDistanceToMove As Long, lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As Any) As Long
Private Declare Function GetSystemDirectory Lib "kernel32" Alias "GetSystemDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long
Private Declare Function GetDiskFreeSpace Lib "kernel32" Alias "GetDiskFreeSpaceA" (ByVal lpRootPathName As String, lpSectorsPerCluster As Long, lpBytesPerSector As Long, lpNumberOfFreeClusters As Long, lpTotalNumberOfClusters As Long) As Long
Private Declare Function GetFileSize Lib "kernel32" (ByVal hFile As Long, lpFileSizeHigh As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Const GENERIC_READ = &H80000000
Private Const FILE_SHARE_READ = &H1
Private Const FILE_SHARE_WRITE = &H2
Private Const OPEN_EXISTING = 3
Private Const INVALID_HANDLE_VALUE = -1
Private Const GENERIC_WRITE = &H40000000
Private Const OPEN_ALWAYS = 4
Private Const FILE_READ_ATTRIBUTES = (&H80)
Private Const FSCTL_GET_RETRIEVAL_POINTERS = 589939
Private Type RETRIEVAL_POINTERS_BUFFER
dwExtentCount As Long
bytStartingVcn(7) As Byte '这些都可以使用LARGE_INTEGER类型代替
bytNextVcn(7) As Byte '这些都可以使用LARGE_INTEGER类型代替
bytLcn(7) As Byte '这些都可以使用LARGE_INTEGER类型代替
lngTmp(255) As Byte
End Type
Private Type LARGE_INTEGER
LowPart As Long
HighPart As Long
End Type
Private Sub cmdCopy_Click()
Dim strSamPath As String
'如果需要拷贝sam,则修改下边的
' strSamPath = GetSystemPath & "\Config\Sam"
strSamPath = txtSource.Text
If CopySamFile(strSamPath, txtPath.Text) Then
MsgBox "复制完毕!!", vbInformation, "提示"
Else
MsgBox "复制错误!!", vbCritical, "提示"
End If
End Sub
'获取系统目录路径
Private Function GetSystemPath() As String
Dim strTmp As String
strTmp = String(260, Chr(0))
GetSystemDirectory strTmp, 260
strTmp = Left(strTmp, InStr(strTmp, Chr(0)) - 1)
GetSystemPath = strTmp
End Function
Private Function GetFileClusters(ByVal strFileName As String, ByVal lngClusterSize As Long, lngClCount As Long, lngFileSize As Long) As Long()
Dim hFile As Long
Dim lngOutSize As Long
Dim lngBytes As Long, lngCls As Long, lngCnCount As Long, r As Long, lngCount As Long, i As Long, j As Long
Dim lngClusters() As Long
Dim bytInBuf(7) As Byte
Dim objOutBuf As RETRIEVAL_POINTERS_BUFFER
Dim bytOutBuff() As Byte
hFile = CreateFile(strFileName, FILE_READ_ATTRIBUTES, _
FILE_SHARE_READ Or FILE_SHARE_WRITE Or FILE_SHARE_DELETE, _
ByVal 0&, OPEN_EXISTING, 0, 0)
If hFile <> INVALID_HANDLE_VALUE Then
lngFileSize = GetFileSize(hFile, 0)
lngOutSize = 32 + (lngFileSize \ lngClusterSize) * 16
Dim bytOutBuf() As Byte: ReDim bytOutBuf(lngOutSize - 1)
If DeviceIoControl(hFile, FSCTL_GET_RETRIEVAL_POINTERS, bytInBuf(0), 8, _
bytOutBuf(0), lngOutSize, lngBytes, ByVal 0&) Then
CopyMemory objOutBuf, bytOutBuf(0), lngBytes
lngClCount = (lngFileSize + lngClusterSize - 1) \ lngClusterSize
For r = 0 To objOutBuf.dwExtentCount - 1
CopyMemory j, objOutBuf.bytLcn(4), 4
For i = lngClCount To 0 Step -1
ReDim Preserve lngClusters(0 To lngCls)
lngClusters(lngCls) = j
j = j + 1
lngCls = lngCls + 1
Next
Next
CloseHandle hFile
GetFileClusters = lngClusters
End If
End If
End Function
Private Function CopySamFile(ByVal strSamPath As String, ByVal strDestPath As String) As Boolean
Dim lngClusterSize As Long
Dim lngClusters() As Long
Dim lngClCount As Long, lngFileSize As Long, lngBytes As Long
Dim hDrive As Long, hFile As Long
Dim lngSecPerCl As Long, lngBtPerSec As Long, r As Long
Dim curTmp As Currency
Dim ligNo As LARGE_INTEGER
Dim bytBuff() As Byte
GetDiskFreeSpace Left(strSamPath, 2), lngSecPerCl, lngBtPerSec, ByVal 0&, ByVal 0&
lngClusterSize = lngSecPerCl * lngBtPerSec
On Error GoTo ErrHandle
lngClusters = GetFileClusters(strSamPath, lngClusterSize, lngClCount, lngFileSize)
hDrive = CreateFile("\\.\" & Left(strSamPath, 2), GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, OPEN_EXISTING, 0, 0)
If hDrive <> INVALID_HANDLE_VALUE Then
hFile = CreateFile(strDestPath, GENERIC_WRITE, 0, ByVal 0, OPEN_ALWAYS, 0, 0)
If hFile <> INVALID_HANDLE_VALUE Then
For r = 0 To lngClCount - 1
curTmp = CCur(lngClusterSize) * CCur(lngClusters(r)) / 10000 'lngClusterSize * lngClusters(r)
CopyMemory ligNo, curTmp, Len(ligNo)
Call SetFilePointer(hDrive, ligNo.LowPart, ligNo.HighPart, 0)
If lngFileSize < lngClusterSize Then
ReDim bytBuff(lngClusterSize - 1)
Call ReadFile(hDrive, bytBuff(0), lngClusterSize, lngBytes, ByVal 0&)
Call WriteFile(hFile, bytBuff(0), lngFileSize, lngBytes, ByVal 0&)
Exit For
Else
ReDim bytBuff(lngClusterSize - 1)
End If
Call ReadFile(hDrive, bytBuff(0), lngClusterSize, lngBytes, ByVal 0&)
Call WriteFile(hFile, bytBuff(0), lngClusterSize, lngBytes, ByVal 0&)
lngFileSize = lngFileSize - lngBytes
Debug.Print ligNo.LowPart; ligNo.HighPart
Next
End If
CloseHandle hFile
End If
CloseHandle hDrive
CopySamFile = True
Exit Function
ErrHandle:
If hDrive <> -1 Then CloseHandle hDrive
If hFile <> -1 Then CloseHandle hFile
End Function
Private Sub cmdExit_Click()
Unload Me
End Sub
这句代码有问题,因为Fat32和ntfs此处的参数不知道是否有用?
冰天雪地 零下60度裸奔三十里,看是否有高人予以解决!
--------------------编程问答-------------------- 顶大侠。。
联络我把,使用在线验证
这位大侠。联系上吧。
我QQ:26404992
--------------------编程问答-------------------- #14楼 得分:0回复于:2009-07-21 19:01:11或者那位大侠帮下小弟。给我加个锁上去。能控制使用权就OK。定会重谢!QQ:26404992
对我有用[0] 丢个板砖[0] 引用 举报 管理 TOP
springoldbrother
(springoldbrother)
等 级:
#15楼 得分:0回复于:2009-07-21 19:18:29联络我把,使用在线验证
--------------------编程问答-------------------- 学习 --------------------编程问答-------------------- 期待高手高手高高手出手,春哥保佑 --------------------编程问答-------------------- 这是以前我写的代码。
在fat32下计算磁盘偏移是有问题的
需要加上保留扇区以及fatcount等 --------------------编程问答-------------------- chenhui530,你好,这段代码是在网上搜到后修改的,请问如何修改保留扇区以及fatcount呀 --------------------编程问答-------------------- 对是修改一份c代码的,至于怎么计算其实很简单,保留扇区+FatAreaCount*2 --------------------编程问答-------------------- 请问是修改 Call SetFilePointer(hDrive, ligNo.LowPart, ligNo.HighPart, 0)
这个函数吗? --------------------编程问答-------------------- 可否指点一下小弟,如何获取fat32 的保留扇区以及 fatareacount,偏移的时候加上这个值,指的是 setfilepointer 吗? --------------------编程问答-------------------- FDUMP version 1.0 by Armen Hakobyan, 2008
Dumps file to another location reading its sectors directly from disk.
FDUMP [/V] source destination
source Specifies the file to be dumped directly from disk.
destination Specifies the output file name for the dumped data.
/V Produce verbose output.
--------------------编程问答-------------------- 不明白 --------------------编程问答-------------------- 保留和扇区和 fat 表数,都可以计算出来,请问 保留扇区+FatAreaCount*2 是修改那个函数 --------------------编程问答-------------------- 自己再顶一下 --------------------编程问答-------------------- 我看你这代码,正准备进来说叫找陈辉这小子呢.
看来我可以匿了....... --------------------编程问答-------------------- 是呀,陈辉一直不在呀 --------------------编程问答-------------------- 不知myjian兄弟对此可有研究? --------------------编程问答-------------------- 关注
本人一直认为独占打开的access文件是无法复制的。 --------------------编程问答-------------------- 可以的,用上边的代码,如果access所在的分区是 ntfs 的话,一点问题都没有 --------------------编程问答-------------------- 我不懂这个,哈哈.
建议你开个200分的帖叫人帮你写 --------------------编程问答-------------------- ntfs 对小文件你的这个代码也会有问题的
The stream is resident in the MFT and has no clusters allocated
NTFS文件当文件很小时,文件会保存在MFT里,而不会给它分配簇来保存数据
另外一个帖子也给你回了FAT32 起始数据区计算的问题 --------------------编程问答-------------------- 好像小于512的有点问题,不过这个问题我已经处理了一下,是可以的
Call ReadFile(hDrive, bytBuff(0), lngClusterSize, lngBytes, ByVal 0&)
Call WriteFile(hFile, bytBuff(0), lngFileSize, lngBytes, ByVal 0&)
改了一下上边的两个函数
--------------------编程问答-------------------- 非常感谢你的回复,我再研究看看,先结贴 --------------------编程问答-------------------- curTmp = CCur(lngClusterSize) * CCur(lngClusters(r)) + (保留扇区+FatAreaCount*2) * BytesPerSector
还有 这段代码如果分区大于2GB的话 应该也不行,GetDiskFreeSpace Left(strSamPath, 2), lngSecPerCl, lngBtPerSec, ByVal 0&, ByVal 0& 读不出SecPerCl, BtPerSec --------------------编程问答-------------------- @noface: NTFS小文件拷贝问题是如何解决的,望告知,3q
补充:VB , API