Monday, July 05, 2004

I have been using dasblog for a few months now. While I have fixed some of the minor issues, there are some issues that are pending.

 

One of the major issues with dasblog is the time settings. Besides the time [of posting a blog/comment] not being displayed correctly, there is yet another issue. We cannot make a blog post post-midnight for a couple of hours. After Pandu and Rosh had some bad experiences with this in the past, we three deliberately avoid making posts between 12.00 – 5.00 am in the nights.

 

A big thing missing in dasblog is an archive view, there is no real way of viewing your past blog entries based on some archive view. I saw somebody’s implementation of archive view in dasblog, not exactly what I would have liked to have but atleast there is an archive. I should check that out. Anybody else has an archive implementation for dasblog?

 

Some of the other minor issues:

 

  1. No delete comment feature
  2. Post a comment and you are brought to the main page [I have fixed this]
  3. No obfuscation of your own email-id [I have fixed this. You can now add the text you wish to replace @ and . with in the e-id in the config file. Neat?]
  4. Time display error
  5. Sometimes, when you edit an old entry, it makes a new entry. I am not able to re-produce this though. Happens once in a while.
  6. Delete category
  7. Rename category

 

This blog entry doesn’t talk about the good things in dasblog [Yeah, you could read it as whatever is not listed here works good in dasblog ;)]

Monday, July 05, 2004 8:27:15 AM (US Eastern Standard Time, UTC-05:00)  #    Comments [5]Trackback
 Tuesday, June 29, 2004

Ankit Fadia

Recently, Ankit Fadia came to Oxford bookstore at Leela Palace, Bangalore to inaugurate their book exhibition and to give a general awareness talk on internet security. I was quite excited about seeing the young champ.

 

The audience were largely press people with about 3-5 non-press folk; guess this was a publicity funda for Oxford more than anything else. Ankit Fadia started his talk with

“How many of you use messengers like yahoo and msn”

“Don’t use it, its not safe”

 

“How many of you use search engines like yahoo and google?

“Don’t use it, its not safe”

 

etc etc

 

“and finally how many of you use the internet?”

“Don’t use it, its not safe”

 

He went on to say that since that is not practical, it is better to be safe by thinking like a criminal and taking precautions. He gave an example of this lady in Bombay who had a cable internet connection and a web cam and was a chat freak. A guy from Russia who was chatting with her apparently managed to install a Trojan and switch on her webcam. She had no clue about any of this and life went on. She went for a job interview 3 months later and the guy said he was too happy to offer her the job and that he saw her everyday at the porn site. And then she went totally paranoid and is probably not using the internet today. Sounded too contrived to me. Sum total of the talk was that use a proxy server to connect to the internet else you are in soup.

 

Well, wasn’t exactly very enlightening. Had a QA session towards the end when some of the press guys asked a lot of questions. One of the questions was “Is Linux more secure than windows” to which Ankit Fadia answered yes. I was quite curious to hear the reasons. “Since Unix is open source, its more secure. Since it is open source and there are tens of thousands of people working on it, when a bug is found anybody can take it and fix it. Whereas windows will have only about say 1000 people team, so finding and fixing bugs will take time….” [!!???!!!]

 

I didn’t find him technically accurate and after all the media hype this talk was probably a small let down. Then again, for what he is doing at his age he must be quite smart. I wouldn’t have been able to do that when I was 19. And he is at Stanford, obviously the guy is smart. The media is probably a little misleading, can’t really blame the young man.

 

Martin Fowler

I had read some papers and methodologies by Martin Fowler and appreciate the agile methodology a lot especially since I have seen and been a part of the conventional methodology. So I had all the reason to be excited to meet Mr. Fowler. This time excitement was coupled with nervousness, coz he was going to be listening to me do a session at the Bangalore .NET User group meeting.

 

After my talk I had a small conversation with Martin Fowler and others. Was surprised to see how approachable he was and how easily the discussions stemmed and ideas were exchanged. He liked monad, monad is quite agile anyways ;)

 

God

No, I haven’t met God but I think he knows of my existence J

Tuesday, June 29, 2004 5:19:32 AM (US Eastern Standard Time, UTC-05:00)  #    Comments [6]Trackback
  1. get-command

The idea of being able to see all the commands supported by a shell is pretty cool. Has this been there in the past? I doubt. This command outputs not only the standard commands that come with msh but also the cmdlets that have been added by the user.

  1. get-help

get-help followed by a command name gives a detailed help for that command. Try (get-help get-command).synopsis, the get-command here could be any other command. Cool?

  1. get-member

