有关全局对象的问题
一、问题的形成
公司MSS系统里,原有的生成文档方式方式是,利用window.open打开一个wordcreate.aspx文件,然后在这个aspx文件中调用生成文档控件(注:该控件有vb编写,通过引用microsoft office 10.0 object library来生成文档)来生成一个doc文件,但是由于由于现在大多数客户端都安装了广告拦截工具,用这种方式的话,会把生成文档控件所在窗口给屏蔽了,导致不能生成文档。于是现在用ifame标签把wordcreate.aspx嵌入到页面中,来生成文档。用这种方式第一次生成文档的时候,无任何异常情况,但是第二次再执行同样的生成文档操作时,就会发现生成文档控件启动了三个word进程,文档生成结束后,只关闭了一个word进程。这导致生成的文档没有达到预期的效果,并且打开时还提示该文档已被某某用户锁定。
二、问题产生的原因
调试程序发现,当程序运行到ActiveWindow.View.TableGridlines = False时出错,显示462错误:The remote server machine does not exist or is unavailable,而出错后,程序并没有把当前出错进程终止掉,只是把Word.Application类型变量oWord设置成Nothing,并且继续往下执行(注:生成文档的过程是先创建一个word进程,打开一doc文件,然后把该doc文件里的图片,表格,文字复制出来。然后再重复同样的操作,把另一doc文件的信息复制出来。最后一步,把之前复制出来的信息保存到一新的doc文件中, 终止该进程),这样就会出现三个word进程。而那句代码的意思是让改文档里表格线隐藏掉。
上网查找462错误形成的原因,发现ms有一篇《在 Visual Basic 中使用早期绑定时 Office 自动执行出现错误或意外行为》的文章刚好说到这个问题。出现这个错误的原因就是因为使用了全局对象的非限定方法引起的。而代码ActiveWindow.View.TableGridlines = False中的ActiveWindow恰好就是一个全局对象。
三、为什么用window.open和iframe方法会现在两种不同的结果呢?
这得从全局对象说起,全局对象就是在程序中,可以在任何代码位置来调用全局对象的方法和属性,而不需要显式设置对象的大小和创建对象的新实例。如果以前尚未创建该对象,在调用代码时 VB 将创建该对象,然后在一个隐藏的变量中设置对该对象的引用。对该对象的任何非限定方法或属性调用都在隐藏的引用上调用。程序无权访问此隐藏的变量。也无法更改或释放它。该引用直到项目结束后才会自动释放。因此,在页面第一次调用该控件生成文档时,控件就会创建office引用库中的相关全局对象的引用,当用window.open方法生成文档后,会关闭当前IE窗口,从而释放了全局对象的引用。而用ifame方式生成文档后,当前IE窗口并没有关闭,全局对象的引用还是之前第一次生成文档时创建的word对象实例,因此虽然代码在每次运行时都创建 Office 应用程序的一个新实例,但非限定代码(非限定代码:属性过程使用同一名称并返回各自的对象)导致 VB 设置了对旧实例的一个隐藏引用,而旧实例已经结束了,因此就会出现本文开头描述的错误。
公司MSS系统里,原有的生成文档方式方式是,利用window.open打开一个wordcreate.aspx文件,然后在这个aspx文件中调用生成文档控件(注:该控件有vb编写,通过引用microsoft office 10.0 object library来生成文档)来生成一个doc文件,但是由于由于现在大多数客户端都安装了广告拦截工具,用这种方式的话,会把生成文档控件所在窗口给屏蔽了,导致不能生成文档。于是现在用ifame标签把wordcreate.aspx嵌入到页面中,来生成文档。用这种方式第一次生成文档的时候,无任何异常情况,但是第二次再执行同样的生成文档操作时,就会发现生成文档控件启动了三个word进程,文档生成结束后,只关闭了一个word进程。这导致生成的文档没有达到预期的效果,并且打开时还提示该文档已被某某用户锁定。
二、问题产生的原因
调试程序发现,当程序运行到ActiveWindow.View.TableGridlines = False时出错,显示462错误:The remote server machine does not exist or is unavailable,而出错后,程序并没有把当前出错进程终止掉,只是把Word.Application类型变量oWord设置成Nothing,并且继续往下执行(注:生成文档的过程是先创建一个word进程,打开一doc文件,然后把该doc文件里的图片,表格,文字复制出来。然后再重复同样的操作,把另一doc文件的信息复制出来。最后一步,把之前复制出来的信息保存到一新的doc文件中, 终止该进程),这样就会出现三个word进程。而那句代码的意思是让改文档里表格线隐藏掉。
上网查找462错误形成的原因,发现ms有一篇《在 Visual Basic 中使用早期绑定时 Office 自动执行出现错误或意外行为》的文章刚好说到这个问题。出现这个错误的原因就是因为使用了全局对象的非限定方法引起的。而代码ActiveWindow.View.TableGridlines = False中的ActiveWindow恰好就是一个全局对象。
三、为什么用window.open和iframe方法会现在两种不同的结果呢?
这得从全局对象说起,全局对象就是在程序中,可以在任何代码位置来调用全局对象的方法和属性,而不需要显式设置对象的大小和创建对象的新实例。如果以前尚未创建该对象,在调用代码时 VB 将创建该对象,然后在一个隐藏的变量中设置对该对象的引用。对该对象的任何非限定方法或属性调用都在隐藏的引用上调用。程序无权访问此隐藏的变量。也无法更改或释放它。该引用直到项目结束后才会自动释放。因此,在页面第一次调用该控件生成文档时,控件就会创建office引用库中的相关全局对象的引用,当用window.open方法生成文档后,会关闭当前IE窗口,从而释放了全局对象的引用。而用ifame方式生成文档后,当前IE窗口并没有关闭,全局对象的引用还是之前第一次生成文档时创建的word对象实例,因此虽然代码在每次运行时都创建 Office 应用程序的一个新实例,但非限定代码(非限定代码:属性过程使用同一名称并返回各自的对象)导致 VB 设置了对旧实例的一个隐藏引用,而旧实例已经结束了,因此就会出现本文开头描述的错误。