Tuesday, January 30, 2007

Released - PowerShell for Vista

Finally, Windows PowerShell 1.0 for Windows Vista has just released. You can download the x86 version here. Check out the Windows PowerShell team blog.

Monday, January 29, 2007

Automated Web forms


The listed function will Auto Login into Gmail. You can include it in the your Profile for fast execution. BTW, setting the value of a text input in PowerShell doesn’t follow the VBScript syntax, and so :

$ie.document.FormName.InputName.value = "something" will raise an error: Property 'value' cannot be found on this object; make sure it exists and is settable. At line:1 char:18 + $ie.theForm.TheInputName.v <<<< alue="something"

The code also implements the Get-Credential cmdlet. You can prompt the user to enter his credentials in a relative "secure" way (10x to /\/\o\/\/ ThePowerShellGuy for his help).

function Login-GMail{
    param(
        [string]$uname,
        [string]$url="http://www.gmail.com",
        [bool]$cookie=$false
    )

    $creds = get-credential $uname
    $pass = $creds.GetNetworkCredential().Password
    $ie=new-object -com internetexplorer.application
    $ie.visible=$true $ie.navigate($url)
    while($ie.ReadyState -ne 4) {start-sleep -m 100}     
    $ie.document.getElementById("Email").value=$uname     
    $ie.document.getElementById("Passwd").value = $pass     
    $ie.document.getElementsByName("PersistentCookie") | foreach {$_.checked=$cookie}     
    $ie.document.getElementById("gaia_loginform").submit()
}
Set-Alias gmail Login-Gmail

To activate it just type: gmail yourAccountName

$hay

Sunday, January 28, 2007

Inline Progress Bar

Here is a quick one to display inline precentage count (basic demo)

# sets the display two lines bellow the current cursor Y position

$CursorY = $host.UI.RawUI.CursorPosition.Y+2
write-host "`nprocessing something...`n" -fore yellow
1..100 | % {     
   [Console]::SetCursorPosition(0,$CursorY)     
   [Console]::Write("please wait... [ $_% ]")     
   sleep -m 50
}
write-host "`nProcessing something, is done.`n" -fore yellow

and for a "real-world" example:

$events = get-eventlog -logname system
$CursorY = $host.UI.RawUI.CursorPosition.Y+2
for($i -eq 0;$i -lt $events.count;$i++){     
   [int]$p=[math]::round(((100*$i)/$events.count))     
   [Console]::SetCursorPosition(0,$CursorY)     
   [Console]::Write("Percent complete: "+[String]::Format("{0:N0}{1}" ,$p,"%"))
}