Any command gives its output as an object in msh. This object could offer a set of methods and properties. Get-member uses reflection and lets you see these members. For eg: get-command | get-member -methods lists the methods available for the command object

  1. Programmability on  the commandline – write functions, use foreach, if-else etc.
  2. out-*

Killer feature. Try get-process | tail | out-excel. Now try get-process | sort id | tail | out-chart processname, id. You are gonna love what you see J. For other output options, type get-command out-*

  1. –Whatif

What if you had a series of commands, pipes and weren’t 100% sure if it did what you thought it did. What if you spend 2 min thinking if you should press the carriage enter key or not.  You use exactly this feature => the –whatif feature provided by msh. You type in the command and append it with a –whatif. Now the output you see is the output that the command if executed would have given. This is a way to let you know the output of a command without it really executing. Should reduce the average tension in an admins life ;)
stop-process 12,4 -whatif

  1. errorpolicy –confirm

This option gives you an option Yes to all, No to all, yes, no and suspend. Suspend is new. Suspend launches a new shell, lets you explore and find out about the problem, exit and come back to the same option. The idea is that you are probably now surer of which option to choose.

  1. The idea of having cmdlet providers. [Yeah you can traverse the registry as though it were a filesystem. You can write your own providers!!]
  2. where/where-object/reduce-expression

lets you specify a condition, filter. For example.

                                                               i.      gps | where “processname -like n*”

                                                      ii.      $ps get-process

foreach ( $p in ps | where { $_.handlecount -ge 500 } | sort handlecount) {  $p.processname,$p.id }

 

That was a listing of some of the commands that are aha!!

Tuesday, June 29, 2004 2:47:09 AM (US Eastern Standard Time, UTC-05:00)  #    Comments [2]Trackback
 Monday, June 28, 2004

I have been wondering about the cmdlet lifecycle. 

 

How do you add a new cmdlet?

How are the cmdlets loaded by MSH?

 

You use registercommand.exe <Path/dllname> and the new dll is registered. Now what happens when msh is started again? Does it load all the dlls in memory? Or does it load it when a cmdlet in the dll is explicitly invoked? Loading all cmdlet dlls in memory seems like too much memory consumption and overhead. The converse argument could be that practically the number of cmdlets wouldn’t be a very huge number; so doing this at start would give a performance hit.

 

Then again, when do we design stuff for pracrtical cases alone, we usually think of the worst cases!

 

Well, so how do you really find out how MSH is handling commandlet life cycle? There is no cordbg for .Net 2.0 yet and no CLR profilers in the picture.

 

There still is filemon.exe. Thanks to filemon.exe, these are my observations.

 

  1. All the cmdlet dlls are not loaded at msh start up.
  2. get-command doesn’t use reflection on all dlls’ to get all cmdlet names.
  3. Typing a specific cmdlet name loads the corresponding dll, processes and closes it

 These observations lead to the following conclusions:

 

  1. At start-up, msh does not load all the cmdlets in memory
  2. On typing get-command, it does a look-up [may be something like a file lookup], finds all the cmdlet name entries and outputs them
  3. On typing a specific cmdlet at the msh prompt, the corresponding dll is loaded by msh, the processing done, results obtained and dll unloaded [I think]
  4. Due to caching, all cmdlets take time during their first invocation and are faster thereafter.

 

How is a cmdlet executed?

 

First the corresponding dll is found and loaded. Then the cmdlet class is instantiated.

StartProcessing() if overrid is executed. If there are any input parameters, then they are filled with the values by msh and passed to ProcessRecord() if one exists. If pipelined input is enabled then the input parameter is filled with the current pipeline object and ProcessRecord() is exceuted for each of the input records. [So, this kind of looping is not the cmdlet’s responsibility, msh handles it and pumps in the value each time into the input parameter variable]. Finally if EndProcessing() is overrid, then it is executed. The object is then disposed off. Msh handles the output display/formatting/piping/redirection.

 

DISCLAIMER: These are my views only. This is not documented stuff, so I am just taking a guess as to how things may be working under the cover. I could be wrong!

Monday, June 28, 2004 1:15:42 PM (US Eastern Standard Time, UTC-05:00)  #    Comments [0]Trackback
 Friday, June 25, 2004

I took a session on Monad at the Bangalore .NET User Group meeting yesterday. Here is a brief write-up about the session for those of you who missed the session. People starting off on Monad may be interested in reading this.

 

Introduction

Unlike conventional shells that work on text streams and expect the end user to be an expert in text parsing, MSH introduces the idea of using structured object pipelines where objects instead of text flow between commands.

 

At the msh prompt, if we type

MSH C:/ > dir

