Почему я получаю это исключение при использовании CommonOpenFileDialog в консольном приложении? - PullRequest
4 голосов
/ 04 июля 2019

Проблема

Я пытаюсь использовать средство выбора папок CommonOpenFileDialog, как описано в этого ответа . Проблема в том, что даже с очень урезанным примером проекта я получаю исключение при попытке использовать функцию ShowDialog() CommonOpenFileDialog.

Код

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:

Некоторые другие важные сведения

  1. Я использую Visual Studio 2015.
  2. Одна странная вещь в этой ошибке - то, что этот код работал год назад. Я только что снова открыл проект, планируя внести небольшие изменения, и он больше не функционировал.
  3. При создании нового тестового проекта при первом запуске Visual Studio предлагает найти файл с именем CommonFileDialog.cs.

    Исходный каталог, в котором он проверяет наличие файла: «c: \ projects \ Windows API Code Pack 1.1 \ source \ WindowsAPICodePack-NuGet \ Shell \ CommonFileDialogs \ CommonFileDialog.cs», который не существует на моем компьютере.

    Если я выберу «отменить», подсказка не будет возвращаться при будущих отладках Я подозреваю, что этот отсутствующий файл является источником проблемы, но не знаю, что делать с этой информацией.

Что я пробовал

  1. Поиск исключений ничего не дал, кроме этого забавного, но неуместного вопроса .

  2. Установка одинаковых пакетов nuget из нескольких источников не дала мне никаких других результатов. Существует довольно много копий пакетов, потому что какое-то время Microsoft делала их недоступными .

  3. Я попытался найти на моем компьютере файл "CommonFileDialog.cs", но его нигде нет.

1 Ответ

0 голосов
/ 09 июля 2019

Поскольку trykyn упоминается в комментариях , решение этой проблемы заключается в добавлении [STAThread] перед Main.

Рабочий код можно увидеть ниже. Обратите внимание, что для этого требуется вызов 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, этот ответ более подробно об этом: Что делает [STAThread]?

STAThreadAttribute - это, по сути, требование к насосу сообщений Windows для взаимодействия с компонентами COM. Хотя ядро ​​Windows Forms не использует COM, многие компоненты ОС, такие как системные диалоги, используют эту технологию.

...