Welcome

This is Agilior aggregated blog. If you scroll down, you can see the full list of bloggers on the "bloggers" section.

Powered By:

Syndication

Blog Stats

Bloggers (posts, last update)

Latest Posts

How about an extension method?

imageSince the release of this nice feature for the .NET Framework, many of us are using extension methods to simplify our code. And according to the DRY principle it’s best to not re-invent the wheel. So, you can search for already “invented” extension methods in the site http://www.extensionmethod.net/

 

ExtensionMethod.NET is a database of C# 3.0 and Visual Basic 2008 extension methods. It contains many user-rated extension methods that will expand your code library immediately.

Extension methods add functionality to existing classes and allow you to expand the .NET framework. This way your favorite functions integrate seamlessly into the framework. For more information about extension methods visit the C# 3.0 and Visual Basic 2008 MSDN Library pages.

posted @ 10/14/2010 7:25 AM by Rodrigo Guerreiro

The Quine problem

Some time ago, Bruno presented to me and Manso the Quine problem (in the context that it’s a problem used in job interviews). In simple words it’s a program that outputs its own source code without using any IO (of course it uses the standard output for the obvious reasons).

I accepted the challenge and developed my very own implementation in C#.

using System;

namespace Quine
{
class Program
{
static void Main()
{
var s = @"using System;

namespace Quine
{1}
class Program
{1}
static void Main()
{1}
var s = @"
"{0}"";
Console.Write(s, s, (char)123, (char)125);
Console.ReadKey();
{2}
{2}
{2}"
;
Console.Write(s, s, (char)123, (char)125);
Console.ReadKey();
}
}
}

Now I challenge you guys.

Until next time ;)

 

P.S.: wow…two posts in the same day :)

posted @ 10/14/2010 7:09 AM by Rodrigo Guerreiro

Source control Appliances

In my last post I wrote about how to install and configure Subversion and WebSvn on Ubuntu server. During the search on how to do that I tested two very good appliances. This two appliances are virtual machines that contains the installation of several source control and comes configured out of the box :). All I need is download the appliance and start using. There is no excuse to don’t have a private source control :).

 

The first appliance is Revision Source Control from TurnKey and it’s an appliance that includes:

  • Revision Control systems supported: Git, Bazaar, Mercurial, Subversion.
  • SSL support out of the box.
  • Webmin module for configuring Apache2.
  • Includes TurnKey web control panel (convenience).

Again everything it’s installed and configured and ready to use. Just download the appliance and run it on Vmware or Virtualbox.

 

The next appliance, Trac, it’s also from TurnKey and Integrates source control & project management. The appliance includes:

  • Revision Control systems supported: Git, Bazaar, Mercurial, Subversion.
  • SSL support out of the box.
  • Postfix MTA (bound to localhost) to allow sending of email (e.g., password recovery).
  • Webmin modules for configuring Apache2 and Postfix.
  • Trac

These are just two appliances from TurnKey to make a developer life much easy :) again no excuse :P

 

I invite every one to see TurnKey site they have LOTS of appliances…

posted @ 2/9/2010 5:46 PM by Pedro Rainho

Install Subversion and WebSvn on Ubuntu Server

On my last post I wrote about Ubuntu server and Webmin and why I changed WHS with Ubuntu server. Today I'm going to write about Subversion and WebSVN on Ubuntu server. One of the things that I had in WHS was a source control where I stored my code and documents. For that I used VisualSVN. VisualSVN combines Subversion with a web interface of all repositories and also includes user management. To me VisualSVN is the all in one...Veryyy goood product and unfortunately for me VisualSVN is just for Windows :(.

So one of the things I did before move to Ubuntu Server was backup my Subversion repositories so I could restore them on Ubuntu Server.

In Ubuntu Server I had to do install a few packages and do a few steps in order to once again have source control and a web interface. So today I'm going to explain how to install Subversion and WebSVN on Ubuntu server.

The first thing to do is install Subversion and apache package for Subversion. All I need to do is:

sudo aptitude install subversion libapache2-svn

In the next step I need to create a directory where my repositories will be stored. In my case /var/sourcecontrol/svn/. The default location is /var/lib/svn/.

This command will create de directory where all my repositories will be:

sudo mkdir /var/sourcecontrol/svn

After create the directory I copied my entire repository backup from windows into this directory.

Note if I need to create new repositories I just had to do:

sudo svnadmin create /var/sourcecontrol/svn/newRepository

newRepository is the name of the new repository.

Next I need to change the owner of the files in order to access using apache. This can be done with this command:

sudo chown www-data:www-data  /var/sourcecontrol/svn/repositoryName -R

repositoryName is the name of the repository.

Next I just need to configure all my repositories to be access in apache. This can be done by editing the file /etc/apache2/mods-available/dav_svn.conf

To edit I just run the command:

sudo nano /etc/apache2/mods-available/dav_svn.conf

Scroll all the way down and add the following code for each repository:

<Location /repositoryName>   
DAV svn
SVNPath /var/sourcecontrol/svn/repositoryName
AuthType Basic
AuthName "Subversion repository repositoryName"
</Location>

Next restart the apache :

sudo /etc/init.d/apache2 restart

Open a browser and type http://[serverip]/repositoryName and the repository is now availably in browser.

Notice the /repositoryName in the location is the same as /repositoryName in the url.

After this step you can start doing some checkin's :P

The next step is to install WebSVN. WebSVN is a very good web interface to see all repositories.

The first thing to do is install the package. This can be done with the command:

sudo aptitude install websvn

To have syntax highlight in the source code just install enscript . This can be done with this command:

sudo aptitude install enscript

Now a few things you should know:

During the install of WebSVN three screens will appear:
1 - Select the webserver for configuration.
2 - Specify the path of the subversion repositories, in this case (/var/sourcecontrol/svn).
3 - If all repositories are in the same parent folder leave this in blank otherwise you will have to specify all repositories separated by comma.

The package WebSVN is installed into /usr/share/websvn/, it's necessary to copy to /var/www/. This can be done with the command:

sudo cp -r /usr/share/websvn/ /var/www/

After copy to /var/www it's necessary to edit the file /etc/apache2/mods-available/dav_svn.conf, again with the command:

sudo nano /etc/apache2/mods-available/dav_svn.conf

Next, scroll down and add the following

<Location /websvn/>
Options FollowSymLinks
order allow,deny
allow from all
AuthType Basic
AuthName "Subversion Repository"   
</Location>

Save the file and restart apache by doing:

sudo /etc/init.d/apache2 restart

Now just type http://[serverip]/websvn and you will see the WebSVN page and your repositories.

If for some reason your repositories have strange names in just edit the file /etc/websvn/svn_deb_conf.inc with the command :

sudo nano /etc/websvn/svn_deb_conf.inc

In this file you will have something like this:

<?php
// please edit /etc/websvn/config.php
// or use dpkg-reconfigure websvn
$config->parentPath("/var/sourcecontrol/svn/");
$config->addRepository("repositoryName\", file:///var/sourcecontrol/svn/repositoryName1);
$config->addRepository("repositoryName", "file:///var/sourcecontrol/svn/repositoryName2");
$config->setEnscriptPath("/usr/bin");
$config->setSedPath("/bin");
$config->useEnscript();
?>

Here it's possible specify the parent path of all repositories and specify each repository name and location. it's here also that it's specified the path on enscript installed before.

 

Hope you enjoy the source control and as much as I do :)

 

Special Thanks for Guerrix and his post on how to install subversion and websvn.

posted @ 2/6/2010 7:07 PM by Pedro Rainho

From WHS to Ubuntu Server

A few months ago I bought a license of Windows Home Server to the home server pc I built (see this post). My first encounter with WHS was terrible I did a stupid mistake and I almost delete every single file I had.

The second encounter was much better and every thing was running fine until I noticed here at home and confirmed in the web that WHS is not green and everything was always running at full speed, even when I’m not using it.

So I start looking for alternatives and I saw a project called Amahi that basically It’s a Linux home server with steroids (lots of options and software) and runs on top of Fedora.

I decided not to continue with Amahi, for a few reasons, and started looking for a simple OS that allows me to share files and alternatively have a source control, some databases and then I tested two. One was FreeNas and the other was Ubuntu Server. Since I’m a Ubuntu fan I decided to give a try and create a VM with Ubuntu server + SSH + Apache + MySql + Php (LAMP). Note FreeNas is also very good and it has a impressive web UI.

My first impression wasn’t good because the UI of Ubuntu Server It’s just command line. Alternatively I could install gnome by running this command line: sudo apt-get install ubuntu-desktop

But since I want something simple I decided to continue with the command line but needed something visual that could help me configure the home server. I search around and found Webmin.

Webmin has a demo and lots of screenshots here and Webmin it’s spectacular, a very good web user interface that allows me to configures almost the entire home server and that was just what I needed.