we see a list of files [the same way the dos dir worked]. We see the same output for ls.

 

In Monad commands are called cmdlet [Commandlets]. Each cmdlet is a combination of a verb-noun pair. For example the cmdlet get-children or get/children gets all the children [files and directories when invoked in a FS]. dir and ls are aliases of get-children. By default the verb ‘get’ is assumed for a command given without a verb. So typing children gives the result of get-children and command gives the result of get-command. Alias is an exception. Typing alias gives the result of set-alias and typing aliases give the result of get-alias.

 

To see all the commands type command. To see all the aliases type aliases.

 

Some example Commands

 

MSH C:/> get-process

 

By using reflection, any object can list the methods and properties that it supports. To get a list of methods supported by a get-process object [which is a System.Diagnostics.Process object] try the command below.

 

MSH C:/> get-process | get-member -methods

 

MSH C:/> $a = get-process

 

MSH C:/> $a[0]

 

MSH C:/> $a[0].ToString()

 

Here $a is an array of Process Objects. We can invoke any function or property from the process class on object $a[0] and see the results like the ToString() example above.

 

MSH C:/> get-process | get-member -property

 

MSH C:/> $a[0].handlecount

 

MSH C:/> gps

 

MSH C:/> gps | tail

 

MSH C:/> gps | sort id | tail

 

MSH C:/> gps | where “processname –like cmd*”

 

MSH C:/> gps | reduce-expression {$_.handlecount -ge 500}

 

get-process or gps returns an array of objects. Reduce-expression works like a lambda in functional programming languages [similar to anonymous method]

For example in scheme (lambda((a b)(+ a b))) acts as a block of code.

In Monad the block of code after reduce-expression in braces is the script that will be carried for each pipeline object. $_ is set to the current pipeline object. So for each object in the object array returned by gps, $_ is filled with an object (the current pipeline object) for which the block of code is executed.

 

MSH C:/> gps | sort handlecount | tail | out-excel

 

MSH C:/> get-process | out-chart processname,handlecount -Title "Processes" -Filename Processes.html

 

MSH C:/> gps | sort handlecount | tail | out-grid processname,handlecount

 

MSH C:/> get-command out-*

 

MSH C:/> foreach ($p in $a | where "handlecount -ge 500"  | sort handlecount) { "{0,-15} has {1,6} handles" % $p.processname,$p.handlecount }

 

Notice the .NET style for formatting strings above.

 

MSH C:/> function n{notepad}

 

MSH C:/> n

 

MSH C:/> n;n;n

 

MSH C:/> gps [a-c]*,[t-z]* -exclude *[p-t] | stop-process –whatif

 

MSH C:/> gps | where “processname –like notepad*” | stop-ps1 –confirm

 

For invalid process ids, an error message is displaying when trying to stop them.

 

MSH C:/> stop-process 123,345,100000,200000,300000

 

MSH C:/> stop-process 123,345,100000,200000,300000 -errorpolicy notifystop

 

MSH C:/> stop-process 100000,200000,300000 -errorpolicy inquire

[Error stop-process]: (No process found for given ID :  : 100000) 100000"

 

[Error stop-process]: (No process found for given ID :  : 100000) 100000"

Continue :[y/yes/ n/no t/yestoall l/notoall s/suspend] s

MSH C:/> exit

 

[Error stop-process]: (No process found for given ID :  : 100000) 100000"

Continue :

[y/yes/ n/no t/yestoall l/notoall s/suspend] l

Stopped (Cmdlet:stop-process): User requested stop

 

MSH C:/>

 

Cmdlet

Each cmdlet is a managed class and not a separate executable. A simple cmdlet code is given below.

 

using System;

using System.Diagnostics;

using System.Management.Automation;

 

namespace SampleCmdlet

{

#region GetPs1

       [CmdletDeclaration("get", "ps1")]

       public class GetPs1: Cmdlet

       {

              public override void ProcessRecord()

              {

                     WriteObjects(Process.GetProcesses());

              }

       }

#endregion

}

 

The class that is to be exposed as a cmdlet is annotated with a CmdletDeclaration property specifying the verb and noun that is to be used to access this cmdlet. Also your class must inherit from the Cmdlet class and override atleast one of the three functions StartProcessing, ProcessRecord and EndProcessing.

 

A cmdlet that receives some input parameters and does exception-handling is given below

 

using System;

using System.Diagnostics;

using System.Management.Automation;

 

namespace SampleCmdlet

{

#region StopPs1

       [CmdletDeclaration("stop", "ps1")]

       public class StopPs1: Cmdlet

       {

              [ParsingParameterMapping(0)]

