Scott Hanselman

Back to Basics: 32-bit and 64-bit confusion around x86 and x64 and the .NET Framework and CLR

February 11, '09 Comments [34] Posted in ASP.NET | Back to Basics | Learning .NET | Programming | Windows Client
Sponsored By

I'm running 64-bit operating systems on every machine I have that is capable. I'm running Vista 64 on my quad-proc machine with 8 gigs of RAM, and Windows 7 Beta 64-bit on my laptop with 4 gigs.

Writing managed code is a pretty good way to not have to worry about any x86 (32-bit) vs. x64 (64-bit) details. Write managed code, compile, and it'll work everywhere.

The most important take away, from MSDN:

"If you have 100% type safe managed code then you really can just copy it to the 64-bit platform and run it successfully under the 64-bit CLR."

If you do that, you're golden. Moving right along.

WARNING: This is obscure and you probably don't care. But, that's this blog.

Back to 32-bit vs. 64-bit .NET Basics

I promote 64-bit a lot because I personally think my 64-bit machine is snappier and more stable. I also have buttloads of RAM which is nice.

The first question developer ask me when I'm pushing 64-bit is "Can I still run Visual Studio the same? Can I make apps that run everywhere?" Yes, totally. I run VS2008 all day on x64 machines writing ASP.NET apps, WPF apps, and Console apps and don't give it a thought. When I'm developing I usually don't sweat any of this. Visual Studio 2008 installs and runs just fine.

If you care about details, when you install .NET on a 64-bit machine the package is bigger because you're getting BOTH 32-bit and 64-bit versions of stuff. Some of the things that are 64-bit specific are:

  • Base class libraries (System.*)
  • Just-In-Time compiler
  • Debugging support
  • .NET Framework SDK

For example, I have a C:\Windows\Microsoft.NET\Framework and a C:\Windows\Microsoft.NET\Framework64 folder.

If I File|New Project and make a console app, and run it, this is what I'll see in the Task Manager:

64-bit app running in Task Manager