Install Webmin is very simple I just need to run this:

  • On my computer I opened a command line and run the command ssh [serverIP] and login.
    • By doing this I’m now able to run commands on the server. Then I just did
  • sudo apt-get install perl libnet-ssleay-perl openssl libauthen-pam-perl libpam-runtime libio-pty-perl libmd5-perl
    • To install a few dependecies and the this
  • wget http://www.webmin.com/download/deb/webmin-current.deb
    • To download the Webmin, and then since the latest version is 1.500 I just need to run this command
  • sudo dpkg -i webmin_1.500_all.deb

Now I that I have Webmin Installed I just need to open a browser to the URL https://[serverIP]:10000 and I have a UI that allows me to configure my server.

After given a test in a VM I decided definitely to switch from WHS to Ubuntu server with SSH and LAMP and I don’t regret my decision.

Next post will be about install and configure Subversion and WebSvn on Ubuntu Server… And yes my home server also have a source control.

posted @ 1/27/2010 5:09 PM by Pedro Rainho

New year new post

It’s been a long time since my last post… my apologies.

The first post of this new year will be about Ubuntu. It’s been 9 months since I stop using Windows at home and at work and start using Ubuntu as my primary OS (only use Windows in a virtual machine). The reason for the switch was because Ubuntu offers me everything I need, FOR FREE. I only use Windows for developing.

I shift because since Windows XP hadn’t saw any good reason to shift to any other version of Windows.  Why? Because I don’t need and OS that eats all my memory doing stupid things like shiny colors, stupid effects, etc, etc, etc. You can say you can turn that stupid things off… Yes but that doesn’t solve the problem it just minimize it.

At home and at work almost every thing is running linux. Even the home server I switched for a windows home server to a Ubuntu server. The only thing It’s no using linux, yet, it’s the phone.

 

So for this new year I will do some posts about .Net and about Ubuntu and you should also expect some news about a project I’m working on at home.

posted @ 1/24/2010 11:34 AM by Pedro Rainho

My monitor configuration at Home

Today I’ve decided to share with you my monitor configuration at home. I’ve a desktop with two 22’’ monitors and my work laptop with another 22’’. I’m using the same keyboard and mouse to control everything using a freeware program called Synergy. For the second toolbar I’m using also a freeware program called MultiMonitor Taskbar isn't better than Ultramon, but it’s free!

Monitor_Configuration

With this configuration I can have a single monitor for Tweetdeck and another for Outlook, the combinations are huge. My favorite combination is when I play WoW with full screen in my desktop and browsing WoWHead in my laptop without exiting the game or minimize.

It’s time to power off the computers and start reading a new book, see you later!

Reblog this post [with Zemanta] 

posted @ 9/7/2009 7:52 PM by João Manso

Virtualbox as a service on Windows

Did you ever imagine how to run VirtualBox as a windows Service. Check this post on VirtualBox forum and you will have the solution.

Thanks João Manso

posted @ 7/16/2009 7:43 AM by Pedro Rainho

BSOD on windows guest with VirtualBox

Today I came across a blue screen in VirtualBox 3.0.2 in host Ubuntu and guest windows xp. The problem was related with a file intelppm.sys. The solution was simple:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Intelppm

And changing the 'Start' value to '4'.

 

Check this post here and you will get more info. The post talks about Virtual PC but the solution is the same for VirtualBox

posted @ 7/14/2009 8:24 PM by Pedro Rainho

Disable beep on ubuntu shutdown

If you use ubuntu you probably had listen the stupid beep upon reboot/shutdown. To disable this stupid beep just do this:

sudo gedit /etc/modprobe.d/blacklist.conf

And add this

blacklist pcspkr

At the end of the file.

Teboot and no more stupid beep.

This was tested with Ubuntu 9.04 Jaunty

posted @ 7/14/2009 4:59 PM by Pedro Rainho

VirtualBox Clone VDI

Long time I'm a user of VirtualBox, why??? it's much more faster that virtualpc and much more faster that vmware player.

So if any one want to clone a vm just has to do:

VBoxManager clonehd "source.vdi" "destination.vdi"

this command is valid either in windows or linux.

posted @ 7/14/2009 4:53 PM by Pedro Rainho

Office 2010 promo movie

posted @ 7/11/2009 8:51 PM by Pedro Rainho

Build home server from scratch

During last month I had build a home server from scratch, of course I could buy one already build. But after careful exam of most home server sold out there, I notice that:

  • Lack of ram, most of then only have 512mb or the best is 1gb. If i want for instance have a VM running on, that might be a problem
  • All home server I’ve saw, most uses the intel atom CPU with just one core.
  • Power consuming
  • Expansion. I want a home server that I can add disks, if I want, let me just say that my option is not the best but I have 2 sata and 1 ide. So to me it’s enough.
  • Silence, I want a home server silent. My choices were not very good at the beginning but now it’s silent enough.
  • Network card, I wanted to be a gigabit Ethernet card.
  • Price. I didn’t want to spent too much money.

So what were my choices:

First, the case. I choose the the Apex mi-008

 

It’s a small case, and silent. You can check the review here.

Second, the board. For the board I had choose the Intel D945GCLF2D, it’s a mini-itx board very small, but it had a Intel dual core Atom CPU, each core has hyper-thread. It has 2 sata, 1 ide, 8 usb, vga, 1 gigabit Ethernet connection. More info check here.

This board has a big big problem… do you see that small cooler on the board. That is definitely the loudest GPU cooler I’ve ever saw. Believe me when I say it’s loud.

Third , the ram, I have a 2gb ram ddr2.

Finally the disk is a WDC 640gb.

Put all of this together and you have a home server.

Now you can choose either install some linux distribution like freenas, or Windows home server, or something else. I decided to buy a license of home server.

All of these have some pros and cons.

So the pros are:

  • It’s a fast home server. Faster than most home servers sold out there with a fraction of the price. By the way I’ve only spent 230€ here in Portugal for the hardware, plus a license of WHS bought on Amazon.
  • I have dual core CPU with 2 gb of ram.
  • The CPU is fan less, so it’s silent

Cons:

  • Definitely the worst thing in this home server is the GPU cooler

So, after every thing is built I start making changes.

  1. I’ve turned of the GPU cooler, this is not a very smart idea but after I measure temperatures, in speedfan, with fan and without fan, differences were not very different.
  2. Since I’ve turned off the cooler I bought a 120mm very silent fun from Noctua and installed on the side. This way I’m able to cool CPU and a GPU.
  3. Very soon I will buy a silent GPU cooler to replace that “thing”

So my current values of temperatures, on idle, are:

Ambient 37ºC
Remote 1 49ºC
Remote 2 47ºC
HD0 38ºC
Core 1 8ºC
Core 2 16ºC
Core 3 8ºC
Core 4 16ºC

 

My opinion, is that, if you have time a patience you can build a better server that those sold out there…

posted @ 6/27/2009 11:47 AM by Pedro Rainho

From Windows to Ubuntu

A few months ago I was using my home pc, with vista ultimate, and since the beginning I had problems like:

  • Network card should be connected at 1gbit/s and some times was connected at 100mbit/s why, I really don’t know.
    • Solution sometimes I had to restart others I had to disable and enable my network card. Never found the problem and had always the latest drivers.
  • One other problem that I had ever since the beginning was with my creative 5.1 speakers, the sound was not stable. Sometimes the sound goes up and sometimes went down, why??? I don’t know. A friend had exactly the same problem solution…. buy new speakers… stupid when I told him the problem was not with speaker was with vista :P
  • One other problem that I had was copy files from usb disk to my pc… speed 15mb/s – 20mb/s note that the speed of usb 2 is 400mbits/s. Even on my notebook with xp I got better speeds.
  • Copy over lan using 1gbit/s values are between 10mb/s to 15mb/s, impressive hummm
  • copy over ftp speed between 10mb/s to 20mb/s

And there was lots of other problems.

After I become very irritated about this… I had two choices downgrade to xp or use Ubuntu.

I start using Linux back in 98 with Redhat and I stop using it a few years ago… shame on me.

After doing some search about programs that I use in windows and similar programs in ubuntu, I did the switch and format, and install Ubuntu. And this was probably the BEST choice I had done recently why???

  • It’s much more faster that vista and Ubuntu has visual effects too.
  • took me just a few seconds to boot Ubuntu. Next release of ubuntu will be even faster on reboot.
  • Ubuntu only uses 350mb – 400mb of memory after reboot. Vista after reboot consumes me 1.5gb of memory.
  • Every single driver was detected no need to search for drivers and install drivers. The only driver I had to install was the ATI driver and took me one mouse click.
  • The problems I had with network card and speakers are vanished now you understand why I told my friend was stupid buy new speakers lol
  • Now copy usb to disk 35mb/s – 40mb/s more than double the speed
  • copy using ftp 75mb/s – 80mb/s with 1gbit/s network card. Three to four times faster that vista.

 

The most impressive is that I can do every thing with ubuntu, let’s see:

