2010-05-04 4 views
0

У меня есть две сборки, которые я пытаюсь связать.Как передать управляемые объекты из одного процесса в другой?

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

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

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

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); 
} 

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

+0

Так это AppDomain для AppDomain или процесса для обработки? - большая разница. Звучит так, как будто вы хотите Process-Process, и поэтому вы можете исправить вопрос. –

+0

О да, моя ошибка. Моя первая попытка заключалась в использовании GCHandles, и она создала исключение с сообщением о том, что GCHandle не может использоваться вне AppDomain, но это определенно проблема процесса для процесса. –

ответ

1

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

Существует много хороших учебников WCF, если вы хотите сделать снимок.

+0

Это будет работать довольно хорошо, к сожалению, одним из других применений для проекта пользовательского интерфейса является то, что класс, который взаимодействует с фоновым процессом, я в конечном итоге хотел бы использовать для публикации API другим пользователям. Использование неуправляемого кода для IPC определенно более активно, но это позволит мне выйти на рынок для большей аудитории конечных пользователей. –

Смежные вопросы