我需要编写一个围绕第三方api的包装器,它会使用消息泵,因此根据是否在UI线程(例如在wpf应用程序中)实例化包装器(例如控制台应用程序),需要对其进行非常不同的处理)。
如果它不在UI线程上运行,那么我需要一个调度程序并实现我自己的消息泵。
为此,我需要知道包装器是否在wpf应用程序中实例化。仅确定实例化是否发生在UI线程上是不够的(即使在wpf应用程序中,实例化包装器的线程可能不是UI线程)。
有什么办法我可以弄清楚我是在一个带有消息泵或控制台应用程序的wpf或windows窗体环境中我必须实现自己的消息泵吗?
谢谢
如果没有其他答案满足您的需求 - 您可以使用反射来检查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;
}
我认为你可能最好有三个独立的包。
要使其自动选择,您需要在包中引用WPF和WinForms。假设最坏的情况,你的软件包只是让我导入我的控制台应用程序。其他人可能会考虑将WinForms导入到最坏情况的WPF应用程序中,而另一组人可能会执行WinForms,因为他们无法访问WPF(因此您只是将它们从完全使用您的程序包中删除)。
有什么办法我可以弄清楚我是在一个带有消息泵或控制台应用程序的wpf或windows窗体环境中我必须实现自己的消息泵吗?
您可以检查是否有可用的顶级窗口:
if (Process.GetCurrentProcess().MainWindowHandle != IntPtr.Zero)
//WPF
如果WPF应用程序有一个主窗口,MainWindowHandle
应该返回一个句柄。
您还应该能够使用本机GetConsoleWindow函数来确定您是否在控制台应用程序的上下文中。
这可能有效:
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