              [ParsingAllowPipelineInput]

              [ParsingMandatoryParameter]

              [ParsingPromptString( "Input the id: "  )]

              public int [] Id;

      

              public override void ProcessRecord()

              {

                     Process p = null;

                     foreach ( int i in Id )

                     {      if (ShouldProcess(i.ToString()))

                           {

try

                                  {

p = Process.GetProcessById(i);

                                         p.Kill();

                                  }

                                  catch (System.ComponentModel.Win32Exception e)

                                  { WriteErrorObject("No adequate permissions",e); }

 

                                  catch (System.ArgumentException e)

                                  { WriteErrorObject("No such process exists",e); }

                           }

                     }

              }

       }

#endregion

      

}

 

The code declares the input parameter, annotates it with attributes and assumes that the input values have been filled in. It doesn’t care if the input is coming form the pipeline, file, console or any other means. All the parsing and filling up the value is taken care by the shell. The same goes for output. The code calls WriteObject() function to do any output and the shell takes care of the formatting, displaying and routing of output as per the context.

 

The code above is for Monad, March 2004 build. Sample code for July, 2004 build is available at

http://msdn.microsoft.com/theshow/Episode043/Transcript.html

 

Cmdlet Providers

Cmdlet Providers provide the user with a basic set of cmdlets like pushd, move, copy, cd, dir etc that make the provider as navigable as a file store. Two standard providers come with the msh installation, one for registry browsing and the other for active directory.

 

[ProviderDeclaration("REG", "Microsoft", "Windows", "6.0", "MSH", "Registry", "1.0", ProviderCapabilityFlags.None)]

public class RegistryProvider :  NavigationCmdletBase

{

    protected override void GetItem(string path)

    {

        RegistryKey key = GetRegkeyForPath(path, false);

 

        if (key == null)

        {  WriteErrorObject(path, new ArgumentException("does not exist"));

        }

        WriteObject(key);

    }

    ....

}

 

For installing registry provider use:

MSH C:/> new-provider -Assembly "${MSHHOME}\System.Management.Automation.Core.dll" -Provider REG

 

 

 

 

 

Registry Example

To add a new item to the context menu of directories, some values need to be added to the registry. Here is an example that adds a “Launch MSH” option in the context menu of a directory such that on right clicking a directory and selecting “Launch MSH”, Monad is launched and a changedir [or cd] to the corresponding directory is done.

 

