从强制IE会话关闭应用程序 [英] Close application from captive IE session

查看:137
本文介绍了从强制IE会话关闭应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题是:这可以做得更好吗?如果是的话,怎么样?有什么想法吗?

My question is: "Can this be done better?" and if so, how? Any ideas?

我们需要在看不见的C#.NET 3.5应用程序中启动一个强制IE会话,并退出IE会话和父应用程序在处理了某个请求之后。

We need to start a captive IE session from within an "invisible" C# .NET 3.5 application, and quit both the IE session and the "parent" application after processing a certain request.

在过去一周左右的时间里,我一直在解决这个问题......今天早上我终于达到了我的想法是一个强大的解决方案但我有点像C#noob(虽然我已经是一名专业程序员已经10年了),所以我正在寻求第二或第三意见;以及任何其他选项,批评,建议或评论......特别是:SHDocVw仍然是创建圈养但未嵌入的Internet Explorer会话的首选方法?

I've been mucking around with this problem for the last week or so... and this morning I've finally reached what I think is a robust solution; but I'm a bit of a C# noob (though I've been a professional programmer for 10 years), so I'm seeking a second or third opinion; and any other options, critiques, suggestions, or comments... Especially: is SHDocVw still the preferred method of creating a "captive but not imbedded" Internet Explorer session?

在我看到的情况下,棘手的一点是处理非托管的 InternetExplorerApplication COM对象,所以我把它包装在 IDisposable 名为的课程InternetExplorer

As I see things, the tricky bit is disposing of the unmanaged InternetExplorerApplication COM object, so I've wrapped it in an IDisposable class called InternetExplorer

我的基本方法是:


  1. Application.Run MyApp,它是一个ApplicationContext,并且是IQuitable。


    • 我认为需要一个应用来保持程序在我们等待IE请求时保持打开状态?

    • 我猜也许一个(非守护进程)监听器循环线程也可以工作?

背景:

真实的故事是:我正在为 MapInfo GIS 客户端)。该插件劫持了从IE到服务器的开始提取HTTP请求,稍微修改了URL并在其中发送了HTTPRequest。我们将respose XML解析为 MIF文件 [PDF 196K],其中然后我们在MapInfo中导入并打开。然后我们退出IE会话,并关闭插件应用程序。

The real story is: I'm writing a plugin for MapInfo (A GIS Client). The plugin hijacks the "Start Extraction" HTTP request from IE to the server, modifies the URL slightly and sends a HTTPRequest in it's place. We parse the respose XML into MIF files [PDF 196K], which we then import and open in MapInfo. Then we quit the IE session, and close the "plugin" application.

SSCCE

using System;
using System.Windows.Forms;

// IE COM interface
// reference ~ C:\Windows\System32\SHDocVw.dll 
using SHDocVw; 

namespace QuitAppFromCaptiveIE
{
    static class Program {
        [STAThread]
        static void Main() {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MyApp());
        }
    }

    interface IQuitable {
        void Quit();
    }

    public class MyApp : ApplicationContext, IQuitable {
        private InternetExplorer ie = null; 

        public MyApp() {
            // create a new Internet Explorer COM component - starts IE application.
            this.ie = new InternetExplorer(this);
            this.ie.Open("www.microsoft.com");
        }

        #region IQuitable Members

        public void Quit() {
            if (ie != null) {
                ie.Dispose();
                ie = null;
            }
            Application.Exit();
        }

        #endregion
    }

    class InternetExplorer : IDisposable, IQuitable
    {
        // allows us to end the parent application when IE is closed.
        private IQuitable parent;
        private bool _parentIsQuited = false;
        private bool _ieIsQuited = false;

        private SHDocVw.InternetExplorer ie; // Old (VB4 era) IE COM component

        public InternetExplorer(IQuitable parent) {
            // lock-onto the parent app to quit it when IE is closed.
            this.parent = parent;
            // create a new Internet Explorer COM component - starts IE application.
            this.ie = new SHDocVw.InternetExplorerClass();
            // hook-up our navigate-event interceptor
            ie.BeforeNavigate2 += new DWebBrowserEvents2_BeforeNavigate2EventHandler(ie_BeforeNavigate2);
        }

        public void Open(string url) {
            object o = null;
            // make the captive IE session navigate to the given URL.
            ie.Navigate(url, ref o, ref o, ref o, ref o);
            // now make the ie window visible
            ie.Visible = true;
        }

        // this callback event handler is invoked prior to the captive IE 
        // session navigating (opening) a URL. Navigate-TWO handles both
        // external (normal) and internal (AJAX) requests. 
        // For example: You could create a history-log file of every page
        // visited by each captive session.
        // Being fired BEFORE the actual navigation allows you to hijack
        // (ie intercept) requests to certain URLs; in this case a request
        // to http://support.microsoft.com/ terminates the Browser session
        // and this program!
        void ie_BeforeNavigate2(object pDisp, ref object URL, ref object Flags, ref object TargetFrameName, ref object PostData, ref object Headers, ref bool Cancel) {
            if (URL.Equals("http://support.microsoft.com/")) {
                this.Quit();
            }
        }

        #region IDisposable Members

        public void Dispose() {
            quitIE();
        }

        #endregion

        private void quitIE() {
            // close my unmanaged COM object
            if (ie != null && !_ieIsQuited) {
                _ieIsQuited = true;
                ie.Quit();
                ie = null;
            }
        }

        #region IQuitable Members

        public void Quit() {
            // close my unmanaged COM object
            quitIE();
            // quit the parent app as well.
            if (parent != null && !_parentIsQuited) {
                _parentIsQuited = true;
                parent.Quit();
                parent = null;
            }
        }

        #endregion
    }

}


