为啥在控制台应用程序中使用 CommonOpenFileDialog 时会出现此异常?

Posted

技术标签:

【中文标题】为啥在控制台应用程序中使用 CommonOpenFileDialog 时会出现此异常?【英文标题】:Why am I getting this exception when using CommonOpenFileDialog in a Console Application?为什么在控制台应用程序中使用 CommonOpenFileDialog 时会出现此异常? 【发布时间】:2019-11-15 11:18:13 【问题描述】:

问题

我正在尝试使用 CommonOpenFileDialog 的文件夹选择器,如 this answer 中所述。问题是,即使是一个非常精简的示例项目,我在尝试使用 CommonOpenFileDialog 的 ShowDialog() 函数时也会遇到异常。

代码

using Microsoft.WindowsAPICodePack.Dialogs;

namespace DialogTest

    class Program
    
        public static void Main(string[] args)
        
            CommonOpenFileDialog dialog = new CommonOpenFileDialog();
            dialog.InitialDirectory = "C:\\Users";
            dialog.IsFolderPicker = true;

            CommonFileDialogResult result = dialog.ShowDialog();

            if (result == CommonFileDialogResult.Ok)
            
                //Do Stuff
            
        
    

我也在使用以下 nuget 包,作者为 Microsoft:

Microsoft.WindowsAPICodePack-Core Microsoft.WindowsAPICodePack-Shell

例外

此代码在dialog.ShowDialog(); 处产生以下异常:

System.Runtime.InteropServices.COMException was unhandled
  ErrorCode=-2147023116
  HResult=-2147023116
  Message=A null reference pointer was passed to the stub. (Exception from HRESULT: 0x800706F4)
  Source=Microsoft.WindowsAPICodePack.Shell
  StackTrace:
       at Microsoft.WindowsAPICodePack.Dialogs.IFileDialog.SetFileName(String pszName)
       at Microsoft.WindowsAPICodePack.Dialogs.CommonFileDialog.ApplyNativeSettings(IFileDialog dialog) in c:\projects\Windows API Code Pack 1.1\source\WindowsAPICodePack-NuGet\Shell\CommonFileDialogs\CommonFileDialog.cs:line 768
       at Microsoft.WindowsAPICodePack.Dialogs.CommonFileDialog.ShowDialog() in c:\projects\Windows API Code Pack 1.1\source\WindowsAPICodePack-NuGet\Shell\CommonFileDialogs\CommonFileDialog.cs:line 609
       at DialogTest.Program.Main(String[] args) in c:\users\obscerno\documents\visual studio 2015\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs:line 13
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException:

其他一些相关细节

    我使用的是 Visual Studio 2015。 关于这个错误的一个奇怪的事情是这个代码在一年前就可以工作了。我刚刚重新打开项目计划进行一些小的更改,但它不再起作用。

    在创建一个新的测试项目时,在第一次运行时,Visual Studio 会提示我找到一个名为 CommonFileDialog.cs 的文件。

    它检查文件的初始目录是“c:\projects\Windows API Code Pack 1.1\source\WindowsAPICodePack-NuGet\Shell\CommonFileDialogs\CommonFileDialog.cs”,这在我的计算机上不存在。

    如果我选择“取消”,则在以后的调试过程中不会返回提示。我怀疑这个丢失的文件是问题的根源,但不知道如何处理这些信息。

我的尝试

    除了 this amusing but irrelevant question 之外,搜索异常并没有发现什么。

    从多个来源安装相同的 nuget 包并没有给我任何不同的结果。因为for a while Microsoft made them unavailable.

    ,包的副本相当多。

    我尝试在计算机上搜索文件“CommonFileDialog.cs”,但找不到。

【问题讨论】:

你能试着把属性 [STAThread] 放在你的 Main 前面吗? @trykyn 非常感谢你,成功了!您能否将其发布为答案,以便我将此问题标记为已解决? @trykyn 也是,如果你知道为什么这只是在去年才变得必要,我有兴趣了解为什么。如果没有,请不要担心! 【参考方案1】:

作为trykyn mentioned in the comments,解决这个问题的方法是在Main前面加上[STAThread]

工作代码如下所示。请注意,它需要调用System

using System;
using Microsoft.WindowsAPICodePack.Dialogs;

namespace DialogTest

    class Program
    
        [STAThread]
        public static void Main(string[] args)
        
            CommonOpenFileDialog dialog = new CommonOpenFileDialog();
            dialog.InitialDirectory = "C:\\Users";
            dialog.IsFolderPicker = true;

            CommonFileDialogResult result = dialog.ShowDialog();

            if (result == CommonFileDialogResult.Ok)
            
                //Do Stuff
            
        
    

有关什么是 STAThread 的更多信息,此答案将详细介绍:What does [STAThread] do?

STAThreadAttribute 本质上是 Windows 消息泵与 COM 组件通信的要求。尽管核心 Windows 窗体不使用 COM,但操作系统的许多组件(例如系统对话框)确实使用了这种技术。

【讨论】:

以上是关于为啥在控制台应用程序中使用 CommonOpenFileDialog 时会出现此异常?的主要内容,如果未能解决你的问题,请参考以下文章

为啥需要在一个视图控制器中使用委托? [关闭]

为啥我不能在我的导航控制器中推送视图控制器?

为啥只有在 Windows 控制台程序中按 Ctrl+Z 时才会终止输入? [复制]

为啥在模拟器中启动应用程序后 xcode 控制台输出缓慢?

为啥应用安装计数在 Google 开发者控制台中显示少于应用卸载计数

为啥 ActivityViewController 在控制台中显示自动约束错误?