Growing Herbs (Part 1)

We have a number of gardens on our property and some of them are quite specialized. For example, Rebecca grows a wide variety of mint. She has the usual spearmint, of course, but she grows a huge number of other mints. My personal favorite is lime mint. It actually a lime flavor underlying the mint taste. I find it refreshing during the winter months. Lime mint shares most of the same characteristics of other mints. It looks like this:

LimeMint

Some of the mints she grows don’t even have mint in the name. Of course, there’s catnip, a form of mint enjoyed mainly by cats. However, there is also lemon balm, another favorite of mine because it has a perky flavor that’s good during the daylight hours (lime mint is more for the evening to relax). You can see by this picture that the two mints look similarthe best way to tell mints apart is to look at the leaf size and shape, and then rub a bit on your fingers and sniff.

LemonBalm

In addition to these mints, we also have orange mint, chocolate mint, and others. Rebecca will wait until these plants grow a bit taller and then take some (but not all) of the stalks inside for drying. She picks the individual leaves off and dries them in a food dehydrator. Another post will discuss this technique. We’re both strong advocates of dehydrating as a way of saving on storing costs and producing fat-free treats.

Lest you think our herb garden is entirely devoted to mint, we grow a wide variety of other plants as well. A favorite for soups is lovage, which has a strong celery taste. It grows as tall stalks with sparse leaves. Near the middle of the season the lovage plant will produce flowers. You can use the seeds as celery seed. Here’s what lovage looks like (we keep it in a tomato cage so it doesn’t blow over).

Lovage

I use a lot of rosemary and thyme in my cooking, so Rebecca grows quite a bit each year. Rosemary has somewhat thick, almost cylindrical leaves and a strong aromatic odor. It does amazing things for chicken, lamb, and pork. Because we eat a lot of chicken, we use a lot of rosemary. Here’s what the young rosemary plant looks like:

Rosemary

By the way, just in case you’re wondering, yes those are nut shells. We don’t waste anything, not even nut shells. They actually make a fine addition to the herb garden soil and keep it loose. Eventually, the nut shells rot down and make nice compost for the herb garden.

Most people don’t realize it, but there are several different kinds of thyme. This year we have lemon, lime, and orange thyme. All three have a thyme taste and small, but with subtle differences. The plants actually look quite different, so it’s somewhat easy to tell them apart. Here’s the lemon thyme:

LemonThyme

Notice that the lemon thyme has bits of yellow on its leaves. The leaves are also a bit rounder than other kinds of thyme. Compare the lemon thyme to the lime thyme shown here:

LimeThyme

The lime thyme leaves are larger, brighter green, and a little elongated when compared to the lemon thyme. These leaves also last the yellow spots on them (making it a less pretty form of thyme in my opinion). Our newest kind of thyme is the orange thyme, which looks sort of like the lime thyme as shown here.

OrangeThyme

However, as you can see, the leaves of the orange thyme are much darker. In addition, the stems have a significant reddish cast to them. All three are thyme, but each has subtle differences that will make a big difference in cooking. We’ll use all three types with meat dishes, just like the rosemary.

I can’t do our herb garden justice in a single post, so expect to see more as the summer progresses. In the meantime, let me know if you have any questions at John@JohnMuellerBooks.com.

 

Writing a Helpful Review

Reviews are a special kind of opinion, but they’re still an opinion. People often forget this fact as they read a review and accept as factual anything the reviewer has to say. However, even the best review is the opinion of the reviewermaking reviews extremely hard nuts to crack in determining their value to the reader. The best reviews do contain facts and the best reviewers do try to focus their opinion of the product from several perspectives. A good review takes time to write because the author must overcome biases to an extent and try to provide material that will appeal to a larger audience. Good reviews require critical thinkinga type of thinking that’s in short supply in our politically correct society.

