我写了一个监控浏览器的小程序,目的是禁止打开标题中含特定字符串的网页,在VB IDE环境中测试正常,编译为exe以后运行也一切正常,但是如果把它作为系统服务来启动,则会出现 运行时错误"7",内存溢出 的错误而启动失败,有没有朋友知道是怎么回事?说明:
1、用ntsvc.ocx来实现系统服务,与系统服务相关的代码可以保证没有问题;
2、程序中添加了对Microsoft Internet Controls的引用;
3、主要功能通过网上找的两个类模块稍加修改来完成,两个类模块分别引用了SHDocVw.InternetExplorer和SHDocVw.ShellWindows。虽然可以改用其他自启动方式,但是既然发现了这个问题,不解决就很郁闷,请大家给帮帮忙吧!

解决方案 »

  1.   

    关键是在VB IDE中测试和编译为exe后都一切正常,只有作为系统服务启动才会出错,我把代码贴出来,请大家分析一下问题出在哪:类模块cIEWindows:
    Option ExplicitPrivate WithEvents winShell As SHDocVw.ShellWindows
    Private mCol As Collection
    Dim bRefreshing As Boolean, bInit As BooleanPrivate Function Add(IEctl As SHDocVw.InternetExplorer) As IE_Class
        Dim objNewMember As IE_Class
        Set objNewMember = New IE_Class
        Set objNewMember.IEctl = IEctl
        mCol.Add objNewMember
        Set Add = objNewMember
        Set objNewMember = Nothing
    End FunctionPublic Property Get IE(vntIndexKey As Variant) As IE_Class
      Do While bRefreshing
         DoEvents
      Loop
      Set IE = mCol(vntIndexKey)
    End PropertyPublic Property Get Count() As Long
       Count = mCol.Count
    End PropertyPrivate Sub Remove(vntIndexKey As Variant)
       mCol.Remove vntIndexKey
    End SubPublic Property Get NewEnum() As IUnknown
       Set NewEnum = mCol.[_NewEnum]
    End PropertyPrivate Sub Class_Initialize()
      Refresh_Col
    End SubPrivate Sub Class_Terminate()
       Set mCol = Nothing
       Set winShell = Nothing
    End SubPrivate Sub winShell_WindowRegistered(ByVal lCookie As Long)
      Refresh_Col
      Do While bRefreshing
         DoEvents
      Loop
    End SubPrivate Sub winShell_WindowRevoked(ByVal lCookie As Long)
      Refresh_Col
      Do While bRefreshing
         DoEvents
      Loop
    End SubPrivate Sub Refresh_Col()
       bRefreshing = True
       Dim SWs As New SHDocVw.ShellWindows
       Dim var As SHDocVw.InternetExplorer
       Set mCol = Nothing
       Set mCol = New Collection
       For Each var In SWs
           Add var
       Next
       If Not bInit Then Set winShell = SWs
       bInit = True
       Set SWs = Nothing
       Set var = Nothing
       bRefreshing = False
    End Sub
      

  2.   

    类模块IE_Class:
    Option ExplicitPrivate WithEvents IE As SHDocVw.InternetExplorerPublic Property Set IEctl(IncomeIE As SHDocVw.InternetExplorer)
        On Error Resume Next
        Set IE = IncomeIE
    End PropertyPrivate Sub Class_Terminate()
        On Error Resume Next
        Set IE = Nothing
    End SubPrivate Sub IE_TitleChange(ByVal Text As String)
        If InStr(1, Text, "禁止打开的字符串", vbTextCompare) Then
            IE.Navigate "about:blank"
        End If
    End Sub
      

  3.   

    窗体frmMain:
    Option ExplicitDim StopService As BooleanDim IEWin As cIEWindowsPrivate Sub Form_Load()
        App.TaskVisible = False
        
        Set IEWin = Nothing
        Set IEWin = New cIEWindows
        
        StopService = False
        NTService.ControlsAccepted = svcCtrlPauseContinue
        NTService.StartService
    End SubPrivate Sub Form_Unload(Cancel As Integer)
        If Not StopService Then
            NTService.StopService
        End If
    End SubPrivate Sub NTService_Continue(Success As Boolean)
        On Error GoTo ServiceError
        Success = True
        Exit Sub
    ServiceError:
    End SubPrivate Sub NTService_Control(ByVal mEvent As Long)
        On Error GoTo ServiceError
        Exit Sub
    ServiceError:
    End SubPrivate Sub NTService_Pause(Success As Boolean)
        On Error GoTo ServiceError
        Success = True
        Exit Sub
    ServiceError:
    End SubPrivate Sub NTService_Start(Success As Boolean)
        On Error GoTo ServiceError
        Success = True
        
        Exit Sub
    ServiceError:
        NTService.LogEvent svcMessageError, svcEventError, "[" & Err.Number & "] " & Err.Description
    End SubPrivate Sub NTService_Stop()
        On Error GoTo ServiceError
        StopService = True
    ServiceError:
    End Sub
      

  4.   

    看来你没用好NT服务程序,NT服务程序大致分两种,一种是可交互的,一种是不可交互的
    你用不可交互的模式处理交互模式下的浏览器,肯定会出问题的了。
    还有,通常处理浏览器的程序使用BHO(Browser Helper Objects)技术比较好。
    这东西用服务程序作完全是多余的。服务程序是确保用户还没有登陆时都能提供服务而使用的。
    而你的需求必须是用户登陆后才监视得了的浏览器,这么早启动完全没什么意义,
    而且不可交互的NT服务程序也不能处理这样的事,甚至连DDE信息和很多API使用都是无效的,
    建议你看看BHO方面的资料,控制和取得浏览器信息用BHO最合适。
      

  5.   

    问题已经基本解决。
    我现在把程序分成了两部分,主程序为一部分,loader为一部分,loader作为系统服务,启动后运行主程序。
    有意思的是,在loader中如果直接用shell或者shellexecute来执行主程序,还是会出现内存溢出错误,而用shell "cmd /c ..."来调用则不会,哪位朋友可以解释一下这个问题啊?
      

  6.   

    晕,刚才弄错了,问题一点都没解决,用cmd/c来调用还是会内存溢出!
      

  7.   

    看来是你的架构有问题,看看SQL,他有用System启动的NT服务程序,也有用Administrator启动在托盘的用户程序。
    可以通过用户程序改变服务程序的配置,当然也可以服务程序发送信息让用户程序作服务程序不能做或不方便作的事。
    再看看那些下载软件,都是单独用BHO来搞个接口,应用程序也是分离的。如果什么程序都要放在一起,有时候效果反而
    不是很好。
      

  8.   

    1、在资源管理器中直接双击运行;
    2、作为系统服务来运行;
    3、在系统服务中通过shell或者shellexecute或者cmd/c来运行这个exe
    对于exe文件的这三种运行方式,如果说前两种有很大的不同,那么第1种和第3种方式应该区别不大吧,为什么我的exe用第1种方式可以顺利运行,而后两种方式都会出现内存溢出的错误呢?
      

  9.   

    NT服务和应用程序从运行权限和程序的开发本来就有很大不同。
    至少我没有用NT服务直接运行成应用程序,或反过来直接拿应用
    程序加成NT服务来运行我也没这么做过,即使我用,也是在程序里
    做了特殊处理的,比如在运行时判断程序如果是NT服务的话怎么处
    理应用程序安装自己成NT服务一类的,如果是NT服务的话又怎么去
    初始化相关参数。所以就会出现这类的问题。
    建议:比如网络服务用NT服务,其他的控制应用程序的就以应用程
    序的方式作比较好。其实VB做NT服务Microsoft本来就不建议这样
    去做的,相信你也知道,但你还想把这类程序作成万能的,呵呵。
      

  10.   

    不再讨论这个问题了,看来不会有什么结果,我改用其他的实现方式好了,谢谢朋友们的关注和参与。
    就像SupermanKing朋友说的,微软是不建议用VB6写系统服务的,只是我用ntsvc.ocx做个多个服务,只有这一个出了问题,所以对其中的原因很想弄个究竟,并不是非得解决这个问题不可。
    结贴,再次谢谢大家!