Найти адреса запущенных WCF-сервисов в приложении
От: mDmitriy Россия  
Дата: 26.09.22 05:37
Оценка:
Всем привет!

Есть консольное приложение, в котором запускаются некие WCF-службы
Надо определить адреса (в общем случае порты от localhost) запущенных на текущий момент времени служб
Как это сделать?
И можно ли это сделать?
Может, есть место, где все они сами по себе регистрируются?

PS. варианты парсить config или собрать все запускаемые службы в список при открытии просьба не предлагать

Спасибо
Re: Найти адреса запущенных WCF-сервисов в приложении
От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
Дата: 26.09.22 11:10
Оценка: 6 (1)
Здравствуйте, mDmitriy, Вы писали:

Если я правильно понял то ,что вы хотите, то это выглядит так:

Нужно уметь получать в runtime список всех хостящихся в процессе WCF-сервисов, причем мы не имеем возможности контролировать объявление и инициализацию этих сервисов (навешивать атрибуты, менять конфигурацию, использовать свой ServiceHost, ...). Иными словами — код запускающий сервисы для нас "черный ящик", и мы можем только обращаться к инфраструктeре WCF

.

Честно говоря, я не знаю простого и "законного" (т.е. через какое-то публичное API инфраструктуры WCF) способа получить общую информацию обо всех экземпляров сервисов, запущенных в текущем процессе.
Т.е. из того, что я знаю — каждый экземпляр сервиса (ну и всей обвязки вокруг: ServiceHost, всякие Dispatchers, ...) — независим от остальных. Т.е. никакого внутреннего реестра запущенных сервисов нет (ну или не понятно как до него добраться).

Из того, что мало-мальски можно предложить — это "инъекции" behaviours. Например, если написать вот такой
  Endpoint behavior
public class EndpointSpyBehavior : IEndpointBehavior
{
    public static List<Uri> Endpoints = new List<Uri>();

    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    {
        EndpointSpyBehavior.Endpoints.Add(endpoint.Address.Uri);
    }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
    }

    public void Validate(ServiceEndpoint endpoint)
    {
    }
}

А к нему
  BehaviorExtensionElement
public class EndpointSpyBehaviorExtensionElement : BehaviorExtensionElement
{

    public override Type BehaviorType
    {
        get { return typeof(EndpointSpyBehavior); }
    }

    protected override object CreateBehavior()
    {
        return new EndpointSpyBehavior();
    }
}

То можно будет добавить вот такое в конфиг
  App.config
<configuration>
    <system.serviceModel>
        <behaviors>
            <endpointBehaviors>
                <behavior>
                    <mySpy/>
                </behavior>
            </endpointBehaviors>
        </behaviors>
        <extensions>
            <behaviorExtensions>
                <add name="mySpy"
                     type="WcfExtending.EndpointSpyBehaviorExtensionElement, WcfExtending"/>
            </behaviorExtensions>
        </extensions>
    </system.serviceModel>
</configuration>

И можно будет получить список всех endpoints:
  Типа код консольки
static void Main(string[] args)
{
    var serviceHost = new ServiceHost(typeof(Service), new Uri("http://localhost:13056"));
    var serviceHost2 = new ServiceHost(typeof(Service), new Uri("http://localhost:15401"));
    serviceHost.Open();
    serviceHost2.Open();

    EndpointSpyBehavior.Endpoints.ForEach(u => Console.WriteLine(u));

    Console.ReadLine();

    serviceHost.Close();
    serviceHost2.Close();
}

НО!!!
Это работает только если нигде никакой endpoint не ссылается ни на какой behavior configuration (тогда берется дефолтовая). Т.е. если поменять конфиг на такой:
  App.config с явной ссылкой на behavior configuration
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
    </startup>
    <system.serviceModel>
        <services>
            <service name="WcfExtending.Service">
                <endpoint behaviorConfiguration="VVV"
                          binding="basicHttpBinding" 
                          address="http://localhost:1300"
                          contract="WcfExtending.Service"
                          >
                </endpoint>
            </service>
        </services>
        <behaviors>
            <endpointBehaviors>
                <behavior name="VVV"/>
                <behavior>
                    <mySpy/>
                </behavior>
            </endpointBehaviors>
        </behaviors>
        <extensions>
            <behaviorExtensions>
                <add name="mySpy"
                     type="WcfExtending.EndpointSpyBehaviorExtensionElement, WcfExtending"/>
            </behaviorExtensions>
        </extensions>
    </system.serviceModel>