Of course, examples of poor reviews abound. John Dvorak recently wrote a post about the potentially corrupt reviews on Amazon (something I’ve suspected for a long time). Short, single paragraph (or sometimes sentence) reviews aren’t all that helpful. Reviews that gush over a product without saying why the product is so great aren’t helpful either. Equally useless are reviews that decry a product as shoddy without explaining what makes it so terrible. In fact, there are few (if any) perfect or completely useless products out therereviews often become a question of balance between the two extremes. Unfortunately, some organizations that request reviews try to artificially balance the review by asking for the three best and three worst features (even when a product lacks sufficient good or bad features to fill the blanks).

So, how do you write a helpful review? First, you begin by actually using the product. If you’re reviewing a movie, watch the entire movie before you start writing anything. Likewise, read the entire book you’re reviewing or test other products in a real world environment, rather than in a lab. In some cases, you see reviews based on the beginning of a movie, a chapter of a book, or the reviewer’s impression after opening the package. Such reviews are useless because they don’t consider the product as a whole.

After you’ve examined the product completely, it’s time to start writing the review. Explore what you feel about the product. Does it work as intended? Is it helpful? Write down your impressions as they come to you. Take time to think about the product critically. Could someone other than you have a use for this product? After all, you already know how you feel about the producta review is meant to help someone else understand the product better, so you’re writing for them, not for yourself.

Verify your impressions by going back to the product. Does the book really contain 101 secrets to making a million dollars by age 10? Is the movie truly presenting a hidden agenda in a candy-coated package? The act of verifying your impressions is important because we all remember things that aren’t actually there. Checking your facts is the mark of a superior reviewer.

Put your impressions into some sort of comprehensible order. Nothing is worse than reading a review composed of seemingly unrelated thoughts. A review should flow in some sort of order. A movie or book often lends itself to a chronological flowfrom beginning to end. However, some reviews work best if you can provide an overview, the good parts, the bad parts, any special features, and then a bottom line that answers the question, “Is this a good product?” or “Why should you buy this product.”

Set the review aside for a day. Go back and read it again. Does the review still ring true? Do you still feel the words you’ve written or have things changed now that you’ve had time to think about the product more? A review is an opinionit’s biased in some respects. However, even with the opinion, even with the bias, a good review still conveys useful information about the product, especially when you back your opinions and biases up with facts.

Not many people want to take the time to write a helpful review. The best reviews require time and skill to write. A helpful review isn’t written in the heat of the moment and it doesn’t lash out at anyone. When you write a good review, it reflects your honest opinion about the product and doesn’t attack the product’s creator. After all, you know about the product, but know nothing about the product’s creator and there is nothing you can tell anyone about the product’s creator, so why go in that direction?

What else would you add to the skills of a good reviewer? Are there any special features you look for in reviews? Let me know at John@JohnMuellerBooks.com.

 

Cherry Tree Woes

Cherry trees can be incredibly hard to raise, as I’m learning over the years. We originally planted four Northstar cherry trees on our property. The description of the tree seemed perfectit only grows 6′ to 10′ tall, produces copious amounts of tart cherries, and is quite hardy.

Unfortunately, it also has an open structure that Yellow Bellied Sap Suckers find absolutely irresistible (yes, they really do exist). We ended up with neat rows of little holes in the trunk of each of the cherry trees. Because the birds alternated between the wild cherries in our woods and our cherry trees, our Northstar cherries eventually ended up with a disease called bacterial canker. The sappy ooze emitted by the wounds attracted all sorts of other pests. Eventually, the bacterial canker girdled the trunk and killed our Northstar cherries (well, all except one that simply refuses to die, so we let it stay there, but it has yet to produce cherries and it never has grown more than a few feet tall).

We decided to try again with a cherry that the Yellow Bellied Sap Sucker might find less inviting. This time we chose the Mesabi cherry and planted four more trees. The tight branch structure did keep the birds at bay. In fact, the trees produced 53½ pounds of cherries in 2009. However, late last year we noticed that the leaves were turning yellow in mid-summer and that the fruit yield was very low. This year we won’t receive any fruit from our cherries because they’re essentially dead, as shown here.

Cherries01

There are still some leaves on this tree, but it isn’t nearly as full as it should be and it won’t recover. All four trees have a virus they received from an insect (type unknown). There are a number of indicators. The most noticeable is that the tree has almost no leaves, yet, there isn’t anything obviously wrong such as bacterial canker. The leaves the trees do have are yellowish with darker green around the veins, as if the leaves aren’t receiving enough nourishment.

