Сообщений 23    Оценка 41 [+0/-1]         Оценить  
Система Orphus

Встраиваем net send

Автор: Алексей Исаков (Alexx_id)
Источник: RSDN Magazine #3-2006
Опубликовано: 06.12.2006
Исправлено: 10.12.2016
Версия текста: 1.0
Введение
Как это сделать
Простой подход
Что же там внутри
Пример
Нужно больше?
Послесловие

Исходные тексты примера к статье

Введение

Часто возникает желание встроить в свою программу что-нибудь, к чему пользователи привыкли или, по крайней мере, не боятся. Так, может захотеться встроить рассылку уведомлений/сообщений по сети, использующую механизм "net send".

Как это сделать

Простой подход

Если стандартная реализация net send вас устраивает, то можно смело вызвать ShellExecute для net.exe и не читать статью до конца. Минимум кода и предельная простота:

ShellExecute(
    hWnd,
    "open",
    "net.exe",
    " send " + sComputerName + "\"Hello!\"",
    "%SystemRoot%\\system32",
    SW_HIDE
);

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

Что же там внутри

Чтобы понять, с помощью чего отправляются сообщения, пришлось взглянуть на net.exe. Но там ничего интересного не обнаружилось. Оказалось, что тот вызывает net1.exe с теми же параметрами (наверное, был в этом тайный смысл). А вот уже в коде net1.exe удалось найти вызов функции, которая отправляет сообщение – NetMessageBufferSend:

NET_API_STATUS NetMessageBufferSend(
    LPCWSTR servername,
    LPCWSTR msgname,
    LPCWSTR fromname,
    LPBYTE buf,
    DWORD buflen
);

Здесь:

ПРИМЕЧАНИЕ

Посылать сообщений с другого компьютера могут только администраторы!

Чтобы просто "повторить" действия net send для отправки сообщения на некий компьютер, достаточно вызывать:

DWORD dwSize = 12; // Удвоенная длина строки "Hello!", т.к. все-таки уникод
DWORD dwRet = NetMessageBufferSend(NULL, L"<CompName>", NULL, (LPBYTE)L"Hello!", dwSize);

Такое "повторение" само по себе уже приятнее вызова ShellExecute, т.к. позволяет установить причину ошибки в случае отказа.

Но не только это хорошо, третий параметр функции (fromname) можно использовать в качестве имени отправителя! Стоит сразу оговориться, что произвольное имя должно быть зарегистрировано, для чего используется функция NetMessageNameAdd:

DWORD dwRet = NetMessageNameAdd(NULL, L"SenderName");

Здесь первый параметр аналогичен параметру servername, т.е. NULL для локального компьютера.

ПРИМЕЧАНИЕ

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

Отправка сообщения домену в принципе аналогична отправке сообщения на конкретный компьютер, за одним исключением. Предположим, что нужно отправить сообщение на домен «DOMAIN», тогда в качестве имени получателя нужно указать «DOMAIN*». Вот и вся хитрость.

Можно конечно, перебрать все компьютеры домена и послать каждому по сообщению (я даже где-то видел такую реализацию), но это же совсем не то, чего хочется, т.к. в качестве получателя будет имя компьютера получателя, а не имя домена. С другой стороны, каждый получатель будет думать, что сообщение отправляли именно ему и ничье самолюбие не будет задето. :)

ПРИМЕЧАНИЕ

Справедливости ради стоит отметить, что "net send *" на самом деле перерабатывает внутри себя "звездочку" и подает на вход функции NetMessageBufferSend данные для отправки сообщения домену, а не "звездочке" :).

Пример

NetSendSample – пример использования описанных выше возможностей. Все предельно просто: нужно заполнить нужные поля и нажать кнопку отправки. Обязательные поля: "Receiver", "Message", "Send to". Поле "Sender" заполнять не обязательно, если оно не заполнено, сообщение будет отправлено от имени локального компьютера.

Нужно больше?

Понятное дело, что вызов описанных выше функций - не единственное решение поставленной задачи, можно и поглубже копнуть (в некоторых случаях это действительно нужно), но для встраивания net send этого вполне достаточно. Дополнительные сведения можно получить на http://www.rsdn.ru/article/files/Progs/WinPopdown.xml.

Послесловие

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


Эта статья опубликована в журнале RSDN Magazine #3-2006. Информацию о журнале можно найти здесь
    Сообщений 23    Оценка 41 [+0/-1]         Оценить