Bernhard's profileBernhard Grojer - BlogBlogLists Tools Help

Bernhard Grojer - Blog

Talking About .NET

Bernhard Grojer

Occupation
Location
June 23

Microsoft Security Essentials, Codename: Morro


Seit heute gibt es die erste Vorabversion von Microsoft Security Essentials.

Download gibt es via Microsoft Connect.

Anbei ein paar Screenshoot (unter Windows 7 – RC1)

image

image

image

image

May 31

Windows Azure, Visual Studio 2010, Class Library (Klassen Biblioteken)

Scheinbar gibt es unter Visual Studio 2010 bzw. den Windows Azure Templates ein Problem mit zusätzlichen "Projekten" in der Windows Azure Solution.

Fügt man eine neue (leere) Class Library zum Projekt hinzu und setzt Referenzen auf das Projekt kann man das Projekt nicht mehr bauen:


Error 1 The OutputPath property is not set for this project.  Please check to make sure that you have specified a valid Configuration/Platform combination.  Configuration='Debug'  Platform='AnyCPU' C:\Windows\Microsoft.NET\Framework\v4.0.20506\Microsoft.Common.targets 582 10 ServiceState

Es hat sich danach rausgestellt, dass scheinbar in der Class Library (Klassen Bibliothek) nur Build-Einstellungen für x86 verfügbar sind. Dies dürfte das eigentliche Problem auslösen:


Ich habe keine Möglichkeit gefunden dies in Visual Studio 2010 direkt zu ändern. Daher habe ich (manuel) die Projekt-Datei der Class Library bearbeitet:

Die Visual C# Project file (.csproj) - original (nur x86 Build):
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
    <ProductVersion>10.0.20506</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{C4DA9B13-3879-4F55-8510-DE795CD4E9BE}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>ServiceStateLib</RootNamespace>
    <AssemblyName>ServiceStateLib</AssemblyName>
    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <PlatformTarget>x86</PlatformTarget>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <PlatformTarget>AnyCPU</PlatformTarget>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
...

Geändert auf (AnyCPU):
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>10.0.20506</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>C4DA9B13-3879-4F55-8510-DE795CD4E9BE}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>ServiceStateLib</RootNamespace>
    <AssemblyName>ServiceStateLib</AssemblyName>
    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
...


Danach neue einbinden und alles läuft wunderbar.

Windows Azure - Visual Studio 2010

Für Visual Studio 2010 gibt es seit kurzem das Windows Azure May CTP. Damit bekommt man nun auch Unterstüzung für VS 2010 und die passenden "Cloud Templates".

Wahrlich hat man f. VS 2010 keine wirkliche Vorteile durchs neue Framework bei der Azure Entwicklung da .net 4.0 im Moment NICHT unterstützt ist unter Windows Azure.

Da Visual Studio 2010 allerdings Multi-Targeting unterstützt können .net 3.5 SP1 Anwendung ohne Probleme erzeugt werden.

May 26

MKV und Windows 7, XBOX 360

Nunja Windows 7 kommt auf uns zu. Filme finden sich öfters in einem neuen Standard.

Doch wie passt beides Zusammen? Naja leider nicht unterstützt (und scheinbar hat Microsoft in dem Bereich auch nichts vor)

Allerdings bietet Windows7 im MediaCenter gute Erweiterungsmöglichkeiten in dem Bereich und mithilfe von einem Plugin nachbessern: Infos gibts hier: http://labs.divx.com/mkvwin7preview
May 18

Visual Studio 2010 - Beta1 (via MSDN)


Visual Studio 2010 Beta 1 soll ab heute in via MSDN verfügbar sein!

Im Moment ist noch nichts online (Stichwort Zeitverschiebung)
May 15

Silverlight - dotnet Cologne 2009 - Datenaustausch


Anbei die Samples von meiner Session auf der dotnet Cologne 2009 zum Thema "Datenaustausch mit dem Server".

Inhalt: Databinding in Silverlight an ein Webservice (ASMX), Webservice (WCF), REST (WCF) sowie ein Beispiel mit CRUD und den ADO.net DataServices.

Download gibt es hier.
April 09

Silverlight: DataBinding zu WCF Service - Teil 2/2


Im letzten Posting haben wir mithilfe von Silverlight und WCF Daten am Client verfügbar gemacht. Außerdem haben wir bereits deklaratives DataBinding verwendet in XAML.