A more telling symptom is something called flux. The tree is leaking small amounts of sap (not the copious amounts as with bacterial canker). This sap is turning black as bacteria attacks it as shown here.

Cherries02

That blackish spot (circled in red) would be very easy to miss. (Each tree has many of these little black spots.) In fact, I didn’t know what I was looking at. A master gardener friend of mine pointed it out. The ants don’t miss opportunities like this though. The trees are loaded with themall looking for a free meal of sap.

The trees are actually dying from the inside out. There is a wound on one of the trees where you can see the inside of the tree literally rotting as shown here.

Cherries03

Notice how the edge of the wound has lifted upit isn’t curled tight against the wood of the tree. This indicates that the tree is trying to heal itself, but that the new growth has nothing to stick to. The new growth should be tight against the wood.

I’ll be cutting the four trees down sometime soon, drying the wood out, and using it to smoke various meats. It would be a shame to use such nice wood in the wood stove. The trees definitely won’t go to waste.

Unfortunately, I can’t plant new cherry trees in the same spot (or in the location where the other cherry trees were). In both cases, the trees have left their diseases in the ground. If I plant new trees in these locations, they’ll immediately become infected. Consequently, I’ll be looking for a new type of cherry (or cherries) and a completely different location next year. One major lesson I’ve learned is that trees of the prunus genus require significantly more care than either apples or pears.

This spot will be taken over by butternut trees next year.  We don’t have any butternut trees in our woods (they can grow in the wild), so the addition of nut trees will be nice. I know that our woods do contain hickory nuts and plan to gather as many as I can this next fall (as soon as I identify precisely where the trees are located). What are your favorite sorts of nuts and fruits? Let me know at John@JohnMuellerBooks.com.

 

Using Generics with Classes

In the “Working with Generics” section of Professional IronPython (page 135), you find an example of using Generics with integer values. A reader recently tried to apply this example to working with a simple class and wasn’t able to get it to work (read the thread on p2p.wrox.com for details). This post examines what you’d need to do to expand the original example to work with a simple class. I’m using a modified version of the reader’s code for explanation purposes. The example begins with this simple class.

# Define a simple class named Employee that contains a
# first name, last name, and age.
class Employee:
    FirstName = ''
    LastName = ''
    Age = 0

The class is contained in a separate file, FirstClass.py. As you can see, there is nothing special about this class. However, you could easily expand it as needed to accommodate your own code. Except for the comment, this code is precisely the same as that provided by the reader. (By the way, I encourage anyone sending me an example to add comments so I can understand your example with greater ease.)

Let’s look at the application. It essentially follows the same flow as the code in Listing 7-5 that starts on page 135. I’ve used the reader’s modification of that code for the most part, but added comments again for ease of understanding.

# Add the .NET Framework 4.0 to the path.
import sys
sys.path.append('C:\\WINDOWS\Microsoft.NET\\Framework\\v4.0.30319')
 
# Make CLR accessible.
import clr
 
# Import the required assemblies.
import System
import System.Collections.Generic
 
# Import the class you want to work with.
from FirstClass import Employee
 
# Create a list based on the class. Notice that
# you must create the list using an instance, not the
# class itself.
list = System.Collections.Generic.List[type(Employee())]()
 
# Define an instance of Employee and fill it with data.
# Add the instance to the list.
g1 = Employee()
g1.FirstName = 'A'
g1.LastName = 'B'
g1.Age = 35
list.Add(g1)
 
# Define a second instance and add it to the list as well.
g2 = Employee()
g2.FirstName = 'C'
g2.LastName = 'D'
g2.Age = 5
list.Add(g2)
 
# Enumerate the items in the list and display the individual
# members on screen.
for s in list:
    print s.FirstName, s.LastName, s.Age
     
# Pause after the debug session.
raw_input('\nPress any key to continue...')

