Sunday, October 28, 2007

Developing a Microsoft Robotics Studio custom input service in vb.net

Yesterday an MSP (Microsoft Student Partner) friend of mine asked me to help him out on a presentation on Microsoft Robotic Studio [http://msdn2.microsoft.com/en-us/robotics/default.aspx]. To be honest, I was ignorant of this studio’s existence till then. Robotic Studio is an IDE to create robotic applications for a wide variety of computing platforms. If you have taken any signal processing lecture, the whole studio will seem really familiar.



On this article I will try to show you how to create a simple win form control panel and use it as a service in order to control your robot. It will be like the Directional Dialogue that already exists in the service but it will have more buttons. Since I have not yet bought the Lego NXT Intelligent Brick (http://shop.lego.com/product/?p=9841&LangId=2057&ShipTo=US), we will end up with a control panel which will throw messages when a button is pressed instead of propagating these events to a real life robot.



The first think you should do, is create the solution where you will build the new service. Open the command prompt from the Microsoft Robotics Studio (1.5) program file menu. Robotic studio provides us with the dssnewservice utility which creates all the required projects plus it configures the post build events to copy the resulting dlls in the Robotics Studio bin folder. In our example we will create a new service using VB.net under the Robotics namespace and we shall call it MyWindowsFormInputService. That’s interpreted in the following command:



C:\Microsoft Robotics Studio (1.5)\samples>dssnewservice /namespace:Robotics /Service:MyWindowsFormInputService /language:VB



As you may have noticed, I created the solution inside the samples folder, which is not required. You may create the solution anywhere you like or you may even move it after creating it. Open the MyWindowsFormInput.sln using Visual Studio 2005. The solution contains one project with two classes which are both under the namespace Robotics.MyWindowsFormInput. This is an exaggeration since the project also declares the same namespace. Thus the generated classes end up under the namespace Robotics.MyWindowsFormInput.Robotics.MyWindowsFormInput. This problem only occurs in VB since in C# the classes need the namespace declaration. In order to solve this, you must remove the following declaration on both generated files:


Namespace Robotics.MyWindowsFormInput

End Namespace


Let us now start modifying the generated code to meet our needs. First of all we need to be able to provide notifications to other services. The services, with which our service is going to communicate, are called subscribers. In order to be able to keep trace of the subscribers, we will have to give them the opportunity to subscribe. This is why we need to define our subscription message which will inherit from the Microsoft.Dss.ServiceModel.Dssp.Subscribe message. Since we don’t need anything more that the default message, we will leave it to that. The declaration should be:


Public Class Subscribe

    Inherits Subscribe(Of SubscribeRequestType, PortSet(Of SubscribeResponseType, Fault))

End Class


Declaring the Subscribe message type though is not enough. We have to let the other services know that our service supports the Subscribe message… Thus we have to add it in the MyWindowsFormInputOperations declaration. Let’s have a look on that class’s current declaration:


<ServicePort()>  _

Public Class MyWindowsFormInputOperations

Inherits PortSet(Of DsspDefaultLookup, DsspDefaultDrop, [Get])

End Class


This means that we do support a [Get] message which is added for us, but we don’t need it. So replace the [Get] with Subscribe and you should have the following code:


Public Class MyWindowsFormInputOperations

Inherits PortSet(Of DsspDefaultLookup, DsspDefaultDrop, Subscribe)

End Class


If you want, you may delete the Public Class [Get] which is yet another message declaration, and we want need it. If you check the error list, we have 2 errors with description “Too few type arguments to 'Microsoft.Dss.ServiceModel.Dssp.Get(Of TBody, TResponse)'”. By clicking on them you will be transferred in the MyWindowsFormInput.vb file and to be more accurate in the start() sub and the GetHandler sub. As you may know, we have to register a handler for each supported message. The GetHandler sub handles any Get message while the


Arbiter.Receive(Of [Get])(True, _mainPort, AddressOf GetHandler)


line defines that any Get message will be handled by the GetHandler sub.  In accordance to that we create the following handler sub:


Public Sub SubscribeHandler(ByVal subscribe As Subscribe)

End Sub


And modify the Arbiter.Receive line to:


Arbiter.Receive(Of Subscribe)(True, Me._mainPort, New Handler(Of Subscribe)(AddressOf Me.SubscribeHandler)) _


What we do need is a manager to keep track of our subscribing services. This is done by simply declaring a private variable (we shall call it _submgr) giving the following declaration:


<Partner("SubMgr", Contract:="http://schemas.microsoft.com/xw/2005/01/subscriptionmanager.html", CreationPolicy:=PartnerCreationPolicy.CreateAlways, Optional:=False)> _

Private _submgr As New Microsoft.Dss.Services.SubscriptionManager.SubscriptionManagerPort


Let’s have a closer look to that declaration. First of all _submgr is an instance of a standard DSS component. The Partner directive above it, may trouble you a bit. A partner is another service on which our service depends on. When our service starts, it creates a new instance of its partners. If a partner fails to start, our service will also fail to start. So what we actually do here is declare a partner service with the subscriptionmanager contract and we have a port in order to communicate which him.

Having declared the subscriptionmanager, we go back to the subscribe handler and modify it to use the subscribehelper method for the subscribe messages. The sub should look like:


Public Sub SubscribeHandler(ByVal subscribe As Subscribe)

     Me.SubscribeHelper(Me._submgr, subscribe.Body, subscribe.ResponsePort)

End Sub


Since we got to know the messages a little better, we can now create a few more messages that we shall need. We shall need a ButtonPressEvent and a ButtonReleaseEvent message. They will be both inheriting from Microsoft.Dss.ServiceModel.Dssp.Update operation and they will be notifying when a button is pressed and released from the GUI. If you take a closer look in the update class through the Object browser you should see that it requires a TBody:


Public Class Update(Of TBody As New, TResponse As {New, Microsoft.Ccr.Core.IPort})


The TBody is the structure that will contain the transmitted date with this operation. So we will create a simple class called ButtonPressEventArgs which will contain the data that we will be sending whenever we press a button from the GUI. This class should look like this:


<DataContract()> _

Public Class ButtonPressEventArgs


     'This is the name of the command to execute

     Private _commandName As String


     <DataMember()> _

     Public Property CommandName() As String

          Get
     
          Return Me._commandName

          End Get

          Set(ByVal value As String)

               Me._commandName = value

          End Set

     End Property



     Public Sub New()

     End Sub


     Public Sub New(ByVal name As String)

           Me._commandName = name

     End Sub


End Class


It only contains a private member and a property called CommandName. Thus the ButtonPressEvent operation should be:


<DisplayName("ButtonPressEvent"), Description("Indicates when a button in the dialog is pressed.")> _

Public Class ButtonPressEvent

     Inherits Update(Of ButtonPressEventArgs, PortSet(Of DefaultUpdateResponseType, Fault))


     Public Sub New()

     End Sub


     Public Sub New(ByVal body As ButtonPressEventArgs)

          MyBase.New(body)

     End Sub


End Class


We shall create the ButtonReleaseEvent and  ButtonReleaseEventArgs respectively:


<DataContract()> _

Public Class ButtonReleaseEventArgs


     'This is the name of the command to execute

     Private _commandName As String



     <DataMember()> _

     Public Property CommandName() As String

          Get

               Return Me
._commandName

          End Get

          Set
(ByVal value As String)

               Me._commandName = value

          End Set

     End Property



     Public Sub New
()

     End Sub



     Public Sub New
(ByVal name As String)

          Me._commandName = name

     End Sub



End Class



<DisplayName("ButtonReleaseEvent"), Description("Indicates when a button in the dialog is released.")> _

Public Class ButtonReleaseEvent

     Inherits Update(Of ButtonReleaseEventArgs, PortSet(Of DefaultUpdateResponseType, Fault))


     Public Sub New()

     End Sub



     Public Sub New
(ByVal body As ButtonReleaseEventArgs)

          MyBase.New(body)

     End Sub

End Class


Having declared these to operations, we have to let the other services know that we do support them. Thus we return to the MyWindowsFormInputOperations and modify its declaration to look like the following:


<ServicePort()>  _

Public Class MyWindowsFormInputOperations

     Inherits PortSet(Of DsspDefaultLookup, DsspDefaultDrop, Subscribe, ButtonReleaseEvent, ButtonPressEvent)

End Class


And then we will go back to the MyWindowsFormInputService class and add two handlers for the new operations:


Public Sub ButtonPressEventHandler(ByVal e As ButtonPressEvent)

End Sub


Public Sub ButtonReleaseEventHandler(ByVal e As ButtonReleaseEvent)

End Sub


We will fix those two later on (when we do actually create the form). Respectively to the subscribe operation we have to modify the Start method by adding in the ExclusiveReceiverGroup the two new operations. The final ExclusiveReceiverGroup should look like the following:


New ExclusiveReceiverGroup _

( _

     Arbiter.Receive(Of ButtonPressEvent)(True, _mainPort, AddressOf ButtonPressEventHandler), _

     Arbiter.Receive(Of ButtonReleaseEvent)(True, _mainPort, AddressOf ButtonReleaseEventHandler) _

), _


By now you shouldn’t have any error messages in the Error list. The next thing we shall do is create the control panel form. Add a new form in the project and name it NavigationPanel. Let us suppose that out Robot supports the following eight commands: move forwards, move backwards, turn left, turn right, fire, flip over, make noise and switch lights. The simplest navigation panel for our robot would look like the following image:



In order to minimize the code I have to write, I will be naming the buttons after the respective command by simply adding the cmd prefix. So the Fire button will be named cmdFire and the rest of them will be named cmdFlipOver,cmdMakeNoise,cmdMoveBackwards,cmdMoveForwards,cmdSwitchLights,cmdTurnLeft,cmdTurnRight. The argument that I will be sending on the respective event will be the name of the button without the cmd prefix. In order to be able to send messages, this form should get a reference to the MyWindowsFormInputOperations that the MyWindowsFormInputService has (the private variable _mainPort). The simplest way to do that is by overriding the constructor and passing a reference there and storing it in a private variable called _mainPort.


Private _mainPort As MyWindowsFormInputOperations


Using this variable I will be able to Post messages. So I do create two sub to handle the mousedown and the mouseup of my buttons


Private Sub button_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)

     If TypeOf sender Is System.Windows.Forms.Button Then

          Dim button As System.Windows.Forms.Button = CType(sender, System.Windows.Forms.Button)

          Dim CommandName As String = GetCommandFromButton(button)

          Me._mainPort.Post(New ButtonPressEvent(New ButtonPressEventArgs(CommandName)))

     End If

End Sub



Private Sub button_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs)

     If TypeOf sender Is System.Windows.Forms.Button Then

          Dim
