Friday, December 28, 2007

To QuickEdit or not? that's the question

 

In QuickEdit mode, users can cut and paste text, to and from the command shell by using the mouse. There are three ways to change this behavior:

1. Enable/Disable it from the console properties and choose whether to change the behavior for the current window only or to modify the shortcut that started the window (shell).

 

CONSOLE1 copy

 

Clipboard01

 

2. Modify the shortcut that launched the shell.

Clipboard01

If you modify the PowerShell shortcut it will create a new registry key for the PowerShell console.

regedit

 

3. Directly edit the relevant registry values.

 

QuickEdit is a two blade knife. Although it makes your life easier by letting you copy/paste text from/to the console, you can encounter strange behavior situations when you find that you need to press ENETR over and over again to 'wake up the console'.

 

Here's a sample scenario to describe the 'gotcha' when QuickEdit is enabled:

1. Enable QuickEdit
2. Run in PowerShell: 1..100 | foreach  { $_; start-sleep 1 }
3. Let the command loop run once or twice then click with your mouse inside the console window.



CONSOLE3 copy


4. Notice that the command/script pauses when you click in the Powershell console window, the console title also indicates it by preceding the title text with the "Select" word, meaning you're in Quick Edit mode. To make the command run to end you need to press the ENTER key.

I'm sure you don't want this kind of behavior when you run a heavy task script, go to lunch and find out that you accidentally pressed the mouse inside the console window before walking out the office. Sometimes it is hard to spot it if your command/script doesn't write to the console.

 

So, Enable or disable it? That's for you to decide, just be aware of the consequences.

Thursday, December 27, 2007

Bulk image conversion in PowerShell

 

I used to converted large amounts of images from one format to another in Adobe® Photoshop®. Photoshop has an amazing set of tools to bulk convert images and apply different filters/actions on the images. It even offers a COM scripting engine for VBScript and JScript (and AppleScript).

Did you know that you can do it in PowerShell? Well, PowerShell doesn't offer all that Photoshop has, but for a task as image/bulk conversion, PowerShell definitely gives you what you need, fast and simple.

For a complete list of conversion-able formats see the ImageFormat Class.

 

Get all BMP files from the Windows directory, convert them to JPEG files and store them in the C:\Temp directory:

[void][reflection.assembly]::LoadWithPartialName("System.Windows.Forms")
$imgDir = "c:\temp"

get-childitem $env:windir -filter *.bmp | foreach {
    $baseName = [System.IO.Path]::GetFileNameWithoutExtension($_.fullname)
    $img = new-object system.drawing.bitmap $_.fullname
    $img.save("$imgDir\$baseName.jpeg",[System.Drawing.Imaging.ImageFormat]::Jpeg)
}

 

img

 

# build a function to reuse in $profile

function Convert-Image{
    param($image,$toFormat,$saveTo)
    $baseName = [System.IO.Path]::GetFileNameWithoutExtension($image)
    $img = new-object system.drawing.bitmap $image
    $img.save("$saveTo\$baseName.$toFormat",$toFormat)   
}

Convert-Image -image "C:\windows\Blue Lace 16.bmp" -toFormat gif -saveTo c:\temp

Wednesday, December 26, 2007

Extracting icons with PowerShell

 

# Extract all exe file icons from the windows system directory to c:\icons, as icon files.
# The Save() method can extract the files to various image formats: jpg, bmp, gif.

$systemDir = [environment]::SystemDirectory

dir $systemDir -filter *.exe | foreach {
    $baseName = [System.IO.Path]::GetFileNameWithoutExtension($_)
    [System.Drawing.Icon]::ExtractAssociatedIcon("$systemDir\$_").ToBitmap().Save("c:\icons\$BaseName.ico")
}

 

icons

 

# New function to $profile

###########################
##   Extract-Icon
##   Usage:
##      Extract-Icon -file C:\windows\system32\notepad.exe -saveTo c:\icons -ext ico

function Extract-Icon($file,$saveTo,$ext){
    $baseName = [System.IO.Path]::GetFileNameWithoutExtension($file)
    [System.Drawing.Icon]::ExtractAssociatedIcon($file).ToBitmap().Save("$saveTo\$BaseName.$ext")
}

Tuesday, December 25, 2007

Power (shell) to the people!


viva

It has been a great year for PowerShell users, filled with good stuff. It seems that the PowerShell community is growing constantly and people around the world are adopting PowerShell and discovering its true POWER.

The PowerShell news group is live and kicking and the guys at the group are ready for any user - submitted challenge, Cheers!

Many books have been written and there are some more cooking in the oven as we speak.