As with the example in the book, you begin by adding the required path information for the version of the .NET Framework you want to use. The book example uses the .NET Framework 2.0, while this example uses the .NET Framework 4.0. The process is the same in both cases.

Because the example class appears in a separate file, you must import it into the application using the code that appears next. If the file had contained multiple classes, only the Employee class would be imported. You can also import the entire file if desired.

Now, here’s the important part. Notice that the example creates a generic List object, list, based on an instance of Employee. You must use an instance of the class so that you obtain the type of that instance using the type() method. Otherwise, what you’re really obtaining is a List object that’s meant to store classes, not instances of Employee.

So, now list is expecting instances of Employee. The example shows how to add two instances of Employee to list and provides each of them with different information. You could use the techniques in the original example to remove items as well. The point is that list now contains two items. The final bit of code enumerates these items and you see the output shown here:

Generics01

Generic lists are extremely flexible, but you have to remember how IronPython works with data when using them. Always work with an instance of classes when creating a generic list. Let me know if you have any questions at John@JohnMuellerBooks.com.

 

A Visual Studio Quick Guide to Accessibility (Part 2)

In my previous post, A Visual Studio Quick Guide to Accessibility (Part 1), I discussed one particularly important accessibility feature. The use of keyboard accelerators is essential because many people use them to improve productivity. Making them visible is important because you can’t use a feature you can’t see. This post won’t cover all of the ideas and concepts for Visual Studio developers found in Accessibility for Everybody: Understanding the Section 508 Accessibility Requirements. However, it does provide an overview of the most essential accessibility featuresthose that every application should have.

The first feature is the tooltip. Every application should include a ToolTip control. You can then provide a description of every user-accessible control in the ToolTip property for that control. It’s important to stress user-accessible in this case. For example, you won’t provide a ToolTip property value for a Label in most cases because the Label simply marks a user-accessible control such as a TextBox. When the user hovers the mouse over the control, the application displays a helpful bit of information about that control. Screen readers used by those with visual needs also read each of the tooltips to describe the controls to the user. A few rules for using the ToolTip control are:

 

  • Keep the ToolTip text short. Imagine trying to listen to long diatribes about control functionality when working with a screen reader.
  • Make the ToolTip text specific. Tell the user precisely what the control is designed to do.
  • Emphasize the user’s interaction. Tell the user how to interact with the control, such as “Type the message you want displayed.” or “Click to display a message on screen.”


In addition to the ToolTip control, every control has three special accessibility properties as shown here.

Accessibility0201

These properties have specific purposes:

 

  • AccessibleDescription: A description of how the user should interact with the control. In fact, I normally use the same text as the ToolTip property for this entry and rely on the same rules for creating it.
  • AccessibleName: The name that will be reported to accessibility aids. I normally provide the same text that appears on the control’s caption, minus the ampersand used for the keyboard accelerator.
  • AccessibleRole: The task that the control performs. In most cases, Default works just fine. However, when your control performs an unusual task, you should choose one of the more specific entries so that the accessibility aid can help the user interact with the control.


Make sure you fill out each of the properties so that accessibility aids have the best chance of making your application useful to those who have special needs. In fact, it shouldn’t surprise you to discover that AccessibleRole is already filled out for most controls, so you really only need to fill out two properties in most cases.

The final two changes appear on the form itself. Whenever possible, assign controls to the AcceptButton and CancelButton properties. The AcceptButton provides a means of accepting the content of a dialog box or form by pressing Enter. On the other hand, the CancelButton property makes it possible to reject changes to the form or dialog box by pressing Esc. It’s true that you’ll find situations where you can’t assign a control to one or both properties because there isn’t a default acceptance or cancellation control, but this limitation applies to very few applications.

Accessible applications are significantly easier for everyone to use. Less experienced users can benefit from the inclusion of tooltips. Keyboardists benefit from the presence of keyboard accelerators. Adding these features isn’t difficult or time consuming, so all developers should be adding them.  Let me know your thoughts about accessibility and whether you’d like to see additional accessibility posts at John@JohnMuellerBooks.com.

 

A Visual Studio Quick Guide to Accessibility (Part 1)

