2017-05-22 1 views
0

저는 Excel 2007의 32 비트, Windows 7의 64 비트, VBA7을 사용하여 하나의 텍스트 파일을 프로토 타입 목적으로 추가하려고합니다. 이 작업이 끝나면 동일한 방법을 사용하여 여러 파일의 wav 데이터를 함께 추가하고 첨부 된 wav 데이터의 크기가 올바른지 헤더 정보를 수정합니다.kernel32의 vba dll 호출 writefile이 거대한 파일을 생성합니다.

내가 가지고있는 문제는 WriteFile (동 기적으로)을 호출 할 때 완료하는 데 시간이 오래 걸리고 그 이유는 텍스트 파일에 4GB를 쓰고 있기 때문에 20 바이트 만 기록해야한다는 것입니다. (one.txt의 크기). 무엇이 잘못되었거나 어떻게 디버깅 할 수 있습니까?

큰 조직에서 관리하기 때문에이 컴퓨터에서 사용할 수있는 도구가 제한되어 있습니다. 프로그래밍 환경을위한 VBA에만 액세스 할 수 있습니다. Powershell 및 일반 명령 셸 유틸리티를 사용할 수 있습니다. 나는 다음과 같은 연구를 수행 한

: 모든 DLL 호출에 대한 MSDN 기사를 읽고는, VB에서 DLL 절차에 정보를 전달에 MSDN 문서에 대한 32bit vs 64bit compatibility in office 2010을 읽고 읽고 (대부분) 이해 값이 정확한지 확인하기 위해 중단 점을 설정 , this VB에서 varptr과 dll 함수를 호출하는 훌륭한 페이지를 발견했으며, 많은 학습 중에서 msdn C++ 예제에서 코드를 얻었다. 나는이 Win32API_PtrSafe.txt에서 가져온 선언합니다이 모듈에서

Private Sub cmdCopy_Click() 

    #If Win64 Then 
     MsgBox ("Win 64") 
    #Else 
     MsgBox ("Not win 64 bit") ' Developing on 32-bit excel 2010, windows 7 64 bit 
    #End If 


    'Dim dummyPtr As SECURITY_ATTRIBUTES ' not used, just changed Createfile declare last parameter type to Any to 
    ' allow ByVal 0& to be used 
    'dummyPtr = Null 

    Dim hFile As LongPtr 
    hFile = CreateFile("C:\test\one.txt", GENERIC_READ, 0, ByVal 0&, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, ByVal 0&) 
    'hFile = CreateFile("C:\test\one.txt", GENERIC_READ, 0, vbNullString, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, ByVal 0&) 
    If hFile = INVALID_HANDLE_VALUE Then 
     MsgBox ("Could not open one.txt") 
    End If 

    Dim hAppend As LongPtr 
    hAppend = CreateFile("C:\test\two.txt", FILE_WRITE_DATA, FILE_SHARE_READ, ByVal 0&, _ 
     OPEN_ALWAYS, _ 
     FILE_ATTRIBUTE_NORMAL, _ 
     vbNull) ' no template file 
    If hAppend = INVALID_HANDLE_VALUE Then 
     MsgBox ("Could not open two.txt") 
    End If 

    Dim cBuff(4096) As Byte 
    Dim dwBytesRead As Long 
    Dim dwBytesWritten As Long 
    Dim dwPos As Long 
    Dim bRet As Boolean 
    Dim lRet As Long 



    ' not actually a long ptr 
    Dim lpBytesRead As Long 
    'lpBytesRead = VarPtr(dwBytesRead) ' extraeneous because byref in function declare causes VB to pass a pointer to lpBytesRead 

    ' While (ReadFile(hFile, cBuff, Len(cBuff(LBound(cBuff))), ' a way to not hard-code the buffer length in the function call 
    lRet = ReadFile(hFile, ByVal VarPtr(cBuff(0)), 4096, _ 
     lpBytesRead, ByVal 0&) 
    Debug.Print ("Outside while loop: Readfile: lret, lpBytesRead: " + CStr(lRet) + ", " + CStr(lpBytesRead)) 

    While (lRet And lpBytesRead > 0) 
     dwPos = SetFilePointer(hAppend, 0, vbNull, FILE_END) 
     Debug.Print ("cmdCombine: SetFilePointer: dwPos: " + CStr(dwPos)) 

     Dim i As Long 
     'Print the contents of the buffer from ReadFile 
     For i = 0 To lpBytesRead 
      Debug.Print Hex(cBuff(i)); "='" & Chr(cBuff(i)) & "'" 
     Next 

     'bRet = LockFile(hAppend, dwPos, 0, dwBytesRead, 0) 'commented for debugging 
     Dim lpBuffPointer As Long 
     lpBuffPointer = VarPtr(cBuff(0)) 
     Dim lpBytesWritten As Long 
     lpBytesWritten = VarPtr(dwBytesWritten) 
     Dim lpTest As LongPtr 
     bRet = WriteFile(hAppend, ByVal VarPtr(cBuff(0)), 20, ByVal lpBytesWritten, ByVal 0&) 
     'bRet = WriteFile(hAppend, ByVal VarPtr(cBuff(0)), lpBytesRead, ByVal lpBytesWritten, ByVal 0&) 
     'bRet = WriteFile(hAppend, lpBuffPointer, lpBytesRead, lpBytesWritten, ByVal 0&) ' another option for calling 
     Debug.Print ("cmdCombine: Writefile: bRet, lpBytesRead, lpBytesWritten: " + _ 
      CStr(bRet) + " " + CStr(lpBytesRead) + " " + CStr(dwBytesWritten)) 

     'bRet = UnlockFile(hAppend, dwPos, 0, dwBytesRead, 0) 
     lRet = ReadFile(hFile, ByVal VarPtr(cBuff(0)), 4096, _ 
      lpBytesRead, ByVal 0&) 
     Debug.Print ("Readfile: lret, lpBytesRead: " + CStr(lRet) + ", " + CStr(lpBytesRead)) 
    Wend 

    ' TODO: set EOF to the current file pointer location? 
    'SetEndOfFile (hAppend) 

    CloseHandle (hFile) 
    CloseHandle (hAppend) 