Nun wollen wir noch dafür sorgen, dass der Client Änderungen in den (Customer) Objekten mitprotokolliert und diese später mittels WCF wieder an den Server gesendet / gespeichert werden können.

Da wir bereits Objekte gegen unser DataGrid gebunden haben werden die Änderungen auch zurück ins Objekt gespeichert (TWO-WAY DataBinding)

Unsere CustomerDataSource Klasse muss nun nur noch geänderte “Kunden” mitprotokollieren.

Dafür können wir den selben Ansatz verwenden, den auch Silverlight/WPF für die akt. des UI verwendet oder auch der LINQ DataContext dies macht.
Wir hängen uns an das PropertyChanged Event (vom Interface INotifyPropertyChanged) und lassen uns Informieren sobald eine Änderung erfolgt:

 Dictionary<Customer, string> _ChangedObjects = new Dictionary<Customer, string>();
        public void RegisterChangeTracking(Customer c)
        {
            c.PropertyChanged += (sender, e) => 
                { 
                    var cus = sender as Customer;
                    if (_ChangedObjects.ContainsKey(cus))
                        _ChangedObjects[cus] += ";" + e.PropertyName;
                    else
                        _ChangedObjects.Add(cus, e.PropertyName);
                };
        }

Bevor nun ein Objekt in die Observable<T> Liste wandert (und somit im UI dargestellt wird) wird es mithilfe von RegisterChangeTracking T o) registriert.
Ändert sich nun ein Property in der Klasse wird ein Eintrag im _ChangedObjects Dictionary erstellt.

private void LoadCustomers()
        {
            CustomerServiceClient client = new CustomerServiceClient();
            client.GetCustomersCompleted += (sender, e) =>
            {
                foreach (var c in e.Result)
                {
                    _Customers.Add(c);
                    RegisterChangeTracking(c);
                }

            };
            client.GetCustomersAsync();
        }

Nun müssen wir nur noch das Dictionary mit den geänderten Daten dem WCF Service übergeben.

private void SaveCustomers()
        {
            CustomerServiceClient client = new CustomerServiceClient();
            client.SaveCustomersCompleted += (sender, e) =>
            {
                var b = e.Result;
            };
            client.SaveCustomersAsync(_ChangedObjects);
        }

Die Methode SaveCustomer wird nun aus der Silverlight-Anwendung aufgerufen (ein Button im UI triggert folgenden Code):

private CustomerDataSource CustomerDataSource
        {
            get
            {
                return this.Resources["Customers"] as CustomerDataSource;
            }
        }

        private void ButtonSave_Click(object sender, RoutedEventArgs e)
        {
            CustomerDataSource.Save();
        }


Damit ist die Client-Seite abgeschlossen und wir müssen uns nun noch um das tatsächliche Speichern in der CustomerService Klasse kümmern.

Hier möchten wir natürlich Datenbankabfragen minimieren und soviel wie möglich mit einem gang zur Datenbank ausführen.
Außerdem sollen nur die Felder gespeichert werden, die tatsächlich geändert wurden:

public bool SaveCustomers(Dictionary<Customer, string> Customers)
        {
            using (var DB = new NorthwindDataContext())
            {
                var query = from c in DB.Customers
                            where Customers.Keys.Select(cus => cus.CustomerID).Contains(c.CustomerID)
                            select c;

                var lst = query.ToList();
                Type t = typeof(Customer);
                foreach (var kv in Customers)
                {
                    var oldCustomer = kv.Key;
                    var newCustomer = lst.Single(cus => cus.CustomerID == oldCustomer.CustomerID);

                    foreach (var s in kv.Value.Split(new char[] {';'}, StringSplitOptions.RemoveEmptyEntries))
                    {
                        var propInfo = t.GetProperty(s);
                        var v = propInfo.GetValue(oldCustomer, null);
                        propInfo.SetValue(newCustomer, v,null);
                    }
                }

                DB.SubmitChanges();
            }
            return true;
        }

Das fertige Beispiel (selber Link wie im Teil 1 d. Blog-Serie) steht zum Download bereit: SilverlightConsumeWCF 08042009.zip

April 08

Silverlight: DataBinding zu WCF Service - Teil 1/2


In Silverlight kann mittels DataBinding sehr einfach ein WCF-Service konsumiert werden.

image 

