如何解决此 System.IO.FileNotFoundException

Posted

技术标签:

【中文标题】如何解决此 System.IO.FileNotFoundException【英文标题】:How to resolve this System.IO.FileNotFoundException 【发布时间】:2014-05-11 12:48:16 【问题描述】: 该错误仅发生在生产中(不在调试中)。 该错误仅发生在 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, 
      System.Delegate, System.Object, Int32)

   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, 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; 
    

【问题讨论】:

能贴出对应的代码吗? 似乎找不到该文件。没有代码就不可能确定原因。 "Main" 是任何 C# 程序的入口点,尝试在调试异常设置中打开 "FileNotFoundException" 以查看实际行。一些代码也会很好。 @ShaunLuttin 我不知道,有代码,也没有提供异常的详细记录。 @ErikPhilips 在 WPF 程序中总有一个 main 方法,无论您是否亲自编写。看到这个question。 【参考方案1】:

我不想指出明显的问题,但System.IO.FileNotFoundException 表示程序没有找到您指定的文件。所以你需要做的是检查你的代码在生产中寻找什么文件。

要查看您的程序在生产环境中查找的文件(查看异常的 FileName 属性),请尝试以下技术:

写入调试日志, 使用Visual Studio Attach to Process,或 使用Visual Studio Remote Debugging

然后查看机器上的文件系统,看看文件是否存在。最有可能的情况是它不存在。

【讨论】:

我将此标记为答案,因为它导致我使用“附加到处理”。然后我编辑了答案,将附加到进程作为生产调试选项。 “写入调试日志”是什么意思,要写什么? @usefulBee 这意味着您需要存储一些发生的事情的记录以及调试时有用的相关信息。您可以推出自己的日志记录解决方案,但强烈建议查看预先存在的库,例如 Serilog、NLog 等。 这是否意味着无法从事件查看器提供的数据中找出丢失的文件? @usefulBee 这取决于事件查看器中的内容。我当然不会依赖其中的内容。将日志记录掌握在自己手中,这样您就可以准确控制要记录的内容。【参考方案2】:

我在发布 ClickOnce 应用程序后遇到了类似情况,我在不同域的一位同事报告说它无法启动。

为了了解发生了什么,我在 MainWindow 方法中添加了一条 try catch 语句,正如@BradleyDotNET 在原始帖子的一条评论中提到的那样,然后再次发布。

public MainWindow()

    try
    
        InitializeComponent();
    
    catch (Exception exc)
    
        MessageBox.Show(exc.ToString());
    

然后我的同事向我报告了异常细节,这是缺少第三方框架dll文件的引用。

添加参考并解决问题。

【讨论】:

【参考方案3】:

我不止一次被这个错误误导。在花费数小时谷歌搜索、更新 nuget 包、版本检查之后,在使用完全更新的解决方案之后,我重新意识到了一个完全有效、更简单的错误原因。

如果在线程化进程中(例如 UI Dispatcher.Invoke),如果线程管理器 dll(文件)无法返回,则会引发 System.IO.FileNotFoundException。因此,如果您的主 UI 线程 A 调用系统线程管理器 dll B,而 B 调用您的线程代码 C,但 C 因某些不相关的原因抛出(例如在我的情况下为 null 引用),则 C 不会返回,B 会不返回,A只用FileNotFoundException责怪B丢失了……

在进入 dll 版本路径之前...检查离家较近的地方并验证您的线程代码没有抛出。

【讨论】:

【参考方案4】:

仔细检查所有参考文献

目标机器和本地机器上的版本保持不变 如果从 GAC 引用程序集,请确保加载正确的版本

对我来说,通过手动删除来清理整个解决方案,使用与目标计算机同步的版本再次更新(删除和添加)引用,然后使用 Copy Local > False for GAC 程序集进行构建可以解决问题。

【讨论】:

以上是关于如何解决此 System.IO.FileNotFoundException的主要内容,如果未能解决你的问题,请参考以下文章

如何解决此编译错误

如何解决此分段错误:以下代码的 11 错误?

需要帮助:如何解决此功能?

如何解决此科尔多瓦构建错误?

如何解决此覆盖 UITextField 值?

为啥颤振向我显示此错误,我该如何解决?