System.Drawing在Windows或ASP.NET服务

根据MSDN的说法,在Windows服务或ASP.NET服务的System.Drawing命名空间中使用类并不是一个特别好的主意。 现在我正在开发一个类库,它可能需要访问这个特定的命名空间(用于测量字体),但不能保证主机进程不是服务。

现在,如果System.Drawing不可用,还有一个不太理想的方法,但是如果可能的话,我宁愿在System.Drawing中使用类。 所以我想要做的是在runtume中确定System.Drawing是否安全,如果是,则使用它,否则返回到次优选项。

我的问题是: 我怎么可能检测到System.Drawing是否安全使用?

我想我也应该

  • 检测当前进程是Windows服务还是ASP.NET服务
  • 检测GDI是否可用
  • 或者也许有一种方法来问System.Drawing.dll本身,如果它是安全的使用

不幸的是,我不能想出一个方法来实现这些方法。 有没有人有任何想法?

要清除任何混淆,System.Drawing在ASP.NET和服务下工作 ,它只是不受支持 。 可能会出现高负载(非托pipe资源耗尽),内存或资源泄漏(执行不当或称为处理模式)和/或在没有桌面显示时popup对话框的问题。

testing会照顾后者,监测会提醒你前者。 但是,如果/当您遇到问题时,不要指望能够打电话给PSS并要求解决。

那么,你有什么select? 那么,如果你不需要一个完全支持的路线,并且你不要求极端的负荷 – 很多人都忽略了MSDN的警告,并成功地使用了System.Drawing。 他们中的一些人被咬了,但比失败的故事更有成就。

如果你想支持某些东西,那么你需要知道你是否在交互式运行。 就个人而言,我可能只是把它留给托pipe应用程序设置一个非交互式的标志在某处或其他地方。 毕竟,应用程序是处于最佳位置,以确定他们是否在托pipe环境中和/或要冒GDI +的风险。

但是,如果你想自动检测你的环境,我想这里的答案比在这里提供的服务差。 总而言之,您可以检查EntryAssembly以查看它是否从ServiceBaseinheritance,或者尝试访问System.Console。 对于ASP.NET来说,检测HttpContext.Current应该是足够的。

我想应该有一个托pipe或p / invoke的方式来寻找一个桌面(这是所有这一切的真正的决定性因素,我认为)和/或从AppDomain的东西,可以提示你。但是,我不确定它是什么,MSDN也不是很有启发性。

编辑:拖动MSDN,我记得它实际上是一个窗口站 (托pipe桌面),这是重要的一点在这里。 有了这个信息,我能findGetProcessWindowStation() ,它返回当前窗口站的句柄。 将该句柄传递给GetUserObjectInformation()会得到一个USEROBJECTFLAGS结构体,如果你有一个可见的桌面,应该有一个带有WSF_VISIBLE的dwFlags。

或者, EnumWindowsStations会给你一个你可以检查的站点列表 – WinSta0是交互式的。

但是,是啊,我仍然认为只是让应用程序设置一个属性或东西是容易的路线….

再次编辑:7年后,我得到线索Environment.UserInteractive MS 确实GetProcessWindowStation跳舞我上面描述为您….我仍然build议委托给托pipe应用程序(他们可能希望更快,但略有风险更高的System.Drawingpath),但UserInteractive似乎是一个很好的默认设置,而不必让它自己动手。

尽pipe它并没有得到官方的支持,但是我已经在高容量的Web服务器(包括Web应用程序和Web服务)上广泛使用了System.Drawing类多年,没有导致任何性能或可靠性问题。

我认为确定代码是否安全使用的唯一方法是使用{}语句testing,监视和包装具有外部资源的任何对象。

你可以使用TextRenderer 。 我知道从ASP.NET的System.Windows.Forms中使用某些东西是很奇怪的,但是它似乎没有关于ASP.NET中不支持的警告。 我已经使用TextRenderer和Graphics.MeasureString来测量ASP.NET应用程序中的string,所以他们都工作。 我从来没有看到有关System.Drawing警告在ASP.NET中不build议。

TextRenderer比Graphics.MeasureString,FWIW慢很多。

这可能与需要STA线程的GDI子系统有关。 如果是这种情况,请调查在您的@PAGE指令中为所涉及的aspx页面指定ASPCOMPAT = TRUE。 这将在STA线程IIRC中运行aspx页面。

-Oisin

您可能能够将System.Drawing.dll复制到您的应用程序的bin,然后以这种方式使用它。 这可能会保证它的可用性。

只需右键单击应用程序中的引用,然后将“ 复制本地 ”选项更改为true

虽然我可能会误解这个问题