Sie sind auf Seite 1von 41

Dominick Baier

Jörg Neumann

.NET-Anwendungen
sicher und robust durch
Add-Ins erweitern
thinktecture
• Wir unterstützen Software-Entwickler und Architekten
bei der Realisierung von .NET- und Web Services-
Projekten

• Dominick Baier
– Meine Spezialgebiete sind Sicherheit in verteilten
Anwendungen, Identitäts-Management sowie die Windows/.NET
Sicherheits-APIs und Technologien
• Jörg Neumann
– Meine Spezialgebiete sind Client-Technologien und
Datenbanken

• dominick.baier@thinktecture.com
• joerg.neumann@thinktecture.com
Agenda
• Warum erweiterbare Anwendungen?
• Herausforderungen, Probleme und Lösungen
• Der neue API: System.AddIn
• Beispiele auf Client und Server

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Warum Erweiterbarkeit?
• Erlaubt es Benutzern/Herstellern neue Features zu
einer Anwendung hinzuzufügen
– Office AddIns/Makros
– Browser Plugins (Flash, Silverlight, PDF)
– Windows Explorer Extensions
• Anwendung wird zu einer erweiterbaren Plattform
– Office, Visual Studio, Reflector, Photoshop
• Komponentisieren von Anwendungen
– dynamisches Laden von (Fremd-) Bibliotheken (bei Bedarf)

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Technische Hürden (1)
• Assemblies können nicht entladen werden
• Externer Code soll nicht
– die Stabilität des Hosts beeinträchtigen können
– unerlaubt auf Host, OS oder das Netzwerk zugreifen

MyApp

Host
OS / Netzwerk…
3rd party code

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Lösungen (1)
• AppDomains sind der Schlüssel
– sind entladbar
– sind isolierbar
– können mit CAS „sandboxed“ werden

Default AppDomain

Host
3rd party code

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Lösungen (1)
• Der „Simple Sandboxing API“ erzeugt eine AppDomain
– mit eigener Konfiguration (AppBase, Suchpfad…)
– CAS Permission Set
– Liste von Full Trust Assemblies

public static AppDomain CreateDomain(


string friendlyName,
Evidence securityInfo,
AppDomainSetup info,
PermissionSet grantSet,
StrongName[] fullTrustAssemblies)

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Technische Hürden (2)
• Laden von Assemblies
– Cross-AppDomain Kommunikation ist Remoting
– AddIns müssen von MarshalByRefObject ableiten
– Verzeichnis-Struktur?
• AppDomain.CreateInstanceAndUnwrap()
– Erzeugt Proxy zu dem AddIn
– Vorsicht bei statischen Konstruktoren
– Nur mit Interfaces benutzen

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Lösungen (2)
• Typischerweise wird ein „Plugin Manager“ für das
Laden benötigt
– Plugins benötigen kein MBRO
– Kein 3rd Party Code im Host
– Optimieren der Cross AppDomain Kommunikation

Default AppDomain Plugin AppDomain

plugin manager
Host
3rd party code

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Technische Hürden (3)
• Verzeichnis-Struktur
– Host und AddIn(s) sollten nicht im gleichen Verzeichnis sein
– AddIn könnte auf Host Dateien zugreifen
• Trennung hat Implikationen
– Wie findet der Host die AddIns
– Wie findet das AddIn das Interface?

Host 3rd party code

c:\program files\myapp c:\program files\myapp\plugins\blur


myapp.exe.config plugin.config

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


„Version 1“ Probleme
• Finden von AddIns
• Aktivieren von AddIns
• Isolation
• Sandboxing
• Lifetime Management

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


„Version 2“ Probleme
• Vorwärts- und Rückwärts-Kompatibilität
• Komplexität im Griff behalten
• Neue Isolations Anforderungen

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


System.AddIn (MAF)
• Managed Add-In Framework
• Teil von .NET 3.5
• Features
– Add-In Discovery
– Add-In Store
– Sicheres Laden/Entladen/Ausführen von Add-Ins
– Versionierung

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Die Add-In Pipeline

Inherits
Add-In View Abstract Inherits Inherits Inherits Abstract
Base Class Add-In View IContract Host View Base Class

Add-In Add-In Host Host


Add-In Contract Application
Views Adapters Adapters Views

Add-In Add-In V1 to V2 V1 to V2 Host Application


V2 Views V2 Adapter Adapter Views V2 V2

Remoting-Grenze

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Discovery

AddIns MyApplication.exe

AddInSideAdapters Host.Views.dll

AddInViews PipelineSegments.store

Contracts

HostSideAdapters

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Hosting
• AppDomain- oder Prozess-Isolation
• Kommunikation über .NET-Remoting

Application Process Add-In Process


Default Add-In Add-In Add-In
AppDomain AppDomain AppDomain 1 AppDomain 2

Add-In 1 Add-In 2 Add-In 4 Add-In 5

Add-In 3 Add-In 6

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]
Nutzung in Client-Anwendungen
• Visuelle Add-Ins
– Fenster
– Eingebettete Elemente
• Problemstellungen
– UI-Elemente sind nicht serialisierbar
– Übertragung per Referenz nicht möglich

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Client-Support
• Support für WPF
– Basiert auf WPF-Interop
– Visual-Objekte (und Ableitungen) können verwendet werden
– Window Handle wird übertragen
– Läuft auch in XBAP-Anwendungen
– Kein Process-Hosting möglich

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


