środa, 21 listopada 2012

VS2012 w świecie Embedded i .NET 3.9 CF

Tworząc na platformę Windows Embedded Compact (Windows CE) oraz Windows Embedded Handheld (Windows Mobile) programista .NET nie ma zbyt dużego wyboru. Komplet Visual Studio 2008 i .NET 2/3.5 CF jest standardem. Co prawda VS2008 to całkiem solidny kombajn z którym można żyć w zgodzie (zresztą robię to codziennie :)). Nie zmienia to jednak faktu, że nowsze wersje są po prostu lepsze.
Po 5 latach zaniedbywania programistów w końcu coś drgnęło. Microsoft zapowiedział wydanie Windows Embedded Compact 2013 w pierwszym kwartale przyszłego roku (zresztą nazwa 2013 jest dość wymowna ;)). Informacja nie była by taka elektryzująca gdyby nie fakt, iż wraz z system udostępnione zostanie wsparcie dla VS2012 oraz "nowy" .NET 3.9. Jako programista tego segmentu mogę powiedzieć jedno... W końcu!
Ciekawi mnie tylko, jak to wszytko będzie wyglądało. Jak wiele z elementów VS2012 będzie można wykorzystać, żeby usprawnić codzienną pracę. Oprócz kwestii podstawowych jak edytor formatek, kompilacja, debugowanie itp. będzie wsparcie dla TFS i narzędzi AML. Fajnie, ale ani z pierwszego, ani z drugich nie korzystam. Cóż trzeba poczekać, szczegółów jest niewiele.
Inaczej ma się sprawa z .NET 3.9 CF. Z udostępnionych informacji wynika, że API się nie zmieni. Tzn, kod z 3.5 będzie można bezboleśnie (jeszcze zobaczymy jak to będzie) przenieść na nowszą wersję. Bardziej znaczące są zmiany pod spodem. Wymieniane są 3 główne. Mają bezpośrednio wpłynąć na wydajność platformy. A wszystko to wzorowane na elementach Windows Phone. Otrzymamy zatem:
  • Lepszy GC
  • Wsparcie dla wielu rdzeni
  • Sharing Server - współdzielenie bibliotek pomiędzy różnymi aplikacjami
Pomimo całego mojego entuzjazmu martwi mnie jeden fakt. Jeżeli urządzenie miało preinstalowany .NET 2.0 CF to zawsze mogłem wziąć plik CAB od wersji 3.5 i zainstalować nowszą wersję. Czy teraz nie będzie inaczej? Czy .NET 3.9 CF nie będzie bardziej związany z samym systemem? Czy będzie go można zainstalować na CE 5 lub 6. Do tego jeszcze kwestia czy w VS2012 będzie można pisać pod .NET 3.5 CF? Jak na razie, mam więcej pytań niż odpowiedzi...

wtorek, 30 października 2012

Debugowanie usług windows w Visual Studio

Jak wiadomo debuger wielkim przyjacielem programisty jest, ale nie zawsze istnieje możliwość odpalenia go od tak sobie wciskając F5. W przypadku usług (serwisów) windows otrzymamy komunikat:
---------------------------
Błąd uruchomienia usługi systemu Windows
---------------------------
Nie można uruchomić usługi z wiersza polecenia lub z debugera.
Usługa systemu Windows musi być najpierw zainstalowana (przy użyciu pliku installutil.exe),
a następnie uruchomiona za pomocą Eksploratora serwera, 
Narzędzi administracyjnych usług systemu Windows lub polecenia NET START.
---------------------------
OK   
---------------------------
Pozostaje pytanie co z tym fantem zrobić? Jak na razie spotkałem się z kilkoma różnymi sposobami, np:
Nie są one jednak wygodne ponieważ w każdym przypadku wymuszają chwilowe dodawanie kodu, kompilację warunkową lub parametry lini komend sterujące przebiegiem uruchomienia serwisu. Jaki jest więc złoty środek? Otóż istnieje możliwość sprawdzenia czy uruchomiony proces umożliwia użytkownikowi interakcję. Służy do tego właściwość Environment.UserInteractive. Dzięki niej wystarczy prosty warunek w punkcie wejścia do aplikacji aby rozdzielić przebieg raz a skutecznie. Czyli:
  • Zmieniamy rodzaj aplikacji na konsolową (wartość Output Type, zakładki Application, w Properties danego projektu) dzięki czemu zyskujemy wgląd w konsolę
  • Dodajemy kod umożliwiający odpalenie implementacji OnStart i OnStop przeciążonych po ServiceBase:
    public partial class Service1 : ServiceBase
    {
        public Service1()
        {
            InitializeComponent();
        }
    
        internal void Start(string[] args)
        {
            OnStart(args);
        }
    
        internal void Stop()
        {
            OnStop();
        }
    
        protected override void OnStart(string[] args)
        {
            //...
        }
    
        protected override void OnStop()
        {
            //...
        }
    }
    
  • Podmieniamy standardową metodę Main na:
    static void Main(string[] args)
    {
        Service1 svc = new Service1();
    
        if (Environment.UserInteractive)
        {
            Console.WriteLine("Starting...");
            svc.Start(args);
            Console.WriteLine("Started");
            Console.ReadLine();
            Console.WriteLine("Stopping...");
            svc.Stop();
            Console.WriteLine("Stopped");
        }
        else
        {
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[] 
            { 
                svc
            };
            ServiceBase.Run(ServicesToRun);
        }
    }
    
W ten sposób, kiedy wciśniemy F5 uruchomiony zostanie debugger z całym jego dobrodziejstwem. Natomiast po zainstalowaniu i uruchomieniu serwisu z poziomu services.msc odpali się druga klasyczna dla usług nitka kodu. Wilk syty i owca cała ;)

PS. Równie dobrze, zamiast konsoli można przygotować aplikację okienkową, nie ma tutaj ograniczeń, idea pozostaje niezmieniona.