Windows Ubuntu
Explorer Nautilus
Windows update, just updates windows and MS programs Update manager, updates every single application in ubuntu
Notepad Gedit
Messenger Pidgin / Empathy
gtalk Pidgin / Empathy
Remote desktop Terminal server client
Windows media player Banshee, much better can every subscribe podcasts etc…, Movie player
Calculator Calculator like win 7
mspaint Gimp
MS office Openoffice
Outlook Evolution, much better
Filezilla Filezilla
VirtualBox VirtualBox
Nero Brasero
Firefox Firefox
Tcpview Net Activity viewer
deamon tools Gmount-iso
Acrobat reader Acrobat reader
AVG Avast
Windows Firewall Gufw
Tweetdeck Tweetdeck
.Net Mono
Silverlight Monolight
Flash Flash
Netbeans Netbeans
Ruby Ruby

 

And the list continues…

The only, and only program I miss Is Windows Live Writer the rest every thing you can imagine it’s at one click of distance.

I just had to click on “Add and Remove…” type the program you want to install and that’s it… no need to use browser, search for a app, and then download, and then install…

No in, ubuntu, just open “Add and Remove…” type, for instance Filezilla, check it for install and that’s it…

In Ubuntu I even can mount ntfs usb disk. And I can read and write… what do I need more :)

 

what you need more…

Now there is only one reason why I still have a Windows VM…. It’s because I’m a .Net developer and need I need Visual Studio and other tools… despite this in my home pc I just have Ubuntu.

 

How much it costs ubuntu… zero euro. Now everybody knows that vista ultimate is too expensive.

I’m even planning on migrate my work notebook into ubuntu and work with VM.

 

I definitely invite every one to do a test drive on Ubuntu just download VirtualBox and download Ubuntu and create a VM to test Ubuntu and I think every one will love it.

It’s fast…….

posted @ 6/25/2009 7:29 PM by Pedro Rainho

Tip

If you want to debug wsf files just add the //d switch before call the wsf and inside the code add "debugger" where you want to start debugging.

posted @ 6/16/2009 7:25 AM by Pedro Rainho

For whom is sleeping

Have you heard of Project Natal? If not then you’re definitely sleeping…

Fortunately I hereby provide you a real nice video that should hook you up :)

 

Until next time ;)

posted @ 6/5/2009 7:52 AM by Rodrigo Guerreiro

Visual Studio Export Templates and conditional inclusion of content

 

Visual Studio templates are a great way to give you an head start with code that has a lot of boilerplate code.

In fact you may already be using project templates withouth knowing. :-) When do option Open New Project in Visual Studio and select a project type (Windows Application, Console Application,etc) you are in fact selecting the project template that will be used to generate your project skeleton. This project skeleton not only includes some code/data files but it also includes the references to the .Net assemblies that your particular project type needs.

If you are curious of how out of the box project template looks like you can find them at:

  • VS 2005 - %ProgramFiles%\Microsoft Visual Studio 8\Common7\IDE\ProjectTemplates
  • VS 2008 - %ProgramFiles%\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates

Visual Studio not only provides you with a great number of project templates out of the box, but you can also write your own project templates

If you don’t want to spend time writing your project template you can find that a lot of people make them freely available on the net. For example Team System MVP Neno Loje created a project template that you can use to kickstart Team System Utilities.

You can create your own project by hand (which involves some labor) or you can create your project like you regularly do. Create all the boilerplate code, include all the references,all your content and then use that project as your project template by exporting it to a project template using the Export Template wizard (available in File->Export as Template)

I don’t want to get into much details of how you can create project templates. Either by hand or using the export option. There is plenty of information about that already.

You can read some fine information about it on these articles:

Not to get back to the real intent of this post. :-) Conditional inclusion of content.

Starting with VS 2008 your project templates can have content that is only included if a certain condition is met. This is a simple IF condition and all you can do is comparing the value of a parameter to a value.

for this you simple have to use on your template files $if$ (<expression>) <your content here> $endif$

For example if your project template allows framework multi targeting you can use this to include references to Framework 3.5

$if$ ($targetframeworkversion$ == 3.5)using System.Linq;
$endif$

You can check here the list of parameters that are available out of the box and but you can also reference parameters added in the CustomParameters element or parameters added by your wizard.

Now there is a catch. In order to use conditions, your template has to be a template of version 3.0.0 (the template version is defined in VSTemplate element of the .vstemplate file)

eg: <VSTemplate Version="3.0.0" Type="Project" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">

What is the catch then? If you use the export template to create your project template (even in VS 2008) the project template is exported as version 2.0.0 and you have to manually edit the .vstemplate file to use version 3.0.0 if you wish to use the $if$ functionality.

 

Post Scriptum: If you think project templates aren’t up to the level of customization you want, you can also use your own wizard in project template. And from that wizard use the VS API to do more complex things on the created project (or/and the solution that is going to hold it). And if that is not enough you can combine it with Software Factories to make it even more powerful.

posted @ 5/31/2009 9:37 AM by Tiago Pascoal

What are the skills and responsibilities of a web designer?

 

Recently I decided to deepen my knowledge about CSS, reading the book CSS Mastery. This decision was based on the need to create web sites with clean markup, focusing the work of structuring and the look & feel at CSS.

First, I must say that I really enjoyed reading the book. I always saw CSS as being part of the toolbox of a web designer. Let me clarify: I am far away of being a web designer, and to be honest, I was not cut off for the job. But a Web Designer is a must have if you want to succeed doing web sites or web applications.

Let's say that I want to hire a Web Designer to my team: what skills do I have to look for, which distinguish a good web designer? (Comments from web designers are welcome)

One thing I am sure: being just a Designer (not a Web Designer) is not enough for my team. For me, a Designer is someone who knows for example how to work with FreeHand MX, Photoshop, image processing, but has no idea what HTML is, or CSS is, or any other subject related to web. The site that is being produced can even be good looking, but I think the web designer must go further: he has to give me the web template, images, CSSs, etc. More, the Web Designer must understand subjects as Accessibility, or Cross-Browser, Usability, etc. I believe also that there are design types that can be awesome, but they are not for the web. Am I asking too much for a web designer? Don't get me wrong: I am really really out of my comfort zone, since I consider myself as a backend developer (which typically does not work too much with the end user). My question is totally honest!

Why I am posting about this subject? In the moment, my team is configured with a Designer (not a Web Designer), and it was not my decision. Who is trying to fill the gap about web design (html, css, etc,)? We, Web Developers. What is our feeling? That every decision we make (putting a div, a background image, transparencies, etc) is surrounded with the question: are we doing it right? Of course that at the end of the day the job it will be done, with more or less difficulty and errors.

In my opinion, Web Designers are really important to Web Projects and can make the difference about the success or failure of the project. In Web Projects, Web Designers are maybe not sufficient to success, but they are necessary to achieve it.

Again, comments and different visions about the subject are welcome.

 

BFC

posted @ 4/29/2009 5:43 PM by BFC

ASP.NET MVC – What is that?

Many people still think like this. Others think they know what MVC is, but are all wrong. Another type of developers still think that Web Forms is the way to go and MVC generates all bunch of crappy code.

To all of them I say this: Go Learn MVC Now!

…or go read Rob Conery’s post. He wrote a all lot better the reasons why you should learn MVC than I could ever write.

Until next time ;)

posted @ 4/24/2009 12:45 PM by Rodrigo Guerreiro

I’m jealous of the Norwegians

You’re probably wondering why I’m jealous of the Norwegians. As you know, I live in Portugal, that beautiful place bathed by the Atlantic ocean. And now you thinking: “He lost it completely. How could he be jealous of the Norwegians? They have snow and cold when he has sun and warm temperatures. He has lovely beaches when they have nice rocks.” Well, all of that is true. But I’m still jealous and the reason is this.

The Norwegians are so luck. They have the opportunity of watching speakers like Scott Hanselman, Phil Haack, Michael Feathers, Robert C. Martin (aka Uncle Bob), Roy Osherove, Juval Lowy, Ted Neward, Michele Leroux Bustamante, Ayende Rahien, Jeremy D. Miller, Ian Griffiths, Jimmy Nilsson, Scott Bellware and Glenn Block, just to name a few. And all of them are going to be there this year. All together. Oh…I’m so jealous!!!

At some point, in the NDC site, you can find the following:

“The idea behind Norwegian Developers Conference is that it should be able to measure up against any conference in the world. All the speakers are experienced and right at the top of their respective trees.”

I don’t remember in Portugal having this quality in our developer conferences. Until when I have to wait to someone come up with a conference with this quality in Portugal? Until when I have to wait to watch Scott Hanselman or Jeremy D. Miller without having to exit my country?

In Portugal, I estimate that exists, more or less, 10.000 developers. There’s enough audience to support a conference of this quality. I hope that this post enlights someone (aka business-person) to start a similar developer conference able to rival with the best in the world.

Until next time ;)

posted @ 4/24/2009 8:01 AM by Rodrigo Guerreiro

Where the developer meets the social