One of the most important accessibility aids that also applies to common users is the keyboard accelerator (or keyboard shortcut). In fact, this issue figures prominently in both C# Design and Development and Accessibility for Everybody: Understanding the Section 508 Accessibility Requirements. Just why Microsoft decided to turn this feature off in Windows 7 is a complete mystery to me. All of the pertinent examples in Professional Windows 7 Development Guide include keyboard accelerators, but you can’t see them. I’ve received a number of queries about this problem and decided that this two-part post on accessibility for Visual Studio developers is really necessary.

First, let’s discuss the keyboard accelerator from a programming perspective. A keyboard accelerator is the underline you see on a button, label, menu, or other control. You press Alt+Letter to perform the equivalent of a click or selection with the associated control. For example, most people know that you press Alt+F to access the File menu in an application that has keyboard accelerators properly implemented.

To create a keyboard accelerator, the developer precedes the letter or number with an ampersand (the & character). For example, to make the File menu respond to Alt+F, the developer would type &File in the development environment. I’ve always strongly encouraged the use of keyboard accelerators as a must have for any application because many keyboardists are seriously hindered by an application that lacks them. In fact, you’ll find the keyboard accelerators used in the vast majority of my books, even for examples that aren’t related to programming in any way.

Second, some developers who feel as I do about keyboard accelerators are upset that adding them to applications no longer works (apparently). Windows 7 hides the keyboard accelerators for some odd reason known only to Microsoft. The Ribbon interface provides an equivalent when the developer provides it, but we’re talking about all of the applications (the vast majority) that don’t use the Ribbon interface. It turns out that you must manually turn the keyboard accelerator support back on. Follow this steps to accomplish the task manually:

 

  1. Open the Control Panel, followed by the Ease of Access applet. Click the Ease of Access Enter link. You’ll see the list of options shown here:Accessibility0101
  2. Click Make the Keyboard Easier to Use. You’ll see a list of options for making the keyboard easier to use. Near the bottom of the list you’ll see the Underline Keyboard Shortcuts and Access Keys option shown here.
    Accessibility0102
  3. Check this option and then click OK. The system will now display the underlines as before.

One of the biggest questions I had while working through this is whether there is a method for turning this feature on or off at the command line. There isn’t any WMIC command that I’ve found to make the change (nor any other command for that matter), so I’m currently trying to discover the associated registry keys. I’ve found one so far. The On value in the HKEY_CURRENT_USER\Control Panel\Accessibility\Keyboard Preference key must be changed to 1. However, that value alone doesn’t make the change work, so there are more keys and values to find. If anyone has some clues to provide me about this particular need, please let me know at John@JohnMuellerBooks.com. In the meantime, I’ll continue looking for the elusive registry updates required to automate this change.

 

Planting Asparagus – Part 2

Earlier this spring, the Planting Asparagus – Part 1 post discussed some basics of getting the asparagus in the ground. Unlike many other garden plants, asparagus requires quite a bit of effort to get going. However, once planted, an asparagus bed will flourish for many years without much in the way of maintenance, so the up front effort is worth it.

By this time, your asparagus has sprouted and you’ve probably weeded it more than once. It seems as if asparagus attracts weeds for whatever reason. Perhaps it’s the trencheswho knows for certain? If you’ve only seen asparagus in the store, you might have even pulled a few of the young plants accidentally. Here’s what your baby asparagus will look like:

Asparagus011

That’s right, it looks sort of like a fern on a stem. By now you should have a number of these fern-like growths in the trench. When they get this tall, you need to start adding dirt to the trench. Don’t bury any of the branches coming off the main stem. Add just enough loose dirt (don’t pack it down) to bring the trench up to the next level. Burying part of the stem will encourage the asparagus to grow taller.

Now you’ve got some asparagus to tend, but it’s still not done yet for this summer. We’ll visit this topic again. In the meantime, let me know if you have any questions at John@JohnMuellerBooks.com.

 

Getting Started with Chickens

