Запуск пользовательского интерфейса CustomAction, написанного с использованием WPF, из установщика WIX: ошибка при ошибке STAThread - PullRequest
3 голосов
/ 13 января 2012

Мой установщик WIX немедленно запускает настраиваемое действие. Настраиваемое действие запускает диалоговое окно WPF, запрашивающее у пользователя параметры подключения BD (в основном я написал диалоговое окно подсказки БД «новое соединение» в WPF, чтобы получить строку подключения, которую настраиваемое действие можно вставить в файл конфигурации установленного приложения). Код WIX довольно прост для понимания, и я знаю, что прекрасно выполняю настраиваемое действие - я помещаю туда MessageBox и MmsiBreak при вызове моего метода настраиваемого действия. Добираюсь туда без проблем. Когда пользовательское действие создает экземпляр моего диалогового окна WPF, я получаю InvaliOperationException: «Вызывающий поток должен быть STA, потому что это требуется для многих компонентов пользовательского интерфейса».

Тот же код работает нормально, когда я помещаю его в стандартное приложение WPF, потому что VisualStudio генерирует код вспомогательной платы с Main (), в котором есть атрибут STAThreadAttribute. Я не могу прикрепить этот атрибут к вызывающей программе msiexec, и если я пытаюсь установить состояние квартиры потока в моем настраиваемом действии, он завершается неудачно:

Thread.CurrentThread.SetApartmentState(ApartmentState.STA);

Не должен работать для фреймворка после 2.0.

Есть ли способ сделать то, что я пытаюсь сделать здесь? Буду признателен за некоторые советы.


EDIT

Я даже пытался запустить диалог в своем собственном потоке, например код такой:

// Static class members
static ManualResetEvent _done = new ManualResetEvent(false);
static ActionResult _caResult;
static Session _session;
static Thread _worker;

[CustomAction]
static public ActionResult PromptForDB(Session session)
{
    _session = session;
    _worker = new Thread(WorkerThread);
    _worker.Start();
    _done.WaitOne();
    return _caResult;
}

[STAThread]
static void WorkerThread()
{
    try
    {
        Prompter wnd = new Prompter();
        if (!(bool)wnd.ShowDialog())
        {
            _caResult = ActionResult.SkipRemainingActions;
        }
        else
        {
            // Harvest our properties (omitted from this post)
            _caResult = ActionResult.Success;
        }
        catch (Exception ex)
        {
            _caResult = ActionResult.Failure;
            _session.Log("Error: " + ex.Message);
        }
        finally
        {
            _done.Set();
        }
    }

Это тоже не работает.

1 Ответ

3 голосов
/ 14 января 2012

Перед запуском нового потока установите его ApartmentState следующим образом:

_worker.SetApartmentState(ApartmentState.STA);

См. Это:
Вызывающим потоком должен быть STA, поскольку это требуется для многих компонентов пользовательского интерфейса в WPF * 1006.*

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...