Mit Hilfe von INotifyCollectionChanged und INotifyPropertyChanged bekommen wir im Bereich DataBinding ausgezeichnete Möglichkeiten Änderungen ins UI zu puplizieren.

Im Beispiel habe ich die Customer Tabelle der Northwind-Datenbank gewählt und diese über ein WCF Service (BasicHttpBinding mit AspNetCompatibility) bereitgestellt.

[ServiceContract]
    public interface ICustomerService
    {
        [OperationContract]
        List<Customer> GetCustomers();

        [OperationContract]
        bool SaveCustomers(Dictionary<Customer, string> Customers);
    }

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class CustomerService : ICustomerService
    {
        #region ICustomerService Members

        public List<Customer> GetCustomers()
        {
            using (var DB = new NorthwindDataContext())
            {
                var query = from c in DB.Customers
                            select c;
                return query.ToList();
            }
        }

        public bool SaveCustomers(Dictionary<Customer, string> Customers)
        {
            TODO: Implement Save
            return true;
        }

        #endregion
    }

Damit dieses Service verfügbar ist muss noch die passende web.config (Service Configuration Editor) erstellt werden (passende .svc Datei nicht vergessen bei WCF Service unter WAS/IIS)

image

Dieses Service wird in Silverlight von der Klasse CustomerDataSource asynchron konsumiert. Dies hat natürlich den Vorteil, dass das UI sofort verfügbar ist wärend die Daten noch nachgeladen werden. Und das man von der ersten Sekunde an deklaratives DataBinding benutzen kann.

Damit die Daten aber tatsächlich nachgeladen werden können brauchen wir zuerst einen Proxy den wir über “Add Service Reference” erzeugen lassen. (Meta-Daten müssen vom Service aktiviert/bereitgestellt werden).

image

Sobald der CustomerServiceCleint (generierter Code) nun verfügbar ist können wir eine passende Klasse erzeugen und das Service benutzen.

public class CustomerDataSource
    {        
        public CustomerDataSource()
        {
            LoadCustomers();
        }

        private void LoadCustomers()
        {
            CustomerServiceClient client = new CustomerServiceClient();
            client.GetCustomersCompleted += (sender, e) =>
            {
                foreach (var c in e.Result)
                {
                    _Customers.Add(c);
                }

            };
            client.GetCustomersAsync();
        }

        ObservableCollection<Customer> _Customers = new ObservableCollection<Customer>();
        public ObservableCollection<Customer> Customers
        {
            get {
                return _Customers;
            }

        }     
    }


Die Klasse stellt nun eine ObservableCollection<T> (Customers) bereit in Form eines Property. Gegen das wird in XAML deklarativ gebunden.

Die Klasse CustomerDataSource beginnt beim Erzeugen das CustomerService aufzurufen. Sobald das Ergebnis vom Service da ist, wird die Liste _Customers befüllt. Da es sich hierbei um eine ObservableCollection<T> handelt und diese INotifyCollectionChanged implementiert wird das UI informiert sobald ein neuer Customer in die Liste wandert und DataGrid aktualisiert automatisch.

In XAML fehlt und zuletzt noch das Binding:

<UserControl xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"  x:Class="SilverlightConsumeWCF.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:SilverlightConsumeWCF">
    <UserControl.Resources>
        <local:CustomerDataSource x:Key="Customers" />
    </UserControl.Resources>    
    <Grid x:Name="LayoutRoot" Background="White">
        <data:DataGrid ItemsSource="{Binding Path=Customers, Source={StaticResource Customers}}">
        </data:DataGrid>
    </Grid>
</UserControl>

Download: SilverlightConsumeWCF 08042009.zip

Im Teil 2 wird noch editieren der Customer-Objekte ermöglicht. Das Service stellt die entsprechende Methodensignatur bereits bereit.

April 07

Silverlight 3: NetworkChange (u. DataBinding mit INotifyPropertyChanged)

In Silverlight 3 gibt es nun eine einfache Möglichkeit um den aktuellen Netzwerkstatus zu erkennen.

Netzwerkstatus:
Über die statische Methode NetworkInterface.GetIsNetworkAvailable() bekommt man nun die Information ob die Verbindung im Moment verfügbar ist oder nicht.
Die Klasse NetworkChange stellt hingegen das Event NetworkAddressChanged bereit, das gefeuert wird sobald sich der Netzwerkstatus ändert.