Rebecca and I don’t raise chickens every year. We raise chickens for two years, then give the land a rest on the third year. This cycle ensures we meet a number of goals, including the reduction of disease risks that could occur if we raised chickens every year. We normally start with 75 Cornish Rock chicks because that provides us with about 1½ year’s worth of meat. The chicks arrive in a box like this one:

Chickens0101

The baby chicks are packed pretty closely together so they stay warm. Chicks require a considerable amount of warmth or they’ll die. If you get chicks at some point, don’t be surprised at just how tightly they’re packed:

Chickens0102

Of course, you’ll want to get them out of there as quickly as possible (the chicks will tend to want to run all over the place if you let them). However, the chicks don’t know how to drink when you first get them. The safest way to teach them to drink is to dip their beaks in a water solution as shown here.

Chickens0103

The solution shown here is actually Gatorade. It contains a number of things the chicks need to get started. We provide them with watered down Gatorade for the first few days and find that it reduces the number of chick deaths (in most cases, we lose 2 or 3 chicks during this first stage, but we’ve had years where we didn’t lose any).

At this point, you put the chick into some type of container (we use a large cardboard box) with a pan of chick starter. We don’t believe in using many chemicals with our chickens, but we do use a chick starter that has medications in it to prevent diseases such as coccidia.

The chicks are kept under heat lamps until their full feathers grow in. We use disposable tin plates and replace their paper daily to ensure the chicks remain in the healthiest possible environment as shown here:

Chickens0104

As the chicks grow, we’ll move them to non-medicated food. In fact, they’ll often eat garden scraps, plenty of grass, and have access to various other items that chickens would normally eat (such as worms) because we raise them in chicken tractors. We also move our chicks outdoors to chicken tractors so they can get plenty of fresh air and sunshine. I’ll talk about this next stage in a later post. For now, the chicks are snug under the heat lamps.

Chickens0105

It’s important to provide the chicks with enough space, but not too much space. If you provide too much space, the more aggressive chicks will trample and kill the less aggressive chicks. At this point we supply 9 square inches of space for each chick. As the chicks grow, we increase the allotted area to 1 square foot per chicken.  The full grown chickens will have 2 square feet or more of space. (Full grown chickens normally receive 1/2 square foot of space in factory conditions.)

We’ll start out by making food available to them 24 hours a day.  After the first five days, we’ll withdraw food at night to prevent health problems. The chicks will have clean water available 24 hours a day. Overfeeding chicks (as is done in factory conditions) can result in a condition known as flip (the chick dies of a heart attack). We prefer to let our chickens grow slowly.

 

Accessing a Global String

A reader just wrote in today asking for an extension to the example that begins in the Sharing Variables Among Source Files section of C++ All-In-One Desk Reference For Dummies. The example shown in Listings 5-6, 5-7, and 5-8 describes how to declare a global int variable using extern and the reader wanted to extend this example to the string type. The reader had tried several times, but kept getting the following error message (the same message appears in CodeBlocks 8.02 and 10.05 and the update in this post works with both versions):

 

error: ‘string’ does not name a type

I’m assuming that you’ve already read the discussion about this example (be sure you read the entire section from pages 119 to 121). Creating a fix for this problem isn’t hard, but providing some example code will make things easier to understand. The first issue is to include the required support in main.cpp (shown in Listing 5-6). Here’s an updated version that includes an entry for a string variable named CheeseburgerType.

#include <iostream>
#include <string>
#include "sharealike.h"
 
using namespace std;
 
int main()
{
  DoubleCheeseburgers = 20;
  CheeseburgerType = "Deluxe";
  EatAtJoes();
  return 0;
}

As you can see, you must provide #include <string> and then set CheeseburgerType to a value, which is “Deluxe” in this case. Otherwise, the example works precisely the same as before.

Let’s look at sharealike.h next (Listing 5-7). The following code changes are essential or the example will never work.

#ifndef SHAREALIKE_H_INCLUDED
#define SHAREALIKE_H_INCLUDED
 
using namespace std;
 
extern int DoubleCheeseburgers;
extern string CheeseburgerType;
void EatAtJoes();
 
#endif // SHAREALIKE_H_INCLUDED