button As System.Windows.Forms.Button = CType(sender, System.Windows.Forms.Button)

          Dim CommandName As String = GetCommandFromButton(button)

          Me._mainPort.Post(New ButtonReleaseEvent(New ButtonReleaseEventArgs(CommandName)))

     End If

End Sub




'Removes the cmd from the button name and returns the remaining text


Private Function GetCommandFromButton(ByRef button As Button) As String

     Return button.Name.Substring(3)

End Function


The two sub, simply post a new message with the appropriate body (arguments). I should also register the buttons event handlers in the constructor, so the new sub whould look like:


Public Sub New(ByRef mainPort As MyWindowsFormInputOperations)

     Me.InitializeComponent()

     'store the reference to the mainport

     _mainPort = mainPort

     'Add event listeners to button events

     AddHandler cmdFire.MouseDown, AddressOf button_MouseDown

     AddHandler cmdFlipOver.MouseDown, AddressOf button_MouseDown

     AddHandler cmdMakeNoise.MouseDown, AddressOf button_MouseDown

     AddHandler cmdMoveBackwards.MouseDown, AddressOf button_MouseDown

     AddHandler cmdMoveForwards.MouseDown, AddressOf button_MouseDown

     AddHandler cmdSwitchLights.MouseDown, AddressOf button_MouseDown

     AddHandler cmdTurnLeft.MouseDown, AddressOf button_MouseDown

     AddHandler cmdTurnRight.MouseDown, AddressOf button_MouseDown

     AddHandler cmdFire.MouseUp, AddressOf button_MouseUp

     AddHandler cmdFlipOver.MouseUp, AddressOf button_MouseUp

     AddHandler cmdMakeNoise.MouseUp, AddressOf button_MouseUp

     AddHandler cmdMoveBackwards.MouseUp, AddressOf button_MouseUp

     AddHandler cmdMoveForwards.MouseUp, AddressOf button_MouseUp

     AddHandler cmdSwitchLights.MouseUp, AddressOf button_MouseUp

     AddHandler cmdTurnLeft.MouseUp, AddressOf button_MouseUp

     AddHandler cmdTurnRight.MouseUp, AddressOf button_MouseUp

