>错误仅发生在生产中(而不是在调试中).
>该错误仅发生在 Windows登录后的第一个应用程序运行中.
>当我们单击BtnUseDesktop并因此触发BtnUseDesktop_Click事件(下面)时,会发生错误.
>事件查看器堆栈以The.Application.Name.Main()方法开头…
>但是我们的代码没有那个方法(它是一个WPF应用程序).
>该错误仅发生在 Windows登录后的第一个应用程序运行中.
>当我们单击BtnUseDesktop并因此触发BtnUseDesktop_Click事件(下面)时,会发生错误.
>事件查看器堆栈以The.Application.Name.Main()方法开头…
>但是我们的代码没有那个方法(它是一个WPF应用程序).
事件查看器
Application: The.Application.Name.exe Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: System.IO.FileNotFoundException Stack: at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen( System.Object,System.Delegate,System.Object,Int32,System.Delegate) at System.Windows.Threading.Dispatcher.LegacyInvokeImpl( System.Windows.Threading.DispatcherPriority,System.TimeSpan,Int32) at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr,IntPtr,IntPtr) at MS.Win32.UnsafeNativeMethods.DispatchMessage(System.Windows.Interop.MSG ByRef) at System.Windows.Threading.Dispatcher.PushFrameImpl( System.Windows.Threading.DispatcherFrame) at System.Windows.Threading.Dispatcher.PushFrame( System.Windows.Threading.DispatcherFrame) at System.Windows.Threading.Dispatcher.Run() at System.Windows.Application.RunDispatcher(System.Object) at System.Windows.Application.RunInternal(System.Windows.Window) at System.Windows.Application.Run(System.Windows.Window) at The.Application.Name.Main()
BtnUseDesktop_Click
private void BtnUseDesktop_Click(object sender,RoutedEventArgs e) { AvSwitcher switcher = new AvSwitcher(); this.RunAsyncTask(() => switcher.SwitchToDesktop(this.windowSyncSvc.ActiveLyncWindowHandle)); }
Click事件调用的AvSwitcher
public class AvSwitcher { private DeviceLocationSvc deviceLocationSvc; private UIAutomationSvc uiAutomationSvc; private WindowMovingSvc windowMovingSvc; private ManualResetEvent manualResetEvent; private Modality audioVideo; public static bool IsSwitching { get; set; } public AvSwitcher() { this.deviceLocationSvc = new DeviceLocationSvc(); this.uiAutomationSvc = new UIAutomationSvc(); this.windowMovingSvc = new WindowMovingSvc(); } public void SwitchToDesktop(IntPtr activeLyncConvWindowHandle) { this.BeginHold(DeviceLocation.Desktop,activeLyncConvWindowHandle); } public void SwitchToWall(IntPtr activeLyncConvWindowHandle) { this.BeginHold(DeviceLocation.Wall,activeLyncConvWindowHandle); } private Conversation GetLyncConversation() { Conversation conv = null; if (LyncClient.GetClient() != null) { conv = LyncClient.GetClient().ConversationManager.Conversations.FirstOrDefault(); } return conv; } private void BeginHold(DeviceLocation targetLocation,IntPtr activeLyncConvWindowHandle) { AvSwitcher.IsSwitching = true; // make sure the class doesn't dispose of itself this.manualResetEvent = new ManualResetEvent(false); Conversation conv = this.GetLyncConversation(); if (conv != null) { this.audioVideo = conv.Modalities[ModalityTypes.AudioVideo]; ModalityState modalityState = this.audioVideo.State; if (modalityState == ModalityState.Connected) { this.HoldCallAndThenDoTheSwitching(targetLocation,activeLyncConvWindowHandle); } else { this.DoTheSwitching(targetLocation,activeLyncConvWindowHandle); } } } private void HoldCallAndThenDoTheSwitching( DeviceLocation targetLocation,IntPtr activeLyncConvWindowHandle) { try { this.audioVideo.BeginHold( this.BeginHold_callback,new AsyncStateValues() { TargetLocation = targetLocation,ActiveLyncConvWindowHandle = activeLyncConvWindowHandle }); this.manualResetEvent.WaitOne(); } catch (UnauthorizedAccessException) { // the call is already on hold this.DoTheSwitching(targetLocation,activeLyncConvWindowHandle); } } private void BeginHold_callback(IAsyncResult ar) { if (ar.IsCompleted) { DeviceLocation targetLocation = ((AsyncStateValues)ar.AsyncState).TargetLocation; IntPtr activeLyncConvWindowHandle = ((AsyncStateValues)ar.AsyncState).ActiveLyncConvWindowHandle; this.DoTheSwitching(targetLocation,activeLyncConvWindowHandle); } Thread.Sleep(2000); // is this necessary this.audioVideo.BeginRetrieve(this.BeginRetrieve_callback,null); } private void DoTheSwitching(DeviceLocation targetLocation,IntPtr activeLyncConvWindowHandle) { DeviceLocationSvc.TargetDevices targetDevices = this.deviceLocationSvc.GetTargetDevices(targetLocation); this.SwitchScreenUsingWinApi(targetDevices.Screen,activeLyncConvWindowHandle); this.SwitchVideoUsingLyncApi(targetDevices.VideoDevice); this.SwitchAudioUsingUIAutomation( targetDevices.MicName,targetDevices.SpeakersName,activeLyncConvWindowHandle); AvSwitcher.IsSwitching = false; } private void SwitchScreenUsingWinApi(Screen targetScreen,IntPtr activeLyncConvWindowHandle) { if (activeLyncConvWindowHandle != IntPtr.Zero) { WindowPosition wp = this.windowMovingSvc.GetTargetWindowPositionFromScreen(targetScreen); this.windowMovingSvc.MoveTheWindowToTargetPosition(activeLyncConvWindowHandle,wp); } } private void SwitchVideoUsingLyncApi(VideoDevice targetVideoDevice) { if (targetVideoDevice != null) { LyncClient.GetClient().DeviceManager.ActiveVideoDevice = targetVideoDevice; } } private void SwitchAudioUsingUIAutomation( string targetMicName,string targetSpeakersName,IntPtr activeLyncConvWindowHandle) { if (targetMicName != null && targetSpeakersName != null) { AutomationElement lyncConvWindow = AutomationElement.FromHandle(activeLyncConvWindowHandle); AutomationElement lyncOptionsWindow = this.uiAutomationSvc.OpenTheLyncOptionsWindowFromTheConvWindow(lyncConvWindow); this.uiAutomationSvc.SelectTheTargetMic(lyncOptionsWindow,targetMicName); this.uiAutomationSvc.SelectTheTargetSpeakers(lyncOptionsWindow,targetSpeakersName); this.uiAutomationSvc.InvokeOkayButton(lyncOptionsWindow); } } private void BeginRetrieve_callback(IAsyncResult ar) { this.audioVideo.EndRetrieve(ar); this.manualResetEvent.Set(); // allow the program to exit } private class AsyncStateValues { internal DeviceLocation TargetLocation { get; set; } internal IntPtr ActiveLyncConvWindowHandle { get; set; } } }
解决方法
我不想指出明显的,但
System.IO.FileNotFoundException意味着程序没有找到你指定的文件.所以你需要做的是检查代码在生产中寻找的文件.
要查看程序在生产中查找的文件(查看异常的FileName属性),请尝试以下技术:
>写入调试日志,
>使用Visual Studio Attach to Process,或
>使用Visual Studio Remote Debugging