【问题标题】:How to detect .Net application type?如何检测 .Net 应用程序类型?
【发布时间】:2009-05-18 16:36:21
【问题描述】:

我有一个库,它需要以不同的方式响应异常,具体取决于它是在控制台应用程序、WinForms、AspNet 还是 Windows 服务中运行。我已经尝试查看 System.Windows.Forms 和 System.Web 命名空间中的各种属性,但我找不到可靠的方法来准确检测托管我的库的应用程序类型。有人来过这里吗?有人有可靠的解决方案吗?

【问题讨论】:

标签: .net asp.net winforms console


【解决方案1】:

如果我正确理解您在寻找什么,那么您有一个单独的库来处理错误,但您希望该库知道源是 Web、控制台、winforms 等吗?

您也许可以利用库中的一个属性,比如一个枚举,来跟踪正在使用的应用程序类型是什么。比如……

ErrorLogger error = new ErrorLogger(ErrorLoggerAppType.WinForm);
ErrorLogger error = new ErrorLogger(ErrorLoggerAppType.Web);
ErrorLogger error = new ErrorLogger(ErrorLoggerAppType.Console);

编辑
来自 cmets 中的 Samir...
此外,您总是可以让每种类型的应用程序的类在您的错误记录器库中实现相同的接口。

例如在您将使用的 Web 应用程序中:

WebErrorLogger error = new WebErrorLogger();

【讨论】:

  • 或者:error = new GUIErrorLogger(); / 错误 = 新的 WebErrorLogger(); / 错误 = 新的 ConsoleErrorLogger();它们都实现了接口ErrorLogger。
  • 这是我目前所处的位置 - 但我正在尝试消除消费者以这种方式进行初始化的需要。如果没有人能想出更好的主意,那么我可能不得不坚持下去。
【解决方案2】:

在走这条路之前我会质疑你的设计,但我认为这是一个有趣的挑战,想看看我是否能找到。

ASP.Net:检查 HttpContext.Current 不为空。您还可以查看 System.Web.Hosting.ApplicationManager.GetApplicationManager(),但我不确定它在 Asp.net 之外的表现如何

窗口表单:您可以尝试使用 System.Windows.Forms.Application.OpenForms,这将返回任何打开的表单。假设 Windows 窗体应用程序永远不会没有任何窗体。此外,控制台应用程序也可以启动 win 表单。

服务:对此不确定,但我想知道您是否可以检查进程的名称。还必须有一个 Windows API,因为任务管理器会显示进程何时是服务(至少在 Vista 上是这样)

【讨论】:

  • 小心使用 HttpContext.Current;它将在 ASP.NET 应用程序的非请求线程中返回 null。
【解决方案3】:

这听起来最好通过配置来处理。也许通过 IOC 注入类似 IExceptionHandler 接口的东西。

【讨论】:

    【解决方案4】:

    这感觉就像您想要更多地研究设计,但这是我的自发性。类库不需要知道关于它的调用者的那些事情。

    您希望根据运行的上下文对异常处理行为进行哪些更改?

    根据您的评论,我建议考虑为错误处理程序定义一个接口,然后创建该接口所需数量的实现(一个用于 WinForms,一个用于控制台等),并让客户端应用程序创建并注入相应的实现到库中。这样,您就可以从库中提取知识需求并将责任转移到客户端应用程序上。这些实现仍然可以驻留在您的类库中,但使用哪个实现将由客户端应用程序来决定。

    【讨论】:

    • 它是一个支持库,为可在各种上下文中使用的其他库和应用程序提供基础架构。这个想法是,这个库提供了一种处理未处理错误并将它们报告给主机应用程序的通用方法。
    • 在所有情况下,都会向 Jira 服务器发送一封包含详细信息的电子邮件。但在 Windows 中,会截取屏幕截图并向用户显示对话。在控制台应用程序中,详细信息被写入控制台。我在这里提到了错误处理,但也可能有其他目的。
    【解决方案5】:
    BOOL IsConsole(PBYTE file)
    {
        PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)file;
        if(pDosHeader->e_magic == IMAGE_DOS_SIGNATURE) 
        {
            PIMAGE_NT_HEADERS pImageHeaders = (PIMAGE_NT_HEADERS)(file + pDosHeader->e_lfanew);
            if(pImageHeaders->Signature == IMAGE_NT_SIGNATURE) 
            {
                IMAGE_OPTIONAL_HEADER optionalHeader = pImageHeaders->OptionalHeader;
                return (optionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI);
            }
        }
    
        return FALSE;
    }
    

    IMAGE_SUBSYSTEM_WINDOWS_CUI 可以与IMAGE_SUBSYSTEM_WINDOWS_GUI 交换,以检测它是否是 GUI 应用程序而不是控制台。

    windows中的服务通常有'services.exe'作为它们的父进程,确定父进程的方法在CodeProject中有很好的描述。

    ASP.NET进程运行在名为ASPNET的特殊用户下,用户名可以从an access token获取。

    【讨论】:

    • 这最接近我想要实现的目标。此链接似乎提供了有关二进制文件是否是控制台应用程序的合理信息量。:codeguru.com/cpp/w-p/system/misc/article.php/c2897。我不能依赖正在使用的 ASPNET 用户——我们使用各种服务帐户来运行各种目的。我认为结合下面乔希的回答,我可能会想出一个合理的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-20
    • 2010-11-28
    • 1970-01-01
    • 2023-03-09
    相关资源
    最近更新 更多