Как я могу передать управляемые объекты из одного процесса в другой? - PullRequest
0 голосов
/ 05 мая 2010

У меня есть две сборки, которые я пытаюсь связать вместе.

  1. Один из них - это своего рода фоновый процесс, который построен с помощью WinForms и предназначен для работы в качестве службы Windows.
  2. У меня есть второй проект, который будет выступать в качестве пользовательского интерфейса для фонового процесса всякий раз, когда пользователь запускает его.

Я никогда раньше не пытался делать что-то подобное с управляемым кодом, поэтому я начал пытаться использовать сообщения Windows для связи между двумя процессами. Однако я испытываю трудности, когда дело доходит до передачи большего, чем просто IntPtrs.

Вот код из элемента управления в моем проекте пользовательского интерфейса, который регистрируется в фоновом процессе:

public void Init()
{
    IntPtr hwnd = IntPtr.Zero;
    Process[] ps = Process.GetProcessesByName("BGServiceApp");
    Process mainProcess = null;
    if(ps == null || ps.GetLength(0) == 0)
    {
        mainProcess = LaunchApp();
    }
    else
    {
        mainProcess = ps[0];
    }
    SendMessage(mainProcess.MainWindowHandle, INIT_CONNECTION, this.Handle, IntPtr.Zero);
} 

protected override void  WndProc(ref Message m)
{
    if(m.Msg == INIT_CONFIRMED && InitComplete != null)
    {
        string message = Marshal.PtrToStringAuto(m.WParam);
        Marshal.FreeHGlobal(m.WParam);

        InitComplete(message, EventArgs.Empty);
    }
    base.WndProc(ref m);
}

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

 protected override void WndProc(ref Message m)
 {
     if(m.Msg == INIT_CONNECTION)
     {
         RegisterUIDispatcher(m.WParam);
         Respond(m.WParam);
     }

     if(m.Msg == UNINIT_CONNECTION)
     {
         UnregisterUIDispatcher(m.WParam);
         if(m_RegisteredDispatchers.Count == 0)
         {
             this.Close();
         }
     }
     base.WndProc(ref m);
}

private void Respond(IntPtr caller)
{
     string test = "Registration confirmed!";
     IntPtr ptr = Marshal.StringToHGlobalAuto(test);

     SendMessage(caller, INIT_CONFIRMED, ptr, IntPtr.Zero);
}

Процесс пользовательского интерфейса получает сообщение INIT_CONFIRMED от моего фонового процесса, но когда я пытаюсь собрать IntPtr обратно в строку, я получаю пустую строку. Область кучи, которую я использую, выходит за рамки другого процесса, или мне не хватает какого-либо атрибута безопасности? Есть ли лучший и более чистый способ сделать что-то подобное с использованием модели, управляемой событиями?

1 Ответ

1 голос
/ 05 мая 2010

Не уверен, что вы хотите пойти по этому пути, но вам может быть проще использовать WCF в качестве уровня IPC, чем низкоуровневые компоненты Windows IPC. Вам нужно будет создать и предоставить интерфейсы для службы, а затем подключиться к ним с помощью приложения UI.

Есть много хороших учебных пособий по WCF, если вы хотите попробовать.

...