Today, I’ve watched the presentation that Scott Hanselman gave in Devscovery last monday. (if you also want to watch it, check Scott’s post)

His keynote got me thinking, whereas the reason for this post. I’m just going to write about my own experiences and I assume that who reads this later may or may not agree with me.

I’m not social. Period!

You may think that as developers our work needs a very small percentage of social interaction. Basically, meetings. Well, but if we want to succeed as developers and climb the ladder in software engineering you’ll need social interaction. I’m really up for information/knowledge sharing. We, the geeks, know the tools that better help us doing that sort of thing.

 

Where am I

  • Blog: This blog has the purpose to share my ideas with others (and getting their reaction, which until now result in just one person) but mainly I’m using it in order to google myself later :) and you can find great developer/blogger out there that have valuable information. I do think that reading blogs is far more important than writing one. There are already great information on how build apps using best practices, a specific technology, how to test our code and so on.
  • Linkedin: In the past it was usual to exchange business cards. I remember my father having an agenda with all his connection’s business cards. But now, I use Linkedin simply because the people on my network is constantly updating their profile and anyone who wants can check what I’m doing or what I’ve done. Since I created my profile I was contacted more often, for job interviews.
  • Twitter: Where you’ll find me more often. I really like the way I’m getting information from the people I follow. The Twitter usage is suppose for you to write what you’re doing. But I’m using it mostly to share articles and posts that I find interesting. And that engaged some very interesting discussions.
  • Stackoverflow: I blame myself for forget to mention that lately you can also find me at Stack Overflow. It’s an incredibly web app that allows a community information exchange. The site is like QA with wiki. Very cool. Way better than this one. [UPDATE]

 

It’s all about sharing information

I think that is also important some sort of gathering where we all discuss and exchange ideas in software engineering. See one of my latest posts:

…put people talking and sharing experiences with each other.

The bottom line is: developer meeting the social == exchanging information

Until next time ;)

posted @ 4/22/2009 2:28 PM by Rodrigo Guerreiro

WCF and net.pipe exception

Today I came across an odd problem related with WCF and net.pipe binding.

If I expose one pipe on address “net.pipe://aaa/service/endpoint” and another on address “net.pipe://bbb/service/endpoint” I got this exception

“Cannot listen on pipe name net.pipe://bbb/service/endpoint because another pipe endpoint is already listening on that name. “

 

I found this very strange.

 

The logical explanation I have is this:

- net.pipe:// represents the transport protocol.

- aaa or bbb represents the machine or domain. Since net pipes are local I think aaa and bbb are ignored.

- service/endpoint represents the absolute path where the service is exposed.

 

So the solution to solve this problem was this:

net.pipe://pipe/aaa/service/endpoint

net.pipe://pipe/bbb/service/endpoint

 

Now the absolute path /aaa/service/endpoint and /bbb/service/endpoint are different and no exception is generated

posted @ 4/22/2009 1:59 PM by Pedro Rainho

How to create a Tool Window in Visual Studio

After you create an Add-in you need to create a User Control

image_thumb[30]

 

Then I will have to change the Connect.cs file

The first thing you need to do is declare 2 fields one for the window it self and other for the user control

private Window _toolWindow;
private MyAddInToolWindow _toolWindowControl;

 

Next you will need to change the OnConnection method. This method receives notification that the Add-in is being loaded. This method when it’s generated adds the necessary code to show a add-in icon in the Tools menu.

/// <summary>Implements the OnConnection method of the IDTExtensibility2 interface. Receives notification that the Add-in is being loaded.</summary>
/// <param term='application'>Root object of the host application.</param>
/// <param term='connectMode'>Describes how the Add-in is being loaded.</param>
/// <param term='addInInst'>Object representing this Add-in.</param>
/// <seealso class='IDTExtensibility2' />
public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
{
    _applicationObject = (DTE2)application;
    _addInInstance = (AddIn)addInInst;
    if(connectMode == ext_ConnectMode.ext_cm_UISetup)
    {
        ...
    }
}

 

Next I need to change this method to enable me to show my tool window. To do that I just need to do this:

 

/// <summary>Implements the OnConnection method of the IDTExtensibility2 interface. Receives notification that the Add-in is being loaded.</summary>
/// <param term='application'>Root object of the host application.</param>
/// <param term='connectMode'>Describes how the Add-in is being loaded.</param>
/// <param term='addInInst'>Object representing this Add-in.</param>
/// <seealso class='IDTExtensibility2' />
public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
{
    _applicationObject = (DTE2)application;
    _addInInstance = (AddIn)addInInst;
    if(connectMode == ext_ConnectMode.ext_cm_UISetup)
    {
        ...    
    }
    else if (connectMode == ext_ConnectMode.ext_cm_AfterStartup)
    {
        CreateToolWindow();
    }
}
 

If connect mode is After Startup, I will show the tool window.

To show the tool window I just need to call method  “CreateToolWindow2”. This method receives some parameters and one of the parameters is the “Namespace.Usercontrol”, in this case "MyAddin1.MyAddInToolWindow"

 

private void CreateToolWindow()
{
    if (_toolWindow == null || _toolWindow.Visible == false)
    {
        #region Load Tool Window
        object programmableObject = null;
        string guidString = "{73000449-0035-43ad-985F-A3071ECBC079}";
        Windows2 windows2 = (Windows2)_applicationObject.Windows;
        Assembly asm = Assembly.GetExecutingAssembly();
        _toolWindow = windows2.CreateToolWindow2(_addInInstance, asm.Location,
            "MyAddin1.MyAddInToolWindow",
            "MyAddin1", guidString, ref programmableObject);
        _toolWindow.Visible = true;
        _toolWindowControl = (MyAddInToolWindow)_toolWindow.Object;
        #endregion
    }
}
 

After the creation of the tool window don’t forget to do _toolWindow.Visible = true; other wise the tool window might now show :)

After this, just press run and test it.

 

image_thumb[37]

 

And you can also dock the tool window.

image_thumb[39]

 

Now, if you close the tool window and then open it again the tool window will not show. You will need to change the method Exec and add the CreateToolWindow().

 

/// <summary>Implements the Exec method of the IDTCommandTarget interface. This is called when the command is invoked.</summary>
/// <param term='commandName'>The name of the command to execute.</param>
/// <param term='executeOption'>Describes how the command should be run.</param>
/// <param term='varIn'>Parameters passed from the caller to the command handler.</param>
/// <param term='varOut'>Parameters passed from the command handler to the caller.</param>
/// <param term='handled'>Informs the caller if the command was handled or not.</param>
/// <seealso class='Exec' />
public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)
{
    handled = false;
    if(executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
    {
        if(commandName == "MyAddin1.Connect.MyAddin1")
        {
            handled = true;
            CreateToolWindow();
            return;
        }
    }
}

 

Now test it and you can close and the open the tool window and you will have no problems.

One other thing you can do Is show the icon in menu “View” instead of menu “Tools”, to do that just change the method OnConnection and where you have the string “Tools” just change it to “View” very simple :)

 

Here is where the icon will appear after this change.

 image_thumb[34]

 

This is a very fast tutorial, there are other in the web that explains everything, one other choice is check MSDN.

posted @ 4/21/2009 2:17 PM by Pedro Rainho

How to create an add-in in Visual Studio

Create Add-ins is very simple

Create a project.

image

 

Then select the project as a Visual Studio Add-in.

image

 

And then follow the Wizard.

image

 

Here you choose the language, I’m going to user C#.

image

 

Here you choose where the add-in will work.

image

 

Here you choose the add-in name and description.

image

 

Here you choose how the add-in will work.

image

 

Here you choose the information you want to show when you do Help/About in Visual Studio.

image

 

Here is the final summary.

image

 

And finally our add-in is created. Just press run and you will have a icon of the add-in in Visual Studio Tools menu.

image

 

As you can see it’s very simple to create an add-in, basically it’s just Next, next, next.

posted @ 4/21/2009 1:54 PM by Pedro Rainho

A kind of deep zoom made in flash

I know this is not like Silverlight deep zoom but I invite every one to check this link it named infinite photograph.

posted @ 4/20/2009 7:02 AM by Pedro Rainho

Twitter API II

Continue the effort to find a good library that will enable me, from my VSTwitter add-in, to query Twitter,  yesterday I create a sample console app to test most of the methods of Tweet#. I must say this is a very good library and also very simple plus it has a fluent interface.

So here is the sample I create to test this library:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Dimebrain.TweetSharp.Fluent;
using Dimebrain.TweetSharp;
using Dimebrain.TweetSharp.Extensions;
using Dimebrain.TweetSharp.Model;

namespace TweetSharpSample
{
    class Program
    {
        static StringBuilder sb = new StringBuilder();

