Lepiej późno niż wcale. O projekcie Centennial, czyli moście do przenoszenia desktopowych (Win32/.NET) aplikacji do Windowsa 10 i platformy uniwersalnych aplikacji (UWP), wiemy już od ponad roku. Nadal jednak, mimo kolejnej konferencji Build, która szeroko omawiała ten temat, pojawia się wiele nieporozumień w kwestii czym naprawdę jest projekt Centennial.
Definicja
Na początku króciutki opis czym Centennial jest. I czym nie jest. Projekt ten to most, który pozwala użyć istniejących desktopowych projektów (kodu) i „opakować” je w standardową paczkę .AppX, którą wysyła się do sklepu Windows Store lub instaluje jednym kliknięciem. Celowo użyłem słowa przepakować, a nie przekonwertować. Przepakowywać, bo ani kod źródłowy aplikacji, ani jej procesy się nie zmieniają. Paczkę .AppX, używając dużego skrótu myślowego, możemy porównać do paczki .rar czy .zip, która nie zmienia zawartości, a jedynie ją „opakowuje”. Skoro to tylko paczka („kontener”) dla niezmienionego kodu, po co to całe zamieszanie? O tym więcej w dalszej części wpisu, ale na tym etapie najważniejsze jest, żeby zrozumieć, iż narzędzia projektu Centennial nie konwertują w magiczny sposób starych programów desktopowych do nowych aplikacji UWP. Nie zmienia się (niemalże) niż – ten sam kod, interfejs i to samo środowisko uruchomieniowe. Projekt Centennial nie jest:
- Konwersją aplikacji Win32/.NET do aplikacji uniwersalnych platformy UWP,
- Dostosowaniem tych appek do dotyku,
- Sposobem na uruchomienie aplikacji desktopowych na smartfonie, Xboksie czy HoloLens (aplikacje Win32/.NET nie mogą być uruchamiane na procesorach architektury ARM lub innych urządzeniach z systemem bez desktopowego środowiska uruchomieniowego),
- Pomysłem na uruchamianie aplikacji desktopowej w bezpiecznym sandboksie UWP („piaskownica”, która ogradza proces aplikacji, ograniczając jej możliwości bezpośredniej ingerencji w system, pliki czy inne aplikacje – w sandboksach komunikacja z innymi appkami czy systemem odbywa się poprzez bezpieczne systemowe protokoły).
Dlaczego Windows to bagno
Jak więc działa Centennial? Zanim zaczniemy się w to zagłębiać, chciałbym wymienić największe problemy związane z desktopowymi aplikacjami dla Windowsa:
- „Piekło .dll” (eng. „dll hell”). Wiele osób spotkało się z tym terminem. Dll-le, czyli dynamiczne biblioteki Windowsa, są dodawane lub nadpisywane w folderach systemowych za każdym razem, gdy instalujemy nową desktopową aplikację. Przy uruchamianiu narzędzia do odinstalowania danego programu, nie wie ono czy może usunąć dany plik .dll, bo być może jest on współdzielony z inną istniejącą aplikacją i jego usunięcie spowoduje jej uszkodzenie lub nawet uszkodzenie całego systemu.
- Burdel w rejestrze. Zdecydowana większość aplikacji dodaje klucze do rejestru przy swojej instalacji. I problem jest taki sam, jak z plikami .dll. Niektóre klucze są współdzielone, a ich rosnąca liczba po instalacjach, deinstalacjach i reinstalacjach w zauważalnym stopniu potrafi spowolnić system – szczególnie czas jego uruchomienia, gdy cały rejestr musi zostać zmapowany w celu alokacji odpowiednich przestrzeni adresowych dla aplikacji. Żeby zrozumieć skalę tego problemu, instalacja Visual Studio dodaje… kilka milionów kluczy do rejestru. Łatwo sobie wyobrazić co się dzieje z systemem operacyjnym po kilkunastu miesiącach intensywnego użytkowania.
- Źródła aplikacji. Instalatory aplikacji desktopowych można ściągnąć z dowolnych źródeł – z szemranych linków w meandrach internetu, Torrentów czy fizycznych nośników. Nie muszą być one cyfrowo podpisane – wystarczy, że przy instalacji klikniemy „zgadam się” na komunikacie ostrzegającym o uruchamianiu aplikacji wykonywalnej. I obawiać powinniśmy się nie tylko wirusów, ale też toolbarów, oprogramowania śmieciowego, niepotrzebnych dodatków czy zbyt dużych uprawnień.
- Instalatory. Każdy niedomyślny instalator może wyczyniać cuda z naszym systemem, ingerując w istniejące pliki, sterowniki, rejestr czy wchodząc w reakcje z istniejącymi programami. Zostawianie tworzenia kodu instalatora programistom od aplikacji jest bardzo nieodpowiedzialne i prowadzi do częstych frustracji związanych z błędami pojawiającymi się po zakończeniu pracy instalatora. Nie wspominając o śmieciach, które te instalatory mogą po sobie zostawiać.
- Uprawnienia. Kolejna kwestia to uruchamianie aplikacji z prawami administratora czy pozwalanie na komunikację procesów między poszczególnymi użytkownikami. W 99% przypadków, uruchamianie programu z prawami administratora z dostępem do poziomu jądra („kernel mode”) jest niepotrzebne i świadczy o źle napisanej aktualizacji. A to kolejny element, który może niekorzystnie wpływać nie tylko na stabilność systemu, ale też na bezpieczeństwo.
- Autoaktualizacje. Aktualizacje automatyczne to w desktopowym Windowsie koszmar. Nie ma żadnego rozwiązania udostępnianego przez system, więc każda aplikacja musi uruchamiać własne oddzielne procesy działające w tle, sprawdzające czy jest dostępna nowsza wersja najczęściej przy użyciu usługi NT services. Pomijając kwestie bezpieczeństwa, wpływa to bardzo negatywnie na żywotność baterii.
- Sterowniki. Aplikacje uruchamiane jako administrator mogą nadpisywać czy dodawać nowe sterowniki do systemu. W teorii jest to zjawisko dobre, rozszerzające możliwości systemu, ale w praktyce wiąże się to z niebezpiecznymi precedensami i problemami wydajnościowymi oraz problemami ze sprzętem. O sterowniki powinien dbać system operacyjny, a nie programy użytkownika.
- Full trust. Programy uruchamiane w trybie full trust, w przeciwieństwie do tych umieszczanych w sandboksie, mają pełne prawo do wykonywania dowolnego kodu przez swój proces. Pozwala to na dużą elastyczność i możliwości, ale brak izolacji procesów oraz ograniczenia ich interakcji z systemem powoduje, że kod wykonywany full trust może przypadkiem lub celowo mieć negatywny wpływ na działanie naszego systemu czy jego bezpieczeństwo.
Centennial rozwiązaniem
Centennial został stworzony, żeby rozwiązać większość tych problemów. Zdecydowaną większość, ale nie wszystkie. Wróćmy teraz do tego, jak działa Centennial i jak wygląda architektura tego rozwiązania. Często finalnym efektem pracy programistycznej jest właśnie paczka z instalatorem (.exe, .msi), który ma trafić do użytkownika i zostać przez niego uruchomiony. Dzisiaj do programistów trafiło narzędzie Microsoftu, które pozwala przeanalizować działanie takiego instalatora (głównie śledzenie zmian, które chce wprowadzić w systemie) i stworzenie paczki .AppX, która może być wysłana do sklepu lub uruchomiona bezpośrednio – zainstalowana jednym kliknięciem za pomocą domyślnego instalatora wbudowanego w Windows 10 (a nie zewnętrznego instalatora stworzonego przez programistę) – to rozwiązuje problem niedomyślnego instalatora. Mało tego, po konwersji, instalator ten wrzuca pliki TYLKO do folderu danej aplikacji – bez zmian rejestru czy wrzucaniu plików .dll do folderów systemowych. Następuje tak zwana wirtualizacja rejestru i przestrzeni nazw dla plików .dll i tak każda aplikacja ma własny separowany folder na dysku, a jej odinstalowanie to jedno kliknięcie i usunięcie WSZELKICH pozostałości po niej. To rozwiązuje kolejne trzy problemy: piekła .dll, burdelu w rejestrze i odinstalowywania aplikacji. Dodatkowo, jednym kliknięciem mogą być instalowane tylko paczki cyfrowo podpisane – z zaufanego źródła. Dzięki temu pozbywamy się kłopotu z appkami z podejrzanych źródeł. Jeśli natomiast aplikacja była zainstalowana przez Sklep, a nie ściągnięcie i uruchomienie paczki, to rozwiązany mamy też problem autoaktualizacji, którymi zajmuje się sam Sklep. Appki wykorzystujące narzędzie Centennial dalej jednak działają w trybie full trust, więc wszelkie niebezpieczeństwa związane z działaniem poza sandboksem UWP pozostają realne.
Ograniczenia
Powiedzmy teraz o głównych ograniczeniach dla aplikacji, które mogą być przepakowane przy użyciu narzędzi projektu Centennial:
- Programy mogą działać tylko w trybie użytkownika (user mode – Centennial zabrania kernel mode),
- Programy nie mogą wykorzystywać NT services,
- Programy nie mogą ingerować w sterowniki, ani ich instalować.
Te ograniczenia rozwiązują nam kolejne dwa problemy, o których pisaliśmy wcześniej – uprawnienia i sterowniki. Podsumowując – w najprostszej wersji Centennial to po prostu przepakowanie aplikacji do kontenera .AppX, zapewnienie mu izolowanej przestrzeni dyskowej (dedykowany folder aplikacji, obok aplikacji UWP), wirtualizacja przestrzeni nazw oraz rejestru, ograniczenie uprawnień (choć nie jest to automatyczne – uprawnienia musi ograniczyć sam programista przed kompilacją kodu). Wszystko to pozwala na wrzucanie tych aplikacji do Sklepu lub instalowanie/odinstalowywanie jednym kliknięciem przy użyciu uniwersalnego instalatora wbudowanego w Windowsa 10.
W tej postaci Centennial jednak nie jest mostem, a jedynie protezą. Oczywiście jest to coś znacznie lepszego niż całkowity bajzel, który był dotychczas, ale nadal nie rozwiązuje wszystkich problemów. Dlatego jest to tylko faza pierwsza. Docelowo, Centennial ma pomóc programistom stopniowo przenosić się na API i rozwiązania oferowane przez platformę UWP rezygnując z odwołań do starych API aplikacji Win32/.NET. Ma się to odbywać przez dodawanie kolejnych funkcji (takich jak dynamiczne kafelki, powiadomienia) i zastępowanie starych API nowymi.
Okres przejściowy
W okresie przejściowym („na moście”) uruchomienie aplikacji spowoduje uruchomienie dwóch procesów – jednego procesu full trust dla aplikacji Win32/.NET („stara cześć kodu”) i procesu w sandboksie UWP, zawierającego część nowego kodu pisanego dla UWP. W tym okresie przejściowym oba procesy mogą się ze sobą komunikować przez protokół zapewniany przez projekt Centennial. Microsoft radzi, żeby zacząć od przenoszenia interfejsu z WPF (Windows Presentation Foundation) do XAMLa, czyli markupu do tworzenia wizualnej części aplikacji uniwersalnych. Następnym krokiem będzie sukcesywne przenoszenie funkcji związanych z logiką aplikacji. W momencie przeniesienia wszystkich funkcji do UWP, część związana z Win32/.NET znika nam całkowicie, a aplikacja staje się w pełni uniwersalna – jesteśmy już „za mostem”. Appka działa w bezpiecznym sandboksie UWP i jest kompatybilna ze smartfonami ARM i x86, Xboksem, HoloLens czy Surface Hubem. W tym momencie niczym nie różni się ona od innych aplikacji UWP, bo cała część starego kodu desktopowego została zastąpiona przez nowy kod związany z API dla UWP.
Proces przejściowy nie będzie łatwy z uwagi na konieczność utrzymywania dwóch projektów w Visual Studio i braku niektórych API, których uzupełnienie może zająć Microsoftowi nawet kilka lat. Ale taki właśnie jest plan – gdy Windows 10 całkowicie zastąpi Windows 7 zarówno w przestrzeni konsumenckiej, jak i korporacyjnej, wtedy MS może wreszcie uwolni się od obciążenia starym, niebezpiecznym i trudnym do utrzymywania kodem Win32/.NET. Ale sukces tej misji będzie w dużej mierze zależeć od szybkości adopcji Windowsa 10. Bez tego, Windows 7 stanie się następnym Windowsem XP, okupującym korporacje przez kolejne 10 lat.
Zagrożenia
Centennial to jednak broń obosieczna. Do Sklepu Windows, kojarzonego do tej pory z bezpiecznymi aplikacjami uruchamianymi w sandboksach, trafią aplikacje desktopowe uruchamiane w trybie full trust. Oczywiście będą one indywidualnie weryfikowane, ale nie można wykluczyć pojedynczych „wpadek”. A nie ma nic gorszego dla rozwoju Sklepu, niż utrata zaufania użytkowników co do bezpieczeństwa jego użytkowania. Microsoft jednak nie ma wyboru. Od aplikacji Win32/.NET i pulpitu nie można się odciąć grubą kreską, więc firma robi co może, żeby ten proces przejściowy przeszedł możliwie bezboleśnie. Jest to pierwsze podejście Microsoftu do stworzenia jakiejkolwiek zunifikowanej platformy aplikacji, bo do tej pory w Windowsie nawet ciężko było zdefiniować czym jest desktopowa aplikacja. Zrobiono naprawdę bardzo dużo dzięki projektowi Centennial, zapewniającym uniwersalny instalator oraz izolację przestrzeni plików i rejestru, ale ten okres przejściowy to wojna, a na każdej wojnie są ofiary. I Microsoft z pewnością ich nie uniknie.