Страница: 1 |
|
Вопрос: Связать приложения через Windows-сообщения
|
Добавлено: 06.02.09 09:08
|
|
Автор вопроса: Oleg | ICQ: 407182478
|
Доброго дня. Подскажите плиз, как в VB объявить/зарегестрировать новое событие для приложения и процедуру обработки этого события, для того, что бы из другого приложения можно было посылать сообщения, например через API SendMessage?
Ответить
|
Номер ответа: 2 Автор ответа: Oleg
ICQ: 407182478
Вопросов: 9 Ответов: 10
|
Профиль | | #2
|
Добавлено: 06.02.09 18:14
|
Ок. Давайте конктретно. Мне необходимо из моего приложения считывать и записывать данные из ячеек Excel(причём в большом количестве).
Используя технологию VSTO(кажется так), пробовал 10000 раз считать значение одной ячейки - становится грустно, результата не дождался,
а если то же самое провернуть под Excel т.е. на VBA, время исполнения кода примерно 0,5 сек. Вот и задался я вопросом о другом методе межпроцесового взаимодействия и Windows-сообщения - первое(и по ходу последнее) что пришло в голову. Что скажите?
Ответить
|
Номер ответа: 6 Автор ответа: Oleg
ICQ: 407182478
Вопросов: 9 Ответов: 10
|
Профиль | | #6
|
Добавлено: 07.02.09 18:26
|
Кстати, уважаемый, если вы намекаете, что эксель очень быстрый, скажу вам это весьма опасное заблуждение
я тоже не разделяю иллюзий по этому поводу
Подключаешь модель экселя и рулишь ей как хочется, на VB6 элементарно.
А в .Net как всегда нужно закопаться куданибудь типа гейтс.билл.микрософт.офис.эксель.открыть "Мои документы\Забубенный.xls"
Правильно, только в этом случае обращение к Excel происходит через COM-компонент, т.е.
- Imports Microsoft.Office.Interop.Excel
- Dim App As New Application
- Dim wb = App.Workbooks.Open("d:\DataBase.xls")
- Dim ws As Worksheet = wb.Worksheets("Tree")
при этом VB создаёт собственные классы-обёртки вокруг COM-сервисов Excel, а это и является основной причиной "тормозов" при выполнении кода.
есть еще такие вещи как пайпы (pipes) (кстати в нет 3.5 есть), а также файлы, проецируемые в память (mapped file)(как-то так).
Пайпы то ведь используются как виртуальные каналы для передачи данных меж приложениями/компами, а в моём случае надо принимать/передавать маленькие порции данных, причём по команде одного из приложений, т.е. синхронно.
А можно пару "цивилизованых методов межпроцесового взаимодействия"?
Вот, вот.
Ответить
|
Номер ответа: 9 Автор ответа: AgentFire
ICQ: 192496851
Вопросов: 75 Ответов: 3178
|
Профиль | | #9
|
Добавлено: 11.02.09 16:07
|
Dim PSI As New System.Diagnostics.ProcessStartInfo("процесс.exe", "/параметры"
PSI.RedirectStandardOutput = True
PSI.RedirectStandardInput = True
PSI.UseShellExecute = False
PSI.CreateNoWindow = True
Dim PP = Process.Start(PSI)
...
'Писать так
PP.StandardInput.WriteLine(Buffer)
'А читать так
Buffer = PP.StandardOutput.ReadLine
Ответить
|
Номер ответа: 11 Автор ответа: EROS
Вопросов: 58 Ответов: 4255
|
Профиль | | #11
|
Добавлено: 12.02.09 01:28
|
А можно пару "цивилизованых методов межпроцесового взаимодействия"?
да легко! Если речь идет о NET-приложениях на обоих концах, то вполне можно заюзать WCF,Remoting,DDE,TCP/IP и еще кучу технологий которые на всидку не вспомнил.. Все зависит от конкретной ситуации. Но в этом,конкретном случае, я приму сторону топикстартера.. имхо он прав. Вариант с отправкой сообщения самый безболезненный и легкореализуемый в случае с Excel
Теперь по теме.. К счастью, я не использую VB, поэтому пример набросал на C# но если очень надо, то перевести на VB труда не составит..
как в VB объявить/зарегестрировать новое событие для приложения и процедуру обработки этого события, для того, что бы из другого приложения можно было посылать сообщения, например через API SendMessage?
для регистрации события юзай API RegisterWindowMessage, а вариантов перехвата сообщений - туча:
- NativeWindow
- WndProc
- IMessageFilter
- и т.д.
опять таки повторюсь, но все зависит от конкретной ситуации..
Я покажу пример перехвата сообщения через реализацию интерфейса IMessageFilter(ты можешь заюзать любой другой способ)
В примере я все части(регистрация, отправка и перехват) реализовал в рамках одного приложения, но ты можешь разнести эти части как угодно.
1. Регистрация сообщения
-
- using System;
- using System.Runtime.InteropServices;
- using System.Windows.Forms;
-
- namespace SendMsg
- {
-
- static class Program
- {
-
- [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
- static extern int RegisterWindowMessage(string lpString);
-
-
- [STAThread]
- static void Main()
- {
- /* регистрируем свое событие */
- MessageId = RegisterWindowMessage("MSG_VBNET_SAMPLE");
-
- /* запускаем приложение */
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- Application.Run(new Form1());
- }
-
- /* ID нашего события */
- private static int m_messageId;
- public static int MessageId
- {
- get { return m_messageId; }
- private set
- {
- m_messageId = value;
- }
- }
- }
- }
2. Отправка и перехват
-
- using System;
- using System.Runtime.InteropServices;
- using System.Windows.Forms;
- using System.Diagnostics;
-
- namespace SendMsg
- {
- /* имплементируем IMessageFilter */
- public partial class Form1 : Form, IMessageFilter
- {
- /* API declaration */
- [DllImport("user32.dll", CharSet = CharSet.Auto)]
- static extern IntPtr PostMessage(IntPtr hWnd, int msg, IntPtr wParam, string lParam);
-
- public Form1()
- {
- InitializeComponent();
-
- /* добавляем нашу форму в очередь сообщений */
- Application.AddMessageFilter(this);
- }
-
- protected override void OnFormClosing(FormClosingEventArgs e)
- {
- /* удаляем из очереди
- * необязательно, но я привык убирать мусор за собой
- */
- Application.RemoveMessageFilter(this);
- base.OnFormClosing(e);
- }
-
- private void DoWork(string message)
- {
- /* тут чего нибудь делаем ... */
- MessageBox.Show(message, "VBNET.RU", MessageBoxButtons.OK);
- }
-
- private void btnSend_Click(object sender, EventArgs e)
- {
- /* отправляем сообщение сами себе */
- PostMessage(this.Handle, Program.MessageId, IntPtr.Zero, "Hello from vbnet.ru!");
- }
-
- #region IMessageFilter Members
-
- public bool PreFilterMessage(ref Message m)
- {
- /*
- * Проверяем ID полученного сообщения
- * и если это наше сообщение, то вытаскиваем переданные параметры
- */
- if (m.Msg == Program.MessageId)
- {
- /* получаем переданную строку или что там у тебя будет */
- string message = Marshal.PtrToStringAuto(m.LParam);
- /* вызываем какой нибудь метод для обработки или что то еще... */
- DoWork(message);
- }
-
- return false;
- }
-
- #endregion
-
- }
- }
стоит так же отметить тот факт, что при первом вызове RegisterWindowMessage, она зарегистрирует сообщение, а при последующих вызовах просто будет возвращать ID уже имеющегося сообщения. Таким образом ты можешь не волноваться по поводу того, что при каждом вызове это ф-ии будет разный ID, он будет неизменный в рамках сессии юзера.
Ответить
|
Страница: 1 |
Поиск по форуму