WPF-Support
• Contract
– INativeHandleContract
– Namespace: System.AddIn.Contract
– Assembly: System.Addin.Contract.dll
• Adapter
– ViewToContractAdapter
– ContractToViewAdapter
– Namespace: System.AddIn.Pipeline.FrameworkElementAdapters
– Assembly: System.Windows.Presentation.dll

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


UI-Elemente übertragen

INativeHandleContract
IntPtr GetHandle();

FrameworkElementAdapters
FrameworkElement ContractToViewAdapter(INativeHandleContract hwnd);
INativeHandleContract ViewToContractAdapter(FrameworkElement root);

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


UI-Elemente übertragen

INativeHandleContract GetUI() FrameworkElement GetUI()


FrameworkElementAdapters. FrameworkElementAdapters.
ViewToContractAdapter() ContractToViewAdapter()

FrameworkElement INativeHandleContract FrameworkElement


GetUI() GetUI() GetUI()

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]
Windows Forms Support
• Kein Support für Windows Forms
• Eigene Implementierung
– Übertragung von WinForms-Elementen
– Add-In-Verwaltungsdialoge
– Command-Modell für Menüs und Toolbars
– Download: http://headwriteline.blogspot.com

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Windows Forms Add-In Proxy

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]
AddIns in Server Umgebungen
• Features
– dynamisches Erweitern von Server-Funktionalität zur Laufzeit
– Entladen von AddIns zur Laufzeit
– Kein „runterfahren“ des Servers notwendig
– Abfragen von AddIn-Features ohne Laden des Assemblies
– Laden von AddIns von alternativen Speicher-Orten

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Beispiel: Universeller WCF
Service Host • Überwachen von AddIn Verzeichnissen
• Abfragen von AddIns (actions)
• Entladen von AddIns

SOAP-Action

Client

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


System.AddIn und Performance
• Jeder AddIn Aufruf muss eine Isolations-Grenze
übertreten
– Cross-Prozess
– Cross-Domain
– Cross-Domain Fastpath
• Strategien zur Performance-Optimierung
– Maximieren der Geschwindigkeit beim Überqueren der Grenze
– Reduzieren der Anzahl der Cross-Domain Aufrufe

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Fastpath
• Interne Optimierung von Remoting Calls
– [LoaderOptimization(LoaderOptimization.MultiDomainHost)]
– Contract Assembly muss im GAC sein
– Daten müssen [Serializable] sein

Calls per Second


Fastpath Cross-Domain Cross-Process
int GetInt(int) 166,667 6,666 4,016
void DoStuff (struct) 71,428 2,777 2,358

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]
Ressourcen
• CLR Add-In Team Blog
http://blogs.msdn.com/clraddins

• Add-In Samples
http://www.codeplex.com/clraddins

• Windows Forms Support für MAF


http://www.HeadWriteLine.BlogSpot.com

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]
{ In-depth support and consulting for
software architects and developers }
http://www.thinktecture.com/
dominick.baier@thinktecture.com
www.LeastPrivilege.com

joerg.neumann@thinktecture.com
www.HeadWriteLine.BlogSpot.com

37
Windows Forms Add-In Proxy

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Commands
ICommand IUICommand

Name Command
ParentCommand Text
ChildCommands ParentCommand
Enabled ChildCommands
Tooltip
Visible
Checked
HasState
BeginGroup
Index
DisplayStyle
Image
CommandType
ShortcutKeys

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Command Services
ICommandContext
ICommandService
UICommandService
ShowSurface()
event SurfaceShown

ICommandService IUICommandService

GetMainMenu() GetMainMenu()
GetMainToolbar() GetMainToobar()
GetCommand() GetUICommand()
CreateCommand() CreateMenuItem()
CreateToolbarItem()
CreateSeparator()
GetIconArray()
GetImageArray()

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Command-Contracts
IAddInCommandContract
InitializeCommands(ICommandContext)
NotifyCommandExecuted(ICommand)
WindowProxyBase GetSurface()

IAddInContract AddInHostView : IAddInContract


InitializeCommands(ICommandContext) InitializeCommands(ICommandContext)
NotifyCommandExecuted(ICommand) NotifyCommandExecuted(ICommand)
WindowProxyBase GetSurface() WindowProxyBase GetSurface()

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Components
AddInHost WindowProxyPanel

AddInPath SetWindow()
AvailableAddIns TabInto()
LoadedAddIns
CommandContext
MainMenuStrip
MainToolStrip AddInManagerForm
WindowProxyPanel
AutoSurfaceBinding AddInPath
CreateCommands() AvailableAddIns
RegisterAddIn() LoadedAddIns
UnregisterAddIn() ActivatedAddIns
DeactivateAddIn() DeactivatedAddIns
ShowAddInManager() ShowActiv.Options
GetToolItem() AddInActiv.Type
CommandExecuted AddInSecurityLevel
SurfaceShown

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Kommunikation
InitializeCommands(ICommandContext)

CreateCommand(ICommand)

Add-In Host
NotifyCommandExecuted(ICommand)

ShowSurface(WindowProxy)

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]


Contract
Assembly

Application Add-In
Assembly Add-In
Assembly
Assembly V2

Dominick Baier [www.LeastPrivilege.com] | Jörg Neumann [www.HeadWriteLine.BlogSpot.com]