The release of PowerShell v2.0 CTP and the addition of PowerShell to the Common Engineering Criteria (CEC  is a great vote of confidence for the product and for the architects/team that brought this project to life.

As for me, I couldn't be happier. PowerShell keeps me busy (fanatic) ALL DAY LONG, even when I sleep! I even opened a new blog on Microsoft Israel to spread the word to Israeli audience. No matter how much I drink from my PowerShell cup, it seems to refill on its own. Yes, I'm a proud PoSHoholic too!!!

As for the Windows PowerShell team, you should be proud of yourself, you've been doing a great job! I've collected some names of the people behind the scenes of PowerShell that I found on the team blog and around the net. I am sure that it's an incomplete list, so please forgive me if I've left anyone out. Ladies and gentleman's, HATS OFF!

 

(alphabetically)
Abhishek Agrawal - Windows PowerShell team
Brent Taft - Senior Program Manager
Bruce Payette - Principal Developer, Windows PowerShell Team
Jeffrey Snover - Windows Management Partner Architect
Jonathan White - Windows PowerShell Test
June Blender - Windows PowerShell Documentation
Krishna - Windows PowerShell Development
Lee Holmes - Windows PowerShell Development
Narayanan Lakshmanan - Windows PowerShell Development
Wassim Fayed - Cmdlet Help Editor
Wei Wu - Windows PowerShell Team

Jeffrey, if you read this, if there's a way to publish the team picture on the team blog,
I would like to see their faces and virtually pat each one on the shoulder. 

 

Viva La Revolucion, Power (shell) to the people!
Thanks you and Merry Christmas ALL.

The crazy antics of Remi Gaillard

 

Saw that yesterday on the UK EuroSport channel, you can see more videos of Remi's tricks here.

 


 


Monday, December 24, 2007

Scheduled blog posts


There is a neat feature in Windows Live Writer (Version 2008 Build 12.0.1367.1128) that lets you set your post publish date to any point in time, past or future. This is very useful if you need to repost from an older blog to your new one and you want to retain the original posts date.

sched

 

 

 

 

 

 

 

 

 

It might not work on all blog service providers. For example, Blogger doesn't support it and I get this dialog box. Check yours.

warn

Sunday, December 23, 2007

How many days in a month? and more...

 

Ask the [datetime] type :-). Give it a Year and month number.

 

PS>[datetime] | gm -static days*

   TypeName: System.DateTime

Name        MemberType Definition
----        ---------- ----------
DaysInMonth Method     static System.Int32 DaysInMonth(Int32 year, Int32 month)

 

# number of days in January 2007
PS > [datetime]::DaysInMonth(2007,1)
31

 

 

# number of days in each month of year 2007
PS > $year = 2007
PS>1..12 | foreach { "There are {0} days in: {1} {2}" -f [datetime]::DaysInMonth($year,$_),(get-date -month $_ -f MMMM),$year }

There are 31 days in: January 2007
There are 28 days in: February 2007
There are 31 days in: March 2007
There are 30 days in: April 2007
There are 31 days in: May 2007
There are 30 days in: June 2007
There are 31 days in: July 2007
There are 31 days in: August 2007
There are 30 days in: September 2007
There are 31 days in: October 2007
There are 30 days in: November 2007
There are 31 days in: December 2007

 

# another method to get month names (depending on the culture)
PS > [System.Globalization.DateTimeFormatInfo]::CurrentInfo.MonthNames

January
February
March
April

(...)

 

# get month names by number
PS > 1..12 | foreach { [System.Globalization.DateTimeFormatInfo]::CurrentInfo.MonthNames[$_] }

(...)
August
September
October
November
December

 

# with PowerShell new-object cmdlet

PS > $dtfi = new-object system.globalization.datetimeformatinfo

PS > $dtfi.DayNames

Sunday
Monday
(...)

 

PS > $dtfi.DayNames.Get(0)  # same as $a.DayNames[0]
Sunday

 

PS > $dtfi.MonthNames
January
February
March
(...)

 

PS > $dtfi.MonthNames[11]
December

 

# get month names for a specific culture
PS > ([System.Globalization.CultureInfo]"en-US").DateTimeFormat.MonthNames
January
February
March
April
(...)

 

# Hebrew day names

PS:48 >([System.Globalization.CultureInfo]"he-IL").DateTimeFormat.DayNames
יום ראשון
יום שני
יום שלישי
יום רביעי
יום חמישי
יום שישי
שבת

 

# CultureTypes Enumeration
# http://msdn2.microsoft.com/en-us/library/system.globalization.culturetypes.aspx

PS > $AllCultures = [System.Globalization.CultureTypes]::AllCultures
PS > [System.Globalization.CultureInfo]::GetCultures($AllCultures)

