Проблема в том, что если никто не подписывается на событие, оно является нулевым. И вы не можете ссылаться на ноль. На ум приходят три подхода:
public event EventHandler MyEvent = delegate {};
При проверке на нулевое значение, чтобы быть потокобезопасным, вы должны в теории сначала захватить ссылку на делегат (в случае, если она изменяется между проверкой и вызовом) :
protected virtual void OnMyEvent() {
EventHandler handler = MyEvent;
if(handler != null) handler(this, EventArgs.Empty);
}
Методы расширения имеют необычное свойство - они могут вызываться в нулевых экземплярах ...
public static void SafeInvoke(this EventHandler handler, object sender)
{
if (handler != null) handler(sender, EventArgs.Empty);
}
public static void SafeInvoke<T>(this EventHandler<T> handler,
object sender, T args) where T : EventArgs
{
if (handler != null) handler(sender, args);
}
, затем вы можете позвонить:
MyEvent.SafeInvoke(this);
, и он является как нулевым (через проверку), так и поточным (прочитав ссылку только один раз).
Возможно, пользователю, с которым вы выполняли процесс, не разрешено использовать стек TCP / IP?
Попробуйте запустить приложение от имени администратора, который не является вашей учетной записью.
Запустите на нем Process Monitor и посмотрите, не удается ли ему найти файл или раздел реестра. Возможно, профиль олицетворенного пользователя не загружен и Winsock (или поставщик услуг, который он пытается загрузить) что-то там ищет.
Возможно, у вас нет необходимых прав для запуска процесса от имени другого пользователя. Попробуйте получить дескриптор токена доступа с помощью вызова OpenProcessToken и добавьте SE_IMPERSONATE_NAME с помощью вызова AdjustTokenPrivileges, а затем вызовите CreateProcessAsUserW. Я сам не пробовал.
Фрагмент кода на Python для выполнения чего-то подобного с вызовами win32
Всегда запускайте WinSock в верхней части основного и оставляйте его включенным. Необходимость запустить WinSock является архитектурной случайностью и больше не имеет отношения к какой-либо проблемной области.