推荐答案

它的长短似乎(我仍然不是专家,无论想象力如何) SHDocVw.dll仍然是启动强制Internet Explorer会话的首选方法(因为它适用于在您的应用程序中嵌入浏览器)。

The long and the short of it appears to be (I'm still NOT an expert, by any stretch of the imagination) that SHDocVw.dll is still the preferred method for launching a "captive" Internet Explorer session (as apposed to embedding a browser in your application).

我之前发布的代码是恕我直言,这是最好的解决方案。在最终版本中:

The code I posted previously isn't the best solution, IMHO. In the final version:


  • IQuitable 是历史

  • 两者 MyApp InternetExplorer 类实现 IDisposable

  • 两个 Dispose 方法只返回* _isDisposed *为真。

  • IQuitable is history
  • Both MyApp and InternetExplorer classes implement IDisposable
  • Both Dispose methods just return if *_isDisposed* is true.

以下编码包含一些伪代码,为简洁起见:

The following coded includes some pseudocode, for brevity:

  private volatile bool _isDisposed = false;

  /**
  * _isDisposed stops the two "partners" in the conversation (us and 
  * Internet Explorer) from going into "infinite recursion", by calling 
  * each others Dispose methods within there Dispose methods.
  *
  * NOTE: I **think** that making _isDisposed volatile deals adequately
  * with the inherent race condition, but I'm NOT certain! Comments
  * welcome on this one.
  */
  public void Dispose() {
    if (!_isDisposed) {
      _isDisposed = true;
      try {
        try { release my unmanaged resources } catch { log }
        try {
          IE calls MyApp.Dispose() here // and FALLOUT on failure
          MyApp calls IE.Dispose(); here
        } catch {
          log
        }
      } finally {
        base.Dispose(); // ALLWAYS dispose base, no matter what!
      }
    }
  }

退出应用程序IE类你只是调用它的本地Dispose方法,它调用MyApps Dispose,它再次调用IE的Dispose但isDisposed是真的所以它只返回。然后我们调用Application.ExitThread()并从MyApp的Dispose中删除...然后我们失去了IE的Dispose方法,并且事件系统停止了;并且应用程序很好地终止。最后!

To quit the application from the IE class you just call it's local Dispose method, which calls MyApps Dispose, which calls IE's Dispose again but isDisposed is true so it just returns. Then we call Application.ExitThread() and fall out of MyApp's Dispose... and then we fall out of IE's Dispose method, and the event-system stops; and the application terminates nicely. Finally!

注意编辑:我刚刚使用Robo框架流程重用这种方法,这是一个俘虏过程 MyApp ......它是远程控制的东西。令人费解,但它确实有效...所以当我在这里时,我用我最新的学习内容更新了我的自我回答。

NOTE ON I've just reused this approach with a Robo framework process, which is as a "captive process" of MyApp... the thing it's remote-controling. Convoluted, but it works... So I update my "self answer" with my latest learnings while I was here.

这篇关于从强制IE会话关闭应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