LCID             Name             DisplayName
----             ----             -----------
1                ar               Arabic
2                bg               Bulgarian
3                ca               Catalan
4                zh-CHS           Chinese (Simplified)
5                cs               Czech
(...) 
 
 

# format each culture date, base on its local datetime ShortDatePattern, extend each returned item with a new property (ShortDate)

$AllCultures = [System.Globalization.CultureTypes]::AllCultures
$cultures = [System.Globalization.CultureInfo]::GetCultures($AllCultures)
$cultures | foreach {
    $df = ([System.Globalization.CultureInfo]$_.name).DateTimeFormat.ShortDatePattern
    $_ | add-member -membertype noteproperty -name ShortDate -value (get-date -f $df)
    $_
} | select DisplayName,ShortDate | format-table -auto

 

# truncated list

DisplayName                                        ShortDate
-----------                                        ---------
Arabic (Saudi Arabia)                              23/12/07
Catalan (Catalan)                                  23/12/2007
Chinese (Taiwan)                                   2007/12/23
Czech (Czech Republic)                             23.12.2007
Danish (Denmark)                                   23-12-2007
German (Germany)                                   23.12.2007
Greek (Greece)                                     23/12/2007
English (United States)                            12/23/2007
Finnish (Finland)                                  23.12.2007
French (France)                                    23/12/2007
Hebrew (Israel)                                    23/12/2007


 

This is just the tip of the iceberg and there is ton more to explore.

Saturday, December 22, 2007

How to get attributes metadata on AD object


Querying Active directory for disabled user objects is pretty straightforward. But how can you tell exactly when the user was disabled? How about get the metadata for one or more attributes on a specific active directory object?

Check out Brandon's blog for the answer.

Friday, December 21, 2007

Channel 9 interview with Mark Russinovich

 

Russinovich_bio

Mark Russinovich, Technical Fellow and SysInternals founder, talks on working at Microsoft, Windows Server 2008 Kernel, MinWin vs ServerCore, HyperV, Application Virtualization.

See it on Channel 9.

Hyper-V demo videos

 

Windows Server 2008 Hyper-V

Windows Server 2008 Hyper-V is the hypervisor-based virtualization feature included as a role of Windows Server 2008. It contains everything needed to support machine virtualization.

It is available now for evaluation with Windows Server 2008 RC1. There are also some demo videos available on Arlindo's Blog.

Thursday, December 20, 2007

Quest Software AD cmdlets goes RTM


quest_logo

 

 

The ActiveRoles Management Shell for Active Directory is a set of PowerShell commands (CMDLETs) that can be used for free to perform administrative tasks within Active Directory.


Congratulations,

The RTM version has just released (v1.0.6). According to Dmitry Sotnikov (Powershell MVP), this version has one new cmdlet and a few improvements and bug fixes as well as full PowerShell v2 compatibility, and YES it's still free. AWESOME!!!




You can download it here. Check out Dmitry's blog for the full version description.

HowTo Install Virtual Server in Windows 2008 Server Core

 

2008 Global Launch Wave
68
Days
Windows Server 2008, Microsoft Visual Studio 2008, Microsoft SQL Server 2008

Mark Kaelin, will take you through the process of configuring Virtual Server 2005 to work in server core, with detailed command-line steps.

Exchange Certificate Command Generator

 

Having troubles figuring out how to use Exchange 2007 New-ExchangeCertificate cmdlet?
Not sure what parameters to use and how?

DigiCert, a security corporation specializing in providing High-Assurance SSL certificates came up with a web GUI 'wrapper' to make your life easier. Clicking inside each text box shows a brief explanation of each field.

digi

Tuesday, December 18, 2007

Interview with Lee Holmes


TechNet Script Center interview with Lee Holmes, developer on the Windows PowerShell team and author (chef) of Windows PowerShell Cookbook.

Saturday, December 15, 2007

OS Install date

 

Yesterday, I had to query some computers for the date/time the OS was installed. I remembered that there is a registry key for that so I checked the registry under:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion
-or-
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Setup

 

Nope, no sign for it, it wasn't there. I found it under:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion

The key is named InstallDate but its value was a number that didn't resemble any date time format.

 

installdate

 

 

 

 

 

 

 

 

 

According to Microsoft,  this value represents a time/date as an offset in seconds from
midnight, January 1, 1970. Hmm... no problem, I can use the AddSeconds() method of the [datetime] type to return the exact OS install date:

 

### EDIT 12/23/2007 ###

