Не называйте свои сборки "security.dll"

Недавно, работая над текущим проектом, потратил кучу времени, разбираясь с загадочным исключением - "Не удается найти точку входа EnumerateSecurityPackagesW в DLL (security.dll)".

Предыстория. Приложение на базе WCF. На сервисной части запускается набор сервисов. Затем на клиентской части вызываются методы удаленного объекта. Все работало замечательно. До тех пор, пока я не начал писать Security часть всего этого.

В какой-то момент времени все просто перестало работать — на клиенте выбрасывалось указанное исключение. Все мои попытки что-либо сделать ни к чему не приводили. После того как я просидел с этой проблемой некоторое время выяснилось следующее.

После того, как я из главного проекта добавил Reference на сборку Security, у меня, естественно, в папке с исполняемым файлом появился файлик "security.dll". WCF работал поверх HTTP, используя защищенное соединение (т.е. https). При работе через http инфраструктура WCF, видимо, использует объект HttpWebRequest. Как позже выяснилось, при работе через защищенные соединения, HttpWebRequest импортирует библиотеку "C:\Windows\System32\security.dll", которая является частью ОС. Причем, при импорте данной библиотеки он смотрит сначала в папку, в которой находится исполняемый файл моей программы, а только потом - в System32. Соответственно, когда я сделал Reference на свою сборку "Security", она скопировалась в папку с программой и HttpWebRequest пытался загрузить ее. Теперь понятно откуда исключение :)

Для меня такое решение (поиск библиотеки в папке с программой) достаточно сомнителен в данной ситуации. А что если бы я при разработке использовал NetTcpBinding или HTTP, но не защищенный? А потом у Заказчика развернул бы на базе HTTPS? Поэтому, рекомендую не использовать в качестве имени сборки название "security.dll".

Ну и напоследок, продемонстрируем как это "работает". :) Создаем приложение и добавляем следующий код:

HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("https://mcp.microsoft.com/mcp/");
WebResponse response = webRequest.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader r = new StreamReader(responseStream);
MessageBox.Show(r.ReadToEnd());
responseStream.Close();

Запускаем, видим HTML-код с сайта Microsoft. Заходим в папку с программой и создаем пустой файл с названием "security.dll".

Запускаем указанный выше код еще раз. "Наслаждаемся". :)

Ну и повторюсь еще раз, что если работать не через https, то HttpWebRequest не импортирует указанную библиотеку и все работает нормально.