        static void Main(string[] args)
        {
            TwitterClientInfo myClientInfo = new TwitterClientInfo();
            myClientInfo.ClientName="VsTwitter";
            myClientInfo.ClientUrl="http://www.agilior.pt/blogs/pedro.rainho";
            myClientInfo.ClientVersion="0.0.0.1";
            

            FluentTwitter.SetClientInfo(myClientInfo);
            var request = FluentTwitter.CreateRequest(myClientInfo).AuthenticateAs("user", "pass");
            //var request = FluentTwitter.CreateRequest();

            AddMessageToTwitter(request);


            PrintStatusUser(request);

            PrintStatusPublic(request);

            PrintStatusFriend(request);

            PrintFollowers(request);

            PrintFriends(request);

            PrintUserInfoUserStatus(request);

            AddRemoveMessageFromTwitter(request);

            PrintFavorites(request);

            PrintReceivedDirectMessages(request);


            SendDirectMessageToInvalidUser(request);
            SendDirectMessageToValidUser(request);

            PrintSendDirectMessage(request);

            BlockUnblockUser(request);



            AddFriendRemoveFriend(request);


            //UserProfile
            PrintUserProfile();
        }

        private static void PrintUserProfile()
        {
            var profile = FluentTwitter.CreateRequest().Users().ShowProfileFor("pedrorainho").AsJson().Request().AsUserProfile();
            string strJson = FluentTwitter.CreateRequest().Users().ShowProfileFor("pedrorainho").AsJson().Request();
            string strXml = FluentTwitter.CreateRequest().Users().ShowProfileFor("pedrorainho").AsXml().Request();

            WriteUser(profile, 0);
        }

        private static void AddFriendRemoveFriend(IFluentTwitter request)
        {
            TwitterUser friend = request.Friendships().Befriend("userXXX").AsJson().Request().AsUser();
            TwitterUser friendRemove = request.Friendships().Destroy("userXXX").AsJson().Request().AsUser();
            TwitterUser friendAdd = request.Friendships().Befriend("userXXX").AsJson().Request().AsUser();
            string result = request.Friendships().Verify("userXXX").AsJson().Request(); //Erro
        }

        private static void BlockUnblockUser(IFluentTwitter request)
        {
            request.Blocking().Block("userXXX").AsJson().Request().AsUser();
            request.Blocking().Unblock("userXXX").AsJson().Request().AsUser();
        }

        private static void PrintSendDirectMessage(IFluentTwitter request)
        {
            IEnumerable<TwitterDirectMessage> colSentDirectMessage = request.DirectMessages().Sent().AsJson().Request().AsDirectMessages();
            sb.AppendLine("SentDirectMessage:");
            foreach (TwitterDirectMessage message in colSentDirectMessage)
            {
                WriteDirectMessage(message, 0);
            }
        }

        private static void SendDirectMessageToValidUser(IFluentTwitter request)
        {
            TwitterDirectMessage sendDirectMessage = request.DirectMessages().Send("userXXX", "teste do Tweet#").AsJson().Request().AsDirectMessage();
        }

        private static void SendDirectMessageToInvalidUser(IFluentTwitter request)
        {
            TwitterError error = request.DirectMessages().Send("userXXX", "teste do Tweet#").AsJson().Request().AsError();
        }

        private static void PrintUserInfoUserStatus(IFluentTwitter request)
        {
            TwitterUser userManso = request.Users().ShowProfileFor("userXXX").AsJson().Request().AsUser();
            WriteUser(userManso, 0);
            WriteStatus(userManso.Status, 1);
        }

        private static void PrintReceivedDirectMessages(IFluentTwitter request)
        {
            IEnumerable<TwitterDirectMessage> colReceivedDirectMessage = request.DirectMessages().Received().AsJson().Request().AsDirectMessages();
            sb.AppendLine("ReceivedDirectMessage:");
            foreach (TwitterDirectMessage message in colReceivedDirectMessage)
            {
                WriteDirectMessage(message, 0);
            }
        }

        private static void PrintFavorites(IFluentTwitter request)
        {
            IEnumerable<TwitterStatus> colFavorites = request.Favorites().GetFavorites().AsJson().Request().AsStatuses();
            sb.AppendLine("Favorites:");
            foreach (TwitterStatus stat in colFavorites)
            {
                WriteStatus(stat, 0);
            }
        }

        private static void AddRemoveMessageFromTwitter(IFluentTwitter request)
        {
            TwitterStatus status = request.Statuses().Update("Testing Tweet#").AsJson().Request().AsStatus();

            TwitterStatus statres = request.Statuses().Destroy(status.Id).AsJson().Request().AsStatus();
        }

        private static void PrintFriends(IFluentTwitter request)
        {
            IEnumerable<TwitterUser> colFriends = request.Users().GetFriends().AsJson().Request().AsUsers();
            sb.AppendLine("Friends:");
            foreach (TwitterUser user in colFriends)
            {
                WriteUser(user, 0);
            }
        }

        private static void PrintFollowers(IFluentTwitter request)
        {
            IEnumerable<TwitterUser> colFollowers = request.Users().GetFollowers().AsJson().Request().AsUsers();
            sb.AppendLine("Followers:");
            foreach (TwitterUser user in colFollowers)
            {
                WriteUser(user, 0);
            }
        }

        private static void PrintStatusFriend(IFluentTwitter request)
        {
            IEnumerable<TwitterStatus> colStatusFriend = request.Statuses().OnFriendsTimeline().Request().AsStatuses();
            sb.AppendLine("Status Friend:");
            foreach (TwitterStatus stat in colStatusFriend)
            {
                WriteStatus(stat, 0);
            }
        }

        private static void PrintStatusPublic(IFluentTwitter request)
        {
            IEnumerable<TwitterStatus> colStatusPublic = request.Statuses().OnPublicTimeline().Request().AsStatuses();
            sb.AppendLine("Status Public:");
            foreach (TwitterStatus stat in colStatusPublic)
            {
                WriteStatus(stat, 0);
            }
        }

        private static void AddMessageToTwitter(IFluentTwitter request)
        {
            TwitterStatus status = request.Statuses().Update("Testing Tweet#").AsJson().Request().AsStatus();
        }

        private static void PrintStatusUser(IFluentTwitter request)
        {
            IEnumerable<TwitterStatus> colStatusUser = request.Statuses().OnUserTimeline().Request().AsStatuses();
            sb.AppendLine("Status User:");
            foreach (TwitterStatus stat in colStatusUser)
            {
                WriteStatus(stat, 0);
            }
        }

        public static void WriteDirectMessage(TwitterDirectMessage message, int numberTabs)
        {
            string tab = "".PadLeft(numberTabs * 2, ' ');
            sb.AppendLine(tab + "DirectMessage.CreatedDate: " + message.CreatedDate);
            sb.AppendLine(tab + "DirectMessage.Id: " + message.Id);
            if (message.Recipient != null)
            {
                WriteUser(message.Recipient, ++numberTabs);
            }

            sb.AppendLine(tab + "DirectMessage.RecipientId: " + message.RecipientId);
            sb.AppendLine(tab + "DirectMessage.RecipientScreenName: " + message.RecipientScreenName);

            if (message.Sender != null)
            {
                WriteUser(message.Sender, ++numberTabs);
            }

            sb.AppendLine(tab + "DirectMessage.SenderId: " + message.SenderId);
            sb.AppendLine(tab + "DirectMessage.SenderScreenName: " + message.SenderScreenName);
            sb.AppendLine(tab + "DirectMessage.Text: " + message.Text);
        }

        public static void WriteStatus(TwitterStatus stat, int numberTabs)
        {
            string tab = "".PadLeft(numberTabs * 2, ' ');
            sb.AppendLine(tab + "Status.CreatedDate:" + stat.CreatedDate);
            sb.AppendLine(tab + "Status.Id:" + stat.Id);
            if (!string.IsNullOrEmpty(stat.InReplyToScreenName))
            {
                sb.AppendLine(tab + "Status.InReplyToScreenName:" + stat.InReplyToScreenName);
            }
            sb.AppendLine(tab + "Status.InReplyToStatusId:" + stat.InReplyToStatusId);
            sb.AppendLine(tab + "Status.InReplyToUserId:" + stat.InReplyToUserId);
            sb.AppendLine(tab + "Status.IsFavorited:" + stat.IsFavorited);
            sb.AppendLine(tab + "Status.IsTruncated:" + stat.IsTruncated);
            sb.AppendLine(tab + "Status.Source:" + stat.Source);
            sb.AppendLine(tab + "Status.Text:" + stat.Text);

            if (stat.User != null)
            {
                WriteUser(stat.User, ++numberTabs);
            }
        }