Thanks to TRB86 for pointing me to initialize the hour/minute/second parameters.
If you won't define those parameters (which I thought will default to zero, respectively) you'll end up with the correct date but with your local time values.
So, if you're local time is  10:23:11, then doing so will initialize $date to 01/01/1970 10:23:11

$date = get-date -year 1970 -month 1 -day 1
$date -format "MM/dd/yyyy HH:mm:ss"
01/01/1970 10:23:11

#####################

 

PS > $path = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion'
PS > $id = get-itemproperty -path $path -name InstallDate
PS > $d = get-date -year 1970 -month 1 -day 1 -hour 0 -minute 0 -second 0
## the following returns the datetime -2 hours which is my GMT offset (+02:00).
## $d.AddSeconds($id.InstallDate) -f "MM/dd/yyyy"
## 02/28/2007 23:56:23

## add to hours (GMT offset)
PS > ($d.AddSeconds($id.InstallDate)).ToLocalTime().AddHours(2) -f "MM/dd/yyyy"

03/01/2007 01:56:23

 

## to get the timezone offset programatically:
## get-date -f zz

PS > ($d.AddSeconds($id.InstallDate)).ToLocalTime().AddHours((get-date -f zz)) -f "MM/dd/yyyy"

03/01/2007 01:56:23

 

 

 

The same can be achieved with WMI :

PS > $os = get-wmiobject win32_operatingsystem
PS > $os.ConvertToDateTime($os.InstallDate) -f "MM/dd/yyyy"

03/01/2007 01:56:23

Monday, December 10, 2007

Invalid Characters

 

System.IO.Path class has two interesting (among others) static methods:

GetInvalidPathChars - Gets an (char[]) array containing the characters that are not allowed in path names.
GetInvalidFileNameChars - Gets an (char[]) array containing the characters that are not allowed in file and directory names.

 

The methods name are pretty straightforward, lets examine the results from both methods, forcing the output to a one line string:

PS > $GetInvalidPathChars = [System.IO.Path]::GetInvalidPathChars()
PS > $GetInvalidFileNameChars = [System.IO.Path]::GetInvalidFileNameChars()

Clipboard01


 

 

 

 

 

 

Although I forced the output to a string, you can see that the result shows in two lines. This is because there is a rendered non printable char (ENTER).

Now, print the characters ASCII value:

PS > "$($GetInvalidPathChars | foreach { [int]$_ } )"
34 60 62 124 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

PS > "$($GetInvalidFileNameChars | foreach { [int]$_} )"
34 60 62 124 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 58 42 63 92 47

PowerShell utilizes GetInvalidPathChars() method in the Test-Path -IsValid parameter.

Note that the above list of invalid characters can vary based on the system you're running the code on.

Sunday, December 9, 2007

Quotation Marks in Remote Commands

 

69178_scrptctrr_hero-left

This is a must read article (tipped by Jon, PowerShell NG) for PowerShell 2.0 CTP users. June Blender, Windows PowerShell Documentation Team, untangles the quotation marks spaghetti and provides very important rules of thumb for writing efficient remote commands with Invoke-Expression.

Read it on TechNet Script Center.

PowerShell scripts cooking

cookbook

I'm so excited, just got my printed copy of "Windows PowerShell Cookbook" by Lee Holmes.

Get yours here.

Wednesday, December 5, 2007

PowerShell remoting on XP and IIS

 

In order to use remoting in PowerShell CTP, all machines should have WinRM (KB936059) and PowerShell CTP installed. After the installation you should run the "Configure-Wsman.ps1" script (resides in the PowerShell home directory). The scripts configures WSMan to enable PowerShell remoting.

 

PS > & $pshome\Configure-Wsman.ps1

 

After the installation, the winrm service is not running (stopped state) so you should start it manually.

 

PS > get-service winrm

Status   Name               DisplayName
------   ----                     -----------
Stopped WinRM             Windows Remote Management (WS-Manag...

 

PS > get-service winrm | start-service

 

To make it load automatically when Windows starts:

PS > Set-Service winrm -StartupType automatic

 

Then I tried to run a command :

PS > Invoke-Expression -ComputerName  computer -Command Get-Process

 

It returned an error

Invoke-Expression : [computer] The WS-Management service does not support the
request.
At line:1 char:18
+ Invoke-Expression <<<< -ComputerName spare -command "get-process"

 

I posted a question in the PowerShell newsgroup and eventually the problem found with help from Marco Shaw.

If you have IIs installed on the machines your installed PowerShell CTP then there is a collision between WinRM port and IIs port.

To solve it temporary, stop the w3svc service and restart winrm service, or try to change the port setings for winrm.

There should be a public KB article from Microsoft on this issue somewhere soon.