FolderBrowserDialog зависает в проекте установки .Net - PullRequest
4 голосов
/ 02 апреля 2012

Я написал инструмент, который должен вызываться как часть проекта установщика .Net.

Он должен запросить у пользователя каталог, а затем обновить мой конфиг.

Я использую следующий код, чтобы показать dlg для выбора файла:

{
    FolderBrowserDialog dlg = new FolderBrowserDialog();

    dlg.Description = "Trace-Verzeichnis auswählen";
    dlg.ShowNewFolderButton = true;

    if (DialogResult.OK ==  dlg.ShowDialog( this ))
    {
        tbTraceDir.Text = dlg.SelectedPath;
    }
}

Если я запускаю инструмент из командной строки, FolderBrowserDialog показывает нормально. Если он вызывается как часть пакета установщика из класса установщика, он бесконечно зависает в ShowDialog ()

Редактировать: То же поведение, когда я запускаю его из VStudio или из командной строки ... Я использую .Net 4 (не профиль клиента)

Любые намеки, что я могу делать не так?

спасибо

Mario

Ответы [ 3 ]

2 голосов
/ 04 ноября 2014

Кажется, я пропустил лодку на этом, но я искал что-то подобное, и нашел отличный ответ, который на самом деле работает , и я объясню почему.Вы должны добавить новое пользовательское действие в ваш проект установщика.Затем все, что вам нужно сделать, это:

[CustomAction]
public static ActionResult SpawnBrowseFolderDialog(Session session)
{
    Thread worker = new Thread(() =>
    {
        FolderBrowserDialog dialog = new FolderBrowserDialog();
        dialog.SelectedPath = session["INSTALLFOLDER"];
        DialogResult result = dialog.ShowDialog();
        session["INSTALLFOLDER"] = dialog.SelectedPath;
    });
    worker.SetApartmentState(ApartmentState.STA);
    worker.Start();
    worker.Join();
    return ActionResult.Success;
}

Или вы можете просто делать все что угодно внутри нового потока ... действительно, причина, по которой это работает, заключается в том, что вам нужно выделитьновая тема, которая должна иметь состояние квартиры ГНА.Компоненты пользовательского интерфейса в Windows, как правило, должны выполняться в однопоточном (STA) состоянии, поскольку это обеспечивает надлежащий параллелизм для компонента пользовательского интерфейса, поскольку только один поток может изменять пользовательский интерфейс одновременно.

1 голос
/ 03 апреля 2013

У меня была похожая проблема сегодня. У меня был следующий код:

using System;
using System.Windows.Forms;

class dummy{

    public static void Main() {
        FolderBrowserDialog f = new FolderBrowserDialog();
        f.SelectedPath = System.Environment.CurrentDirectory;
        f.Description= "Select a folder, for great justice.";
        f.ShowNewFolderButton = true;
        if(f.ShowDialog() == DialogResult.OK) {
            Console.Write(f.SelectedPath);
        }
    }
}

Выглядит хорошо, верно? Он скомпилирован и связан без ошибок, но полученный исполняемый файл просто зависает, даже не отображая средство выбора папки.

Что для меня исправило, так это добавление [STAThread] до Main().

using System;
using System.Windows.Forms;

class dummy{
    [STAThread]
    public static void Main() {
        FolderBrowserDialog f = new FolderBrowserDialog();
        f.SelectedPath = System.Environment.CurrentDirectory;
        f.Description= "Select a folder, for great justice.";
        f.ShowNewFolderButton = true;
        if(f.ShowDialog() == DialogResult.OK) {
            Console.Write(f.SelectedPath);
        }
    }
}

А теперь окно браузера папок отображается правильно.

1 голос
/ 02 апреля 2012

Проблема заключается в том, что настраиваемое действие ожидает (бесконечно) пользовательского ввода, но оно выполняется под учетной записью SYSTEM.

Настраиваемое действие, для которого требуется доступ к пользовательскому интерфейсу, должно быть запланировано на последовательность пользовательского интерфейса с немедленным выполнением, которое олицетворяетучетная запись пользователя.

WiX пример:

<CustomAction Id='FooAction' 
              BinaryKey='FooBinary' 
              DllEntry='FooEntryPoint' 
              Execute='immediate'
              Return='check'/>

<Binary Id='FooBinary' SourceFile='foo.dll'/>

<InstallUISequence>
  <Custom Action='FooAction' After='AppSearch'></Custom>
</InstallUISequence>
...