End Sub


In order to be able to validate that the body of each message is valid I will add in this form a shared readonly property which shall give me a List(of string) listing the available commands. The code should be the following:


Private Shared Sub InitializeAvailableCommands()

     _AvailableCommands = New List(Of String)

     _AvailableCommands.Add("Fire")

     _AvailableCommands.Add("FlipOver")

     _AvailableCommands.Add("MakeNoise")

     _AvailableCommands.Add("MoveBackwards")

     _AvailableCommands.Add("MoveForwards")

     _AvailableCommands.Add("SwitchLights")

     _AvailableCommands.Add("TurnLeft")

     _AvailableCommands.Add("TurnRight")

End Sub



Private Shared
_AvailableCommands As List(Of String)


Public Shared ReadOnly Property AvailableCommands() As List(Of String)

     Get

          If
_AvailableCommands Is Nothing Then

               InitializeAvailableCommands()

          End If

          Return
_AvailableCommands

     End Get

End Property


Now we are ready to implement the ButtonPressEventHandler and the ButtonReleaseEventHandler to sendnotifications to other services.


Public Sub ButtonPressEventHandler(ByVal e As ButtonPressEvent)

     If NavigationPanel.AvailableCommands.Contains(e.Body.CommandName) Then

          e.ResponsePort.Post(DefaultUpdateResponseType.Instance)

          Me.SendNotification(Of ButtonPressEvent)(Me._submgr, e)

     Else

          e.ResponsePort.Post(W3C.Soap.Fault.FromCodeSubcodeReason(W3C.Soap.FaultCodes.Receiver, _
            DsspFaultCodes.UnknownEntry, (String.Format("Unknown command {0}!", e.Body.CommandName))))

     End If

End Sub



Public Sub
ButtonReleaseEventHandler(ByVal e As ButtonReleaseEvent)

     If NavigationPanel.AvailableCommands.Contains(e.Body.CommandName) Then

          e.ResponsePort.Post(DefaultUpdateResponseType.Instance)

          Me.SendNotification(Of ButtonReleaseEvent)(Me._submgr, e)

     Else

          e.ResponsePort.Post(W3C.Soap.Fault.FromCodeSubcodeReason(W3C.Soap.FaultCodes.Receiver, _
            DsspFaultCodes.UnknownEntry, (String.Format("Unknown command {0}!", e.Body.CommandName))))

     End If

End Sub


There is only one last thing left to get this ready. We have to invoke the form. As you may imagine this should occur in the start method, but first we have to add a reference to Ccr.Adapters.WinForms.dll located in C:\Microsoft Robotics Studio (1.5)\bin\.

After that, we need to create a method in the MyWindowsFormInputService class that will create the new form instance. Let’s call it CreateNavigationPanelForm:


Public Function CreateNavigationPanelForm() As System.Windows.Forms.Form

     Return New NavigationPanel(_mainPort)

End Function


Having this function we may now modify the start method and add the following line exactly below the DirectoryInsert() call:


Me.WinFormsServicePort.Post(New Microsoft.Ccr.Adapters.WinForms.RunForm(New Microsoft.Ccr.Adapters.WinForms.WinFormConstructor(AddressOf CreateNavigationPanelForm)))


That’s all about it. No more coding from here on… What we do have to do is build the project. You can do that by either pressing the build button in the Visual studio or by opening once again the command prompt through the Robotic studio and issuing the following command:


C:\Microsoft Robotics Studio (1.5)\samples\MyWindowsFormInput>msbuild MyWindowsFormInput.sln


As you should notice the output is copied directly inside the C:\Microsoft Robotics Studio (1.5)\bin folder and there are also a .proxy.dll and a .transform.dll with the same name. All these files are required in order to be able to use your service inside the Robotics Studio.


Now it’s time to fire up the Visual Programming Language. If everything went fine, the new service will be listed in Services panel as MyWindowsFormInput. To test it you may create the following diagram:



Running it will give you the following screen:



This concludes the how to create a window form and use it as an input service in Microsoft Robotics Studio. Please note that I have been playing around with Robotic Studio for less than a day and thus my knowledge is not deep enough to be able to explain what is going on under the hood but still I hope someone may find this useful at least to begin with.


Resources:


Friday, September 28, 2007

Systray disappearing icons

I recently installed Super Copier 2 a fascinating program that overrides the default windows copy mechanism and provides the user with options such as continue on error etc. The main problem I face is that it does override every copy mechanism which causes problems especially when you try to copy things from your mobile phone or through a zip file. Thus I have to deactivate every now and then to achieve some tasks. It can be easily deactivate through its icon on the systray (a.k.a notification area).

The problem is that recently (about a month after installing the program) the systray icon disappeared. That’s when I realized that most of my systray icons (including the Sql Server Service Manager) were gone. Initially I though I had activated the option “Hide inactive icons” on the Taskbar and Start Menu Properties but that was not my case. So I started googling and ended up on an article entitled “Systray icons missing Windows Problem Solver”.

I tried the systray_cleanup.reg then the systray_plus.reg and finally the systray.reg which actually solved my problem. I have uploaded their script just in case their site goes down. You can download them here

Saturday, September 8, 2007

Windows plus Worms plus Trojans equals Nightmare

I do remember the time when antivirus programs were not obligatory if you were careful and didn’t run “suspicious” applications. Back then, firewall was considered a useless resource consuming application. Over the past few years though, with the broadband evolution, things have changed. Nowadays one receives hundreds of mails, most of them spam which may contain a virus. Even worse, since the Blaster worm in August 12 2003, firewall became a necessity in order to be able to surf on the net without having windows restart every minute or so. Things have changed and we have to adapt… Even if you think you are safe, you may not be. Everyday new vulnerabilities arise from guys who check each and every array to find a buffer overflow which may crush the victim’s computer (DoS attack) or even worse, detect a loophole which will give them remote access to the victim’s computer. But then again, everyone knows these things. Why mention them once more?
Well, I am a windows user (developer to be more precise) and this is my quest for Trojan removal. All started yesterday while I was wandering in the Event Viewer. I noticed that the maximum TCP/IP connections limit was reached twice for that day. Immediately I realized that the web browsing was slow not because someone in the same rooter was downloading, but because my laptop was communicating with someone intensively.
I freaked out. I opened a command prompt (Start-->Run-->type “cmd”) and executed the most useful command in such occasions:

Netstat –ano


A table appeared listing all open ports, the destination ip and which process is handling this port (PID). Needless to say that my laptop was communicating with a lot of (more that 10) web servers (it was connecting to port 80) and all connections where made by a PID 1448. In order to find out the process’s id (PID), normally you may run the “tasklist” command. In my case it displayed an empty list which is equivalent to no processes running. That was impossible, so the tasklist command was modified which verified my virus suspicion. So how do you match a PID to a process without tasklist? Through the Windows Task Manager. You open it, go to the Processes panel and press “view-->select columns…”. From there you may display a lot of useful info concerning the running processes including their PID.
As most worms, the guilty process was svchost.exe. In over simplified words, this process encapsulates many many many libraries and applications. As you may have noticed there are several svchosts running in your windows installation. That is normal. Each is responsible for a totally different task and all together provide windows with network support, encryption, web server, file system etc…
Closing the svchosts also terminated the connections to the remote server and gave me time to go check my firewall settings. I do use the build in firewall of windows XP sp2 which blocks all incoming traffic besides the programs or ports defined in the list of Exceptions. There I came across the third sign which indicated I have picked up a Trojan. A port was open to public under the disguise of “messenger” which is ridiculous in my case since I don’t even have windows messenger installed! Disabling this exception or removing it from the list would not do any good since in every restart in would be recreated and the port would change.
Back in the college days (the days when firewall was not a necessity) we were fooling around with Trojans. These programs provide control of a victim’s pc. You may browse his/hers files, capture video, show funny pop up messages etc. What we did was a contest. Every one who dared to enter the contest would have to get a private file from the computer of the opponent. Our motives were pure educational. No civilians were attacked, only the contestants. Back then, the best Trojan was sub7 which was undetectable by Norton and McAfee. I got a lot of wins but I also ended up formatting my computer too, since a contestant created a Trojan by himself. That was not detectable even by Kaspersky which could detect sub7. When this madness came to an end and we realized that it doesn’t worth reformatting every two days, we got together and started discussing the experiences we had. The one who beat me told me the architecture of the Trojan he created. It was simple. A small process which would be melted into (combined with, in common words) a system process and would listen to a specific port. Actually it would only open the port for thirty seconds every five minutes in order to be stealth. That process would expect a specially crafted message which would contain a port. By receiving that, it would start another bigger process which would be listening to the received port and expose the whole windows api. It was brilliant.
A variant of the above architecture must have hit me now. A small process had melted into something that was loaded by the svchost. That process was responsible to report my online presence in some free web servers (send my ip on a script so that the attacker gets notified that I am online and where to find me) and more over it was opening the port so that the main Trojan could communicate with the attacker and provide him with remote access.
Anyhow, I opened my swish army toolbox which is mostly downloaded from http://www.sysinternals.com/ and started poking with the contaminated svchost. With process explorer I could suspend the process and monitor any threads running. Unfortunately the only suspect process that was executed under the svchost was C:\WINDOWS\system32\wbem\wmiprvse.exe which I verified the hash and seemed to be ok. With Procmon I noted the registry keys and the files modified by the specified process and its children. That was exhausting I must say and it didn’t lead to anything useful. Finally, I tried running the RootkitRevealer but with no luck since I had killed the svchost and the RootkitRevealer could not be executed (actually no installation could begin). By the way, if you kill an svchost, it is almost certain that the annoying “Windows will shut down” message will pop up giving you one minute to save your work. Do not panic. Press Start-->run-->type “shutdown –a” and the message disappears.
I did also try spybot and Adaware but they are specialized in worms and malware rather than Trojans, so nothing came up (besides a couple of hundreds of spy cookies).
In my despair, I started downloading every antivirus available, every Trojan removal tool I could find in trusted web sites. Nothing came up. So I started taking drastic measures. Safe mode and delete any “useless” dll such as the C:\Program Files\Bonjour\mdnsNSP.dll which was referenced a lot by the infected svchost. Nothing happened. The port was still opening and my laptop was socializing with every free web server on the net!!! I installed wireshark (which is a packet sniffer) but the packets I was interested about were encrypted.
I did a lot of google search and I read a lot of opinions. None seemed to fit exactly to my case. As a desperate move, I downloaded a program that would clean up the temp folders, internet history, useless log files in windows etc and then run an antispyware. When the cleaning finished, it managed to remove 250Mb of useless files and I started the file checking. The antispyware didn’t find anything (although it tried hard I may say) and told me that I had to reboot. That was the last time I saw my desktop. Since then after the welcome screen an exception occurred in winlogon.exe and that’s about it… BSOD.
I got my windows XP cd, and repaired the existing windows installation. This process took about 40 minutes. After that I had a windows installation which would once again throw the Blue Screen Of Death after the welcome screen!!!
It was 4 a.m. and I hadn’t copied my files from c:\. I didn’t have a small Philips screwdriver to remove the disk and pick up the data from another pc and leaving the laptop as is was not an option. I had to have the laptop fixed by today. In order to retrieve my data I resorted to Knoppix live dvd. For no apparent reason (actually a driver incompatibility between Toshiba A100-912 and Knoppix) I had to avoid pcmcia auto detection in order to boot. Through the KDE I mounted my file server’s shares and copied everything I needed (basically the whole c:\ partition besides the Windows folder). By 6 o’clock in the morning all data had been transferred. Reboot, format, and here we go again… setup, setup, setup…
To conclude this scary story, I have to admit that I should have listened to my colleagues who told me that since Nod32 could not detect it, it is useless to try to defeat it by myself. That would have saved me a lot of hours since the format was imminent. The moral of this story is that we are never secure. I don’t know if I by mistake executed the infected application or someone else did it for me, the point is that since there are web sites like the http://www.nuclearwintercrew.com/ where a script kid can buy an undetectable Trojan, we have to use our minds in order to protect our digital data. Be always alert, and constantly check your systems. A rootkit could compromise your privacy and cause data loss. Although I used to say that and used to have daily computer checks (with nessusd etc), I got careless since no incident had occurred. On the bright sight, this incident will place me back in track…

Wednesday, July 4, 2007

Remix 2007, Βουδαπέστη

Το συνέδριο