        public static void WriteUser(TwitterUser user, int numberTabs)
        {
            string tab = "".PadLeft(numberTabs * 2, ' ');
            sb.AppendLine(tab + "User:");
            sb.AppendLine(tab + "User.CreatedDate:" + user.CreatedDate);
            sb.AppendLine(tab + "User.Description:" + user.Description);
            sb.AppendLine(tab + "User.FavouritesCount:" + user.FavouritesCount);
            sb.AppendLine(tab + "User.FollowersCount:" + user.FollowersCount);
            sb.AppendLine(tab + "User.FriendsCount:" + user.FriendsCount);
            if (user.HasNotifications != null)
            {
                sb.AppendLine(tab + "User.HasNotifications:" + user.HasNotifications.Value);
            }

            sb.AppendLine(tab + "User.Id:" + user.Id);

            if (user.IsFollowing!= null)
            {
                sb.AppendLine(tab + "User.IsFollowing:" + user.IsFollowing.Value);
            }

            sb.AppendLine(tab + "User.IsProfileBackgroundTiled:" + user.IsProfileBackgroundTiled);
            sb.AppendLine(tab + "User.IsProtected:" + user.IsProtected);
            sb.AppendLine(tab + "User.Location:" + user.Location);
            sb.AppendLine(tab + "User.Name:" + user.Name);
            sb.AppendLine(tab + "User.ProfileBackgroundColor:" + user.ProfileBackgroundColor);
            sb.AppendLine(tab + "User.ProfileBackgroundImageUrl:" + user.ProfileBackgroundImageUrl);
            sb.AppendLine(tab + "User.ProfileImageUrl:" + user.ProfileImageUrl);
            sb.AppendLine(tab + "User.ProfileLinkColor:" + user.ProfileLinkColor);
            sb.AppendLine(tab + "User.ProfileSidebarBorderColor:" + user.ProfileSidebarBorderColor);
            sb.AppendLine(tab + "User.ProfileSidebarFillColor:" + user.ProfileSidebarFillColor);
            sb.AppendLine(tab + "User.ProfileTextColor:" + user.ProfileTextColor);
            sb.AppendLine(tab + "User.ScreenName:" + user.ScreenName);
            //sb.AppendLine(tab + "User.Status:" + user.Status.);
            sb.AppendLine(tab + "User.StatusesCount:" + user.StatusesCount);
            sb.AppendLine(tab + "User.TimeZone:" + user.TimeZone);
            sb.AppendLine(tab + "User.Url:" + user.Url);
            sb.AppendLine(tab + "User.UtcOffset:" + user.UtcOffset);
        }
    }
}

Hope everybody enjoy :) I sure did :)

 

So, tomorrow I will start develop the add-in using this library.

Soon I will release more posts on how am 'I going to create the add-in.

posted @ 4/16/2009 7:36 PM by Pedro Rainho

Twitter API

Recently, I join Twitter after some pressure at home and at work :). But since I don’t like to publish my life there, I’m doing this, I’m doing that, bla bla bla, I decided to view Twitter in a different perspective. I decided to view the Twitter API. While I was watching the Twitter API I discovered that there are lot’s of libraries that try to do a wrapper around the Twitter API, including .Net libraries.

One of the libraries I had recently looked and done some testes was Twitterizer. Twitterizer has a very easy interface BUT doesn’t support every Twitter method plus, the last version present in the site has some problems that raises and exception. (To solve this problem I had to dig into the issues and discovered there a zip will the working libraries)

 

So Here is my sample application it’s intention was test almost every method.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Twitterizer.Framework;

namespace TwitterSample
{
    class Program
    {
        static void Main(string[] args)
        {
            if (Twitter.VerifyCredentials("twitter_user", "twitter_password"))
            {
                Twitter twitter = new Twitter("twitter_user", "twitter_password", "my_app");

                PrintReplies(twitter);
                PrintFollowers(twitter);
                PrintFriends(twitter);
                PrintDirectMessages(twitter);
                PrintFriendsTimeline(twitter);
                PrintPublicTimeline(twitter);
                PrintUserTimeline(twitter);

                //post a message
                twitter.Status.Update("Testing 123, Testing");
            }
            Console.ReadKey();
        }

        public static TwitterUser GetUserInfo(Twitter twitter, string userId)
        {
            TwitterUser user = twitter.Status.Show(userId);

            return user;
        }

        public static void PrintReplies(Twitter twitter)
        {
            TwitterStatusCollection col = twitter.Status.Replies();

            Console.WriteLine("Replies");

            foreach (TwitterStatus status in col)
            {
                Console.WriteLine("------------------------------------------");
                Console.WriteLine("Created:                " + status.Created);
                Console.WriteLine("ID:                     " + status.ID);
                Console.WriteLine("InReplyToStatusID:      " + status.InReplyToStatusID);
                Console.WriteLine("InReplyToStatusID:      " + status.InReplyToUserID);
                Console.WriteLine("IsFavorited:            " + status.IsFavorited);
                Console.WriteLine("IsTruncated:            " + status.IsTruncated);
                Console.WriteLine("RecipientID:            " + status.RecipientID);
                Console.WriteLine("Source:                 " + status.Source);
                Console.WriteLine("Text:                   " + status.Text);
                Console.WriteLine("TwitterUser.ScreenName: " + status.TwitterUser.ScreenName);
            }
        }

        public static void PrintFollowers(Twitter twitter)
        {
            TwitterUserCollection col = twitter.User.Followers();

            Console.WriteLine("Followers");

            foreach (TwitterUser user in col)
            {
                Console.WriteLine("------------------------------------------");
                Console.WriteLine("Description:       " + user.Description);
                Console.WriteLine("Friends_count:     " + user.Friends_count);
                Console.WriteLine("ID:                " + user.ID);
                Console.WriteLine("IsProtected:       " + user.IsProtected);
                Console.WriteLine("Location:          " + user.Location);
                Console.WriteLine("NumberOfFollowers: " + user.NumberOfFollowers);
                Console.WriteLine("ProfileImageUri:   " + user.ProfileImageUri);
                Console.WriteLine("ProfileUri:        " + user.ProfileUri);
                Console.WriteLine("ScreenName:        " + user.ScreenName);
                if (user.Status != null)
                {
                    Console.WriteLine("Status.Text:       " + user.Status.Text);
                }
                Console.WriteLine("TimeZone:          " + user.TimeZone);
                Console.WriteLine("UserName:          " + user.UserName);
            }
        }

        public static void PrintFriends(Twitter twitter)
        {
            TwitterUserCollection col = twitter.User.Friends();

            Console.WriteLine("Friends");

            foreach (TwitterUser user in col)
            {
                Console.WriteLine("------------------------------------------");
                Console.WriteLine("Description:       " + user.Description);
                Console.WriteLine("Friends_count:     " + user.Friends_count);
                Console.WriteLine("ID:                " + user.ID);
                Console.WriteLine("IsProtected:       " + user.IsProtected);
                Console.WriteLine("Location:          " + user.Location);
                Console.WriteLine("NumberOfFollowers: " + user.NumberOfFollowers);
                Console.WriteLine("ProfileImageUri:   " + user.ProfileImageUri);
                Console.WriteLine("ProfileUri:        " + user.ProfileUri);
                Console.WriteLine("ScreenName:        " + user.ScreenName);
                if (user.Status != null)
                {
                    Console.WriteLine("Status.Text:       " + user.Status.Text);
                }
                Console.WriteLine("TimeZone:          " + user.TimeZone);
                Console.WriteLine("UserName:          " + user.UserName);
            }
        }

        public static void PrintDirectMessages(Twitter twitter)
        {
            TwitterStatusCollection col = twitter.DirectMessages.DirectMessages();

            Console.WriteLine("DirectMessages");

            foreach (TwitterStatus status in col)
            {
                Console.WriteLine("------------------------------------------");
                Console.WriteLine("Created:                " + status.Created);
                Console.WriteLine("ID:                     " + status.ID);
                Console.WriteLine("InReplyToStatusID:      " + status.InReplyToStatusID);
                Console.WriteLine("InReplyToStatusID:      " + status.InReplyToUserID);
                Console.WriteLine("IsFavorited:            " + status.IsFavorited);
                Console.WriteLine("IsTruncated:            " + status.IsTruncated);
                Console.WriteLine("RecipientID:            " + status.RecipientID);
                Console.WriteLine("Source:                 " + status.Source);
                Console.WriteLine("Text:                   " + status.Text);
                Console.WriteLine("TwitterUser.ScreenName: " + status.TwitterUser.ScreenName);
            }
        }

        public static void PrintFriendsTimeline(Twitter twitter)
        {
            TwitterStatusCollection col = twitter.Status.FriendsTimeline();

            Console.WriteLine("FriendsTimeline");

            foreach (TwitterStatus status in col)
            {
                Console.WriteLine("------------------------------------------");
                Console.WriteLine("Created:                " + status.Created);
                Console.WriteLine("ID:                     " + status.ID);
                Console.WriteLine("InReplyToStatusID:      " + status.InReplyToStatusID);
                Console.WriteLine("InReplyToStatusID:      " + status.InReplyToUserID);
                Console.WriteLine("IsFavorited:            " + status.IsFavorited);
                Console.WriteLine("IsTruncated:            " + status.IsTruncated);
                Console.WriteLine("RecipientID:            " + status.RecipientID);
                Console.WriteLine("Source:                 " + status.Source);
                Console.WriteLine("Text:                   " + status.Text);
                Console.WriteLine("TwitterUser.ScreenName: " + status.TwitterUser.ScreenName);
            }
        }

