来自 kernel32 的 vba dll 调用 writefile 创建巨大的文件

内森·史密斯

我正在尝试在 excel 2010 32 位中使用 VBA7 将一个文本文件附加到另一个文本文件,在 Windows 7 64 位上用于原型设计。一旦成功,我将使用相同的方法将来自多个文件的 wav 数据附加到一起,并修改标题信息以使其与附加的 wav 数据的大小相符。

我遇到的问题是当我调用WriteFile(同步)时,需要很长时间才能完成,原因是它正在向文本文件写入 4 个演出,它应该只写入 20 个字节(大小one.txt) . 出了什么问题,或者我该如何调试?

我在这台机器上可用的工具有限,因为它是由一个大型组织管理的。我只能访问用于编程环境的 VBA。Powershell 和普通命令 shell 实用程序可用。

我做了以下研究:阅读所有 dll 调用的 msdn 文章,设置断点以验证值是否正确,阅读Office 2010 中的 32 位与 64 位兼容性,阅读并理解(主要是)关于将信息传递给 dll 程序的 msdn 文章VB,在 VB 中找到了关于 varptr 和调用 dll 函数的这个很棒的页面,并从 msdn C++ 示例中获得了代码,其中有很多学习。

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

在模块中,我有来自 Win32API_PtrSafe.txt 的声明,修改后允许我为 UDT 传递 Null:

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
格塞尔格

你正在传递vbNullSetFilePointer.

vbNull是一个枚举常数,等于1它是VarType()可以返回的可能结果之一它不是 C++nullptr或 VB 的Nothing. 传递此值 aslpDistanceToMoveHigh指示函数使用 64 位寻址并将 the1作为高位dword

显然你想通过ByVal 0&byref当您想传递空指针时,它就是您传递给参数的内容。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

覆盖来自 kernel32 的调用

来自分类Dev

为什么我的程序终止调用KERNEL32!FileTimeToSystemTime()?

来自分类Dev

如何覆盖或删除writefile()调用使用的文件?

来自分类Dev

在Nano Server上运行ASP.NET 5会引发“无法加载DLL'kernel32'”

来自分类Dev

解决从Excel Vba调用DLL函数的问题

来自分类Dev

我可以从32位版本的Excel VBA调用64位DLL吗?

来自分类Dev

来自单个DLL文件的MS Office线程?

来自分类Dev

从VBA调用JavaScript文件

来自分类Dev

Excel VBA:“运行时错误” 49“:错误的DLL调用约定”调用C ++ dll

来自分类Dev

从VBA调用Fortran 95 dll,其结构包含动态数组

来自分类Dev

Web服务调用32位dll函数

来自分类Dev

VBA检查文件(来自网站)是否存在

来自分类Dev

VBA检查是否存在文件(来自网站)

来自分类Dev

如何调用java中的dll文件

来自分类Dev

使用包含来自Node.js的char数组的结构调用C ++ dll

来自分类Dev

来自Unity3D的OpenCV dll调用导致FPS下降

来自分类Dev

VBA打开文件和DLL程序

来自分类Dev

来自 dll 的函数调用 [表观调用括号前的表达式必须具有(指向)函数类型]

来自分类Dev

来自被调用文件的魔术常数 - 不是动作文件

来自分类Dev

根据用户输入,使用VBA调用来自不同工作表的数据的优雅方法

来自分类Dev

如何从powerbuilder11.5调用win32 dll?

来自分类Dev

在我的项目中调用64位Dll 32位VC ++

来自分类Dev

从C#调用Advapi32.dll本机EventWrite函数?

来自分类Dev

我的64位程序如何成功调用32位DLL?

来自分类Dev

从Win32 dll调用.Net内置类

来自分类Dev

在我的项目中调用64位Dll 32位VC ++

来自分类Dev

从C#调用Advapi32.dll本机EventWrite函数?

来自分类Dev

JavaScript和NodeJS:来自不同JS文件的调用方法

来自分类Dev

如何使用带有来自VBA的打开事件的xslm文件

Related 相关文章

  1. 1

    覆盖来自 kernel32 的调用

  2. 2

    为什么我的程序终止调用KERNEL32!FileTimeToSystemTime()?

  3. 3

    如何覆盖或删除writefile()调用使用的文件?

  4. 4

    在Nano Server上运行ASP.NET 5会引发“无法加载DLL'kernel32'”

  5. 5

    解决从Excel Vba调用DLL函数的问题

  6. 6

    我可以从32位版本的Excel VBA调用64位DLL吗?

  7. 7

    来自单个DLL文件的MS Office线程?

  8. 8

    从VBA调用JavaScript文件

  9. 9

    Excel VBA:“运行时错误” 49“:错误的DLL调用约定”调用C ++ dll

  10. 10

    从VBA调用Fortran 95 dll,其结构包含动态数组

  11. 11

    Web服务调用32位dll函数

  12. 12

    VBA检查文件(来自网站)是否存在

  13. 13

    VBA检查是否存在文件(来自网站)

  14. 14

    如何调用java中的dll文件

  15. 15

    使用包含来自Node.js的char数组的结构调用C ++ dll

  16. 16

    来自Unity3D的OpenCV dll调用导致FPS下降

  17. 17

    VBA打开文件和DLL程序

  18. 18

    来自 dll 的函数调用 [表观调用括号前的表达式必须具有(指向)函数类型]

  19. 19

    来自被调用文件的魔术常数 - 不是动作文件

  20. 20

    根据用户输入,使用VBA调用来自不同工作表的数据的优雅方法

  21. 21

    如何从powerbuilder11.5调用win32 dll?

  22. 22

    在我的项目中调用64位Dll 32位VC ++

  23. 23

    从C#调用Advapi32.dll本机EventWrite函数?

  24. 24

    我的64位程序如何成功调用32位DLL?

  25. 25

    从Win32 dll调用.Net内置类

  26. 26

    在我的项目中调用64位Dll 32位VC ++

  27. 27

    从C#调用Advapi32.dll本机EventWrite函数?

  28. 28

    JavaScript和NodeJS:来自不同JS文件的调用方法

  29. 29

    如何使用带有来自VBA的打开事件的xslm文件

热门标签

归档