DataBinding:
Über DataBinding können wir nun recht einfach die Funktionalität im UserInterface darstellen.
Mithilfe von einem Binding von der Klasse zu einer CheckBox auf das Property IsChecked=”{Binding Path=IsOnline, Source={StaticResource State}}” kann nun in XAML an eine Ressource angebunden werden. (in dem Fall wird das Property IsOnline abgegriffen von der Resource mit dem Key State)

image 

Somit haben wir im UserInterface (= unser Silverlight UserControl) 0 Zeilen Programmcode.

Klasse:

	public class NetworkState : INotifyPropertyChanged
    {
        public NetworkState()
        {
            NetworkChange.NetworkAddressChanged +=
                   (sender, args) => SendNotifyPropertyChanged("IsOnline");
        }

        public void SendNotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        public bool IsOnline
        {
            get
            {
                return NetworkInterface.GetIsNetworkAvailable(); ;
            }
        }
        
        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }

UserControl (XAML):

<UserControl x:Class="SilverlightNetworkState.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:SilverlightNetworkState"
    Width="400" Height="300">
    <UserControl.Resources>
        <local:NetworkState x:Key="State" />
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White">
        <CheckBox Margin="10" IsChecked="{Binding Path=IsOnline, Source={StaticResource State}}" Content="Online" />
    </Grid>
</UserControl>

Download: SilverlightNetworkState 07042009.zip

March 03

HYPER-V Managment unter Windows 7


Unter Windows 7 gibt es einen extra Download um die Managment Tools für Hyper-V zu bekommen. Und zwar versteckt sich die Angelegenheit unter Remote Server Administration Tools for Windows 7.

 image_thumb1

Nachdem man den Download installiert hat kann man unter “Turn Windows features on or off” das enstprechende Managment-Tool aktivieren (Hyper-V Tools).

image_thumb3

February 12

Visual Studio 2008, WPF, NVidia Treiber = (Designer)Problem


Unter Windows 7 scheint mit der aktuellen NVidia Notebook-Treibern (die off. NICHT für Windows 7 verfügbar sind) ein kleines  merkwürdiges Problem mit VisualStudio 2008 u. WPF zu geben.

Zumindest auf meiner Box funktioniert danach im Visual Studio der “WPF Designer” nicht mehr. Nur mehr ein weißes “Fenster” und ein Visual Studio das mit 100% CPU Auslastung im endlos-loop läuft.
Die Anwendung (nachdem man sie via XAML reingehackt hat) läuft aber einwandfrei.

Mit den Windows7 Treibern für Nvidia Geforce Go (die man via Windows-Update bekommt) läufts soweit fein.

ObjectDataSource in ASP.net (Keine Einträge in der “Auswahlliste” mit Klassen f. Datenquelle)


Gerade eben bin ich auf ein sehr merkwürdiges Problem gestossen.

In meiner Solution gab es keine Klassen in der Datenquellen-Auflistung.
Alles x-mal gecheckt und obwohl alle Referenzen verfügbar waren, die Klassen auch als public defeniert waren und alles wunderbar kompilierte klappt es nicht.