        public static void PrintPublicTimeline(Twitter twitter)
        {
            TwitterStatusCollection col = twitter.Status.PublicTimeline();

            Console.WriteLine("PublicTimeline");

            foreach (TwitterStatus status in col)
            {
                Console.WriteLine("------------------------------------------");
                Console.WriteLine("Created:                " + status.Created);
                Console.WriteLine("ID:                     " + status.ID);
                Console.WriteLine("InReplyToStatusID:      " + status.InReplyToStatusID);
                Console.WriteLine("InReplyToStatusID:      " + status.InReplyToUserID);
                Console.WriteLine("IsFavorited:            " + status.IsFavorited);
                Console.WriteLine("IsTruncated:            " + status.IsTruncated);
                Console.WriteLine("RecipientID:            " + status.RecipientID);
                Console.WriteLine("Source:                 " + status.Source);
                Console.WriteLine("Text:                   " + status.Text);
                Console.WriteLine("TwitterUser.ScreenName: " + status.TwitterUser.ScreenName);
            }
        }

        public static void PrintUserTimeline(Twitter twitter)
        {
            TwitterStatusCollection col = twitter.Status.UserTimeline();

            Console.WriteLine("UserTimeline");

            foreach (TwitterStatus status in col)
            {
                Console.WriteLine("------------------------------------------");
                Console.WriteLine("Created:                " + status.Created);
                Console.WriteLine("ID:                     " + status.ID);
                Console.WriteLine("InReplyToStatusID:      " + status.InReplyToStatusID);
                Console.WriteLine("InReplyToStatusID:      " + status.InReplyToUserID);
                Console.WriteLine("IsFavorited:            " + status.IsFavorited);
                Console.WriteLine("IsTruncated:            " + status.IsTruncated);
                Console.WriteLine("RecipientID:            " + status.RecipientID);
                Console.WriteLine("Source:                 " + status.Source);
                Console.WriteLine("Text:                   " + status.Text);
                Console.WriteLine("TwitterUser.ScreenName: " + status.TwitterUser.ScreenName);
            }
        }
    }
}

After some tests in this library I was disappointed because I wasn’t able to find the documentation and some other features that are supported by Twitter are missing.

Now when I’ve some free time I will do some tests to other library named Tweet#, and from what I’ve seen it’s much more complete and it’s fluent.

 

I’m doing this not only for fun, but to continue evolve and learn new things :) and if you saw this post, you know that this is Agilior culture.

Learn and evolve, learn and evolve.

So like I wrote, I’m learning a bit of Twitter because there are lots of client applications around Twitter but I haven’t saw any add-in that Integrates with Visual Studio and since I know few things :) about how to develop extensions and software factories to Visual Studio I decided to start my Twitter Add-in. I’m only in the beginning (testing libraries) but I will release more news soon. Also, I’m intend to create a series of posts to show how to create a VS add-in and in particular how I’m creating this Twitter Add-in.

posted @ 4/15/2009 12:46 PM by Pedro Rainho

Building a Culture in a Small Professional Services Firm

One of the most difficulties that exists when managing a small professional services firm is to guarantee that exists a common culture which identifies all the developers in the firm. It is not uncommon to have one developer exclusively dedicated to a customer during a while, or for example, have a team of two developers mixed with customer developers to develop some project. We have some projects that can be developed in-house, and other that cannot. Of course we prefer to develop projects in-house. The daily living is one of the major contributions to build a culture. We can know better each other, and we can see the team as a family. When this kind of dally living is impossible, we must have alternatives to promote our culture.

 

Recruitment

The culture of a firm starts at the recruitment. When managing a small company, making a mistake when hiring can be the END. I will not detail our recruitment process here, but at interviews we always mention some characteristics that must be present to work at Agilior. Basically we tell our motto: "Learn or Out". We tell to the candidate that at Agilior we are always in continuous learning, and that we have passion about technology. We are always trying to evolve all the time. We tell to the candidate if he does not identify with this kind of behavior he is free to finish the interview.

 

Conventions

We have conventions defined to our projects at many levels

  • Source control organization
  • Visual studio (project structure)
  • C#
  • Database
  • BizTalk
  • Unit Tests

 

The main goal of conventions is to define some practices that must be used in all projects. The use of conventions guarantee some consistency between projects, and switching between projects is easy for a developer. The definition of conventions is a "work in progress", since there are always changes to be included. Some time ago we did a task force to draft the initial version. Of course we discussed a lot, since we all have different tastes. But the important is to have our people being committed in the process. We have also to be careful when defining conventions, since the developer creativity can be compromised when defining excessive conventions.

 

Sharing Knowledge

Having mechanisms to sharing knowledge is extremely important. We have an internal blog, which is much more active that our public blog. Many posts in the internal blog are links: interesting posts, tools, applications, etc. Right now we have 288 posts since January 2008.

We also have a Wiki and Forums in our intranet, however not so active.

One of our fringe benefits is to give to every developer an annual budget to buy books (remember: Learn or Out). The budget can only be used in books (technology, management, entrepreneurship). There is a list in our intranet where we register the books, so everyone knows what is being read at Agilior.

 

Agilior Meetings

 

And finally I have to mention that we have our monthly meetings. At the last Friday of each month we schedule a meeting with everyone. This is a technical meeting, where one or two of us are invited to give a presentation about a technical subject. This month, the subject is "Developing in Mono".  After the presentation (and discussion) we make some kind of a daily scrum,  and each one answer to:

  • What did you do last month?
  • What you will do in the next month?

 

After the meeting, we dine together at our preferred restaurant, with some beers, and "healthy" conversations .

 

I would like to have all the projects developed in-house, having the team all together, and investing in a good office space, with big monitors, great chairs, etc.. Maybe this is impossible in a consulting firm, and only possible when developing products. For now, we have to deal with the distance, and promote new ways to enrich our culture.

 

BFC

posted @ 4/15/2009 7:47 AM by BFC

Twitter

Finally some one convinced me to create a account on twitter here is the URL to follow me. Link. [UPDATE] Link fixed thanks Rodrigo

posted @ 4/11/2009 5:10 PM by Pedro Rainho

Microsoft Dynamics CRM - A RAD Platform!

 

Since the end of 2008 that we, at Agilior, decided to extend our offer in terms of professional services. We decided to include in our portfolio CRM implementations, using Microsoft Dynamics CRM 4.0. As usual, we started our internal research, buying some books, experimenting the product, and tried some scenarios and customizations.

As we were going forward in our research, it was obvious to us that the product was extremely well featured with respect to customizations. In fact, when you install the product, you can consider that you have a CRM installation, where you can register all the interactions with your customer, help you sales team to be more productive, etc., etc. However, after knowing the product features in terms of customization, you can use the same platform to build any line of business application (LOB)! But the most powerful think about this, is that you can build the LOB application without writing almost any code.  It seems that we are not alone in this reflection. In fact there is already a book named CRM as a Rapid Development Platform.

Jason Hunt and Aaron Helder, now from Ascentium, wrote an excellent article explaining why MSCRM is a business application platform. Jason and Aaron were part of the Microsoft CRM development team, and the platform was originally designed to be a development platform, and the CRM happens as sample application to manage customer relationships.

 

Regarding the development of any LOB application, in the article it is said that,

We‘ve found that using Microsoft CRM as your platform generally saves 50% to 70% of the development time. Effort you would have spent on the platform can be put towards the harder problem of identifying the right functionality and providing it in the right way.

 

I am confused, and maybe I am missing something. So, knowing that Microsoft  it is extremely  efficient in terms of marketing and sales, why Microsoft does not push to the masses the Dynamics CRM as a development platform? Of course that Microsoft has its internal reasons to not to do that. Sincerely, I would like to hear from Microsoft the public reason, and, let's say, the real reason.

The ecosystem has many companies which sells RAD Platforms (I will not mention names). But imagine that Microsoft starts to push Dynamics CRM as the new RAD/Agile Development Platform, maybe re-branded with a new product name. How the market will respond to this new product? What will be the future of the most of the companies that are in this market space? Do you really need a team with too many great developers?

 

Putting my developer hat, I must to say that what I really love to do is to craft software, and this kind of RAD development is not my first choice. However, I recognize the business benefits when adopting this kind of platform, in terms of costs, maintenance, etc.. And I must say that I am really impressed with Dynamics CRM capabilities as a development platform. I hope to see the re-brand of the platform inside Microsoft, a good marketing campaign set, a good licence scheme, and maybe, we have the tipping point of the Dynamics CRM, not as a CRM solution, but as a Business Application Development Platform.

posted @ 3/30/2009 4:40 PM by BFC

The best movie about helpdesk

posted @ 3/29/2009 6:38 AM by Pedro Rainho

Exception across App Domains