</configuration>

Или аналогичное сделать в коде (т.е. указать behavior configuration явно там) — всё, behavior configuration по умолчанию (он без имени) подхватываться не будет.

Теоретически можно добавить еще ServiceBehavior (примерно так же делается) и в нем смотреть — если для endpoint наш behavior не добавлен, то добавить.
Но это тоже полумеры (ломается так же — у сервиса явно указан свой behavior
Re: Найти адреса запущенных WCF-сервисов в приложении
От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
Дата: 26.09.22 11:39
Оценка: 6 (1)
Здравствуйте, mDmitriy, Вы писали:

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

Без такого, боюсь, останется только что-то из "хакерского" набора (всё далее — это предположения, ничем подобным я не занимался):
— попробовать настроить запись в логи (там есть запись в XML), подсунуть свой форматер и попробовать ловить события с нужным типом.
— поймать события создания инстансов объектов (например, DispatchRuntime) и попробовать порыть от них.
— просто порыться в исходника внутренних объектов (того же DispatchRuntime) — вдруг-таки есть какой-то внутренний shared объект, от которого можно пробежаться по экземплярам инфраструктуры

— ну и подобное ...
Re[2]: Найти адреса запущенных WCF-сервисов в приложении
От: mDmitriy Россия  
Дата: 26.09.22 17:36
Оценка:
Здравствуйте, Михаил Романов, Вы писали:

МР>Если я правильно понял то ,что вы хотите, то это выглядит так:

да, Михаил, спасибо, это выглядит именно так

но у меня нет возможности ориентироваться на config — часть служб конфигурируется программно
там каша полная, доступиться туда пока нельзя, потому и спрашиваю такой идиотский вопрос
Re[2]: Найти адреса запущенных WCF-сервисов в приложении
От: mDmitriy Россия  
Дата: 26.09.22 17:58
Оценка:
Здравствуйте, Михаил Романов, Вы писали:

МР>В добавление к предыдущему моему ответу: может всё же есть какие-то вещи, на которые вы можете влиять: указывать behavior для всех сервисов (и в коде это нельзя перекрывать) или запуск-таки осуществляет какой-то ваш код (хотя вы писали, что это не вариант, но вдруг есть лазейка), в конце концов может вы можете выставить какие-то требования к конфигу...

увы, нет
можно только жутко наговнокодить, чего хочется избежать

МР>Без такого, боюсь, останется только что-то из "хакерского" набора (всё далее — это предположения, ничем подобным я не занимался):

МР>- попробовать настроить запись в логи (там есть запись в XML), подсунуть свой форматер и попробовать ловить события с нужным типом.
логи тоже надо как-то службе разрешить

МР>- поймать события создания инстансов объектов (например, DispatchRuntime) и попробовать порыть от них.

МР>- просто порыться в исходника внутренних объектов (того же DispatchRuntime) — вдруг-таки есть какой-то внутренний shared объект, от которого можно пробежаться по экземплярам инфраструктуры
исходники я копал, но ничего не нашел — все совершенно независимо
пробовал слушателей обнаруживать — обнаруживаются, но большой кучей, на уровне системы, со службами их не связать
есть вариант связать их с процессом и покопать оттуда

Discovery пробовал, но он по голому IP вроде как не может
Re: Найти адреса запущенных WCF-сервисов в приложении
От: igorl_r  
Дата: 26.09.22 21:03
Оценка: 97 (2)
Здравствуйте, mDmitriy, Вы писали:

D>Есть консольное приложение, в котором запускаются некие WCF-службы

D>Надо определить адреса (в общем случае порты от localhost) запущенных на текущий момент времени служб
D>Как это сделать?
D>И можно ли это сделать?
D>Может, есть место, где все они сами по себе регистрируются?

Можно попробовать через ETW.
Там есть разные события (например, для net.tcp вот из такого можно достать порт).

Можно через WMI. Но для этого нужно включить поддержку в конфиге.
Re[2]: Найти адреса запущенных WCF-сервисов в приложении
От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
Дата: 27.09.22 07:14
Оценка:
Здравствуйте, igorl_r, Вы писали:

_>Можно через WMI. Но для этого нужно включить поддержку в конфиге.

Похоже, это как раз то, что искал mDmitriy — добавить одну настройку в конфиг уж точно реализуемо (можно даже проверять это и если что, править в приложении-хосте).
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.