Το REMIX '07 (11 και 12 Ιουνίου, 2007, Βουδαπέστη) αποτέλεσε το Ευρωπαϊκό συνέδριο της Microsoft γύρω από τις τεχνολογίες Web. Το συνέδριο διοργανώθηκε στον απόηχο του MIX'07, του σημαντικότερου event της Microsoft για τεχνολογίες Web, για να δώσει την ευκαιρία στους Ευρωπαίους developers, designers και decision makers να αποκτήσουν μια ευρεία γνώση των τεχνολογιών και πρακτικών Web της Microsoft. Σε μια μαγευτική Ευρωπαϊκή πόλη, στον εντυπωσιακό χώρο του Μουσείου Καλών Τεχνών της Βουδαπέστης και για δύο ημέρες, είχαμε την ευκαιρία να συναντηθούμε και να συνομιλήσουμε με συναδέλφους μας γύρω από το "νέο Internet", καθώς και τα εργαλεία και τις τεχνολογίες που θα μας βοηθήσουν να το δημιουργήσουμε. Το συνέδριο είχε δύο θεματικές ενότητες οι οποίες παρουσιάζονταν ταυτόχρονα. Η πρώτη αφορούσε τους designers ενώ η δεύτερη τους developers. Οι συμμετέχοντες έπρεπε να δηλώσουν την θεματική ενότητα που τους ενδιαφέρει αλλά η απόφαση αυτή δεν ήταν υποχρεωτική μιας και μπορούσαμε να εναλλάσσουμε τις αίθουσες χωρίς καμία κύρωση.


Οι ομιλητές

Ο κεντρικός ομιλητής του REMIX'07 ήταν ο Scott Guthrie (http://www.scottgu.com/), γενικός διευθυντής (General Manager) στον τομέα των Development Tools. Υπεύθυνος των τεχνικών ομάδων που βρίσκονται πίσω από την υλοποίηση των :

  • Common Language Runtime (CLR)

  • .NET Compact Framework

  • ASP.NET / Atlas

  • Windows Forms

  • Windows Presentation Foundation

  • Microsoft Silverlight (WPF/e)

  • IIS 7.0

  • Commerce Server

  • Visual Web Developer

  • Visual Studio Tools for WPF

