Friday, December 22, 2006

Remote Desktop tips and tricks

Here's a list of tips and tricks that I have compiled from my reading list, I've seen a tip here and a trick there, but not a full list, so here it is (for me to remember J)

shutdown or restart a workstation

Note: These tips work on Windows XP, but there is no guarantee that they will work in future versions of Windows.

One way to do this is to run Task Manager and select your shutdown option from the "Shut Down" menu.

Another trick is to click on the desktop and type Alt+F4. This will call up the shutdown dialog, where you get the usual shutdown options like "Shut down", "Shut down without installing updates", "Restart", "Stand by", and "Hibernate".

These next two tricks are documented and will continue to work in future versions of Windows:

If you're a command line person, you can run shutdown.exe, but that program supports only shutdown and restart; it doesn't do stand-by or hibernate. But the shutdown.exe program has a serious flaw: It requires you to have administrator privileges. If you are a limited user with shutdown privileges, the shutdown.exe program will complain. (Which means that I don't use it.)

Finally, if your computer isn't using Fast User Switching, you can type the Ctrl+Alt+End hotkey, which is the Remote Desktop version of Ctrl+Alt+Del and consequently takes you to a dialog where you can do various system-type things, among them logging off and shutting down.

Connecting to terminal services when all active sessions are used:

mstsc /console

Mapping drives via Remote Desktop

Open the remote desktop application. Click on the Options button and go to the Local Resources tab. The bottom section of the tab is titled Local Devices, and there you will see a check box labeled Disk drives. Checking this box will automagically connect all disk drives on you local machine to the remote machine when you open the RDC.

Remote Desktop on a non-standard port

Modify this registry key:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TerminalServer\WinStations\RDP-Tcp

Connecting via remote desktop to the non-standard port

Suppose you change the port for the virtual machine to listen in on port 3900. You simply append 3900 to the server name (or IP) when connecting via Remote Desktop.

Important shortcut keys:

Alt + Page Up
Switches between programs from left to right.

Alt + Page Down
Switches between programs from right to left.

Alt + Insert
Cycles through the programs in the order they were started.

Alt + Home
Displays the Start menu.

Ctrl + Alt + Break
Switches the client between a window and full screen.

Ctrl + Alt + End
Brings up the Windows Security dialog box.

Ctrl + Alt + Pause
Toggles between fullscreen and windowed mode
(note that this does not set the client desktop to the correct size)

Alt + Del
Displays the Windows menu

Ctrl + Alt + Num -
Places a snapshot of the client's active window on the clipboard

Ctrl + Alt + Num +

References

http://blogs.msdn.com/oldnewthing/archive/2006/10/20/849575.aspx

http://haacked.com/archive/2005/10/13/Remote_Desktop_To_Console_Session.aspx

http://stevenharman.net/blog/archive/2006/10/22/Mapping_Drives_via_Remote_Desktop.aspx

http://haacked.com/archive/2006/10/17/Remote_Desktop_On_A_NonStandard_Port.aspx

http://www.codinghorror.com/blog/archives/000570.html

Reading list

Visual Studio 2005 SP1 for Windows Vista (Beta)

is ready, just in time for christmas

Wednesday, December 20, 2006

function to generate random numbers, without repeating digits

The code for this article applies to C#

Reading blogs, I found this post (in italian), where Marco wants to write a function to generate random numbers with the following rules:

  • 5 digits long
  • result should be returned in a string
  • all the digits should be different (on each result you can't have two of the same digit)

The function he came up with was the following:

private string GetRandom()
{
Random rn = new Random();
string resultnum=string.Empty;
do
{
string a = rn.Next(0, 9).ToString();
if (resultnum.Contains(a)!=true)
resultnum = resultnum + a;
}
while (resultnum.Length<5);
return resultnum;
}

I felt curious to see what areas I could improve, and I started writing a function to get the same result, but in a more optimized way

A couple things that jump out to my mind are:

  1. string concatenation
  2. the loop and comparing each time to see if the digit is in the result already

So I wanted to write a function that: would avoid concatenation and would execute the loop exactly 5 times, this is the result:

static char[] allNumbers = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
Random r = new Random();
public string GetRandom2() {

char[] result = new char[5];
int max = 9, pos=0;
for (int i=1; i<6; i++) {
pos = r.Next(0, max);
result[i - 1] = allNumbers[pos];
//*** swap positions
allNumbers[pos] ^= allNumbers[max];
allNumbers[max] ^= allNumbers[pos];
allNumbers[pos] ^= allNumbers[max--];
}
return new string(result);
}

The technique I used was:

  • Have a predefined array with all possible characters
  • I have a variable max that I use to call the method Random.Next(0, max)
  • the variable is decremented on each iteration
  • I swap the digit from the result to the last position, with this I leave this digit out of the posibilities for the next call

The performance gain from these changes was minimal (3 ms per 1000 calls), then I thought about moving the Random variable declaration outside the function, so it could be reused between calls, this gave me the performance gain I was looking for, calling the function 10,000 times takes ~114ms using the old method and only ~6ms using the new one, that's where the problem was, the rest was pretty much insignificant =o(

I'm sure someone else can write a faster version, but I accomplished my goal =o)

Tuesday, December 19, 2006

A sign that you've been blogging too much: blog deja vu

Antonio Ganci says (blog in italian) sometimes when he's about to blog something, he gets this feeling that he already posted about that, kinda like blog deja vu, then he actually checks the old posts just to find out he hadn't written that post

I thought it was funny, hasn't happened to me yet, but probably happens to a lot of people; I find the Deja Vu effect quite interesting... and I few days ago I saw the Deja Vu movie which was pretty good (but I thought I found one error on the movie)

Monday, December 18, 2006

deleting items from a generic list

The code for this articles applies to C# 2.0
A more or less common task on a generic list is to remove items from it, lets see what approaches we can take:

#1 The definitive wrong way to do it:

List<Person> l1 = GetList();
//*** The wrong way
foreach (Person p in l1) {
    if (p.Age > 30)
        l1.Remove(p);
}

This code will throw an InvalidOperationException: "Collection was modified; enumeration operation may not execute."

#2 Kinda works (and allows you to perform an action on the item being deleted)

List<int> ints = new List<int>();
ints.Add(1);
ints.Add(2);
ints.Add(3);
ints.Add(4);
ints.Add(5);
ints.Add(6);

ints.ForEach(delegate(int i) {
if ((i % 2) == 0) {
Console.WriteLine("removing"+i.ToString());
ints.Remove(i);
}
});



If you run that code it will work just as we expect it, but there is a problem with it, if you add all the pair numbers first you would see that it doesn't delete all of them, it doesn't throw an exception, it just breaks out of the loop and keeps going, so this method works but on very specific conditions


#3 The right way: we traverse the collection backwards and delete items

int x = ints2.Count;
while (--x>=0) {
if (ints2[x] < 4)
ints2.RemoveAt(x);
}



#4 A better way: the list has a method for this purpose

ints2.RemoveAll(delegate(int i) {
return i <4;
});



#5 But what if I need to perform an action on the item being deleted?

ints2.RemoveAll(delegate(int i) {
if (i < 4) {
//*** Perform action here
Console.WriteLine("removing :" + i.ToString());
return true;
}
else
return false;
});



if the item was a class we could call methods on it before deleting it from the list (perhaps a call to a DB)


On future posts I'll talk on detail about why exactly #1 and #2 don't work

put the focus on a ChangePassword Control UserName field

I was trying all sorts of things to set the focus to the UserName control of the ChangePassword Control, turns out it was as simple as:

if (!Page.IsPostBack)
ChangePasswordControl.Focus();

works for the Login Control too

if (!Page.IsPostBack)
LoginControl.Focus();

macros in good old DOS

I just read this post (from Jeffery Hicks?): Make an old friend do your work where he explains how you can use good old doskey to make your life easier (at the command line), and it motivated me to write a blog entry for 2 reasons:

- he missed a few points
- I want to remember this stuff too, since it seems I'm starting to forget stuff =o(

Let's see, first of all he defines a macro like this:
doskey xl="%programfiles%\Microsoft Office\Office11\Excel.exe" $1 $2 $3 $4 $5

and explains "You can use variables like $1 and $2 (all the way up to $9)".
but why limit yourself to 9 parameters? you can write it as:
doskey xl="%programfiles%\Microsoft Office\Office11\Excel.exe" $*

that will take whatever number of parameters you pass to it. To test that it actually took more than 10 parameters I created a file 1.xls and then ran this command (a lot of people don't know this one):

for /l %e in (2,1,11) do copy 1.xls %e.xls

Which by the way means (loop from 2 to 11 in steps of 1, copy file 1.xls to [variable].xls);
now I had 11 files to play with, so I called my macro:
xl 1 2 3 4 5 6 7 8 9 10 11

which brings me to another point he missed: "from a command prompt I can type xl file1.xls file2.xls file3.xls and have Excel open all three files"
You don't have to specify the extension, you can just pass the file name-no extension and excel will open it happily

This also brings me to another point: if you just wanted to open a single file, you could just type the file name:
1.xls
and Windows will open it in the default application (most likely excel) so for single files, we don't even need the macro

finally, this macro thing doesn't really work for notepad (or notepad2) if you call
np 1.txt 2.txt it tries to open the file "1.txt 2.txt"

you can only open single files =o(

one last tip, to delete a macro you just do
doskey myMacro=

Sunday, December 17, 2006

Get (another's class) private fields

About 2 months ago I wrote a couple articles on reflection, specifically about executing another's class private methods, someone left a question on how you can get the private fields, just now I found the time to answer to that; first of all let's create a test class:

class TestClass {
private int prop1;

public int Prop1 {
get { return prop1; }
set { prop1 = value; }
}

private string prop2;

public string Prop2 {
get { return prop2; }
set { prop2 = value; }
}

private bool prop3;

public bool Prop3 {
get { return prop3; }
set { prop3 = value; }
}

public bool field4;

public TestClass() {
prop1 = 10;
prop2 = "20";
prop3 = false;
field4 = true;
}
}



Then we create an instance of it, and use the method GetFields to (you guessed) get the list of fields, we just have to specify on the parameters that we want private members and they have to be instance members (non-static), once we get the list we can do *whatever* we want with it, in this case the code prints the field type and it's value


TestClass test = new TestClass();
FieldInfo[] fields = test.GetType().GetFields(BindingFlags.NonPublic BindingFlags.Instance);
foreach (FieldInfo f in fields)
Console.WriteLine(string.Format("type:{0} \t value:{1}", f.FieldType.ToString(), f.GetValue(test)));


That's about it. Now, just to make it a little bit more interesting I created a small generic function to accomplish the previous task and now you can reuse that with any other class:

static void PrintPrivateFields<T>(T theInstance) where T:class {
Type t = theInstance.GetType();
FieldInfo[] fields = t.GetFields(BindingFlags.NonPublic BindingFlags.Instance);
foreach (FieldInfo f in fields)
Console.WriteLine(string.Format("type:{0} \t value:{1}", f.FieldType.ToString(), f.GetValue(theInstance)));
}



To use it, we just create an instance of that class and pass the instance to the function:


TestClass test = new TestClass();


PrintPrivateFields(test);


Note that I don't need to specify the type when calling the function


PrintPrivateFields<TestClass>(test);


The compiler is smart enough to figure it out (since the only parameter is of that type).


Hope the code is useful, you can find the full code here

I just finished browsing "The Internet"

From tecblog

or more accurately, I just got caught up reading blogs, I have been sick and very busy for the last month or so and that's the reason I haven't posted much here. However blog writers don't give me a break and whenever I don't read blogs for a couple days I get really behind; here's a list of the blog entries that I have found most interesting (out of the 266 blogs that I subscribe to), I'll try to include this list on my blog

My starred items

Friday, December 15, 2006

How to install Visual Studio SP 1 in less than an hour

Visual Studio SP 1 update is all over the blogs now, however there are many reports that the install takes a long time (over 2 hours), I managed to install it in about 30 minutes by shutting down every program and stopping a bunch of services (except machine debug manager, I don't think is necessary but didn't want to risk it) and that was it, the installation finished really quick, hopefully it'll do it for you too

Update: on my old machine (where I just installed Windows Vista a few days ago), it took 20 minutes by following these simple steps

Monday, December 11, 2006

Tour Juarez-Chihuahua 2006

Is this time of the year where I get to back to my home town to visit family and friends, I will be in Juarez & Chihuahua from Dec. 23 to the end of the year, if you're interested in meeting, have some dinner, geek talk or whatever, drop me a line and we'll arrange something

Saturday, December 09, 2006

Windows is unable to find a system volume that meets its criteria for installation

I had a hard time installing Windows Vista on my old machine (hey, my machine is older than a year... and hey! I have been blogging for over a year!!) anyway... oh, the error message, I kept getting that error when trying to install to any of the (3) partitions on my SATA drive, I deleted them, formatted them, recreated them, nothing worked... one guy had posted a vague answer to this very problem: "Vista should be installed on active partition", what the h* is that supposed to mean?

on one last desperate attempt, I disconnected the other drive (that I didn't mention before) from my machine, leaving only the SATA drive connected, ran the installation and voila!, that's all I needed to do, the installation ran smooth after that, everything is working great so far, I think I even like IE7 a lot better in Vista and Aero Glass is sweet canadian mullet!

here are some shortcuts keys for you guys new to Vista

and hopefully my experience will be helpful to some other soul, now if you excuse me I got some playing to do, next stop: Office 2007 baby

Thursday, December 07, 2006

give me beans and fries and I can stop a plane

this is hillarious, unless, of course, it happened to you

Wednesday, December 06, 2006

Novell commands to remember

I "grew up" using Novell networks and DOS, I used to be really good at managing Novell servers but I haven't touched a Novell server in quite a while; yesterday they were having problems with an old Novell server and they asked me for help, I couldn't remember some of the basic commands, so this post is for me to remember those commands later, and maybe you are so lucky that you may need these ones sometime

Server commands

  • server - at the DOS prompt, actually starts the server
  • restart server - bring the server down and restart immediately
  • VRepair - use it to correct volume problems (you can't use vrepair on a mounted volume), also use it to remove name space entries from directory entry tables
  • enable/disable login - to prevent users from logging in
  • mount - make a volume available to users (mount all to mount all volumes)
  • dismount - make a volume unavailable to users
  • volume - get a list of mounted volumes, or information about a volume (parameter)
  • down - take the server down (nicely)
  • load/unload monitor - load/unload the monitor (get the nice UI)
  • tcpcon - nice monitor with a bunch of information about TCP and other network protocols
  • display environment/processors/servers/networks / modified environments / interrupts -
  • list devices - gets a list of storage devices (disk drive, cd-rom, etc)
  • memory - displays total amount of installed memory that the operating system can address
  • mirror status - view status of mirrored disk partitions, view percentage of mirrored data on each partition
  • modules - get a list of loaded modules

Workstation commands

  • attach - connects to another server, but remains logged in to the current server
  • caston/castoff - enables/disables network messages from other workstations and the server if the ALL option is used
  • chkvol - shows volume information, free space, usage, deleted files, etc
  • login/logout - you get the idea
  • rights - display rights for files and directories
  • rconsole - remote console, to control a server from a workstation, if no server specified, a list is shown
  • purge - removes (previously deleted) files permanently, files purged can't be recovered
  • slist - list of servers
  • syscon - manage user, groups, rights, etc

Tuesday, December 05, 2006

you have been using patterns for a while

Take this one for instance, the Composed method:
Divide your program into methods that perform one identifiable task. Keep all of the operations in a method at the same level of abstraction. This will naturally result in programs with many small methods, each a few lines long.
That's as simple as breaking a method into smaller methods, something you do in every day programming, there are many simple patterns like this one, all they do is describe the tasks you do on a daily basis.

The whole point is that by knowing the names of the patterns, you can communicate much faster, easier, better and by using them you will be a more educated programmer, a better developer; remember that a great developer is not only the one who can write amazing code, but who can communicate ideas and is able to work on a team

"the best code in the world is meaningless if nobody knows about your product."

You are already using patterns, learn their names, learn more patterns, use them and pass them on to your team, you will learn even more, by teaching others.

Monday, December 04, 2006

If you're talented, the tools don't matter that much

This is the first post using blogger beta, we'll see how this goes, check what this guy can do using Paint



...or this other guy using Excel

Sunday, December 03, 2006

css tips: header, footer, and scrollable middle area full document

Back in the days, I used to start a page with a html table with 3 rows, one for the header, one for the middle area at 100%, and a footer

Nowadays this approach doesn't work any more and we're told that we have to use pure CSS, not tables, blabla... so, how do we accomplish this with pure CSS?

We are going to need some css and a bit of javascript, first of all, lets see the css

html,body,form
{
margin:0;
padding:0;
}//prevent some default spacing on some browsers
.header
{
text-align:center;
background-color:Navy;
color:White;
width:100%;
}
.footer
{
background-color:Orange;
color:Navy;
position:absolute;
bottom:0;
border:0;
}
div.scrollable{
overflow:auto;
border-left-width:0px;
border-bottom-width:0px;
border-top-width:0px;
border-right-width:0px;
background-color:Gray;
color:White;
position:absolute;
}

the most interesting is the last class div.scrollable, overflow:auto makes it scrollable, and the rest is to eliminate the borders and set the color.


Now lets see the html:

<html>
<head>
</head>
<link rel="stylesheet" type="text/css" href="test.css" />
<body>

<div>
<div id="header" class="header" height="20px">
This is the header
</div>

<div id="mainDiv" class="scrollable">
This is the main body<br>
There is a lot of stuff in the main
<br><br><br><br><br><br><br><br><br><br>
There is a lot of stuff in the main
<br><br><br><br><br><br><br><br><br><br>
There is a lot of stuff in the main
<br><br><br><br><br><br><br><br><br><br>
There is a lot of stuff in the main
<br><br><br><br><br><br><br><br><br><br>
There is a lot of stuff in the main
<br>
<br><br><br>
This is the last line
</div>

<div id="footer" class="footer" height="20px">
<div style="float:left">This is a div on the left</div>
<div style="float:right">This is a div on the right</div>
</div>

</div>

</body>
</html>

I put a lot of lines in the middle, just so you can see the document scrolling. As a "bonus" I put two divs on the footer, one aligned to the left and one to the right, both in the same "row", this is one of those things that people have a hard time finding. We're almost there, we just need some javascript now:

var mainDivHeight;
var mainDivWidth;

function AdjustFullSize() {
var screenHeight = 450;
var screenWidth = 610;

if (window.innerHeight) {
screenHeight = window.innerHeight;
screenWidth = window.innerWidth;
}
else if (document.body) {
screenHeight = document.body.clientHeight;
screenWidth = document.body.clientWidth;
}

mainDivHeight = screenHeight - 20 - 20; //20+20 for header and footer
mainDivWidth = screenWidth - 0;

document.getElementById('mainDiv').style.height = mainDivHeight + 'px';
document.getElementById('mainDiv').style.width = mainDivWidth + 'px';
}

The different browsers have different properties to access the document height and width, we account for that and then assign the size to the main div, call this function on the body onload (and resize!) and we are done, the end result looks like this, you can get the full source from there, hope you find it useful.