Call CopyMemory2(gDM.DevMode, gDM.lpDevMode, Len(gDM.DevMode))这句代码,执行的时候,有时好使,有时就出错,是在特定的打印机时出错,程序直接提示系统异常,VB的错误处理截获不了错误信息。
现在我的问题是,用什么方法,可以把出错时的错误信息能截获下来,  或者  能想办法即使这行代码错了,也让程序继续执行下去。有些急了,各位高手,拜托了啊。

解决方案 »

  1.   

    声明:Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

    gDM.DevMode为目标地址,如果是数组,应该为数组首单元desArray(0);
    gDM.lpDevMode为源地址,如果是数组应该也为数组首单元surArray(0); 
    对于最后的Length,你要保证gDM.DevMode的确有给定Length的长度,如果是数组,则Ubound(desArray)>=Length-1;
    而且gDM.lpDevMode也必须有Length的长度的数据,如果是数组,则Ubound(surArray)>=Length-1;如果以上有一个条件没有满足,很有可能导致内存溢出,程序无故退出等问题。
      

  2.   

    在调用这个函数的地方设置断点debug,做VB开发debug非常重要,需要跟着事件流程一步一步跟踪下去找到出错的原因点!如果想即使出错也让程序继续执行下去的话,那就把调用这段函数的地方注释掉即可!
      

  3.   

    你先保证以上没有问题吧,如果要捕获错误可用vb中err.LastDllError获得错误号,然后再查下dll错误号对应的错误描述,上goole搜下就行,因为CopyMemory是dll中调用的,如果用vb本身的err.number是没有错误号的!
      

  4.   

    你可以这样:
    Call CopyMemory2(gDM.DevMode, gDM.lpDevMode, Len(gDM.DevMode)) 
    中把gDM.DevMode,gDM.lpDevMode用特定的值取代,再把原本获取的地方注释掉!
      

  5.   

    to (打死不掉牙) 
     
    err.LastDllError这个我没有用过吗,怎么用啊,再有,结合我给的那行代码,他们结合使用啊,谢谢拉
      

  6.   

    你试试这个看看!
    private sub subxxx()
    on error goto errhandle:
     '//调用copymemory的地方
    exit sub
    errhandle:
    msgbox err.LastDllError
    end sub
      

  7.   

    因为你现在获取不了这些参数值,那获取了error信息也没什么用处,先用特定值取代之后模拟一下试试!
      

  8.   

    On Error,特定的值 这些方法我都用过,都不好用,没有什么意义,大家再想想别的办法吧,谢谢了啊
    to (打死不掉牙) :subxxx这样的方法我用过,不好用,截获不到。再帮想想还有什么好的办法吗啊,谢谢了
      

  9.   


    你说的各项参数获取不到是指什么?
    是指Call CopyMemory2(gDM.DevMode, gDM.lpDevMode, Len(gDM.DevMode)) 
    中的gDM.DevMode, gDM.lpDevMode参数值为空吗?
      

  10.   

    如果on error都捕获不到,而且copymemory是无返回值的,不能作为判断执行成功与否的依据,那只好在每次调用copymemory之后记录下err.LastDllError了,可以记录到文件里,当程序无故退出,看看最后一次记录的值是什么。我觉得很有可能是你gDM.lpDevMode内存区没有Len(gDM.DevMode)) 这么长的内存单元导致的,你可以同时记录下Len(gDM.DevMode)) ,gDM.lpDevMode等信息,这个要在copymemory之前记录下,因为很有可能程序在执行copymemory时对内存非法操作了,会直接退出程序,接下来的记录err.LastDllError可能都不能执行。
      

  11.   

    问题也有可能出在Len(gDM.DevMode)上,len只是表示字符个数,lenB是表示确切的字节个数,两个在字符集不同的时候可能会有差异,所以当客户机上操作系统设置等问题也许会产生一些差异,这些是我的猜测,可以借鉴下!
      

  12.   


    Len(gDM.DevMode)---->改为:Len(gDM.lpDevMode)
      

  13.   

    不一定要改Len(gDM.DevMode)---->改为:Len(gDM.lpDevMode),主要看他的应用的,如果只取Len(gDM.DevMode)这么长的数据呢,主要看能不能保证gDM.lpDevMode是否有Len(gDM.DevMode)的数据了!
      

  14.   

    这个是我从FoxAPI上复制下来的代码,希望能给你帮助
    'Example Name: Maintaining Form Aspect Ratio During Resizing'------------------------------------------------------------------------------
    ' BAS Module Code 
    '------------------------------------------------------------------------------
     
    Option Explicit
    Public defWindowProc As Long
    Private Const GWL_WNDPROC As Long = (-4)
    Private Const WM_DESTROY = &H2
    Private Const WM_SIZING = &H214'wParam for WM_SIZING message
    Private Const WMSZ_LEFT = 1
    Private Const WMSZ_RIGHT = 2
    Private Const WMSZ_TOP = 3
    Private Const WMSZ_TOPLEFT = 4
    Private Const WMSZ_TOPRIGHT = 5
    Private Const WMSZ_BOTTOM = 6
    Private Const WMSZ_BOTTOMLEFT = 7
    Private Const WMSZ_BOTTOMRIGHT = 8Private Type RECT
       Left As Long
       Top As Long
       Right As Long
       Bottom As Long
    End TypePrivate Declare Function GetWindowLong Lib "user32" _
        Alias "GetWindowLongA" _
       (ByVal hwnd As Long, _
        ByVal nIndex As Long) As Long
        
    Private Declare Function SetWindowLong Lib "user32" _
        Alias "SetWindowLongA" _
       (ByVal hwnd As Long, _
        ByVal nIndex As Long, _
        ByVal dwNewLong As Long) As Long
       
    Private Declare Function CallWindowProc Lib "user32" _
        Alias "CallWindowProcA" _
       (ByVal lpPrevWndFunc As Long, _
        ByVal hwnd As Long, _
        ByVal uMsg As Long, _
        ByVal wParam As Long, _
        ByVal lParam As Long) As LongPrivate Declare Sub CopyMemory Lib "kernel32" _
       Alias "RtlMoveMemory" _
       (hpvDest As Any, _
        hpvSource As Any, _
        ByVal cbCopy As Long)Public Sub Unhook(fhwnd As Long)    
       If defWindowProc Then
          Call SetWindowLong(fhwnd, GWL_WNDPROC, defWindowProc)
          defWindowProc = 0
       End IfEnd SubPublic Sub Hook(fhwnd As Long)    
       defWindowProc = SetWindowLong(fhwnd, _
                                     GWL_WNDPROC, _
                                     AddressOf WindowProc)                            
    End SubFunction WindowProc(ByVal hwnd As Long, _
                        ByVal uMsg As Long, _
                        ByVal wParam As Long, _
                        ByVal lParam As Long) As Long   Dim rc As RECT   
       Select Case uMsg
       
          Case WM_SIZING
             CopyMemory rc, ByVal lParam, LenB(rc)
             Select Case wParam
             
                Case WMSZ_LEFT
                   rc.Bottom = (rc.Right - rc.Left) + rc.Top
                   CopyMemory ByVal lParam, rc, LenB(rc)
                   WindowProc = 1
       
                Case WMSZ_RIGHT
                   rc.Bottom = (rc.Right - rc.Left) + rc.Top
                   CopyMemory ByVal lParam, rc, LenB(rc)
                   WindowProc = 1
       
                Case WMSZ_TOP
                   rc.Right = (rc.Bottom - rc.Top) + rc.Left
                   CopyMemory ByVal lParam, rc, LenB(rc)
                   WindowProc = 1
       
                Case WMSZ_BOTTOM
                   rc.Right = (rc.Bottom - rc.Top) + rc.Left
                   CopyMemory ByVal lParam, rc, LenB(rc)
                   WindowProc = 1
       
                Case WMSZ_TOPLEFT
                   rc.Left = (rc.Top - rc.Bottom) + (rc.Right)
                   CopyMemory ByVal lParam, rc, LenB(rc)
                   WindowProc = 1
                   
                Case WMSZ_TOPRIGHT
                   rc.Right = (rc.Bottom - rc.Top) + rc.Left
                   CopyMemory ByVal lParam, rc, LenB(rc)
                   WindowProc = 1
       
                Case WMSZ_BOTTOMLEFT
                   rc.Bottom = (rc.Right - rc.Left) + (rc.Top)
                   CopyMemory ByVal lParam, rc, LenB(rc)
                   WindowProc = 1
                   
                Case WMSZ_BOTTOMRIGHT
                   rc.Bottom = (rc.Right - rc.Left) + rc.Top
                   CopyMemory ByVal lParam, rc, LenB(rc)
                   WindowProc = 1
       
                End Select
          
             Case WM_DESTROY:
                If defWindowProc <> 0 Then
                   Call Unhook(form1.hwnd)
                End If
          
        End Select
        
      '处理windows消息
       WindowProc = CallWindowProc(defWindowProc, _
                                   hwnd, _
                                   uMsg, _
                                   wParam, _
                                   lParam)End Function
     
    '------------------------------------------------------------------------------
    ' Form Code 
    '------------------------------------------------------------------------------ 
    '在Form中需要一个Command Button(Command1)
    Option ExplicitPrivate Sub Form_Load()
       With form1      
          .Width = 6000
          .Height = 6000
          Call Hook(.hwnd)   
       End With   
    End SubPrivate Sub Command1_Click()
       Unload Me  
    End Sub
    Private Sub Form_Unload(Cancel As Integer)
        Call Unhook(Me.hwnd)
    End Sub
      

  15.   

    copymemory 的错误是捕捉不到滴,如果是在IDE中按F5编译运行,错误后直接把你的VB也退了!
    而且使用这个函数,有时在IDE环境下不能工作正常的,必须得编译后才能看到效果!所以楼主只能一点点的调试了
      

  16.   

    多谢各位的帮助啊,但是copymemory 的错误,难道就没有办法取得的了吗??不能吧,希望大家继续帮我找找啊,我刚刚注册csdn,分数太少了,希望得到大家好的办法,分数一定送上!!!拜托了
      

  17.   

    你的 gDM 这个类型是如何定义的?gDM.DevMode、 gDM.lpDevMode 分别是什么类型的成员?
      

  18.   

    gDM 是 ifDevMode 类型的结构体 。
    '    Type ifDevMode
    '        hDevMode        As Long
    '        lpDevMode       As Long
    '        DevModeSize     As Long
    '        DevMode         As tagDevMode
    '    End Type
    '
    '    Type tagDevMode
    '    dmDevicName(1)     As Byte
    '    dmSpecVersion       As Integer
    '    dmDriverVersion     As Integer
    '    dmSize              As Integer
    '    dmDriverExtra       As Integer
    '    dmFields            As Long
    '    dmOrientation       As Integer
    '    dmPaperSize         As Integer
    '    dmPaperLength       As Integer
    '    dmPaperWidth        As Integer
    '    dmScale             As Integer
    '    dmCopies            As Integer
    '    dmDefaultSource     As Integer
    '    dmPrintQuality      As Integer
    '    dmColor             As Integer
    '    dmDuplex            As Integer
    '    dmYResolution       As Integer
    '    dmTTOption          As Integer
    '    dmCollate           As Integer
    '    dmFormName(1)      As Byte
    '    dmUnusedPadding     As Integer
    '    dmBitsPerPel        As Integer
    '    dmPelsWidth         As Long
    '    dmPelsHeight        As Long
    '    dmDisplayFlags      As Long
    '    dmDisplayFrequency  As Long
    'End Type
      

  19.   

    如果lpDevMode地址后面跟的内存单元中没有len(DevMode)这么长的数据,那肯定是会出错的!
      

  20.   

    你改成这样Call CopyMemory2(VarPtr(gDM.DevMode), gDM.lpDevMode, Len(gDM.DevMode))试试
      

  21.   

    为什么要把gDM.DevMode 改成 VarPtr(gDM.DevMode)呢?????
      

  22.   

    按你所提供的结构,你所要使用的目标地址应该是DevMode这个结构体首地址啊,VarPtr(gDM.DevMode)返回的值就是gDM包含的DevMode结构体的首地址。而你gDM.lpDevMode所存储的也应该是另外一个tagDevMode结构体的首地址,这样内存单元拷贝时才能对应起来。
      

  23.   

         memcpy  内存复制 是不会失败的    
    但VB下使用要注意它的传递类型  否则是肯定非操的    还有 这个是无法捕获的  LZ只要弄清楚  memcpy 参数的传递类型 就不会非操了不过 初学者要彻底弄清楚这个  也不容易  
      

  24.   

    to (打死不掉牙) Call CopyMemory2(VarPtr(gDM.DevMode), gDM.lpDevMode, Len(gDM.DevMode))不加VarPtr,程序也是好使的啊,只是有时不好使,所以,还是想问,非得加VarPtr吗,理由是什么呢,谢谢
      

  25.   

    不加vb应该也会自动将gDM.DevMode的首地址传过去,但是加了你会明确知道你传的是首地址啊。不知道能不能肯定gDM.lpDevMode所指的内存地址之后存的就是tagDevMode这样一个结构。
      

  26.   

    也许我说的也是错的,你自己最好在调用CopyMemory2前都记录下gDM.DevMode等相关的值吧,这样也有助于分析!
      

  27.   

    你的:CopyMemory2() 跟 CopyMemory() 是同一个 API 吧?
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long楼主是想把 gDM.lpDevMode 所指向的一块数据区拷贝到 gDM 的 DevMode 这个结构体成员的内存区吧?如果是这样的话,试试:
    Call CopyMemory2(gDM.DevMode, ByVal gDM.lpDevMode, Len(gDM.DevMode))当然,执行这句前,你得确保 gDM.lpDevMode 所指向的那片数据块包含正确的 tagDevMode 数据信息。
      

  28.   

    看来你还得说一下你的:CopyMemory2() 是如何声明的。
    声明方式不一样,调用时的写法也不一样。
    错误的调用方法有可能造成程序崩溃。
      

  29.   

       VB的传递方式 不统一    用API
     按照你申明的不同  传递方式也不同  
    把有问题的参数 用byval LONG型申明   然后传递 地址指针  试试
    也就是用varptr 获取变量的内存首地址传递   以前用VB时  也碰到过 频繁调用memcpy时    确实会非操  就算传递的参数都是正确的 
    可以试试 NT函数NtWriteVirtualMemory   句柄用-1代替 就是自身内存了   
    我以前就是这样解决的非操问题 总之 就是觉得VB  一点都不方便  
    还是VC好 直接操作内存  想怎么弄 怎么弄 哈哈 非常方便