For this we create new items, “Launch msh” and “Command: in the registry using msh commands to give HKLM:/Software/Classes/Directory/Shell/Launch MSH/Command. Note: The escape character in MSH is ` => the back quote character.

 

MSH C:/> $val = format-string "`"{0}`" `"{1}`" `"{2}`" "  "${MSHHOME}\msh.exe" "-command" "cd  '%1' "

 

MSH C:/> $val

 

MSH C:/> new-item -path "HKLM:/SOFTWARE/Classes/Directory/shell" -name "Launch MSH"

 

MSH C:/> new-item -path "HKLM:/SOFTWARE/Classes/Directory/shell/Launch MSH" -name "Command"

 

MSH C:/> set-item -path "HKLM:/SOFTWARE/Classes/Directory/shell/Launch MSH/Command" –value $val

 

Now on right clicking any directory an option “Launch MSH” should appear. On selecting that option, MSH is launched with the current directory as the directory that was right clicked. Neat?

 

MSH C:/> Get-drive

 

MSH C:/> cd HKLM:/

 

MSH HKLM:/> dir

 

MSH HKLM:/> cd Software

 

Yeah, the registry provider lets you move through the registry just the way you move through a file system!

 

Download and Installation

Monad Beta Release 1.0

  1. Go to beta.microsoft.com
  2. Sign in with your passport id
  3. Enter Guest login as mshPDC
  4. Fill up the form with your details and submit
  5. After 24-36 hours you should be able to login to the system. Click the downloads link on left pane
  6. Click the Microsoft Command Shell link.
  7. Download .NET framework 2.0. Install this [22.16MB] [It does not interfere with your earlier .NET versions]
  8. Download msh – Microsoft Command Shell Preview [1.88 MB]

 

System requirements

Windows XP or Windows Server 2003.

[If you are on another windows version read 1 and 2]

 

Reference Material

http://msdn.microsoft.com/theshow/Episode043/default.asp

 

The best way to learn monad is to download the shell and read the documentation that comes with the shell. As of now, there are no technical resources about the shell except for the video by Jeffrey Snover – Architect, Monad and Jim Truher – Program Manager, Monad[link above]

 

Take a look at profile.msh file that is installed along with Monad in the user’s home directory.

There is a lot of code using aliases, environment variables, functions, commandlets etc – a good place to pick up some tips from.

 

Do write to me your feedback about Monad – good and bad.

Friday, June 25, 2004 6:22:04 AM (US Eastern Standard Time, UTC-05:00)  #    Comments [14]Trackback
 Tuesday, June 15, 2004

Monad works on .NET framework V2.0. After a comment on one of my earlier entries, I decided to find out if there were any framework 2.0 dependencies in Monad. If not, then we could get it to run on an earlier version of the framework with a bit of work. Else, it will be good to know what features of the new framework are being used by Monad. [Optimistic, ain’t I? ;)]

 

I modified the version numbers in the IL generated by ildasm [.NET framework V1.0 and V1.1] on msh.exe and tried assembling the modified IL using ilasm. Worked smoothly. Next step was to take the dependent assemblies and generate each of them for .NET framework 1.1. On disassembling System.Management.Automation.Core.dll [one of the assemblies referenced by monad], changing the version info in the IL and assembling it back an error message with failure popped up. Looking through the IL generated I noticed generics being used throughout the code.

 

Okay, so monad is using generics. Well, that ensures that Monad will not work on earlier version of .NET framework. Generics is one of the new additions in the new .NET framework. So I have decided not to get too ambitious as to try and get this working on the earlier version(s) of .NET framework.

 

So much for installing Monad J

 

I noticed that .NET framework 2.0 doesn’t come with ildasm.exe. ilasm.exe is there though.

 

[If you are not able to install monad do read my previous post]

Tuesday, June 15, 2004 2:53:58 AM (US Eastern Standard Time, UTC-05:00)  #    Comments [11]Trackback

Recently, an installation exe refused to run on my OS with an error message saying that the adequate OS was not present. All I wanted to do was extract the files from the package. If I could just get past the OS check within the installation exe, then I could get the files. Changing the OS string and environment variable etc didn’t help in this case.

 

Fortunately, I found an easier way to do this.

 

How do you extract files from an install shield exe?

 

If it is based on install shield wizard you may want to take a look at i6comp tool.

If it is based on msi package, then you first need to get the msi out of the exe.

 

From Brad’s e-mail:

Quote

To Hack the MSI file you have to first get to the .MSI file. Begin the install process by double clicking on the .EXE file. When you get the error message DO NOT click ok. Browse to your /local settings/temp folder in /Documents and Settings/. In the temp  folder look for a new folder with current date and time. Inside the folder you will see  file called, "Microsoft command shell Preview.msi" This file can be edited with a program called ORCA.

Unquote

 

Once you have the msi file, you need to edit the target OS version in the file using orca. [Refer this KB article]. Save the msi file after making the changes. Run the msi and you should be able to install the package.

 

Credits: Thanks to Brad Hite for helping out with install shield exe/msi packages.

Tuesday, June 15, 2004 1:32:45 AM (US Eastern Standard Time, UTC-05:00)  #    Comments [9]Trackback
 Thursday, June 10, 2004

Microsoft Command Shell [codename Monad] is Microsoft’s upcoming shell that is planned to ship with Longhorn. I read up a bit about the shell and decided that I have to try things for myself to believe that it was actually true. There is not much material about Monad on the internet now, except a lot of blogs, most people blogging about it are PDC attendees.

 

I downloaded the monad beta bits, its release notes claim that monad will work on Windows XP and Windows Server 2003 only. Monad requires .NET framework 2.0. I installed the framework on my Win2k Professional machine and tried installing monad. The monad installer started off and displayed a message box with the message “The operating system is not adequate for running Microsoft Command Shell Preview”. I did the same things on another machine with win2k3 server. Monad installed and I could work on the shell. Monad is a .NET application and I can’t think of reasons why this shouldn’t work on my win2k machine. Good time to use the deployment feature of .NET apps that I keep talking about. I copied the extracted files [dll,exe and configs] from the server machine to my machine. Launched cmd.exe, moved to the monad folder in my machine [where I copied the monad files from server] and started msh.exe. Bingo, after a minute the shell prompt appeared. Something was different though. I did not see the regular message “Microsoft Command Shell (msh)” that is displayed when you start msh. I took the profile.msh file from my home directory on the server machine and copied to my home directory in my machine. And presto, I have msh.exe working on my win2k machine now. I haven’t found anything missing until now, the behavior of the shell seems to be the same on my machine as on the server machine.


Monad is cool :), absolutely!

Thursday, June 10, 2004 6:54:34 AM (US Eastern Standard Time, UTC-05:00)  #    Comments [17]Trackback
 Tuesday, May 18, 2004