Notice the inclusion of using namespace std;. The example will fail to compile without this statement added unless you specify the namespace as part of the type declaration. Once you define this addition, you can create the extern string CheeseburgerType; declaration. Of course, if string were part of another namespace, you’d use that namespace instead.

The final part of the puzzle is to create the required implementation. This part appears in sharealike.cpp (Listing 5-8). Here’s the final piece of the example:

#include <iostream>
#include <string>
#include "sharealike.h"
 
using namespace std;
 
int DoubleCheeseburgers;
string CheeseburgerType;
 
void EatAtJoes() {
  cout << "How many cheeseburgers today?" << endl;
  cout << DoubleCheeseburgers << " " << CheeseburgerType << endl;
 }

As with main.cpp, you must add the appropriate #include. In addition, this part of the example updates EatAtJoes() to include CheeseburgerType in the output. When you run this example, you’ll now see a cheeseburger type in the output as shown here:

GlobalVariable

Are there any questions on this extension? Please let me know at John@JohnMuellerBooks.com.

 

Interacting with the Remote System Using Telnet

Today marks the last post in my Telnet series unless someone writes with additional ideas on issues they’d like me to cover. So far, I haven’t received any requests for Telnet scripting topics, so I’ve decided that perhaps there isn’t a lot of interest in this topic. I discussed basic Telnet connectivity in the Using Telnet to Perform Tasks post. The last post, entitled “Sniffing Telnet Using Wireshark,” covered Telnet security issues. Today’s topic is a natural extension of the topics discussed so farnow that you have an interactive session with a remote system (router, server, or workstation, it doesn’t matter), what can you do with it?

My book, Administering Windows Server 2008 Server Core,” provides a few ideas on the topic, but not very many. I’m thinking now that perhaps I should have discussed this topic in “Windows Command-Line Administration Instant Reference,” but then there is always the question of the cost to other topics and I had no idea when I wrote that book that Telnet was still so popular with some administrators. The short answer is that you have a fully functional command prompt.

The problem is that you’re working with a remote command prompt, not the local command prompt. So, the command prompt you’re accessing is the one on the remote system, with all its attendant resources and limitations. As a consequence, unless you’re working with that system every day, you’ll want to type Ver and press Enter to see which version of the command prompt you’re using. It seems like a simple thing to do, but some administrators don’t and later discover that problems at the command line had nothing to do with the session, but the version of the command line. If you’re working with Windows, you can find a complete list of Windows OS Version numbers on MSDN.

Knowing the version number and the associated operating system name lets you look for commands for that OS in either of my books or you can look them up online. For example, you can use the search phrase, “Windows XP Command Line” on Google (or any other search service) to obtain quick access to sites such as Technet where you can find a listing of associated commands from A to Z. Obviously, these sites will only tell you which commands are available, not how to use them, but knowing what’s available does help.

Another problem that many administrators encounter is that they don’t consider the environment. Again, the environment focuses on the remote system, not your local machine. So, that favorite path might not be part of the Path environment variable and typing a much beloved command won’t work at all. Consequently, it pays to type Set | More and press Enter so that you can look through the environment variables to ensure everything you need is available. This command also provides some essential cues about the remote system configuration. For example, if the Set command reveals a ProgramFiles(x86) environment variable, then you know you’re working with a 64-bit system and some older commands may not work as anticipated. Use the Set command to add or modify any environment variables required to get your work done.

At this point, you know which commands you can execute and you know that the environment is configured for use. What you don’t know is whether you have the rights required to accomplish the task. You can use commands such as ICACLS to verify your rights or you can simply try the command to see whether it completes successfully. The important thing to keep in mind is that newer versions of Windows employ the UAC, even at the command line, so you might find your efforts thwarted.

Even when everything is working properly and you have all of the required rights, you should avoid using certain commands in a remote session. For example, you definitely don’t want to start another copy of Telnet from the remote session (assuming the remote session will even allow it). Using the WinRS command probably won’t work well either. However, Terminal Server commands such as QWinSta appear to work just fine. Let me know your thoughts about Telnet at John@JohnMuellerBooks.com.