Από την Microsoft, παρουσίαση έκανε και ο Pete LePage (http://blogs.msdn.com/petel/) ο οποίος αποτελεί τον υπεύθυνο προϊόντων για τα δικτυακά εργαλεία της Microsoft (Product Manager for Web Tooling). Ο Pete, αποτελεί το άτομο που εξασφαλίζει ότι τα προϊόντα Internet Explorer, Visual Web Developer και Expression Web καλύπτουν τις απαιτήσεις των πελατών της Microsoft.

Σημαντική ήταν και η παρουσία της Molly Ε. Holzschlag. Η Molly είναι γνωστή συνήγορος, εκπαιδευτικός, και συντάκτης προτύπων Ιστού (Web standards advocate). H Molly εκπαιδεύει σχεδιαστές ιστοσελίδων πάνω σε θέματα υλοποίησης βιώσιμων, συντηρήσιμων, προσιτών, διαλογικών και όμορφων ιστοχώρων. Είναι συγγραφέας 34ων βιβλίων ένα εκ των οποίων είναι το «The Zen of CSS Design»

Εντυπωσιακός ήταν και ο Steve Marx (http://www.smarx.com/), ο οποίος είναι πρώην developer των Windows και τώρα δουλεύει στην Microsoft σαν ευαγγελιστής του Asp.net AJAX.

Ελαφρώς άτυχος ήταν ο ομιλητής Beau Ambur (http://beaumix.spaces.live.com/) στον οποίο δεν λειτούργησαν με την πρώτη οι δύο εφαρμογές που υλοποίησε κατά την διάρκεια των παρουσιάσεων του. Ο Beau είναι ο CEO και ιδρυτής της Metaliq η οποία έχει να παρουσιάσει μερικά πολύ εντυπωσιακά παραδείγματα σε SilverLight όπως την online επεξεργασία video.

O Paul Dawson (http://blogs.conchango.com/pauldawson/) είναι ο υπεύθυνος εμπειρίας καταναλωτών (Experience Director) της Conchango. Η εταιρία του αποτελεί μια από τις κορυφαίες ευρωπαϊκές εταιρίες σχεδιασμού και υλοποίησης web sites.

Ο Wayne Smith (http://www.wayne-smith.org/) είναι ο Group Product Manager για το Microsoft Expression και αποτελεί μέλος της οικογένειας της Microsoft από τα μέσα του 2005 ενώ παλιότερα υπήρξε technical product manager της Macromedia Europe.

Τέλος μίλησαν και οι George Moore και Koji Kato που ανήκουν στην ομάδα ανάπτυξης της πλατφόρμας Windows Live.

Οι παρουσιάσεις

Ο Scott Guthrie έκανε την πρώτη παρουσίαση του συνεδρίου (ή οποία ήταν κοινή για τους designers και τους developers) παρουσιάζοντας σε γενικές γραμμές τις νέες τεχνολογίες και τις δυνατότητες που έχουμε με τα νέα εργαλεία και πλατφόρμες της Microsoft. Ειδικότερα, έκανε μια εισαγωγή στην νέα πλατφόρμα ανάπτυξης web εφαρμογών που ονομάζεται SilverLight, παρουσίασε το νέο πακέτο ανάπτυξης εφαρμογών Expression Studio το οποίο θα είναι άρρηκτα συνδεδεμένο με το νέο Visual Studio 9 (με κωδικό όνομα Orcas) και τέλος έκλεισε την παρουσίαση του δείχνοντας μας παραδείγματα δικτυακών εργαλείων τα οποία υλοποιήθηκαν πάνω στο νέο SilverLight.

Μετά το εισαγωγική παρουσίαση, ακολούθησε μια 2ωρη παρουσίαση («Building Silverlight Applications using .NET») για τον τρόπο ανάπτυξης εφαρμογών στο SilverLight, η οποία αφορούσε τους developers. Σε αυτή την παρουσίαση οι προγραμματιστές μάθανε πως γίνεται ο σχεδιασμός και η υλοποίηση μιας εφαρμογής σε SilverLight καθώς και τις νέες δυνατότητες που αποκτούν εκτελώντας κώδικα στον τελικό καταναλωτή της ιστοσελίδας και όχι στον κεντρικό εξυπηρετητή που φιλοξενεί την σελίδα. Παράλληλά έγινε σύγκριση μεταξύ της ταχύτητας εκτέλεσης κώδικα γραμμένος στο SilverLight σε σχέση με την Javascript η οποία μέχρι στιγμής αποτελούσε τον πιο διαδεδομένο τρόπο για να εκτελεί κώδικα ο browser του πελάτη. Χαρακτηριστικό παράδειγμα αποτελεί τον σκάκι που βρίσκεται στην ιστοσελίδα http://silverlight.net/samples/1.1/chess/run/default.html, το οποίο εκτελεί έναν απλό αλγόριθμο δενδρικής αναζήτησης υλοποιημένο σε javascript και σε SilverLight όπου φαίνεται ξεκάθαρα ότι ενώ η Javascript μπορεί να ελέγξει το πολύ μέχρι 1000 κόμβους το δευτερόλεπτο, ο κώδικα σε SilverLight μπορεί να ελέγξει περίπου 1,5 εκατομμύρια κόμβους.

Παράλληλα με την παρουσίαση για τους προγραμματιστές, ο Pete LePage έκανε μια παρουσίαση για τους σχεδιαστές εφαρμογών με τίτλο «Search Engine Optimization with Rich Media». Στην συγκεκριμένη παρουσίαση προσπάθησε να εξηγήσει πως γίνεται να μορφοποιηθεί κατάλληλα το περιεχόμενο των ιστοσελίδων ώστε να είναι εύκολα προσβάσιμο από τις μηχανές αναζήτησης. Οι μηχανές αναζήτησης αποτελούν το βασικό εργαλείο ανεύρεσης πληροφοριών από το διαδίκτυο και η υλοποίηση «φιλικών» ως προς τις μηχανές αναζήτησης ιστοσελίδων αποτελεί τον μοναδικό τρόπο να μοιραστείς πληροφορίες με τους υπόλοιπους χρήστες του internet. Προς αυτή την κατεύθυνση παρουσιάστηκαν ορισμένες βασικές αρχές που πρέπει να ακολουθούνται κατά την υλοποίηση δικτυακών εφαρμογών όπως:

  1. η χρήση Url Rewriters,

  2. η χρήση το πολύ 2 παραμέτρων στο query,

  3. η αποφυγή των postbacks στα links,

  4. η απενεργοποίηση του viewstate για να είναι όσο το δυνατόν πιο κοντά στο αρχικό html tag το περιεχόμενο της σελίδας,

  5. η επιλογή σωστών και περιγραφικών τίτλων για τις σελίδες,

  6. η χρήση meta tag για την περιγραφή του περιεχόμενου και τέλος

  7. η αποφυγή σελίδων λάθους 404.

Η παρουσίαση ασχολήθηκε επίσης με το πως μπορεί να γίνει αναγνώσιμη μια σελίδα με Rich Media content από τις μηχανές αναζήτησης οι οποίες δεν μπορούν να κατανοήσουν τέτοιο περιεχόμενο. Τέλος έγινε αναφορά στο νέο κίνημα των Semantic HTML το οποίο επιβάλει την μορφοποίηση του περιεχομένου μιας σελίδας με βάση της σημασιολογία του και όχι την τοποθέτηση του ή την εικαστική του μέσα στην σελίδα. Βασικές αρχές όπως το consistent linking και οι χρήση των κατάλληλων H# tags αναφέρθηκαν και επεξηγήθηκε ο τρόπος και η συχνότητα χρήσης τους.

Στην συνέχεια, ενώ ήταν προγραμματισμένη μια δεύτερη παρουσίαση για τους designers με τίτλο «The Desktop and Browser Evolution», λόγω ασθένειας της ομιλήτριας Carrie Longson δεν έγινε με αποτέλεσμα να παρακολουθήσουμε το δεύτερο μέρος της παρουσίασης του Scott Guthrie για το SilverLight.

Η τρίτη παρουσίαση που αφορούσε τους σχεδιαστές έγινε από την Molly Holzschlang με τίτλο «Thinking in CSS: How to build great looking sites». Σε αυτή την παρουσίαση, η Molly έκανε εισαγωγή στα Cascading Style Sheets εξηγώντας τα πλεονεκτήματα που αποκομίζουν οι σχεδιαστές από την χρήση τους. Ειδικότερα, ανέφερε ότι πέρα από την εύκολη συντήρηση και ανανέωση που κερδίζουμε χρησιμοποιώντας css, οι σελίδες είναι πιο «φιλικές» προς τις μηχανές αναζήτησης. Εδώ πρέπει να αναφερθεί ότι η Molly παρουσίασε και μια βιβλιοθήκη με Javascripts υλοποιημένη από τον Dean Edwards η οποία ονομάζεται ie7 scripts και με την βοήθεια της οποίας ο internet explorer 6 συμπεριφέρεται όπως ο internet explorer 7 όσον αφορά τα style sheets. Η βιβλιοθήκη διατίθεται δωρεάν στην σελίδα http://dean.edwards.name/ie7/.

Παράλληλα, στην αίθουσα για τους προγραμματιστές ο Steve Marx παρουσίαζε τα Gadgets στην παρουσίαση του με τίτλο «Developing Gadgets for Windows Live, Vista Sidebar and your own Site». Η σημαντική πληροφορία που απέσπασαν οι προγραμματιστές είναι ότι τα Gadgets αποτελούν απλές html σελίδες με αποτέλεσμα οποιαδήποτε εφαρμογή σε html ή και SilverLight μπορεί να γίνει Gadget απλά και μόνο συμπιέζοντας την σε ένα zip το οποίο μετονομάζεται για να έχει κατάληξη .gg και προσθέτοντας ένα μανιφέστο μέσα στο zip.

Η πρώτη μέρα έκλεισε με την παρουσίαση με τίτλο «Designing Stunning Sites with Silverlight» του Beau Ambur για τους designers στην οποία υλοποιήθηκε μια εφαρμογή σε SilverLight με χρήση του νέου εργαλείου Expression Suite. Η συγκεκριμένη εφαρμογή έδειχνε μια πανοραμική φωτογραφία στην οποία μπορούσε να προηγηθεί ο χρήστης. Στους developers, o Steve Marx συνέχισε με την παρουσίαση «Build Your Own Video Site» στην οποία παρουσίασε το νέο streaming media add-on για τον IIS7 και υλοποίησε μια πλήρως διαδραστική σελίδα με SilverLight χρησιμοποιώντας streaming video.

Την δεύτερη μέρα ξεκίνησε με μια κοινή για τους σχεδιαστές και τους προγραμματιστές παρουσίαση με τίτλο «WPF and Silverlight: Creating designs that will Captivate not Intimidate users» από τον Paul Dawson. Σε αυτή την παρουσίαση προβλήθηκαν πρότυπα για το πως πρέπει να είναι οι εφαρμογές (είτε αν είναι φτιαγμένες σε WPF, ή σε SilverLight ή ακόμα και σε flash) ώστε να μην τρομάζουν τον χρήστη με τις πολλές δυνατότητες που έχουν. Παράλληλα, έθιξε το τρόπο με τον οποίο θα πρέπει να συνεργάζονται οι σχεδιαστές με τους προγραμματιστές ώστε να υλοποιούνται εφαρμογές που είναι εφικτές από άποψη τεχνολογίας και παράλληλα να είναι ελκυστικές στους καταναλωτές.

Στην συνέχεια, οι designers είχαν την ευκαιρία να παρακολουθήσουν τον Wayne Smith στην παρουσίαση του «Designing Rich Client Experiences with Expression Blend and WPF» κατά την οποία ξεδίπλωσε πολλές πτυχές του νέου εργαλείου Expression Blend. Ειδικότερα, σε αυτή την παρουσίαση δημιούργησε μια εφαρμογή στο Windows Presentation Foundation χρησιμοποιώντας μόνο το Expression Blend και χωρίς να γράψει γραμμή κώδικα. Την ίδια ώρα, ο Pete LePage έδινε την διάλεξη με τίτλο «Using Visual Studio "Orcas" to design and develop rich AJAX enabled Web sites» για τους προγραμματιστές. Η παρουσίαση εστίασε στα καινούργια features που θα έχει το νέο Visual Studio με κυριότερο από όλα τα AJAX intellisense και την γενικότερη εγγενή υποστήριξη του AJAX και τα νέα controls που ενσωματώθηκαν στο .net 3.5.

Ο Wayne συνέχισε στο designer session με την παρουσίαση «Design in Motion: Video Production Workflow» όπου παρουσίασε τον Expression Media Encoder και πως μπορούν να συμπιεστούν video και να ενσωματωθούν με δυναμικό περιεχόμενο. Από την άλλη, οι developer θαύμασαν τον Steve Marx ο οποίος με την παρουσίαση του με τίτλο «Exploring Ajax Patterns» είχε την ευκαιρία να επιδείξει την ταχύτητα και ακρίβεια που έχει στο να γράφει κώδικα. Σε αυτή την παρουσίαση σχολίασε διάφορες λεπτομέρειες που μπορεί να έχουν ξεφύγει στους περισσότερους προγραμματιστές που χρησιμοποιούν AJAX όπως την αποδοτική χρήση των triggers και την χρήση web services για την αποφυγή των συνεχών postbacks. Τέλος, έκλεισε την παρουσίαση του υλοποιώντας μια AJAX εφαρμογή η οποία συγχρόνιζε streaming video με δυναμικό περιεχόμενο.

Η μέρα τέλειωσε για τους developers με την δίωρη παρουσίαση των George Moore & Koji Kato με τίτλο «Using Windows Live Services in Your Own Web Application» στην οποία παρουσιάστηκαν τα Live Services που προσφέρει η Microsoft για να τα ενσωματώσουν οι developers στις ιστοσελίδες τους (όπως το Maps, Messenger και το Hotmail) και η τιμολογιακή πολιτική τους. Αντιθέτως, οι σχεδιαστές είχαν την ευκαιρία να παρακολουθήσουν την δεύτερη παρουσίαση της Molly Holzschlag με τίτλο «Web Standards and IE7» στην οποία παρουσιάστηκαν τα «κρυφά» (για τους περισσότερους) features που προσφέρουν τα CSS και τα επερχόμενα features που θα προσφέρουν οι καινούργιες εκδόσεις. Την μέρα για τους σχεδιαστές, έκλεισε ο Paul Dawson με την παρουσίαση του με τίτλο «Killer Digital Reading Experiences» στην οποία παρουσίασε την εφαρμογή που έχει αναπτύξει η εταιρία τους για την εφημερίδα Daily Mail και πως μπορούμε να επωφεληθούμε από τα νέα εργαλεία της ομάδας Advanced Reading Technologies της Microsoft με κυριότερο από όλα το Commercial Publishing SDK.

Οι παρουσιάσεις του συνεδρίου βρίσκονται στον δικτυακό τόπο http://www.microsoft.com/hun/ceeremix2007/agenda.aspx


Τεχνολογίες που παρουσιάστηκαν

SilverLight

Το SilverLight αποτελεί μια νέα πλατφόρμα ανάπτυξης εφαρμογών η οποία έχει πολλά κοινά με το .net framework. Στην πράξη αποτελεί μια ελαττωμένη έκδοση του .net framework το οποίο υποστηρίζει τις βασικές λειτουργίες που γνωρίζουν οι προγραμματιστές του .net. Το SilverLight αποτελεί ένα web browser plugin (αντίστοιχο με το Adobe flash plugin) το οποίο διαβάζει το xaml αρχείο που περιέχει την μορφή και διάφορες ενέργειες της φόρμας καθώς και ένα dll το οποίο περιέχει τον compiled κώδικα που έχει υλοποιήσει ο developer. Έχοντας αυτές τις πληροφορίες, ο browser μπορεί να εκτελέσει τον κώδικα. Το γεγονός ότι αποτελεί browser plugin έχει αναγκάσει τους βασικούς προγραμματιστές του framework να ελαττώσουν τις δυνατότητες του SilverLight για να κρατήσουν μικρό το εκτελέσιμο που πρέπει να εγκαταστήσουν όσοι θέλουν να επισκεφτούν ένα site φτιαγμένο με την τεχνολογία αυτή. Ένα από τα βασικά πλεονεκτήματα της χρήσης του SilverLight σε σχέση με άλλες browser scripting γλώσσες είναι η ταχύτητα εκτέλεσης η οποία φτάνει και 1000 φορές πιο γρήγορα σε σχέση με την Javascript.

Windows Presentation Foundation

To WPF αποτελεί ένα νέο τρόπο υλοποίησης windows εφαρμογών. Παρόλο που έχει ενσωματωθεί με το .net framework 3.0, ο σχεδιασμός φορμών ήταν αρκετά περιορισμένος με τα addons που κυκλοφόρησαν για το Visual Studio 2005. Μέσω του συνεδρίου και ειδικότερα με την παρουσίαση του Wayne Smith έγινε ξεκάθαρο ότι ο σχεδιασμός των xaml (τα αρχεία που περιέχουν την περιγραφή της φόρμας) γίνεται μέσα από το Expression Blend και μάλιστα από τους γραφίστες που ασχολούνται με την εφαρμογή.

Microsoft AJAX

Χρησιμοποιώντας Javascript οι δικτυακές εφαρμογές μπορούν να γίνουν πιο ελκυστικές και πολύ πιο ελαφριές καλώντας ασύγχρονα web services και αντικαθιστώντας τα κομμάτια της HTML που χρειάζεται να αλλάξουν. Το AJAX προσφέρει στους προγραμματιστές την δυνατότητα να αξιοποιήσουν αυτή την τεχνολογία εύκολα και χωρίς να ασχοληθούν με τα javascripts που απαιτούνται.

Stylesheets

Τα Cascading Stylesheets (για συντομία, CSS) εμφανίστηκαν για πρώτη φορά το 1996. Αποτελούν μια ειδική διάλεκτο της γλώσσας HTML και μας επιτρέπουν να ορίσουμε με μεγαλύτερη ακρίβεια τον τρόπο απεικόνισης των σελίδων μας από τον browser.

Χρήσιμοι σύνδεσμοι

Σελίδα του remix07
http://www.microsoft.com/hun/ceeremix2007/default.aspx


Blog του dimis που περιγράφει την ζωή που κάναμε εκεί
http://www.studentguru.gr/blogs/dimis/archive/2007/06/18/budapest-remix-07-travel-report.aspx

Sunday, June 17, 2007

SSMS and win32k.sys Blue Screen

I recently came across each user’s nightmare. The Blue Screen Of Death (aka BSOD). The BSOD occurred while I was trying to open a table in SQL Server Management Studio (aka SSMS) which was installed with my brand new SQL Server 2005.
The symptoms where not that clear because the blue screen would appear either when SSMS was trying to open the table and some other times SSMS would open the table (I was lucky enough to see the actual contents of the table) and while I was editing the cell values, the Blue screen would appear showing the following error:
*** STOP: 0x0000008E (0xc0000005,0xbf8E270C,0A8E11868,0x00000000)
*** win32k.sys - Address BF8E270C base at BF800000
The error was the same in each case. Searching around the net I found a few references to this BSOD but the following SQLServer feedback had actually a few workarounds:
No one suggested why this could be happening although there are some things in common:
  1. In each and every reference I found, this screen would appear in a laptop with intel dual core
  2. Most of these laptops had intellipoint 6.1 or later driver for their mice.
The suggested workarounds were:
  1. Turn off multiple CPU core's in BIOS: which would be an unacceptable option for me. Why buy a dual core if I am going to use it as a single core!!!
  2. Disabling hardware acceleration in the advanced display properties : I did actually try this but when no hardware acceleration is active, many programs wont run and everything gets a little bit slower
  3. Disabling or uninstalling IntelliPoint 6.1 Software (also listed in the following url http://connect.microsoft.com/SQLServer/feedback/Workaround.aspx?FeedbackID=262721) : This actually did the trick for me.
So after uninstalling the IntelliPoint 6.1 Software and installing the IntelliPoint 5.2 instead, the blue screens disappeared.

I hope some one might find this useful cause I was starting to believe that I will never again be able to edit the contents of my tables from SSMS...

Wednesday, June 13, 2007

Silverlight with Visual Studio .NET 2005 and vb.net

I just got back from Budapest's Remix 2007. It was an awesome conference where I got amazed by the new Silverlight 1.1 possibilities. Thus the first thing I did was to try build a simple ‘Hello world’ application using vb.net. First of all, although the guys in Microsoft have Silverlight support in visual studio Orcas, there is no integration (at least as far as I know) with vs 2k5. Looking around on the net, I found a tip given by Scott Louvau to Bryant Likes on how to create a silverlight c# application with vs2k5.
Well, in VS2005 you can create a class library which will build against the Silverlight runtime, but it's a little work.
  1. Create a Class Library/
  2. Remove all references from it.
  3. Right-click on the Project and pick Properties.
  4. On the Build tab, click Advanced and check 'Do not reference mscorlib.dll'
  5. Manually add references to mscorlib, agclr, System,System.Core, System.Silverlight, and System.Xml.Core from the Silverlight install folder (\Program Files\Microsoft Silverlight\)

At this point your build outputs should be Silverlight consumable binaries. It looks
like the equivalent command line call to csc.exe (the C# compiler) should include the references to the mentioned binaries and the /nostdlib option but may require others as well.

The above mentioned solution could not be implemented on a VB project because there was no way I could tell the vb compiler to not reference mscorlib.dll as the compiler requires the Microsoft.VisualBasic.dll which refers to system.dll and finally we get a reference to mscorlib.dll. Thus I had to find a workaround for this…

The idea was to trick visual studio and use the silverlight framework instead of the normal .net 2.0. So I created a class library project based on the .NET Compact Framework 2.0 for Windows CE 5.0. Thus I got the compiler looking for the framework in the following path: "C:\Program Files\Microsoft Visual Studio 8\SmartDevices\SDK\CompactFramework\2.0\v2.0\WindowsCE\"


Since I am not currently developing any windows CE application I simply replaced the contents of that path with the ones from the silverlight framework (located at "C:\Program Files\Microsoft Silverlight\").

So, we have tricked the compiler to not use the regular .net framework. From now on the things are quite straight forward.

  1. Create a Class Library.

  2. Remove all references from it.

  3. Manually add references to mscorlib, agclr, System, System.Core, System.Silverlight, and System.Xml.Core from the Silverlight install folder (\Program Files\Microsoft Silverlight\)


Done. Create your xaml, html and js files and you are ready to experience the silverlight experience through visual studio 2005 and vb.net :)


Bryant Likes offers a c# example of the Hello world application on his blog http://blogs.sqlxml.org/bryantlikes/archive/2007/05/02/silverlight-hello-world-in-c-from-vs-2005.aspx .

Thus I converted the above example in to the following vb.net hello world example:


http://users.ntua.gr/abot/VbSilverLightVS8.zip