End Sub 

은 나를 UDT에 대해 널을 통과 할 수 있도록 수정 : 당신은 SetFilePointervbNull를 전달하는

Declare PtrSafe Function WriteFile Lib "kernel32" (ByVal hFile As LongPtr, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As Any) As Long 
'Declare PtrSafe Function WriteFile Lib "kernel32" (ByVal hFile As LongPtr, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As OVERLAPPED) As Long 
Declare PtrSafe Function ReadFile Lib "kernel32" (ByVal hFile As LongPtr, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As Any) As Long 
'Declare PtrSafe Function ReadFile Lib "kernel32" (ByVal hFile As LongPtr, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As OVERLAPPED) As Long 
Declare PtrSafe 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 LongPtr) As LongPtr 
'Declare PtrSafe Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As SECURITY_ATTRIBUTES, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As LongPtr) As LongPtr 

Declare PtrSafe Function SetFilePointer Lib "kernel32" (ByVal hFile As LongPtr, ByVal lDistanceToMove As Long, lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long 
Declare PtrSafe Function CloseHandle Lib "kernel32" (ByVal hObject As LongPtr) As Long 

Declare PtrSafe Function LockFile Lib "kernel32" (ByVal hFile As LongPtr, ByVal dwFileOffsetLow As Long, ByVal dwFileOffsetHigh As Long, ByVal nNumberOfBytesToLockLow As Long, ByVal nNumberOfBytesToLockHigh As Long) As Long 
Declare PtrSafe Function UnlockFile Lib "kernel32" (ByVal hFile As LongPtr, ByVal dwFileOffsetLow As Long, ByVal dwFileOffsetHigh As Long, ByVal nNumberOfBytesToUnlockLow As Long, ByVal nNumberOfBytesToUnlockHigh As Long) As Long 

답변

3

.

vbNull1과 같은 열거 형 상수입니다. VarType()이 반환 할 수있는 가능한 결과 중 하나입니다. 그것은 C++의 nullptr이나 VB의 Nothing이 아닙니다. 이 값을 lpDistanceToMoveHigh으로 지정하면이 함수는 use 64-bit addressing으로 지정되고 1dword으로 표시됩니다.

분명히 ByVal 0&을 전달하고 싶었습니다. 널 포인터를 전달하고자 할 때 byref 매개 변수에 전달하는 것입니다.

+0

정답입니다. 내가 이것을 추적하지 못한 이유는'SetFilePointer'가 예상 된 값을 길게 반환했기 때문이며 실제 파일 포인터 위치를 나타내는 64 비트 longlong의 상위 32 비트는'vbNull' 또는 '1 '. –

+0

다음은이 버그를 수정하기 전에 디버그 명령문의 출력입니다. 외부 while 루프 : ReadFile을 : lret, lpBytesRead : 1, 20 cmdCombine : SetFilePointer를 : dwPos 7 74 = 't' 68 = "H" 69 = 'i'를 73 = 'S' 20 = ' 69 = 'i'를 73 = 'S' 20 = ' 74 ='t ' 65 ='E ' 78 ='X ' 74 ='t ' 20 =' 6F = ' o ' 6E ='n ' 65 ='e ' 2E ='. ' 74 = 't'78 = 'X' 74 = 't'= 0 ' cmdCombine :의 WriteFile : 브레, lpBytesRead, lpBytesWritten 트루 20 20 에서 ReadFile : lret, lpBytesRead : 1,0 –