throw new Exception();// TODO: Delete Me! For Testing Purposes
Monday, October 09, 2006
testing ThinkStar insert code plugin
Friday, October 06, 2006
Using generics and anonymous delegates to populate a drop down list from a dictionary
but mostly just testing Douglas Stockwell's plugin
private void LoadDropDownListFromDictionary<TKey, TValue>(DropDownList ddl,
IDictionary<TKey, TValue> dict,
GetNameDelegate<TValue> getName,
ConditionDelegate<TKey> getCondition)
{
foreach (KeyValuePair<TKey, TValue> pair in dict) {
if ((getCondition == null) || (getCondition(pair.Key)))
ddl.Items.Add(new ListItem(getName(pair.Value), pair.Key.ToString()));
}
}
and yes, you can also databind it directly using the dropdownlist.DataSource,
DataTextField and DataValueField
Tuesday, October 03, 2006
Doing the Filemon
| I was looking for the some video where they show the filemon tool (I think I saw it on the hanselminutes) to pass it to some co-worker, and I found this instead, I was curious to see what he was doing with the Filemon or what was the deal, it got me laughing instead | |
Saturday, September 30, 2006
Game programming from scratch
In programming there are several different... I guess I could call them branches, each requiring very different skills, to name a few we have
- Operating System's development
- Device programming
- Device drivers
- Anti-virus
- Virus writing
- Large Frameworks (I'm talking about .NET for example)
- Game programming
Event just in Windows you could talk about
- Native win32
- Managed
- windows services
- web services
- web programming
- etc...
Game programming is one of those branches that requires a lot more knowledge on quite a few different topics than (and usually in addition to) regular traditional programming.
Game programming is something that I have always been interested in, the most I've done however, are a couple text based games and a domino game that can be played over a LAN; as part of my interests I have studied OpenGL and DirectX, I even wrote a few beginner articles on Delphi and OpenGL.
I have read quite a bit about game programming in general, enough to know that your first game should be something simple, most people trying game programming for the first time attempt to create something big like a 3D first person shooter, most people however, fail.
The guys who have been there and know game programming recommend you create something like a Tetris for your first game, even though this is a really simple game, it's got all the elements of any game
- input
- logic
- animation
- levels
- a game loop (every game has a game loop)
Other good choices for your first game could be an steroids, bricks, pac-man. If you need more ideas you could visit sites like miniclip, they have hundreds of flash games, you can even chose to write a simpler version of a game you chose, the whole point is that you should finish it, and once you finish it, maybe you extend it, but you would have already finished v1.0 of your first game and that is really important.
These days starting a game "from scratch" is really far from what it used to be just a few years ago, where you had to create everything, maybe even your own format and format loader, and every single pixel that was drawn you had to write code for that, years have gone and now we have standard formats for models, sounds, graphics, etc. and most importantly we have plenty of frameworks to build your game on top of them.
One of the latest and greatest frameworks to create games is XNA; you can think of XNA for game programming pretty much like Visual Studio for programming in C#, it allows you to focus on the actual game (theme, logic, etc), giving you all the functions ready to be used to do most of the drawing stuff, one of the cool things about XNA is that it will allow you to run your own games in your XBox 360, it doesn't get much better than that
A couple of friends and I have decided to start writing games just for fun, we will probably start with a simple pac-man, although we'll plan on making it extensible, we'll start with something really simple.
A rough idea of what we're shooting for if we go for the pac-man would be:
- Single world
- Single level
- one type of ghost
- we'll most likely create our own graphics in Paint and create our own sounds.
points of extensibility could be
- plug-in model to create new ghosts
- plug-in model to create new worlds and levels
as simple as that is, it allows you to extend as much as you can, however, we have to get there first.
I will blog about all my experiences (and source code) creating this first game, I'm really hoping not to fail as many have before. Just as many guys before me, I hope to, if not help, at least inspire other people to start in the wonderful art of game programming
If you want to join me, you could start by downloading XNA and Visual Studio 2005 Express Edition, you also need to download The Wizard, which is a simple animation that will teach you most of the basics of what you need to create your first game and will help you get familiar with XNA.
Until next time
Thursday, September 28, 2006
google reader finally has a decent user interface
I have been using google reader for a couple months now, but to be honest it had a horrible user interface, until just now, it finally groups the feeds by category in folders and shows you counts of unread items... just like a normal RSS reader
this is probably all over the news now, but I just logged in to check my blogs and saw the new interface, it wasn't there this morning... anyway, check it out
Monday, September 25, 2006
Simple Generic Factory
Last time I presented you with simple factory pattern using dictionaries of methods and talked about Steven's (much more elegant and generic) implementation. I kept playing with Steven's code, whilst the dynamic code generation is pretty cool I kept thinking there was an easier way to accomplish the same thing; I finally came up with a much shorter version, here it is:
public static class SimpleStaticGenericFactory<TKey, TBaseType> where TBaseType : class {
public delegate TBaseType BaseTypeInvoker();
private static Dictionary<TKey, BaseTypeInvoker> methods =
new Dictionary<TKey, BaseTypeInvoker>();
public static void Add(TKey key, BaseTypeInvoker instantiatorMethod) {
if (!methods.ContainsKey(key))
methods.Add(key, instantiatorMethod);
}
public static void CreateInstance(TKey key) {
if (methods.ContainsKey(key))
methods[key]();
else //what would you like to do in this case?
throw new ArgumentException(string.Format("{0} not found", key));
}
}
that's it!, or if you prefer the non-static version:
public class SimpleGenericFactory<TKey, TBaseType> where TBaseType : class {
public delegate TBaseType BaseTypeInvoker();
private Dictionary<TKey, BaseTypeInvoker> methods =
new Dictionary<TKey, BaseTypeInvoker>();
public void Add(TKey key, BaseTypeInvoker instantiatorMethod) {
if (!methods.ContainsKey(key))
methods.Add(key, instantiatorMethod);
}
public void CreateInstance(TKey key) {
if (methods.ContainsKey(key))
methods[key]();
else //what would you like to do in this case?
throw new ArgumentException(string.Format("{0} not found", key));
}
}
We *don't really need* the CreateInstance method there, we could call the method directly if the dictionary was public, but it wouldn't be good to give them access to the dictionary. Using the reports from our last example, we could use it like:
SimpleStaticGenericFactory<string, BaseReport>.Add("report1", delegate() { return new Report1(); });
SimpleStaticGenericFactory<string, BaseReport>.Add("report2", delegate() { return new Report2(); });
SimpleStaticGenericFactory<string, BaseReport>.CreateInstance("report1");
or using the non-static version:
SimpleGenericFactory<string, BaseReport> reports1 =
new SimpleGenericFactory<string, BaseReport>();
reports1.Add("report1", delegate() { return new Report1(); });
reports1.Add("report2", delegate() { return new Report2(); });
reports1.CreateInstance("report1");
nice and simple, I'll put an example together for a plug-in model using this factory
Saturday, September 23, 2006
Simple factory pattern using Dictionaries of methods
I have been talking about arrays of methods, dictionaries of methods, how both techniques are very similar in implementation, when you can use either one, and a practical implementation of the simple factory pattern using arrays of methods. Today I'll show you the implementation of the simple factory pattern using dictionaries of methods and then we'll move into more interesting things, Steven posted an implementation of the same pattern that leaves my implementation in the dust, I'm still posting my code here as another example of how you can use dictionaries of methods.
using ReportCreatorDictionary = Dictionary<string, ReportCreatorDelegate>;
//this is our base product
abstract class BaseReport {
public BaseReport() {
Console.WriteLine("Base Report Created");
}
public abstract void Execute();
}//product 1
class Report1 : BaseReport {
public Report1():base() {
Console.WriteLine("Report1 created");
}
public override void Execute() {
Console.WriteLine("Report1");
}
}//product 2
class Report2 : BaseReport {
public Report2():base() {
Console.WriteLine("Report2 created");
}
public override void Execute() {
Console.WriteLine("Report2");
}
}
delegate BaseReport ReportCreatorDelegate();
//this is the actual factory
class ReportGenerator {
static BaseReport CreateReport1() {
return new Report1();
}
static BaseReport CreateReport2() {
return new Report2();
}
static ReportCreatorDictionary reports;
static ReportGenerator() {
reports = new ReportCreatorDictionary();
reports.Add("Report1", new ReportCreatorDelegate(CreateReport1));
reports.Add("Report2", new ReportCreatorDelegate(CreateReport2));
}
public static BaseReport Execute(string reportType) {
return reports[reportType]();
}
}
and the way to use it:
BaseReport report1 = ReportGenerator.Execute("Report1");
report1.Execute();
BaseReport report2 = ReportGenerator.Execute("Report2");
report2.Execute();
of course the choice of the report to be executed can come from anywhere (drop down list, link on a web page, configuration, etc)
The problem with this implementation, as Steven points out, is that you have to change the factory every time you add a new product to the factory and is not flexible enough to create (for example) a plug-in model, because all the types are required to be known at compile time; and if you need a factory for another product you have write a new factory (duh!, you might think). Steve's implementation is a Generic factory that can be re-used with any other types (products); no need to write the factory, you just add the products to it and is ready to be used, go check it out, is definitely worth reading.
Steve's code has given me another idea, I'll see if it actually works the way I have pictured it and then blog about it
for now here's the code for the dictionaries of methods and this example of the factory; as always, play with it, learn from it, improve it
Friday, September 22, 2006
IE "Blog this" integrates with Live Writer
a few days ago I was reading on Geoff's blog that he became a Live Writer Junky and I commented that I just missed the "blog this" and "send to web snippets" features from Flock; well, Geoff wrote an extension for IE that adds this functionality and allows you to blog in Live Writer kinda the way Flock does it, but of course you get all the niceties (is this a word?) of Live Writer
that also led me to learn something new, I didn't know it was so easy to create an extension for IE, just using javascript and some registry keys, check it out
Thursday, September 21, 2006
Basic good practices
I've been kinda busy lately doing a lot of refactoring, I hope to be back to post about C# interesting things like generics and patterns soon
meanwhile, I've been catching up reading my blogs, I got to this post from Jeremy Miller, "The Will to be good", there are a few points that I have always taken to heart:
- Don't tolerate bad code.
- Don't write code on top of bad code.
- Fix a broken build
- The "design hat" never comes off.
- Does quality even matter?. Absolutely
For me these things are more basic than even testing, if you follow these simple guidelines your tests will run smoothly
I don't tolerate bad code and/or developers who write sloppy code, I don't even tolerate to have warnings in my code
You will always find people in some teams who are not very good at these basic things (and I'm not talking about my current team, in case they are reading this), and you have to learn how to deal with these people, if you are the team lead that's part of your job, you have to show them better techniques, even though I know is hard, specially if you are younger than them; if you are not the team lead it gets even harder, but all you can do is be an example, if you follow those practices you will be a better developer than one that doesn't, and people will see that and start listening to you at some point.
Managers may get scared when they hear you are refactoring like mad, but that shouldn't stop you from doing so (you might even have to do it after work hours), after all you are just making life easier for you and your team
Friday, September 15, 2006
Wasabi on Wails
People rewriting their stuff in this new cool framework, what are you waiting for?
JJJ
smart-er Rootkits in Codecs
I'm afraid this is going to bite a LOT of people
You’re surfing the web, and you find a video that you really want to watch, (no, not one of “those” videos… well, not necessarily anyway), but it says you have to install a codec. Codec stands for compressor/ decompressor and is used to make otherwise huge video files into a more manageable size. You install the codec, and maybe you see the video, and maybe you don’t, but guess what? You’ve been rootkitted! Now, on one level, that’s just the classic bait and switch/ trojan horse scenario, but the _details_ are quite interesting.
be careful out there
Wednesday, September 13, 2006
Tuesday, September 12, 2006
Incremental search in Internet Explorer "a la Firefox"
In case you haven't seen this yet (and if you use Internet Explorer for whatever reason), you can now have the (very requested) feature of finding text as you type in IE, almost like in Firefox
Dictionaries of methods in C#
This article is a follow up of my previous article arrays of methods in C#, as noted by some of the commenters, it is possible to implement this technique using dictionaries, Steven even (Steven even... kinda funny... anyway, where was I? oh ok) posted a comment with the full implementation of my code using dictionaries, I just wanted to hightlight some of the differences and perhaps give you a hint on when to use either one (although it should be obvious, but I've learnt that there is no such thing as obvious)
Since the dictionaries implement a <Key, Value> way of storing stuff, you can store an int or a string, or any other type as the key as long as you don't have duplicated entries, and on the value you can store the pointer to the method you want to execute, when using arrays you are limited to use types that can be converted to integers for the index, with dictionaries you could use other types as the index.
let's see the last example and how it changes, the changes -as you will see- are pretty minimal to switch between the two
- The delegate declaration doesn't change
- now instead of an array, we have a dictionary, it looks something like this:
Dictionary<int, AddStringDelegate> addStringMethods;- The methods declaration stay the same
- Adding the methods to our dictionary is just a little bit different:
addStringMethods = new Dictionary<int, AddStringDelegate>(4);
addStringMethods.Add((int)StringType.Type1, new AddStringDelegate(AddStringType1));
addStringMethods.Add((int)StringType.Type2, new AddStringDelegate(AddStringType2));
addStringMethods.Add((int)StringType.Type3, new AddStringDelegate(AddStringType3));
addStringMethods.Add((int)StringType.Type4, new AddStringDelegate(AddStringType4));
- The implementation to use the methods remains exactly the same
public void AddString(string someValue, StringType stringType) {
addStringMethods[(int)stringType](someValue);
}
We're done! so we just had to change a couple places and we are now using dictionaries of methods instead of arrays.
So when do I use dictionaries over arrays? basically, when you need it, arrays are a lot more simple and lightweight, dictionaries add weight but give you a lot more flexibility, for example if you want to use a string as the index to access your method, then the dictionary is the way to go; dictionaries also allow you to add/remove items from it, I don't know that it would be a good idea to apply that in this case, but you can do it. If you can get an integer index I would use the array instead, you don't really need the dictionary in that case.
If no one (out of my 3 readers J) beats me to it, I'll run some tests using both approaches and see if there is any relevant difference in speed and I'll post the results here. If you do the tests, and you blog about it, and I find out, I'll put a link here just as a follow up to this
Here's the full code, play with it, break it, expand it, make it better
class FileGeneratorBase {
Dictionary<int, AddStringDelegate> addStringMethods;
public FileGeneratorBase() {
addStringMethods = new Dictionary<int, AddStringDelegate>(4);
addStringMethods.Add((int)StringType.Type1, new AddStringDelegate(AddStringType1));
addStringMethods.Add((int)StringType.Type2, new AddStringDelegate(AddStringType2));
addStringMethods.Add((int)StringType.Type3, new AddStringDelegate(AddStringType3));
addStringMethods.Add((int)StringType.Type4, new AddStringDelegate(AddStringType4));
}
public void AddString(string someValue, StringType stringType) {
addStringMethods[(int)stringType](someValue);
}
void AddStringType1(string someValue) {
OutputText(string.Format("String Type 1: {0}", someValue));
}
void AddStringType2(string someValue) {
OutputText(string.Format("String Type 2: {0}", someValue));
}
void AddStringType3(string someValue) {
OutputText(string.Format("String Type 3: {0}", someValue));
}
void AddStringType4(string someValue) {
OutputText(string.Format("String Type 4: {0}", someValue));
}
void OutputText(string someValue) {
Console.WriteLine(someValue);
}
}
class Program {
static void Main(string[] args) {
//*** Arrays of methods demo
FileGeneratorBase fg = new FileGeneratorBase();
fg.AddString("some value", StringType.Type1);
fg.AddString("some other value", StringType.Type2);
fg.AddString("one last value", StringType.Type3);
fg.AddString("testing out of bounds", StringType.Type4);
Console.ReadLine();
}
}
on my next article I'll show you the implementation of this technique applied to the simple factory pattern just to close the loop.
Friday, September 08, 2006
Simple factory pattern made simpler
A Simple Factory pattern returns an instance of one of several possible classes depending on the data provided to it.
Last week I talked about a technique that allows you to reduce (and effectively reuse) code when you have a pattern of 2..n values, where for each value you want to execute a different method with the same signature
if (someValue == SomeEnum.Type1)
Method1("value 1");
else if (someValue == SomeEnum.Type2)
Method2("value 2");
else if (someValue == SomeEnum.Type2)
Method3("value 3");
while the method is valuable by itself, there is a pattern where it fits perfectly, this is the simple factory method; let's start with a reports example.
Suppose we have a Base Report class, and two implementations of it:
abstract class BaseReport {To use the arrays of methods, we have to declare our delegate to instantiate the reports:
public BaseReport() {
Console.WriteLine("Base Report Created");
}
public abstract void Execute();
}
class Report1 : BaseReport {
public Report1():base() {
Console.WriteLine("Report1 created");
}
public override void Execute() {
Console.WriteLine("Report1");
}
}
class Report2 : BaseReport {
public Report2():base() {
Console.WriteLine("Report2 created");
}
public override void Execute() {
Console.WriteLine("Report2");
}
}
enum ReportType {
Report1,
Report2
}
delegate BaseReport ReportCreatorDelegate();Then we have our factory class that contains:- An array of methods
- a method to instantiate each report
- The method to execute the requested report, depending on the parameters
class ReportGenerator {
static BaseReport CreateReport1() {
return new Report1();
}
static BaseReport CreateReport2() {
return new Report2();
}
static ReportCreatorDelegate[] reports;
static ReportGenerator() {
reports = new ReportCreatorDelegate[2];
reports[0] = new ReportCreatorDelegate(CreateReport1);
reports[1] = new ReportCreatorDelegate(CreateReport2);
}
public static BaseReport Execute(ReportType reportType) {
return reports[(int)reportType]();
}
}
Then here's how we use this code:
BaseReport report1 = ReportGenerator.Execute(ReportType.Report1);Update: Pablo commented "the fact that calling the factory with the type you want to create is kinda the same as creating it yourself", it is true, I could've just created an instance directly my self there, but this was just a bad example from my part, that value could come from a drop down select list, from a configuration file, etc, I just did a bad job showing you how you could use the code.
report1.Execute();
BaseReport report2 = ReportGenerator.Execute(ReportType.Report2);
report2.Execute();
Console.ReadLine();
This particular example is very light weight and works great to implement this simple pattern, but it has the limitation that it works only for values that can be converted to integerAyende and Steven pointed out that the same technique can be implemented using Dictionaries, this would allow us to have other types as the index of our collection of methodsOn my next posts I'll show you this technique, using Dictionaries of methods
You can find the full source code for this and my previous example here
How to install multiple personalities of Turbo Explorer
Andy has created a program that allows you to install multiple personalities of the Turbo Explorer products (since by default you can only install one)
The steps, according to Andy are really simple:
How to install
==============
1. Install the first Turbo Explorer personality with the installer
that is included in the Turbo Explorer download.
2. Extract the next Turbo Explorer personality installer to a directory
of you choice.
3. Start the TurboMerger.exe and select the directory where you have
extracted the next Turbo Explorer personality installer. Press the
"Install" button. In the InstallShield installer do not change the
directories. Doing this will destroy the Turbo Explorer installation.
4. Proceed with step 2. until you have installed all personalities you
want.
if you are one of the people who downloaded these products, this is definitely a must have
where Delphi stands right now
Daniel Wichnewski just posted the number of downloads for the turbo explorer products, a few thousand downloads, these are the most significant numbers:
turbocpp.exe: 464
turbocpp_de.exe: 348turbocsharp.exe: 232
turbocsharp_de.exe: 226turbodelphi.exe: 766
turbodelphi_de.exe: 851turbodelphi4net.exe: 200
turbodelphi4net_de.exe: 266
Delphi for .NET doesn't seem to be very popular
Wednesday, September 06, 2006
XML Notepad
going through my blogs I found this little tool
XML Notepad 2006 provides a simple intuitive user interface for browsing and editing XML documents.
definitely one more to have in the toolbox
Finding great developers
Joel talks about his experiences hiring developers and how difficult it is to get the great ones, his main point is that the great developers are already taken and that most of the resumes you get are from the pretty bad developers
The great software developers, indeed, the best people in every field, are quite simply never on the market.
The average great software developer will apply for, total, maybe, four jobs in their entire career.
I guess I'm on a good path, I'm still on my first job J
I've had many discussions with co-workers about this same topic, while I pretty much agree with everything Joel says on this post, there's some people who think that is not that hard to get good developers
I'm of the idea that from a generation of (so-called) computer scientists you get one or two good developers (the great ones are a lot more rare than that)
Joel then goes on describing how you could get some of those great developers:
Go to the mountain Internships Build your own community*
That pretty much leaves out medium and small companies, there's no way they could afford to do things like that
He closes the article by listing some problems you might face if you use employee referrals
Unfortunately for me I haven't personally met anyone that I consider a great developer, I wish I had because I would've learnt so much more and faster; I have met very few that I consider good developers, but I guess is all up to your own standards, it's about how passionate you are about developing, it's about how good you are
Ayende pictures developing as an art, that describes it fairly well for me, I believe a talent is required, and as such, you are born with it, sure you can learn it, but you won't be anywhere near as good as someone who has the talent
This blog post doesn't make justice to Joel's article, Joel has been on the business for quite a while, he does know a thing or two about developers J, go check his article
The Turbos are back
Not the latest and greatest news, I'm just catching up with my blogs; the guys at "DevCo" have been working really hard and came out with free versions of the IDEs for Delphi, C++ and C#
What does it have for you? If you are using VS for .NET 1.x, not much, if you are using .NET 2.0 there's (almost) nothing here for you, but if you still need Win32 applications, these are by far the best IDEs to create native win32 applications
Please Note! Only one Turbo Explorer edition can be installed per machine, so be sure to download and install the one that's best for you!
It's free and is the best, you can't go wrong with that
Wednesday, August 30, 2006
Arrays of methods in C#
How many times have you written code that goes something like this:
if (someValue == SomeEnum.Type1)
Method1("value 1");
else if (someValue == SomeEnum.Type2)
Method2("value 2");
else if (someValue == SomeEnum.Type2)
Method3("value 3");
maybe you used a switch statement to accomplish the same kind of thing.
You can see the pattern there, Method1, Method2 and Method3 all have the same signature and they get executed when the value Type1, Type2 or Type3 is passed. Wouldn't be nice if we could reduce that to a single line?
That's exactly what arrays of methods can do for you, let's see an example, before we can use them we need to set them up
Since all the methods share the same signature it means we can use a delegate to represent all of the methods.
delegate void AddStringDelegate(string someValue);
Now we can declare an array of delegates:
AddStringDelegate[] addStringMethods;
We will use an enumeration to access the items of the array:
enum StringType {
Type1,
Type2,
Type3,
Type4
}
Then we need the actual methods declaration:
void AddStringType1(string someValue) {
OutputText(string.Format("String Type 1: {0}", someValue));
}
void AddStringType2(string someValue) {
OutputText(string.Format("String Type 2: {0}", someValue));
}
void AddStringType3(string someValue) {
OutputText(string.Format("String Type 3: {0}", someValue));
}
finally, on the constructor of our class, we assign the methods to the array to get our array of methods:
addStringMethods = new AddStringDelegate[3];
addStringMethods[(int)StringType.Type1] = new AddStringDelegate(AddStringType1);
addStringMethods[(int)StringType.Type2] = new AddStringDelegate(AddStringType2);
addStringMethods[(int)StringType.Type3] = new AddStringDelegate(AddStringType3);
It's ready to be used, let's see what the implementation looks like:
public void AddString(string someValue, StringType stringType) {
addStringMethods[(int)stringType](someValue);
}
As you can see we can access the required method by converting the enumeration to an int type, our code was just reduced to 1 line; passing the desired enum type gets to our method in one shot
I'll let you decide when you want to use this technique, I wouldn't recommend using it in a small class that gets instantiated and thrown very fast and often, but in some cases it might even be useful there
I think it would be specially useful if we had this kind of pattern inside a singleton class where the class could potentially live a lot longer, you could do all the work to initialize your array of methods and be able to re-use it effectively
Here's the full code for this example, on my next post I'll show you how you could use this technique to implement some kind of factory pattern or what is sometimes referred to as simple factory pattern
class FileGeneratorBase {
delegate void AddStringDelegate(string someValue);
AddStringDelegate[] addStringMethods;
public FileGeneratorBase() {
addStringMethods = new AddStringDelegate[4];
addStringMethods[(int)StringType.Type1] = new AddStringDelegate(AddStringType1);
addStringMethods[(int)StringType.Type2] = new AddStringDelegate(AddStringType2);
addStringMethods[(int)StringType.Type3] = new AddStringDelegate(AddStringType3);
addStringMethods[(int)StringType.Type4] = new AddStringDelegate(AddStringType4);
}
public void AddString(string someValue, StringType stringType) {
addStringMethods[(int)stringType](someValue);
}
void AddStringType1(string someValue) {
OutputText(string.Format("String Type 1: {0}", someValue));
}
void AddStringType2(string someValue) {
OutputText(string.Format("String Type 2: {0}", someValue));
}
void AddStringType3(string someValue) {
OutputText(string.Format("String Type 3: {0}", someValue));
}
void AddStringType4(string someValue) {
OutputText(string.Format("String Type 4: {0}", someValue));
}
void OutputText(string someValue) {
Console.WriteLine(someValue);
}
}
class Program {
static void Main(string[] args) {
FileGeneratorBase fg = new FileGeneratorBase();
fg.AddString("some value", StringType.Type1);
fg.AddString("some other value", StringType.Type2);
fg.AddString("one last value", StringType.Type3);
fg.AddString("testing out of bounds", StringType.Type4);
Console.ReadLine();
}
}
updated: To initialize the array using the same enum instead of hardcoded values of 0..4
Monday, August 28, 2006
Hiding generics complexity part II
on previous articles I talked about complex generic types
and how to make those types more readable by using aliases
using System.Collections.Generic;
using FilesList = List<string>;
using FoldersWithFiles = Dictionary<string, List<string>>;
using ComputersWithFiles = Dictionary<string, Dictionary<string, List<string>>>;
Here is another technique to accomplish readable code while still using generics.
We can subclass the generics in this way:
class FilesList2 : List<string> { }
class FoldersWithFiles2 : Dictionary<string, List<string>> { };
class ComputerFiles2 : Dictionary<string, Dictionary<string, List<string>>> { }
class ComputersWithFiles2 : Dictionary<string, Dictionary<string, List<string>>> { }
The code to use them is pretty much the same as when we were using aliased generics, but there is a little "problem", KeyValuePair is a struct and as such it doesn't support inheritance, which means we can't apply this technique to this type, so we can combine aliased types for the KeyValuePair and sub-classing for the rest
This brings us to another point, when we have code like this:
Console.WriteLine("List of Directories with files");
FoldersWithFiles2 foldersWithFiles = GetFoldersWithFiles();
foreach (FoldersWithFilesPair kv in foldersWithFiles) {
Console.WriteLine(string.Format(" Folder: [{0}]", kv.Key));
ListFiles((FilesList2)kv.Value);
}
If we want to use FoldersWithFilesPair.Value as a FilesList2 type we have to typecast it, this is because FilesList2 is a new type and FoldersWithFilesPair.Value is a List<string>; remember that C# is a type-safe language.
Subclassing the generic types in this way can give you more benefits than simply more readable code, as any other class they can implement methods so you can assign them more specific tasks/methods that reflect more accurately their responsibility
There is a big difference betwee using aliased generics and subclassed generics, aliased types are the exact same type, just with a different name, subclassed generics are a new name and a new type.
This is it for now, you now have a new tool in your toolbox, as with everything else in life, don't abuse it!
Hope to see some code where people are using these techniques
as promissed, here is the full source code, the code is free as in LPGL
Sunday, August 27, 2006
the church of... Google?
Thou shalt have no other Search Engine before me, neither Yahoo nor Lycos, AltaVista nor Metacrawler. Thou shalt worship only me, and come to Google only for answers.
..way too much free time on their hands
what!? you are going to join?
Friday, August 25, 2006
The programmer's Bill of Rights
I propose we adopt a Programmer's Bill of Rights, protecting the rights of programmers by preventing companies from denying them the fundamentals they need to be successful.
...is just weird that the link is 666...
finally {} is not a good place to commit your transactions
I just fixed some code (not written by me!) that went something like this:
transaction = connection.BeginTransaction();
try {
try {
//***.... database operations here...
} finally {
transaction.Commit();
}
} catch {
transaction.RollBack();
}
First of all, there is a bug there, if an exception is ever raised, it will raise a new exception because it cannot rollback a transaction that was committed (the message will not be that clear, but that's what it means, the exception says something about unable to complete the operation due to the current state of the object), and you'll lose the original exception that you got
Second, it's just wrong, it defeats the purpose of using a transaction, is like you are saying
//*** delete some records
//*** update some records
//*** some db operation that caused some exception
//*** finally, commit what I had done so far
leaving your data in an unknown state because you commited all the operations up until it failed
hint: always use "using" for any DB related stuff (connections, commands, transactions, etc)
Tuesday, August 22, 2006
Hiding generics complexity
On my last post I showed you some wicked use of generics, Ayende says he can't read code like that and provided an alternative; I agree with him, it is very ugly code, but there is hope!
here's the equivalente code for the first section (note that I'm still using generics, even if it doesn't look like it), where we wanted to store a list of file names:
FilesList filesList = GetFilesList();Then we have the bidimensional generic, to store folder name and the files in it:
ListFiles(filesList);
FoldersWithFiles foldersWithFiles = GetFoldersWithFiles();
foreach (FoldersWithFilesPair kv in foldersWithFiles) {
Console.WriteLine(string.Format(" Folder: [{0}]", kv.Key));
ListFiles((FilesList)kv.Value);
}
And finally where we store computer names, with the folders, with the files in it:
ComputerFiles computerFiles = GetComputerFiles();And my last example would now look like this:
foreach (ComputersWithFoldersPair kv in computerFiles) {
Console.WriteLine(string.Format("Computer: [{0}]", kv.Key));
foreach (FoldersWithFilesPair kv1 in kv.Value) {
Console.WriteLine(string.Format(" Folder: [{0}]", kv1.Key));
ListFiles((FilesList)kv1.Value);
}
}
ComputerFiles computerFiles = new ComputerFiles();instead of this:
Dictionary<string, Dictionary<string, List<string>>> ComputerFiles =
new Dictionary<string, Dictionary<string, List<string>>>();
Now, if the code is equivalente and I'm still using generics, what did I do?
I am using aliased generics (yup, invented here too J) which give me friendly names, instead of the ugly multidimensional generics syntax
Here's the aliases declaration:using System.Collections.Generic;
using FoldersWithFilesPair = KeyValuePair<string, List<string>>;
using ComputersWithFoldersPair = KeyValuePair<string, Dictionary<string, List<string>>>;
using FilesList = List<string>;
using FoldersWithFiles = Dictionary<string, List<string>>;
using ComputerFiles = Dictionary<string, Dictionary<string, List<string>>>;
The best of both worlds, you can use complex generic data structures and keep your code readable.
You put all the uglyness in a simple place, and you are able to use friendly names which look like normal classes, plus you get more extensibility because you could change the signature of the aliased generics without breaking the code.
On my next post I'll show you another technique to accomplish the same thing, and some gotchas, then I'll put the full source code in a zip file so you can download it.
Blogging since 1969
some people have just been blogging for too long
(oh yeah, and I wanted to test the Live Writer image uploading capabilities...)
Monday, August 21, 2006
C# multidimensional generics
You can think of Generics as Arrays on steroids or Collections on steroids or a combination of both, they offer an extensible list of items with type safety; or as MSDN puts it:
Generics allow you to define type-safe data structures, without committing to actual data types.
One thing that I haven't seen much is how you can use multidimensional generics (yup, invented here J), let me explain what I mean
let's say we wanted to store a list of file names, we could do something like:
List<string> filesList = GetFilesList();
ListFiles(filesList);
now, we want a list of directories with the files in them, we could use a bidimensional generic type to keep the directory name on a dictionary key and the list of files on the dictionary value:
Dictionary<string, List<string>> foldersWithFiles = GetFoldersWithFiles();
foreach (KeyValuePair<string, List<string>> kv in foldersWithFiles) {
Console.WriteLine(string.Format(" Folder: [{0}]", kv.Key));
ListFiles(kv.Value);
}
finally, let's say we want a list of computers, with folders that contain files, we can use a multidimensional generic type that has the computer name on a dictionary key, and the folders with files on another dictionary stored as the key:
Dictionary<string, Dictionary<string, List<string>>> ComputerFiles = GetComputerFiles();
foreach (KeyValuePair<string, Dictionary<string, List<string>>> kv in ComputerFiles) {
Console.WriteLine(string.Format("Computer: [{0}]", kv.Key));
foreach (KeyValuePair<string, List<string>> kv1 in kv.Value) {
Console.WriteLine(string.Format(" Folder: [{0}]", kv1.Key));
ListFiles(kv1.Value);
}
}
For the sake of completeness here's the ListFiles function, just so you can see some cool use of generics combined with anonymous delegates:
static void ListFiles(List<string> filesList) {
filesList.ForEach(new Action<string>(delegate(string s) { Console.WriteLine(string.Format(" {0}", s)); }));
}
As you can see, with generics we can create some complex type-safe data structures, however, as always, some people will complain that multidimensional generics become very cryptic;
and you can see it if you did something like:
Dictionary<string, Dictionary<string, List<string>>> ComputerFiles = new Dictionary<string, Dictionary<string, List<string>>>();
in my next post I'll show you a couple techniques you can use to hide the generics complexity while keeping all of their benefits
Tuesday, August 15, 2006
RegisterChannel is obsolete, use RegisterChannel instead
I got this error:
Warning 6 'System.Runtime.Remoting.Channels.ChannelServices.RegisterChannel(System.Runtime.Remoting.Channels.IChannel)' is obsolete: 'Use System.Runtime.Remoting.ChannelServices.RegisterChannel(IChannel chnl, bool ensureSecurity) instead.'
It threw me off for a little while because System.Runtime.Remoting.ChannelServices.RegisterChannel doesnt' really exist
the problem there was that they just missed the .Channels part of the namespace, so it should've been:
"use 'System.Runtime.Remoting.Channels.ChannelServices.RegisterChannel(IChannel chnl, bool ensureSecurity) instead"
ok, that was the first part, now if this overload is obsolete, which one is the equivalent?
RegisterChannel(chnl, true)
or
RegisterChannel(chnl, false)
Reflector to the rescue, the equivalent is to use false as the second parameter, that's what the current function does right now when you call
RegisterChannel(chnl);
it calls:
ChannelServices.RegisterChannelInternal(chnl, false);
Monday, August 14, 2006
First bug in live write
This happens when you add multiple blogs accounts, on the last dialog if you uncheck the "switch to this blog now" (or something like that) the new blog won't appear in your list of blogs, so you are not able to switch to that
restarting the app refreshes the list
Hello world from live writer
This thing is pretty cool, it allows me to write to my multiple blogs just fine, check out their blog too
cool use of the coallesce ?? operator in C#
We just coded something like (please disregard the variable names, I'm just illustrating the point)
return myCollections.Services ?? (myCollections.Services = dbLayer.GetServices());
one-liner to do a bunch of stuff, and it's still clear what you are trying to do, if you know the ?? operator you can stop right here, if you don't let me explain a bit more
the ?? operator returns the left-hand operator if it is NOT NULL, else it returns the right operand
so this code is the equivalent of:
if (myCollections.Services == null)
myCollections.Services = dbLayer.GetServices();
return myCollections.Services;
Wednesday, August 09, 2006
Notepad hidden features: How to use Notepad to create a (manual) log file
To create a log file in Notepad:
1. Click Start, point to Programs, point to Accessories, and then click Notepad.
2. Type .LOG on the first line, and then press ENTER to move to the next line.
3. On the File menu, click Save As, type a descriptive name for your file in the File name box, and then click OK.
When you next open the file, note that the date and time have been appended to the end of the log, immediately preceding the place where new text can be added.
You can use this functionality to automatically add the current date and time to each log entry.
How to Use Notepad to Create a Log File
Pretty cool, everytime you open the file after that (in Notepad), it adds a timestamp
and you can enter some text
get Delphi for free
Turbo Delphi, Turbo Delphi for .NET, Turbo C++ and Turbo C# will be generally available in the third quarter of 2006. The Turbo Explorer editions of these products will be free. Pricing for the Turbo Professional editions will be under $500. Student academic pricing for the Turbo Professional editions will be under $100. For more information, visit www.turboexplorer.com.
August 8, 2006 - Turbos Press Release
We'll see what they can do against the Microsoft Express versions which have been out and free for a while, right now I don't see how they could compete but we'll see; if they run (and probably will) against the .NET Framework 1.1 that will discourage a lot of people
Monday, August 07, 2006
I'm natural hacker material J
Points For Style
Again, to be a hacker, you have to enter the hacker mindset. There are some things you can do when you're not at a computer that seem to help. They're not substitutes for hacking (nothing is) but many hackers do them, and feel that they connect in some basic way with the essence of hacking.
* Learn to write your native language well. Though it's a common stereotype that programmers can't write, a surprising number of hackers (including all the most accomplished ones I know of) are very able writers.
* Read science fiction. Go to science fiction conventions (a good way to meet hackers and proto-hackers).
* Train in a martial-arts form. The kind of mental discipline required for martial arts seems to be similar in important ways to what hackers do. The most popular forms among hackers are definitely Asian empty-hand arts such as Tae Kwon Do, various forms of Karate, Kung Fu, Aikido, or Ju Jitsu. Western fencing and Asian sword arts also have visible followings. In places where it's legal, pistol shooting has been rising in popularity since the late 1990s. The most hackerly martial arts are those which emphasize mental discipline, relaxed awareness, and control, rather than raw strength, athleticism, or physical toughness.
* Study an actual meditation discipline. The perennial favorite among hackers is Zen (importantly, it is possible to benefit from Zen without acquiring a religion or discarding one you already have). Other styles may work as well, but be careful to choose one that doesn't require you to believe crazy things.
* Develop an analytical ear for music. Learn to appreciate peculiar kinds of music. Learn to play some musical instrument well, or how to sing.
* Develop your appreciation of puns and wordplay.
Saturday, August 05, 2006
The problem of naming your blog after a technology
You can't know it all, so what to do?
You can't know it all. No matter how smart you are, no matter how comprehensive your education, no matter how wide ranging your experience, there is simply no way to acquire all the wisdom you need to make your business thrive.Donald Trump - Learning - Business - Knowledge
In the programming world we hear this more and more often, frameworks have thousands of classes, functions and features, even the people behind those frameworks don't know other parts of the framework, what makes you think you can know it all
It's key to be comfortable with your own ignorance. Understand that you can't know it all and stop trying to or pretending that you do. Understand that other people are ignorant too, and help educate them when you can rather than resenting their shortfall. On the same track, don't resent someone who's trying to teach you something either, swallow your pride and better yourself for it.
The Critical Path / eMail Newsletter / Issue 6.1
My approach to this issue is to learn the language features as good as I can, then on the features of the frameworks I make a distinction on technologies that I'm interested in learning right now and learn them, and as many others that might be useful at some point, but the point is to be aware that such features exist and what they do; that way when you actually need them you can find them a lot faster because you know there is something to do just that and you avoid reinventing the wheel in many cases
services like del.icio.us can help you with this problem, if you see something cool that you might be interested in the future you can save a link and tag it with something like "future" and you can build a list of things to learn or that you can posibly use some time later
You can't put everything in your brain, so use the existing tools to do some of that work for you
Is just like in soccer, is always good to win, but if you can't win is good to tie, if you can't tie is good to lose for as little difference as possible
Improve your tabbed browser experience
Ctrl Tab Preview
This is an extension that replaces the behavior of Ctrl+Tab. Instead of directly changing tab it works some thing like Alt+Tab on windows. It views preview of the tab and you can change directly to the tab you want to or just go through all tabs to see what you got in them. A pictures tells more then thousands words so look at the pictures or try it.

SessionSaver
SessionSaver restores your browser -exactly- as you left it, every startup, every time. Not even a crash will phase it. Windows, tabs, even things you were typing -- they're all saved. Use the menu to add + remove sessions; right, shift, or middle-clicking will delete. "Simple mode" for peace of mind, or "Expert mode" for advanced flexibility. Just Click. Install. Rad.
Perma Tabs
Adds the ability to turn tabs of your choice into permanent tabs ("permaTabs") that can't be closed, and stick around between sessions.
Multiple home pages in your browser
One of those things that not many people know, most modern browsers these days allow multiple home pages.
Firefox/Flock
Internet Explorer
Opera also allows you to do it, quite a bit more complicated, but can be done
Multiple home pages in OperaIn Firefox/Flock there is also an extension that allows you to cycle your home pages:
Home Page Cycler
Load a different home page each time Firefox starts.
Tuesday, August 01, 2006
Sunday, July 30, 2006
using the right tool for each job, which web browser do you use?
I use 5 different browsers approximately as:
70% - Flock - This is like a Firefox on steroids (actually based on the Firefox engine), allows me to blog from it, integrates with flickr, etc, Any firefox extension that I use, I load on this browser
10% - Firefox - I use this browser pretty much clean of all extensions, when I want to load a site and leave it running on the background I use this browser.
10% - Internet Explorer 7 - Beta 3 at this point, so far I like it a lot, but there are a bunch of sites that just refuse to work with it, once it becomes a release version I'm sure I'll use it more
5% - Internet Explorer 6 - On the other hand, there are some sites that only look good or only allow Internet Explorer 6, I use this browser for IE specific sites and/or sites that I trust (e.g. intranet)
5% - Opera - Since out of my list of browsers, this is the least used, this kinda gives me more "protection" when I'm visiting sites that I don't trust that much (e.g. sites about hacking)
Friday, July 28, 2006
new class for creating SQL connection strings in .NET 2.0
SqlConnectionStringBuilder Class Note: This class is new in the .NET Framework version 2.0.Provides a simple way to create and manage the contents of connection strings used by the SqlConnection class
SqlConnectionStringBuilder Class (System.Data.SqlClient)
once you create an instance of that class, you can read/write to the individual items of the connection through properties or through the indexer as:
//you could pass the connection string in the constructor too
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
//using the indexer
builder["DataSource"] = "someDataSource";
//or using the property
builder.DataSource = "someDataSource";
this would be useful in a number of cases, for example if you had two connection strings that were different only by the server name
Thursday, July 27, 2006
Google help
Those of us in user support had a pet peeve: there was no single place that held all of Google's help information at your fingertips. So we decided to build one -- and now you can visit Google Help to find tips, tricks, and troubleshooting solutions for just about every Google product and service. We don't want you to have to work hard to find anything, so we also added an A-Z guide in case you do know exactly what you're looking for.
Official Google Blog: A roadmap for Google help
technorati tags:google
How to capture a PowerShell terminal session
Just found about this cmd-let that captures all the input/output in Powershell
to start it simply type:
Start-Transcript
it will tell you where the transcript is being stored, by default it creates a text file on your "c:\documents and settings\user\..." folder, but you can specify where you want the transcript to be stored just passing a file name after the cmd-let, you can also pass -append so that if the file exists, it keeps adding to it
To stop it:
Stop-Transcript
technorati tags:PowerShell
Free MSDN library from now on
For the first time, we're making the MSDN Library freely available for download from Microsoft Downloads. Previously, the Library was only available for download to MSDN subscribers. The current download is the May 2006 Edition and future editions will also be available when we release them.
Rob Caron : Free Download: MSDN Library May 2006 Edition
now this is great news!
Tuesday, July 25, 2006
Crazy windows bug
CRAZY COMPUTER BUG
Ruby for Visual Studio 2005
Ruby in Steel for Visual Studio 2005Posted by: Regina Lynch on July 25, 2006SapphireSteel Software will be releasing Ruby in Steel, a Ruby add-in allowing developers to take advantage of the Visual Studio IDE. The product will include debugging, Intellisense, code completion, code snippets and support for Rails.With the 1.0 release, both a free personal version and a developer version will be available. The developer version will include more advanced functionality, such as a fast debugger. SapphireSteel is planning to release several beta versions prior to release in order to implement further VS features and fix reported bugs.Ruby in Steel version 0.7 is currently available for download. It includes a Rails New Project Wizard, import capabilities, integrated SQL Server development, automated database setup and syntax error checking.
Ruby in Steel for Visual Studio 2005
check it out
Saturday, July 22, 2006
10 years ago, today
10 years... that's a long time, it's the difference between being 19 or 29 years, I hope I have been able to help some people through my work.
Fortunately I won't have to bring a pound of chocolate per every year at the company or anything like that
Thursday, July 20, 2006
Windows Shortcut keys
These shortcut keys work fine in Remote Desktop
Wednesday, July 19, 2006
PowerShell:Get a list of paths from the environment variable PATH
First of all, to get access to a variable from the environment you run:
$env:[variableName]
so, to get the PATH you do:
$env:path
on my machine, I get something like this:
PS C:\> $env:path
C:\oracle\product\10.1.0\Db_1\bin;C:\oracle\product\10.1.0\Db_1\jre\1.4.2\bin\c
lient;C:\oracle\product\10.1.0\Db_1\jre\1.4.2\bin;C:\Oracle\product\10.1.0\Clie
nt_1\bin;C:\Oracle\product\10.1.0\Client_1\jre\1.4.2\bin\client;C:\Oracle\produ
ct\10.1.0\Client_1\jre\1.4.2\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\Syst
em32\Wbem;C:\Program Files\Microsoft SQL Server\80\Tools\BINN;c:\Program Files\
Microsoft SQL Server\90\Tools\binn\;C:\Program Files\QuickTime\QTSystem\;C:\Pro
gram Files\Support Tools\;C:\Program Files\Windows PowerShell\v1.0\
PS C:\>
that's kinda hard to read, so you can use this method instead:
$env:path.Split(';')
PS C:\> $env:path.Split(';')
C:\oracle\product\10.1.0\Db_1\bin
C:\oracle\product\10.1.0\Db_1\jre\1.4.2\bin\client
C:\oracle\product\10.1.0\Db_1\jre\1.4.2\bin
C:\Oracle\product\10.1.0\Client_1\bin
C:\Oracle\product\10.1.0\Client_1\jre\1.4.2\bin\client
C:\Oracle\product\10.1.0\Client_1\jre\1.4.2\bin
C:\WINDOWS\system32
C:\WINDOWS
C:\WINDOWS\System32\Wbem
C:\Program Files\Microsoft SQL Server\80\Tools\BINN
c:\Program Files\Microsoft SQL Server\90\Tools\binn\
C:\Program Files\QuickTime\QTSystem\
C:\Program Files\Support Tools\
C:\Program Files\Windows PowerShell\v1.0\
PS C:\>
ah... much better
what? you need the list on a file?
$env:path.Split(';') > list.txt
technorati tags:microsoft, powershell
Technical terms in your language
I found this document: Microsoft Terminology Translations, via Edgar
the document contains almos 15,000 terms in 47 different languages, so if you speak another language, chances are you'll find it there
Tuesday, July 18, 2006
quickly find out which version of the .NET framework is installed on a system
This is something I have answered several times to many people, anything from production personnel to network administrators
is quite easy (the yucky using the mouse way)
You go to the control panel, Add or Remove Programs, wait forever for that to populate the list, then go find "Microsoft .NET Framework X.X"
if you want to do it quicker than that, you can use this method instead:
open a folder to:
c:\WINDOWS\Microsoft.NET\Framework\
or whatever the equivalent on your machine is, like
c:\WINNT\Microsoft.NET\Framework\
first of all, if the folder c:\windows\Microsoft.NET doesn't exist, then you don't have any .NET framework version installed
Then, if you do get to that folder, you should see some folders like
v1.0.3705
v1.1.4322
v2.0.50727
That's the version of the .NET framework installed (the first two digits matter the most)
It's also important to note that just because the folders exist there it doesn't mean that version is installed, to make sure you would actually have to go inside the folder and see that it has a ton of files (100+) and about 6-10 folders
for ~95%+ of the cases though, I just type c:\WINDOWS\Microsoft.NET\Framework\v at the "run" window and see what shows up and that works just fine
Microsoft acquires sysinternals
I’m very pleased to announce that Microsoft has acquired Winternals Software and Sysinternals. Bryce Cogswell and I founded both Winternals and Sysinternals (originally NTInternals) back in 1996 with the goal of developing advanced technologies for Windows. We’ve had an incredible amount of fun over the last ten years working on a wide range of diverse products such as Winternals Administrator’s Pak, Protection Manager, Defrag Manager, and Recovery Manager, and the dozens of Sysinternals tools, including Filemon, Regmon and Process Explorer, that millions of people use every day for systems troubleshooting and management. There’s nothing more satisfying for me than to see our ideas and their implementation have a positive impact.
Mark's Sysinternals Blog: On My Way to Microsoft!
technorati tags:microsoft
Blogged with Flock
Monday, July 17, 2006
PowerShell support for old command line behavior
While playing with PowerShell I noticed that it has pretty good support for the behavior found in "old" CMD and/or "DOS", all the function keys work just as expected
Now, in case you don't know how to use the function keys in "DOS" here are some pointers:
F1 - will repeat the last command one character at a time, so if your last command was "dir", you will get "d", "i", "r" as you press F1 multiple times
F2 - "Copy up to char" function (of the last entered command): Not used much, it allows you to copy up to the character you enter after pressing F2, e.g.
If you previously entered: dir "program files"
on the next line you could enter: dir [F2]m
and it would complete it as: dir "progra
F3 - repeats the last command
F4 - "delete up to", I can't really remember how to use this one, but is rarely used I guess
F5 - iterate backwards through the list of previously entered commands (same as using the up arrow key)
F6 - ^Z or text file terminator: I can't see how to use this in PS, but if you were entering a text using "copy con [filename]" you can get out of it and save the file by pressing F6, which by the way, PS doesn't have support for "copy con" but supposedly this guy wrote something equivalent to it:
http://tfl09.blogspot.com/2005/10/monad-and-command-console.html
F7 - Provides a list of the previously entered commands and you can select one using the arrow keys
F8 - Iterates in a loop backwards (when it gets to the first one it goes the last one) through the previously entered commands
F9 - "Enter command number": allows you to enter the command number you want to execute, to find out the command numbers you would have to use F7 first
technorati tags:microsoft, powershell, command, compatibility
Blogged with Flock
Sunday, July 16, 2006
(PS) how to get back "home"
I have a story of being a keyboard guy and a "command line guy", recently I have been interested in PowerShell; thanks to the secret geek I was encouraged to download it and try a few things, so far I'm loving it!, it's awesome... of course this is definitely not for everyone, specially not for programmers =o(, at least the great mayority of the ones I know don't really like command line stuff, anyway (is not like you are required to be an expert on it, PowerShell is oriented at System Administrators, I just happen to prefer command line when working at a computer, is just so much faster to accomplish things).
I was reading on the secret geek blog about one of the cmd-lets:"Get-PSDrive":
Once Upon A PowerShell i went looking for a cmdLet to display a list of all the current drives.I found one, 'Get-PSDrive' which does exactly that... but i was gobsmacked at what else it revealed!'Power shell drives' are not just your boring old 'C:' etc -- they can be all sorts of hierarchical structures, such a registry keys, environment variables, functions(!) and more.
Babysteps in PowerShell part deux: Variables! Real Proper Variables!
on mi machine it displays something like:
PS C:\> get-psdrive
Name Provider Root
---- -------- ----
A FileSystem A:\
Alias Alias
C FileSystem C:\
cert Certificate \
D FileSystem D:\
E FileSystem E:\
Env Environment
F FileSystem F:\
Function Function
HKCU Registry HKEY_CURRENT_USER
HKLM Registry HKEY_LOCAL_MACHINE
Variable Variable
PS C:\>
notice those Function, HKCU, HKLM and Variable at the end...
you can do a "cd Variable:" then do a "ls" or "dir" and it will list the variables declared, you can do "cd Alias:", then "dir" will list the aliases in the system (alias for the different cmd-lets")
anyway, I was playing with those and for a few seconds I was stuck when I did "cd Alias:", after finding out what was there, I wanted to go back, so I immediatly did "cd ..", didn't work, "cd \", nop... "cd /" nothing... panic!
quite simple actually, we just need "c:" or "cd c:"
(uff, that was close)... and now I have a new category to blog about
technorati tags:powershell, command