Keine Fehlermeldung,- einfach nichts :-(

Bei einem anderem Projekt probiert. Funktionierte einwandfrei.

Am Ende draufgekommen, dass es an meinem Ordnernamen gelegen ist: Scheinbar darf kein “#” in der Ordnerstruktur vorkommen.

Nummernzeichen weg und siehe da,- Es klappt.

Merke: Keinen Ordner C#Training mehr verwenden.

Virtual CD/DVD – Windows 7


Gerade getestet:
Virtual CloneDrive (Freeware) funktioniert einwandfrei mit der Beta (Build 7000) von Windows 7.

February 04

Jobs, Jobs, Jobs, …


Ich habe gerade mal etwas zusammengezählt wie viele Job-Angebote (Xing, Headhunter, Mail, persönlich, …) so im letzten Jahr (1.1.2008 – 31.12.2008) bei mir angekommen sind.

17 Angebote (Deutschland u. Österreich) in 12 Monaten ist ja nicht ungemütlich. Wirtschaftskrise dürfte wohl hier noch nicht angekommen sein.

Wie siehts bei euch aus?

January 27

Generic Delegates: Func<T>

Im letzten Posting habe ich die Möglichkeiten beschrieben einen Delegate als Paramter zu akzeptieren.

Auch dort haben wir bereits den weg über Predicate<T> verwendet:

   1: ... Demo1.GetDemos(  
   2:             delegate(Demo d)   
   3:                 {   
   4:                     return (d.Active && d.Name == "Test");
   5:                 }                  
   6:             );


Oft ist man (wie im letzten Beispiel) nicht mehr gezwungen für alles einen eigenen Delegate zu erstellen. Hierfür kann man nun Func<T> (oder auch Action<T>, …) verwenden.

Aussehen kanns dann so:

   1: Func<int, bool> f = (i) => i == 1;
   2: var res = f(10);

Variable “f” beinhaltet nun unsere eigentliche Logik (Zuweisung über Lambda-Schreibweise). Dessen Aufruf ist dann denkbar einfach und natürlich können wir auch hier wieder Funktionen definieren die einen Parameter Func<T> nimmt.

January 26

Predicate<T> in C# 3.0


Funktionen/Methoden schreiben ist einfach. Paramter übergeben auch.

Schon mal eine Methode definiert die indirekt “Code” (einen Predicate<T>) als Parameter übernimmt?

Mithilfe eines Predicate<T> ermöglichen Sie die übergabe eines Delegates und schaffen somit die Möglichkeit Ihre eigene dynamischen (strongly Typed) Filter zu erstellen.

Wie kanns aussehen?

Zuerst die Funktion definieren die einen Predicate<T> als Paramter nimmt:

   1: public static class Demo1   
   2: {   
   3:     public static List<Demo> GetDemos(Predicate<Demo> p)
   4:     {
   5:         var lst = GetList(); //Ladet eine Liste die gefiltert werden soll   
   6:         foreach (v i in lst) 
   7:         {
   8:             if (p(i))
   9:                 yield return i;
  10:         }
  11:     }
  12: }

Aufruf:

   1: var lst = Demo1.GetDemos(
   2:                 delegate(Demo d) 
   3:                     {
   4:                         return (d.Active && d.Name == "Test");
   5:                     }
   6:                );
Und somit sollten auch die Technolgien die hinter LINQ Stecken wieder etwas 
verständlicher werden.
January 23

LINQ: Join

In einem Linq Model kann man ein “Join” relativ einfach hinbekommen wenn die Einzelnen Elemente bereits Beziehungen haben. (Stichwort EntitySet<T>)

 NorthwindLinq_thumb

Durch diese Beziehung kann man nun Abfragen (die mehr als ein Objekt/Tabelle betreffen) sehr einfach mit der . Schreibweise definieren.

   1: var query = from o in DB.Orders
   2:     select new
   3:     {
   4:         Name = o.Customer.CompanyName,
   5:         OrderID = o.OrderID
   6:     };

Doch oftmals gibts genau diese Beziehung zwischen den Objekten nicht (hier zwischen Customer u. Order).
Wie kommt man trotzdem zum Ergebnis? Join-Keyword!

   1: var query = from o in DB.Orders
   2:     join c in DB.Customers on o.CustomerID equals c.CustomerID
   3:     select new
   4:     {
   5:         Name = c.CompanyName,
   6:         OrderID = o.OrderID
   7:     };

Download Sample: LinqJoin.zip

VSONE – München – 10. bis 13. Feb. 2009


Dieses Jahr werde ich auf der VSONE einen Workshop zum Thema “C# –> LINQ” halten.

ADT_standbild

Delegates, anonyme Methoden und Lambda Expression waren Ihnen immer schon ein Rätsel? Sie wollen mit weniger Code MEHR tun? Holen Sie sich noch einen der letzten Plätze.

Auf der Konferenz gibts eine kompakte Zusammenfassung zum Thema in der Session “C# 3.0 in LINQ”

January 20

Live Mesh

Windows Live Mesh, zu finden unter https://www.mesh.com/ ist eine flexible Möglicheit Daten über mehrere Systeme zu synchronisieren.

zB Favoriten können damit mit 2 klicks

a) im Internet verfügbar gemacht werden
     und
b) über System synchronisiert werden.

Im Moment ist das Produkt noch Beta (und bietet 5 GB kostenlosen Speicher!)

Wie findet Ihr das Teil?

January 01

HAPPY NEW YEAR


… all meinen Lesern/innen.

Spannendes steht uns bevor 2009: Windows 7, .net 4.0, Visual Studio 2010, Oslo, … (oder zumindest eine Beta davon)

Auf was freut ihr euch am meisten?