Notice that a bunch of processes have *32 by their names, including devenv.exe? Those are all 32-bit processes. However, my ConsoleApplication1.exe doesn't have that. It's a 64-bit process and it can access a ridiculous amount of memory (if you've got it...like 16TB, although I suspect the GC would be freaking out at that point.)

That 64-bit process is also having its code JIT compiled to use not the x86 instruction set we're used to, but the AMD64 instruction set. This is important to note: It doesn't matter if you have an AMD or an Intel processor, if you're 64-bit you are using the AMD64 instruction set. The short story is - Intel lost. For us, it doesn't really matter.

Now, if I right click on the Properties dialog for this Project in Visual Studio I can select the Platform Target from the Build Tab:

image

By default, the Platform Target is "Any CPU." Remember that our C# or VB compiles to IL, and that IL is basically processor agnostic. It's the JIT that makes the decision at the last minute.

In my case, I am running 64-bit and it was set to Any CPU so it was 64-bit at runtime. But, to repeat (I'll do it a few times, so forgive me) the most important take away, from MSDN:

"If you have 100% type safe managed code then you really can just copy it to the 64-bit platform and run it successfully under the 64-bit CLR."

Let me switch it to x86 and look at Task Manager and we see my app is now 32-bit.

image

Cool, so...

32-bit vs. 64-bit - Why Should I Care?

Everyone once in a while you'll need to call from managed code into unmanaged and you'll need to give some thought to 64-bit vs. 32-bit. Unmanaged code cares DEEPLY about bitness, it exists in a processor specific world.

Here's a great bit from an older MSDN article that explains part of it with emphasis mine:

In 64-bit Microsoft Windows, this assumption of parity in data type sizes is invalid. Making all data types 64 bits in length would waste space, because most applications do not need the increased size. However, applications do need pointers to 64-bit data, and they need the ability to have 64-bit data types in selected cases. These considerations led the Windows team to select an abstract data model called LLP64 (or P64). In the LLP64 data model, only pointers expand to 64 bits; all other basic data types (integer and long) remain 32 bits in length.

The .NET CLR for 64-bit platforms uses the same LLP64 abstract data model. In .NET there is an integral data type, not widely known, that is specifically designated to hold 'pointer' information: IntPtr whose size is dependent on the platform (e.g., 32-bit or 64-bit) it is running on. Consider the following code snippet:

[C#]
public void SizeOfIntPtr() {
Console.WriteLine( "SizeOf IntPtr is: {0}", IntPtr.Size );
}

When run on a 32-bit platform you will get the following output on the console:

SizeOf IntPtr is: 4

On a 64-bit platform you will get the following output on the console:

SizeOf IntPtr is: 8

Short version: If you're using IntPtrs, you care. If you're aware of what IntPtrs are, you likely know this already.

If you checked the property System.IntPtr.Size while running as x86, it'll be 4. It'll be 8 while under x64. To be clear, if you are running x86 even on an x64 machine, System.IntPtr.Size will be 4. This isn't a way to tell the bitness of your OS, just the bitness of your running CLR process.

Here's a concrete example. It's a pretty specific edgy thing, but a decent example. Here's an app that runs fine on x86.

using System;
using System.Runtime.InteropServices;

namespace TestGetSystemInfo
{
public class WinApi
{
[DllImport("kernel32.dll")]
public static extern void GetSystemInfo([MarshalAs(UnmanagedType.Struct)] ref SYSTEM_INFO lpSystemInfo);

[StructLayout(LayoutKind.Sequential)]
public struct SYSTEM_INFO
{
internal _PROCESSOR_INFO_UNION uProcessorInfo;
public uint dwPageSize;
public IntPtr lpMinimumApplicationAddress;
public int lpMaximumApplicationAddress;
public IntPtr dwActiveProcessorMask;
public uint dwNumberOfProcessors;
public uint dwProcessorType;
public uint dwAllocationGranularity;
public ushort dwProcessorLevel;
public ushort dwProcessorRevision;
}

[StructLayout(LayoutKind.Explicit)]
public struct _PROCESSOR_INFO_UNION
{
[FieldOffset(0)]
internal uint dwOemId;
[FieldOffset(0)]
internal ushort wProcessorArchitecture;
[FieldOffset(2)]
internal ushort wReserved;
}
}

public class Program
{
public static void Main(string[] args)
{
WinApi.SYSTEM_INFO sysinfo = new WinApi.SYSTEM_INFO();
WinApi.GetSystemInfo(ref sysinfo);
Console.WriteLine("dwProcessorType ={0}", sysinfo.dwProcessorType.ToString());
Console.WriteLine("dwPageSize ={0}", sysinfo.dwPageSize.ToString());
Console.WriteLine("lpMaximumApplicationAddress ={0}", sysinfo.lpMaximumApplicationAddress.ToString());
}
}
}

See the mistake? It's not totally obvious. Here's what's printed under x86 (by changing the project properties):

dwProcessorType =586
dwPageSize      =4096
lpMaximumApplicationAddress =2147418111

The bug is subtle because it works under x86. As said in the P/Invoke Wiki:

The use of int will appear to be fine if you only run the code on a 32-bit machine, but will likely cause your application/component to crash as soon as it gets on a 64-bit machine.

In our case, it doesn't crash, but it sure is wrong. Here's what happens under x64 (or AnyCPU and running it on my x64 machine):

dwProcessorType =8664
dwPageSize      =4096
lpMaximumApplicationAddress =-65537

See that lat number? Total crap. I've used an int as a pointer to lpMaximumApplicationAddress rather than an IntPtr. Remember that IntPtr is smart enough to get bigger and point to the right stuff. When I change it from int to IntPtr:

dwProcessorType =8664
dwPageSize      =4096
lpMaximumApplicationAddress =8796092956671

That's better. Remember that IntPtr is platform/processor specific.

You can still use P/Invokes like this and call into unmanaged code if you're on 64-bit or if you're trying to work on both platforms, you just need to be thoughtful about it.

Gotchas: Other Assemblies

You'll also want to think about the assemblies that your application loads. It's possible that when purchasing a vendor's product in binary form or bringing an Open Source project into your project in binary form, that you might consume an x86 compiled .NET assembly. That'll work fine on x86, but break on x64 when your AnyCPU compiled EXE runs as x64 and tries to load an x86 assembly. You'll get a BadImageFormatException as I did in this post.

The MSDN article gets it right when it says:

...it is unrealistic to assume that one can just run 32-bit code in a 64-bit environment and have it run without looking at what you are migrating.

As mentioned earlier, if you have 100% type safe managed code then you really can just copy it to the 64-bit platform and run it successfully under the 64-bit CLR.

But more than likely the managed application will be involved with any or all of the following:

  • Invoking platform APIs via p/invoke
  • Invoking COM objects
  • Making use of unsafe code
  • Using marshaling as a mechanism for sharing information
  • Using serialization as a way of persisting state

Regardless of which of these things your application is doing it is going to be important to do your homework and investigate what your code is doing and what dependencies you have. Once you do this homework you will have to look at your choices to do any or all of the following:

  • Migrate the code with no changes.
  • Make changes to your code to handle 64-bit pointers correctly.
  • Work with other vendors, etc., to provide 64-bit versions of their products.
  • Make changes to your logic to handle marshaling and/or serialization.

There may be cases where you make the decision either not to migrate the managed code to 64-bit, in which case you have the option to mark your assemblies so that the Windows loader can do the right thing at start up. Keep in mind that downstream dependencies have a direct impact on the overall application.

I have found that for smaller apps that don't need the benefits of x64 but need to call into some unmanaged COM components that marking the assemblies as x86 is a reasonable mitigation strategy.  The same rules apply if you're making a WPF app, a Console App or an ASP.NET app. Very likely you'll not have to deal with this stuff if you're staying managed, but I wanted to put it out there in case you bump into it.

Regardless, always test on x86 and x64.

Related Posts

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Hanselman List of Podcasts for .NET Programmers

February 10, '09 Comments [40] Posted in ASP.NET | Learning .NET | Podcast | Programming
Sponsored By

I used to hate podcasts, but that didn't last long. I got a longer commute, bandwidth became less of an issue and podcasts, frankly, got better. Of course, I'm a smidge biased.

I listen to a number of podcasts, not all technical, of course. I also watch the nightly news and a number of other news and political TV shows delivered not over the air or via cable, but by podcast.

Here's some technical podcasts, collected and recommended by my folks and friends on Twitter. I've heard some, and added my thoughts. Others I look forward to listening to. They are listed in no particular order. I threw mine in there as well. ;)

NOTE: If you've created a list of YOUR favorite .NET Podcasts, send me a link to your blog and I'll add it here:

And here's mine:

Hanselman's Super Karate Death Car List of .NET and Software Podcasts


imageThoughtworks IT Matters - I respect a lot of the guys over at Thoughtworks so I'll give this a listen just based on that. It looks like it's updated infrequently, and there's no dates on their shows on the site (the RSS includes them), so hopefully they'll get a nice meter going and perhaps commit to a monthly or weekly schedule. Looks promising and fairy platform-agnostic, so likely useful for anyone programming in any language.


imageHanselminutes - I'll let Scott Bellware's tweeted review of my show speak, rather than toot my own horn: "the one i look forward to is hanselminutes. know it? host is a bit of a nut, but ethical and with a heart :)"

I'm a .NET person, but I also dabble in Ruby and did some time at Nike coding Java. I also like gadgets so the show has become all of the above plus (I think) interesting interviews.


image .NET Rocks - The first and longest running, now on show #418 which is CRAZY. Richard and Carl set the standard for those that followed them. Often interviews, sometimes random, always interesting, .NET Rocks is the gold standard.


image ALT.NET Podcast - "You're the type of developer who uses whatever works while keeping an eye out for a better way, you reach outside the mainstream to adopt the best of any community, you're not content with the status quo and you realize that tools are great, but they only take you so far..." this might be the podcast for you.


image Sparkling Client - Entirely focused on Silverlight and RIA (Rich Internet Application) technologies, I'd call this an "up and comer" in the .NET podcast world.


image ASP.NET Podcast by Wally McClure - The site design is a little wacky, but Wally's got 130+ podcasts focused entirely on ASP.NET and the content continues. He has covered Azure, lots of ASP.NET AJAX, jQuery and many other topics.


image Polymorphic Podcast - Craig Shoemaker works for Infragistics and hosts this .NET focused podcast. It's a little spotty as far as the frequency of updates, but he has an easy style and focuses a lot of ASP.NET. He's also had a couple of killer interviews like his one with craigslist founder Craig Newmark.


imageHerding Code - Hosted by K. Scott Allen, Kevin Dente, Scott Koon and Jon Galloway, this is kind of the TWiT of .NET podcasts. If you ever wish you could go to coffee and shoot the sh*t with some really smart folks, but you just can't find enough find enough smart guys or enough coffee, look no farther than Herding Code. Each host has a different perspective that adds to the conversation. The sound quality and leveling can be a little off, but not enough to distract from the good content.


image Deep Fried Bytes - "Deep Fried Bytes is an audio talk show with a Southern flavor hosted by technologists and developers Keith Elder and Chris Woodruff." Also tends to be a little irregular as far as publish dates, but they always have interesting guests. Mostly Windows focused, but not in a fanboy way, they've had a Linux/Gnome guest and are off to a fine start.  


image Software Engineering Radio - A language and platform agnostic show, these folks have over 120 shows in the can. The audio quality has been a little inconsistent, but the content is diverse and the guests are first class. Frankly this is one of the most diverse podcasts out there, and they do it without sacrificing depth. Recommended.


image The Java Posse - To understand .NET, one has to understand that which came before. The Java Posse has hosts from Sun, Google and Navigenics and is a really quick and terse way to get up to speed on what's happening in the world of Java. It tends to be a little random and conversational, but they have VERY thorough show notes and links. If you're into Java or selling against Java, a podcast to watch.


image OpenWeb Podcast - It's new, but it's got John Resig. They are still getting the handle of the audio and tend to have problems overdriving the microphone and have issues with leveling and so that's a little distracting. However, it's got some really smart Google and Mozilla employees talking about the Open Web and how to keep it open. They also get +2 Charisma for publishing not only in MP3 but also in (the kind of irrelevant but totally open) OGG Vorbis format.

They have been REALLY spotty, publishing only every month or two, but that's probably because they are DOING things to make the web better. Let's pressure them to publish more.


image Ruby on Rails Podcast - Also pretty spotting on their publish dates, but always a good overview about what's going on in the world of Ruby on Rails. Tends to be a little chattier than I like in a technical podcast "Hey, how's it going, good, how's the weather" but that's a stylistic thing.


image This Week on Channel 9 - This is kind of "The Daily Show" for Microsoft Developer Geeks. "Every week Dan Fernandez and Brian Keller sift through hundreds of blogs, videos, and announcements to find the most important stories in the developer community." It's a video podcast primarily, but they also off an MP3 download version as well as versions for iPod and Zune. I visit this show in person every few months, and it's a lot of fun and a great rollup of the week's goings on.

 

 


Elegant Code Cast LogoElegant CodeCast - With a spin towards the Agile/TDD crowd, Elegant CodeCast puts on a show on a roughly twice a month basis.

 

 

 


Enjoy! I say give each one a trial or two and see which shows stick. That's what I do. Then I revisit them a year later to see if they stick differently.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

UrlScan and ADO.NET Data Services (Astoria)

February 10, '09 Comments [6] Posted in ASP.NET | IIS | Web Services
Sponsored By

In an ongoing series on different reasons that I suck, I wanted to share another interesting quasi-debugging story about this public ADO.NET Data Services (Astoria) service I'm trying to help get live at a large company.

I'd mentioned how I had some trouble with UrlScan and Astoria Services in my post on "RTFLF - Read the Expletive Log File."

UrlScan 3.1 is a security tool that restricts the types of HTTP requests that IIS will process. By blocking specific HTTP requests, the UrlScan 3.1 security tool helps to prevent potentially harmful requests from reaching applications on the server. UrlScan 3.1 is an update to UrlScan 2.5 supports IIS 5.1, IIS 6.0 and IIS 7.0 on Windows Vista and Windows Server 2008.

UrlScan is a really valuable tool and a really powerful way to slap down evil and attacks on your Web Server. It is VERY configurable and very powerful and takes a clear mind to make sure that all your application's URLs work well while still preventing evil. Learn how to setup UrlScan here.

When we moved the service onto a production machine, it turned out that their production UrlScan.ini was locked down more than development. They were disallowing single quotes in QueryStrings as well as Dots in Url Paths.

The trick was that they haven't partitioned their sites up by subdomain, or website, just AppDomain. This means that they have 40+ "logical sites" running under one instances of IIS6, which means that they can't setup a separate IIS site with their own configuration and instance of the UrlScan ISAPI Filter. They also didn't feel like making a separate domain or subdomain just for our one little service.

OK, blah blah blah, background, right? So where did things go wrong?

URLScan has a section in the UrlScan.ini file called [AlwaysAllowedUrls] that does just that. It allows access to any URL in that section. Adding a URL there will make UrlScan completely ignore it.

I added our service to this section like this:

[AlwaysAllowedUrls]
/foo/MyService.svc

And I thought this would work. It DID allow us to request that Url. However, no other Astoria queries worked.

When you traverse Entities in ADO.NET Data Services (Astoria), your URLs look like this, for example:

/foo/MyService.svc/Cars()
/foo/MyService.svc/Cars()$filter=((Visible%20eq%20true)

And I didn't initially see why these were being blocked.

The issue, pointed out to me by the IIS Team's Wade Hilmo (check out his blog) was obvious (hence: I suck). The URL isn't the file, it's everything before the ?. It's everything before the QueryString. This is one of those "Duh" moments, and was my bad. I know the difference, of course, and understand Urls fully, but I completely brain-farted this obvious point when looking at ADO.NET Data Service queries and had been mentally parsing them wrong for hours. Once Wade set me straight, configuring UrlScan.ini was trivial:

[AlwaysAllowedUrls]
/foo/MyService.svc/Cars()
/foo/MyService.svc/Houses()
/foo/MyService.svc/Whatevers()

In the ADO.NET Data Services parlance, the Entities exist after the .svc filename, but before the ? delimiter. Once we added those to our UrlScan.ini file, we were able to maintain the existing state of "super locked-down-ed-ness" while still allowing our services to run.

It is not possible to have a SQL Injection attack on a ADO.NET Data Service, due to the complete query rewrite that happens server side when a URL query comes into the system. The analogy is to think of in the same way that a LINQ query goes through a complete query re-write or a translation layer before it actually gets executed as SQL on the server. This re-write or translation is the layer of protection against SQL Injection attacks.

I was happy to learn that I could have my Cake ADO.NET Data Services and my UrlScan too.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

IPrincipal (User) ModelBinder in ASP.NET MVC for easier testing

February 6, '09 Comments [17] Posted in ASP.NET | ASP.NET MVC
Sponsored By

ModelBinders are great. I've blogged a bit about them before like the File Upload Model Binder.

I am working on some code like this:

[Authorize]
public ActionResult Edit(int id) {

Dinner dinner = dinnerRepository.FindDinner(id);

if (dinner.HostedBy != User.Identity.Name)
return View("InvalidOwner");

var viewModel = new DinnerFormViewModel {
Dinner = dinner,
Countries = new SelectList(PhoneValidator.Countries, dinner.Country)
};

return View(viewModel);
}

It's pretty straight forward, but this Controller knows too much. It's reaching into implicit parameters. The id was passed in, but the User is actually a property of the Controller base class and ultimately requires an HttpContext. Having this method "know" about the User object, and worse yet, having the User object go reaching into HttpContext.Current makes this hard to test.

I'd like to have the convenience of passing in the User (actually an IPrincipal interface) when I want to test, but when I'm running the app, I'd like to have the IPrincipal get passed into my method automatically. Enter the Model Binder. I need to teach ASP.NET MVC what to do when it sees a type as a parameter.

This quickie model binder is now responsible for one thing - it knows how to reach down into the HttpContext and get the current User (IPrincipal). It has one single responsibility.

public class IPrincipalModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (controllerContext == null) {
throw new ArgumentNullException("controllerContext");
}
if (bindingContext == null) {
throw new ArgumentNullException("bindingContext");
}
IPrincipal p = controllerContext.HttpContext.User;
return p;
}
}

Now I can release the Controller from the emotional baggage of knowing too much about the User object. It can just have that passed in automatically by the framework. I just need to register the binder to tell folks about it. I can either do it on a one-off basis and put an attribute on this one method parameter:

public ActionResult Edit(int id,                        
[ModelBinder(typeof(IPrincipalModelBinder))]
IPrincipal user)
{...}

But even better, I can just tell the whole application once in the global.asax:

void Application_Start() {
RegisterRoutes(RouteTable.Routes); //unrelated, don't sweat this line.
ModelBinders.Binders[typeof(IPrincipal)] = new IPrincipalModelBinder();
}

Now that ASP.NET MVC knows what to do when it see an IPrincipal as a method parameter, my method gets nicer.

[Authorize]
public ActionResult Edit(int id, IPrincipal user) {

Dinner dinner = dinnerRepository.FindDinner(id);

if (dinner.HostedBy != user.Identity.Name)
return View("InvalidOwner");

var viewModel = new DinnerFormViewModel {
Dinner = dinner,
Countries = new SelectList(PhoneValidator.Countries, dinner.Country)
};

return View(viewModel);
}

Now I can test my controller more easily by passing in fake users. No need for mocking in this case!

[TestMethod]
public void EditAllowsUsersToEditDinnersTheyOwn()
{
// Arrange
DinnersController controller = new DinnersController(new TestDinnerRespository());

// Act
IPrincipal FakeUser = new GenericPrincipal(new GenericIdentity("Scott","Forms"),null);
ViewResult result = controller.Edit(4, FakeUser) as ViewResult;

// Yada yada yada assert etc etc etc
Assert.IsTrue(result.ViewName != "InvalidOwner");
}

Fun stuff.

UPDATE: Phil had an interesting idea. He said, why not make method overloads, one for testing and one for without. I can see how this might be controversial, but it's very pragmatic.

[Authorize]
public ActionResult Edit(int id)
{
return Edit(id, User); //This one uses HttpContext
}

You'd use this one as before at runtime, and call the overload that takes the IPrincipal explicitly for testing.

Yes, I realize I could use an IoC container for this also.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

How To Twitter - First Steps and a Twitter Glossary

February 5, '09 Comments [22] Posted in Musings
Sponsored By

tour_1UPDATE: Want more advanced Twitter Tips?
We're having loads of fun over on Twitter. I've blogged about it before and how it's a conversation starter, a message bus, a subject tagger and conference organizer and a link sharing service. It's a river of uselessfulness and truthiness. It's a permanent cocktail party where you know some folks, and don't know others. Some are famous, some are your friends. There's a the constant background of overheard conversations, except on Twitter, it's socially acceptable, nay, encouraged, to jump in. No need to say, "oh, I couldn't help but overheard, excuse me but..."

A Twitter Glossary

UPDATE: Readers point out there's also a very good "Twictionary" that's much more complete at http://twictionary.pbwiki.com/ so check it out also!

Tweet

When you say something on twitter, it has to be under 140 characters. That's a hard limit. What you say is called a tweet. It's a noun and a verb. "Oh, I saw this tweet..." and "He was tweeting all day."

Alternatively, some folks say "twittered" as in "I am twittering" and "I sent a twitter." I would say this is not typical.

Twitter is permanent (so far) so every tweet has a permalink. That means that every single tweet you put out there is now something that can be linked to, for example, this one: http://twitter.com/shanselman/status/1178002576. This immediately makes twitter different from IRC or other chat systems. That tweet is public and it's out there and it's web searchable.

I have always said, don't give bile a permalink. If you're a jerk on Twitter (and you care) it's in the record. Tweet positively.

Twoosh

A twoosh is a tweet that is exactly 140 characters, no more no less. You've maximized the size of your tweet. Some folks believe this is a sign of skill. You'll tweet and learn that it's usually luck.

Tweeple

People on Twitter. 'Nuff said.

Tweetup

When Tweeple meet in person.

Twitter Client

While you can read tweets and tweet yourself at http://www.twitter.com and http://m.twitter.com on your phone, most folks use a Twitter Client that talks to the Twitter API. Just like you can read your email on the web, but many folks use an email client.

There's lots of them...here's the top 100 twitter clients.

Me, I like:

  • Windows Mobile - Tiny Twitter - fast and small and basic.
  • iPhone - TwitterFon - simple and clean, lets you do everything you can on the web and more.
  • Power User - TweetDeck - powerful as it lets you have multiple columns for search terms you want to monitor.
  • Most Pretty (Vista) - Chirp - Missing some functionality, but it's gorgeous.
  • .NET Educational - Witty - A free open source client for XP and Vista written in WPF

I use TweetDeck the most.

Followers and Following

When you "follow" someone, you are saying you want them to appear in your "timeline" of friends. I follow something like 500 people. It's like subscribing to a blog you're interested in. However, I have more than 500 people following me...but (here's the important part) I don't need to follow everyone back.

If you follow everyone and keep some 1:1 ratio between who you follow and who follows you, that will render your main timeline useless. Follow who is interesting to you, but make sure you can see the @replies from folks you don't follow. This leads me to:

@replies

When you want to reply to someone, you hit the little reply arrow in your client or on the web. The client will insert that users name with an @ sign, like @shanselman. It will also populate some hidden metadata indicating which tweet you were replying to. It's helpful to reply to specific tweets as it makes the conversation easier to follow later. Often newbies reply to the most recent tweet, but then make reference to tweets from days before.

For maximum social-ness, the first setting you should change when you sign up for Twitter is your @replies setting. Set it to show replies from anyone rather than just the replies from people you follow. Otherwise you'll miss out on a lot of the conversation.

I can see your replies even if I don't follow you. You don't need permission from me or anyone to reply and jump into a conversation.

Search.Twitter.com

If you want to watch the replies for a Twitter user that is not you, you can use http://search.twitter.com or a new column in TweetDeck. For example, here's me: http://search.twitter.com/search?q=shanselman. By searching for the string "shanselman" you can see both replies as well as mentions, like http://search.twitter.com/search?q=hanselman. Often new folks try to reply but mention your name rather than correctly using the @shanselman syntax.

You can also subscribe to an RSS feed for search.twitter.com queries. But it's not just for ego-surfing. I also watch for diabetes and asp.net. You get the idea.

Retweet or RT

When you see a tweet you really like, you can "retweet" it. Usually newbies will over-retweet, so watch for that.

The idea is that if @foo has 100 followers and @bar has 100 different followers and @foo retweets @bar's tweet, the idea is magnified, and may go viral.

If you care, there are tools to measure and track retweets. I don't care. I'm in it for the conversation and the sharing. If something strikes you as awesome, retweet it. Many Twitter clients have a "retweet" button now that will do this for you.

Twitter #Hashcodes

Sometimes you'll see a tweet like

Having fun at #mix09

or

bill gates mosquitoes / unleashed on #ted audience / where is the 'green' deet #haiku

The hashcode is an informal way to "tag" something to a category or categories. For example, the second tweet there refers to both the Ted conference and marks the tweet as a Haiku. (Haiku on Twitter are called "Twaiku" but that's pretty geeky. ;)

Hashcodes can help you be social at a conference like #oscon or #mix09 but they can also create informal "chat rooms" like for the show #lost or to find folks that share a common interest like:

any #women out there who are #runners? Trying to get some more ideas for my blog.

When I got to a conference I always ask around for the conference hashcode, then create a search so I can find out where folks are hanging out. It really enhances the experience.

Tiny URLs

image Since you've only got 140 characters for a Tweet, it's really important that you not share large URLs. Nearly everyone on Twitter will use a URL shrinking service like http://bit.ly or http://is.gd or http://tinyurl.com. Funny, TinyUrl is positively HUGE!

Make sure your client will automatically shrink URLs. Most do.

Sharing Pictures with TwitPic

There are a lot of services that "orbit" Twitter. They aren't Twitter, and they usually aren't affiliated with Twitter, but they enhance the service, like the tiny URL makers above.

One of these services is TwitPic. It has an API that lets you attach a photo from your client, then it'll include a tiny link to that photo. Some clients can even extract the photo seamlessly. British entertainer Stephen Fry used Twitter and Twitpic and a mobile phone recently to tweet his way to safety whilst trapped in an elevator, er, lift.

Direct Messages

These are exactly what they sound like - private tweets between two people. The only trick here is that you can only "DM" people who follow you.

Integration with Facebook and other Social Sites

Facebook has "Status Updates" and my friends think I update my status all the time. In fact, there's a Twitter Facebook application that you can add to your Facebook Profile so that your Facebook Status is updated with your Tweets.

I find this to be fun as it allows topics to fire up inside Facebook and lets folks who aren't on Twitter get in on the conversation. Other social sites like FriendFeed and Live.com have similar features.

Overwhelmed?

Most people try out twitter, follow a few people, tweet some, get confused or bored and never come back. Totally understandable, as it's all a big secret handshake.

Here's what I suggest.

  1. Sign up
  2. Pick a Twitter Client (see list above)
    • Don't set the client to bother you (sound, notify, etc) every time something happens. You'll go nuts. I set mine to notify on replies only. I check the "river of tweets" whenever I feel like it. It's an interrupt, remember. You'll never keep up with all the tweets. You'll never have fun if you try to drink from the firehose, so don't. When it bothers you, shut it down. When there's a fun topic happening, jump in.
  3. Pick at LEAST 20 people or more to follow.
    • Mix it up. Follow people in all of the things you're interested in. For example, don't just follow programmers, or famous people, or news sites.
      I've seen folks follow just a few people, then get frustrated because they feel one person is dominating their "tweetstream." If you follow just me and @codinghorror, you'll immediately hate us both because it'll seem like we tweet all day. (I don't, honest) If you have enough people, it'll seem more like a cocktail party with lots of folks talking, as opposed to a lecture by two obnoxious dudes.
    • There are many famous people on twitter but there's also lots of useful bots and news services. For example, @cnn, and @npr, but also companies with Twitter specific discounts like @DellOutlet.
      Another example: I wrote a Twitter-bot that posts funny things that my 3 year old says (or yours!) and cute things that are OverheardAtHome using the totally automated Twitter name @overheardathome.
  4. Watch for other interesting people to follow.
    • If someone you follow seems be having a conversation with someone you aren't following, why not use the "Follow" feature of your client to listen to that new person. You can always unfollow them.
  5. Tweet smartly.

Have fun! See you on Twitter. I'm @shanselman.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.