我需要编写一个围绕第三方api的包装器,它会对消息泵进行处理,因此需要根据是否在UI线程(例如在wpf应用程序中)实例化包装器(例如在wpf应用程序中)进行非常不同的处理(例如控制台应用程序)。
如果它不在UI线程上运行,那么我需要一个调度程序并实现我自己的消息泵。
为此,我需要知道包装器是否在wpf应用程序中实例化。仅确定实例化是否发生在UI线程上是不够的(即使在wpf应用程序中,实例化包装器的线程可能不是UI线程)。
有什么方法可以判断我是在wpf或Windows窗体环境中使用消息泵还是控制台应用程序,我必须实现自己的消息泵?
由于
答案 0 :(得分:9)
我认为最好有三个独立的套餐。
要使其自动选择,您需要在程序包中引用WPF 和 WinForms。假设最坏的情况,你的软件包只是让我将两个导入到我的控制台应用程序中。其他人可能会考虑将WinForms导入到最坏情况的WPF应用程序中,而另一组人可能会执行WinForms,因为他们无法访问WPF(因此,您只是完全不使用您的软件包)。
答案 1 :(得分:6)
如果没有其他答案满足您的需求 - 您可以使用反射来检查Application.Current
是否为null,而不直接引用WPF程序集(和WinForms一样):
private static bool IsWpfApplication() {
var type = Type.GetType("System.Windows.Application, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
if (type == null)
return false;
var currentProp = type.GetProperty("Current", BindingFlags.Public | BindingFlags.Static);
if (currentProp == null)
return false;
return currentProp.GetValue(null, new object[0]) != null;
}
请注意,这可能会将PresentationFramework
dll加载到当前应用程序域中,即使在控制台应用程序中也是如此。如果这对您来说是个问题 - 您可以通过检查已在app域中加载的程序集来执行相同的操作:
private static bool IsWpfApplication2() {
var wpfAsm = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(c => c.GetName().Name == "PresentationFramework");
if (wpfAsm == null)
return false;
var type = wpfAsm.GetType("System.Windows.Application");
if (type == null)
return false;
var currentProp = type.GetProperty("Current", BindingFlags.Public | BindingFlags.Static);
if (currentProp == null)
return false;
return currentProp.GetValue(null, new object[0]) != null;
}
答案 2 :(得分:1)
有什么方法可以判断我是在wpf或Windows窗体环境中使用消息泵还是控制台应用程序,我必须实现自己的消息泵?
您可以检查是否有可用的顶级窗口:
if (Process.GetCurrentProcess().MainWindowHandle != IntPtr.Zero)
//WPF
如果WPF应用程序有一个主窗口, MainWindowHandle
应该返回一个句柄。
您还应该能够使用本机GetConsoleWindow函数来确定您是否在控制台应用程序的上下文中。
答案 3 :(得分:0)
这可能有效:
public static void Main(string[] args)
{
var application = Application.Current;
Console.WriteLine($"Application is {(application == null ? "null": "not-null")}");
Console.ReadKey();
}
需要引用PresentationFramework,并根据Resharper,WindowsBase和System.Xaml