write-host `n

$hay

Tuesday, January 23, 2007

Open In Regedit (IE Context Menu)

About a year ago I contributed a tool I wrote, called "Open In Regedit", to Daniel's Petri IT knowledgebase. (You can read Daniel's review here).

Since I run my own blog now, I decided to re-publish it here and also check if it will run on Windows Vista.

Open In Regedit is a Context-Menu enhancement for Internet Explorer. While browsing the net for some articles , KBs and other system related issues, often you will have to make some registry modifications.

Usually, you will write down copy-paste the key , open regedit.exe and navigate your way inside. Well, not anymore.

Open In Regedit enables you to highlight registry paths written inside web pages, right-click on them and launching regedit.exe with the specified key location already highlighted (depends if the key already exists).

I tested it on Win XP SP2 (IE6) and Windows Vista (Business edition IE7). I have found that the difference between a registry path in XP and Vista is the Prefix "My computer\path_to_key_or_value" and "Computer\ path_to_key_or_value " respectively.

Play with it, and if you find a bug or even extended it in your way, then fill free to drop a comment. You can download it here.

$hay

Sunday, January 21, 2007

Real time command line spy

Generally, every script you write involves running some Windows built-in tools. Applications like regedit.exe or cmd.exe are the most common. For this tools to operate within a script, a command line argument must be supplied to tell the application what "task" to perform otherwise it will just run with the default settings.

As I see it, command line arguments and switches are both fascinating and powerful. There are even undocumented switches, which makes them even more mysterious. For example, running control panel applets can be done with tools like control.exe or rundll32.exe, both with some arguments.

CONTROL.EXE <cplfilename.cpl> RUNDLL32.EXE <dllname>,<entrypoint> <optional arguments>

To run the Internet Properties dialog, type:

control.exe inetcpl.cpl or rundll32.exe shell32.dll,Control_RunDLL INETCPL.CPL

You can even open the applets with another tab in front (using the tab Index number). To open the Internet Properties dialog with the Privacy tab in front, type:

control.exe inetcpl.cpl,,2 rundll32.exe shell32.dll,Control_RunDLL INETCPL.CPL,,2

Traditionally, you will use the /? switch to reveal your application's help, but, if you run rundll32.exe /? you'll end up with nothing, searching for help on these kind of files can be a quiet a challenge, and as you can see with the rundll sample this is not ordinary stuff like cmd.

For quite some time I was puzzled by this. How can I find the rundll's or any other file command line switches and arguments? Can I find more than "exist" in the default documentation or help parameter?.

I started to Google, with no luck. Including the words "command line" in Google's search was a pain. I had to filter out dozens of links, ohhh... until I came across Bryan Keadle's Cool Tools page.

One of Bryan tools called "Intercept" was made exactly for this task. Intercept will replace itself with the selected program, show the parameters being passed, then continue on to the original executable. Fantastic, I downloaded the file, tested it and it worked just fine.

While "Intercept" did a great job on a small scale I was looking for a better solution. Than I came across SysInternals "Process Explorer" (now hosted on TechNet). If you used Sysinternals tools before, than names like regmon, filemon, tcpview and others are no stranger to you (if you didn't use there tools shame on ya :-), you can download the entire Sysinternals Suite (8 MB) from here).

Double-clicking any process in Process Explorer launched the process property dialog. This dialog lists a plethora of information on the process including the command line that started it.

 

Now, all I had to do is click the processes and investigating their command line, and testing them offline. As for the above rundll example, go to the control panel and run any applet you like, once you launched it look for rundll process in Process Explorer, double-click it and view its command line, then you can include it in your scripts.

As for processes that took very small amount of time to execute and appear in the display, I used the "spacebar" key to "freeze" the display from refreshing and then double-clicked the process. This method became very wearying while waiting for processes to execute, much like a mouse and cat chase. The last step in this quest was the release of SysInternals Process Monitor (By Mark Russinovich and Bryce Cogswell).

Process Monitor includes regmon, filemon and Process Explorer in one tool. It captures all the activity of registry, file system, and processes/threads in real time, and logs the results to a file on the local disk. Boom, this was what I looked for. Here is my way of real time spying/monitoring command lines:

1. Run procmon.exe
2. Toggle off registry activity
3. Right Click any Column header and choose "Select Columns..." (or Click Options > Select Columns) and uncheck everything except "Process Name" and "Command Line".

 

4. Viola! Procmon.exe scrolls the results and from now on, no command line switch is immune.

 

In addition filters can be applied to adjust the displayed processes. If you wish to exclude a Process, just right click it and choose "Exclude > Process Name".

Finally, you can save the results to a CSV file for later use. One can even make a Command line Database :-)

 

I strongly recommend viewing Mark's session on "Advanced Windows Troubleshooting with Process Monitor"

 

Enjoy $hay

Wednesday, January 17, 2007

Transcript & search

While experimenting your way in PS> you have probably tested some new commands, browsed some websites, copied and pasted some code into the console and tested their output, closing and re-opening PS> and all over again. Along the way, when you wanted to reproduce the commands, you typed them With some mistakes, the console returns error messages and you are pulling your hair out trying to figure out what is wrong, while wishing you could travel back in time, but this is not possible.

PS> comes to your help with a cmdlet called Start-Transcript (there is also Stop-Transcript) . You can tell PS> to record your sessions by typing Start-Transcript (you can also include it in your profile to automate the action each time you launch PS>).

Finding your command history is instantaneous. PS> records all the commands and command output as you typed them into the console, and at the same time writes them to a text file (similar to the Tee-object).

Running Start-Transcript with no parameters will write a text file to the default file location (My Documents) with a file name similar to PowerShell_transcript.20070114225720.txt So, Here is the relevant portion of my PS> profile file:

New-PSDrive -name PSS -Psprovider FileSystem -root "E:\PowerShell\Scripts"

function Record-Session{
   param(
     
[string]$logname,
      [string]$path
   )

   $path="$path\PSLOG_$logname.log"
   if(Test-Path $path) {Start-Transcript $path -append} else{Start-Transcript $path -force}
}

Set-Alias recse Record-Session recse -path pss:"\history" -logname (Get-Date).ToString("dd-MM-yyyy")

 

The first line defines a new PSdrive for my PS> scripts folder. So, instead of writing the whole path, I can use pss: to access its content (this can also be achieved by creating a new environment variable). Inside the new PSDrive I created a folder named "History" that will contain all the PS> session recordings.

If you choose to include Start-Transcript in your profile file, each time you open PS> the console will show that the Transcript has started (see below for more details regarding this), the output file is:

C:\Documents and Settings\Administrator\MyDocuments\PowerShell_transcript.20070114225720.txt

As this cmdlet delivers the goods, if you open and close PS> 50 times a day or more (I recommend leaving it open all day long), at list 50 transcript files will be created (one for each session) and the folder that contains the files will contain multiple files, dramatically increasing the used space when working with PS> on a daily basis.

To overcome this, the Record-Session was written in a way that the default location for saving the files can be changed, a new file name pattern will be applied and only one transcript file will be generated per day.

The Record-Session function takes two parameters. One for the path to the History folder, and another to the log file name in a format of "PSLOG_dd-MM-yyyy.log". In the last lines, a new alias is made and called for the Record-Session:

Set-Alias recse Record-Session recse -path pss:"\history" -logname (Get-Date).ToString("dd-MM-yyyy")

Note that parameter names can be used when invoking the alias "recse". To quickly search the transcript files (or any other files) just type:

Get-ChildItem pss:"\history" -filter *.log | Select-String -pattern "administrator"

This command will pipe each transcript file it finds under the History folder to the Select-String cmdlet in order to find "administrator". You can supply a regex pattern to the -pattern parameter. Now, when running it on my computer I got an error message.

Select-String : The file can not be read: E:\PowerShell\Scripts\history\PSLOG_14-01-2007.log At line:1 char:66+ Get-ChildItem pss:"\history" -filter *.log -force | Select-String <<<< -pattern "administrator".

I suspect the error caused by trying to open the current (locked) transcript file that is in use by PS>, so searching inside the current transcript file cannot take place. I added the -force parameter to avoid such errors.

Get-ChildItem pss:"\history" -filter *.log -force | Select-String -pattern "administrator"

It didn't help so I tried another variation with -ErrorAction (shorter version -ea), one that will "Resume Next" and wont stop the process:

Get-ChildItem pss:"\history" -filter *.log | Select-String -pattern "administrator" -ErrorAction SilentlyContinue

This time I got a ton of output. Piping it to "more" gave me the option to page the results: Get-ChildItem pss:"\history" -filter *.log | Select-String -pattern "administrator" -ErrorAction SilentlyContinue | more

The matched output is in the format of: FullPathToTheFile:LineNumber:MatchedLineText or
E:\PowerShell\Scripts\history\PSLOG_13-01-2007.log:4:Username : SHAY\Administrator

If a case-sensitive search is required, consider adding the -casesensitive parameter to the Select-String cmdlet. Finally, to display a summary of matches per file you can use:

Get-ChildItem pss:"\history" -filter *.log | Select-String -pattern "administrator" -ea silentlycontinue | group-object Filename | sort-object count -desc | ft count,name -autosize

Count Name
-----    ----
1156    PSLOG_11-01-2007.log 55 PSLOG_12-01-2007.log 15 PSLOG_13-01-2007.log

 

$hay

Wednesday, January 3, 2007

PowerShell Space Invaders

Check out Adrian's Milliner PowerShell blog to download the script. Very cool stuff!!! $hay