Recently I had a very strange exception and took me some time to figure out what was the problem. So lets imagine that I want to execute a piece of code in a different app domain, lets call it “NewDomain”, and that NewDomain throws a custom exception “MyException”.

The code of MyException is this:

[Serializable]
public class MyException : ApplicationException
{
    public MyException()
        : base()
    {
    }

    public MyException(string message)
        : base(message)
    {
        myCustomMessage = "Dear user you got an exception: " + message;
    }

    public MyException(string message, Exception innerException)
        :
        base(message, innerException)
    {
        myCustomMessage = "Dear user you got an exception: " + message;
    }

    public override string Message
    {
        get
        {
            return myCustomMessage;
        }
    }

    private string myCustomMessage;
}

 

If this exception is thrown across app domains you will get this nice exception:

The constructor to deserialize an object of type 'MyException’ was not found.

Server stack trace:

   at System.Runtime.Serialization.ObjectManager.CompleteISerializableObject(Object obj, SerializationInfo info, StreamingContext context)

   at System.Runtime.Serialization.ObjectManager.FixupSpecialObject(ObjectHolder holder)

   at System.Runtime.Serialization.ObjectManager.DoFixups()

   at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)

   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)

   at System.Runtime.Remoting.Channels.CrossAppDomainSerializer.DeserializeObject(MemoryStream stm)

   at System.Runtime.Remoting.Channels.CrossAppDomainSerializer.DeserializeMessageParts(MemoryStream stm)

   at System.Runtime.Remoting.Messaging.SmuggledMethodReturnMessage.FixupForNewAppDomain()

   at System.Runtime.Remoting.Channels.CrossAppDomainSink.SyncProcessMessage(IMessage reqMsg)

I didn’t know what the problem was at the beginning, because my class was marked with the attribute Serializable so what was the real problem???

The problem happens because I was transmitting the exception object across a stream. And across streams mark the class as Serializable is not enough.

So the solution is actually simple.

  1. I need to add a protected constructor with the following signature
    1. protected MyException(SerializationInfo info, StreamingContext context)
  2. My MyException class needs to implement ISerializable, the class System.Exception already implements it
  3. I need to implement the method
    1. GetObjectData(SerializationInfo info, StreamingContext context)
  4. Attribute the method with the following attribute
    1. [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]

 

I need all of this because the constructor is called during deserialization to reconstitute the exception object transmitted over a stream, and I need the method GetObjectData because I need to serialize my fields.

 

So, MyException class will lock like this:

[Serializable]
public class MyException : ApplicationException
{
    public MyException()
        : base()
    {
    }

    public MyException(string message)
        : base(message)
    {
        myCustomMessage = "Dear user you got an exception: " + message;
    }

    public MyException(string message, Exception innerException)
        :
        base(message, innerException)
    {
        myCustomMessage = "Dear user you got an exception: " + message;
    }

    protected MyException(SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
        myCustomMessage = info.GetString("myCustomMessage");
    }

    [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
    public override void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("myCustomMessage", myCustomMessage);

        base.GetObjectData(info, context);
    }

    public override string Message
    {
        get
        {
            return myCustomMessage;
        }
    }

    private string myCustomMessage;
}

Like I wrote I just had to implement a constructor  to deserialize my fields  and a method to serialize them.

posted @ 3/24/2009 7:35 AM by Pedro Rainho

Chrome Experiments

Yesterday a friend show me this link. Basically these experiments work in browsers that support the html element "canvas", such as Chrome, Firefox, Safari….It don’t work with IE, I had try without success.

 

The experiment that left my mouth open was this one. Just follow the tutorial, and you will see a ball being dragged from one with to another and you even can play with the ball, It’s impressive.

I definitely recommend every one to look at all samples, each one is impressive.

posted @ 3/20/2009 6:28 AM by Pedro Rainho

Load and unload assemblies

Last week, I had a problem that probably some .Net developer had faced. The problem consists in load and unload an assembly?.

Can I do that??? Well, I can’t do it in a simple way. One of the things that Assembly doesn’t support in unload, check this post to see why.

 

So, like I wrote, last week I was developing a new feature for a software factory and that feature consisted in get all references and do something else.

My recipe does something like this:

  1. Get project assembly
  2. Copy the assembly DLL to a location
  3. Get all assembly references
  4. Generate a file

 

Do number 1 is simple.

Do number 2 is also simple, but has a problem.

Do number 3 is also simple, but has a problem.

Do number 4 is simple.

 

I’m going to explain first problem number 3 then problem 2

The problem with number 3 it’s because I load a assembly and they I get referenced assemblies. To get referenced assemblies I just do:

Assembly assembly = Assembly.LoadFrom(@"c:\myAssembly.dll");
AssemblyName[] references = assembly.GetReferencedAssemblies();

 

This piece of code has a problem, since I’m loading the assembly and they get referenced assemblies the file myAssembly.dll is now locked this means that the next time I try to  run number 2 I will get an exception and the file will not ne copied. And this is why I had problem  number 2.

Now, how can I load the assembly and then unload that assembly so the file won’t be locked???

 

I came across some solutions.

  1. One of the possible solutions is just copy the assembly to something unique like {GUID}.DLL and then load that {GUID}.DLL, and do everything I need to do, this way I won’t lock my file.
    1. Problem: I will have the assembly {GUID}.DLL loaded (in memory) every time, and can’t delete file {GUID}.DLL, because it’s locked. And finally I can’t unload unless I close Visual Studio.
  2. Why don’t I just load the assembly into an array of bytes and then load the assembly, like this:
    Assembly assembly = Assembly.Load(File.ReadAllBytes(@"c:\myAssembly.dll"));
    1. Problem: I can do this and my file will not be locked but that array of bytes will be in memory and my visual studio memory will grow every time I run that recipe. That memory will be released only when I close the Visual Studio.
  3. I can load the assembly in a new AppDomain and then unload the AppDomain.
    1. Problem: tThis was a strange problem and I don’t know why but I load the assembly in a new AppDomain and that assembly become part of the new AppDomain and the AppDomain.Current. This was strange. Don’t know if I was doing something wrong. Now since the Assembly is loaded in AppDomain.Current I wasn’t able to copy the file, because it was locked.
  4. The last solution I came across to load the assembly and unload it. This solution Consists in create a new AppDomain and then use method DoCallBack:

Here it is the source code:

AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationBase = ApplicationBasePath;

AppDomain newDomainReferences = AppDomain.CreateDomain("AppDomain", null, setup);

CallBackAssemblyReferences call = new CallBackAssemblyReferences(newDomainReferences, filepath);
newDomainReferences.DoCallBack(new CrossAppDomainDelegate(call.LoadAssemblyReferences));
AssemblyName[] assName = (AssemblyName[])newDomainReferences.GetData("AssemblyReferences");

AppDomain.Unload(newDomainReferences);

 

This solution enables me to do a callback in a different domain. My class CallBackAssemblyReferences just does this:

[Serializable]
internal class CallBackAssemblyReferences
{
    #region Members Variables
    private string assemblyFile;
    private AppDomain domain;
    #endregion

    #region Public Implementation
    public CallBackAssemblyReferences()
    {

    }
    public CallBackAssemblyReferences(AppDomain domain, string assemblyFile)
    {
        this.assemblyFile = assemblyFile;
        this.domain = domain;
    }

    public void LoadAssemblyReferences()
    {
        Assembly assembly = this.domain.Load(AssemblyName.GetAssemblyName(this.assemblyFile));

        domain.SetData("AssemblyReferences", assembly.GetReferencedAssemblies());
    }
    #endregion
}

 

This class has a constructor that receives the new domain I’m working on and the path to the assembly I want to load.

public CallBackAssemblyReferences(AppDomain domain, string assemblyFile)

 

Then I just have my callback method WITH NO PARAMETERS.

public void LoadAssemblyReferences()

 

This is the method that will be called when I do

newDomainReferences.DoCallBack(new CrossAppDomainDelegate(call.LoadAssemblyReferences));

 

The callback method only loads the assembly in the new domain and then sets data in the new domain. These data are the assembly references.

When the DoCallBack returns I just had to do

AssemblyName[] assName = (AssemblyName[])newDomainReferences.GetData("AssemblyReferences");

To get the references I had saved.

 

Finally I just unload the AppDomain.

 

Now I can run my recipe every time I need without lock the file and without decrease visual studio performance.

posted @ 3/15/2009 5:59 PM by Pedro Rainho

Moq.me

Currently when I need do unit tests the mock framework that I’m currently using Is the Rhino Mocks.

But today after read a post, I found a new mock framework, named Moq.me. This framework was made by kzu.

kzu is one of the guys behind Clarius.

I know Clarius because I develop software factories and they have this toolkit, that I had tried, named Clarius Software Factory Toolkit and it’s a “software factory to do other software factories”. They also have the Clarius Visual T4(aka T4 Editor).

Now I have download Moq.me and will test it very very soon :)

posted @ 3/8/2009 10:42 AM by Pedro Rainho