PowerShell 3.0 CTP1 includes many new language enhancements. Here are four of them for advanced functions.
CmdletBinding and Parameter attributes
We are no longer required to assign a value of $true to CmdletBinding and Parameter attributes. For example, in v2 we had to write:
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[Parameter(Position=0,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true
)]
[string]$Name
)
In v3 we can omit the assignment.
[CmdletBinding(SupportsShouldProcess)]
param(
[Parameter(Position=0,
ValueFromPipeline,
ValueFromPipelineByPropertyName
)]
[string]$Name
)
The absence of an attribute is same as explicitly setting the attribute to $false, but that isn’t new to v3, is the same as v2.
Built-in support for Paging operations
[CmdletBinding(SupportsPaging)]
When the SupportsPaging attribute of CmdletBinding is specified in advanced functions we get three additional parameters IncludeTotalCount,Skip, and First. These parameters allows us to page the results. When the IncludeTotalCount is specified the function writes to the host the total amount of objects in the form of:
Total count: n
The Skip parameter, UInt64, controls how many objects the function ignores. The value cannot be greater than the total amount of objects in the result. The First parameter, UInt64, controls how many objects the function returns from the beginning of the result.
You can find a script example in the samples folder of CTP1 (Samples\WindowsPowerShell\SupportsPagingSample\SupportsPaging01.ps1).
HelpUri
Assign it a web URL and Get-Help will pick it up when the Online switch has been specified, and will
display the page in your default browser. Get-Command also shows the URI in its result.
[CmdletBinding(SupportsPaging,HelpUri='http://PowerShay.com')]
PositionalBinding
[CmdletBinding(PositionalBinding=$false)]
Setting PositionalBinding to $false allows us to disable positional parameters binding and force users to write the parameter name and its value. See this post for more information.
Windows Management Framework 3.0 Community Technology Preview (CTP1) is available for download for Windows 7 SP1 and Windows Server 2008 R2 SP1.
Read the full announcement on the PowerShell team blog. Check out this post on the PowerShell Magazine site for a quick review of new cmdlets and parameters in v3.
Windows PowerShell supports two kind of parameters: Named and Positional. In a nutshell, Named parameters must be specified on the command line while Positional parameters are inferred by the argument’s position on the command line.
The type of the parameter is controlled by the [Parameter()] attribute (see about_Parameters).
What if we wanted to disable positional parameters and force users to write the parameter name and its value?
Consider the following example, all parameters values are positional. Can you guess the parameter names?
PS> Register-ObjectEvent $timer Elapsed Timer.Random {$random = Get-Random -Min 0 -Max 100}
There is some logic in the order of values but that is a bit hard to read and involves some guess work as well as consulting the help files. It is also not recommended when writing production scripts and can cause a lot of frustration for users who are not familiar with the command.
In PowerShell v2 it was not possible to disable that behavior (see a work around at the end of this post).
By default, values on the command line where treated as positionals, but in PowerShell v3 the PowerShell team added a new
functionality to address it.
The CmdletBinding attribute is used in Advanced functions to identify them as functions that act similar to compiled cmdlets.
When we write advanced functions, we can add the CmdletBinding attribute so that Windows PowerShell will bind the parameters of the function in the same way that it binds the parameters of compiled cmdlets. Some of the known arguments of the CmdletBinding attribute are: SupportsShouldProcess, DefaultParameterSetName and ConfirmImpact.
You can read more about them in the about_Functions_CmdletBindingAttribute help topic.
In PowerShell v3 we have additional CmdletBinding attribute - PositionalBinding (there are more new attributes!).
As its name suggests, when specified it disables positional binding and force the caller to specify parameter names.
Let's test it with the following function.
function Test-PositionalBinding
{
[CmdletBinding(PositionalBinding=$false)]
param(
$param1,$param2
)
Write-Host param1 is: $param1
Write-Host param2 is: $param2
}
As you can see, the PositionalBinding attribute is set to $false. The function will not allow positional binding.
PS> Test-PositionalBinding -param1 one -param2 two
param1 is: one
param2 is: two
In the example above we specified parameter names and the result is as expected. Let's try to pass the value of param1 by its position.
PS> Test-PositionalBinding one -param2 two
Test-PositionalBinding : A positional parameter cannot be found that accepts argument 'one'.
At line:1 char:1
+ Test-PositionalBinding one -param2 two
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Test-PositionalBinding], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Test-PositionalBinding
And it fails. Check this forum thread if you need to enable similar functionality in PowerShell v2, great workaround by @mjolinor.
Want to try PowerShell v3? Download the Windows 8 Developer Preview from MSDN.
I’m excited to announce that MVP Kirk Munro (aka poshoholic) and I are going to present in the upcoming PowerShell Deep Dive track at the The Experts Conference in Frankfurt, Germany (17-19 October 2011).
In this session we will take a deep dive into proxy functions in PowerShell. We have been working together on PowerShell Proxy Extensions, a powerful module that leverages proxy functions and makes it easier than ever to create these powerful extensions to PowerShell. We will demonstrate what proxy functions are and why they are important, and then show how a little scripting savvy (and a really long script) can make your life easier by allowing you to create everything from very simple proxy functions that extend PowerShell to more complex proxy functions that override existing commands, fixing bugs and adding missing features at the same time, all while leveraging inline help as much as possible.
This session will arm you with the knowledge (and tools!) you need to be able to get the most from proxy functions today!
Looking forward to see you there!
מקווה לראותכם בכנס. מהרו להירשם (לחצו על התמונה), מספר המקומות מוגבל!

PowerShell 2.0 supports two kinds of remote configurations: fan-in and fan-out. When we execute a command against a bunch of servers we use fan-out (one to many). Fan-in is used when multiple users are connecting to a remote server (many to one). Exchange server implements a fan-in configuration via a virtual directory on the Exchange server’s IIS. We can connect to the virtual directory (http connection) and manage our Exchange server remotely, without having to install the Exchange Management Tools locally on our admin station.
We can create a remote session (using the currently logged on credentials) with the New-PSSession cmdlet. If you need to connect with alternate credentials, add the –Credential parameter:
PS > $uri = 'http://dc1.homelab.com/PowerShell'
PS > $session = New-PSSession -ConfigurationName Microsoft.Exchange `
-ConnectionUri $uri -Authentication Kerberos
The session is created and we can import the commands from the remote session into our local session and use them as if they were installed locally (aka, implicit remoting).
PS> Import-PSSession –Session $session
When the session finished importing, all commands from the remote session are available in our local session. In the background a module is created that contains all remote commands. Let’s try one command:
PS > Get-MailboxDatabase
Name Server Recovery ReplicationType
---- ------ -------- ---------------
Mailbox Database 0311695863 DC1 False None
Now let’s try to get the database size:
PS > $db = Get-MailboxDatabase -Identity 'Mailbox Database 0311695863' -Status
PS > $db.DatabaseSize
152.1 MB (159,449,088 bytes)
We get back the size of the database in MB and in bytes. Exchange supports several methods to format the size of an object (mailbox/database) through a series of methods: ToBytes(), ToKB(), ToMB() etc. Let’s try to format the size of the database and get the value in bytes:
PS > $db.DatabaseSize.ToBytes()
Method invocation failed because [System.String] doesn't contain a method named 'ToBytes'.
At line:1 char:25
+ $db.DatabaseSize.ToBytes <<<< ()
+ CategoryInfo : InvalidOperation: (ToBytes:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
We get an error that the DatabaseSize property doesn't contain the ToBytes method. We can also see that DatabaseSize is a String. This is the expected behavior in a remoting session. When a source computer sends a script to a remote computer, the code is serialized first (converted to XML), when it gets to the destination machine it's converted back (deserialized) and executed. The result is serialized again and sent back to the source computer. It is important to understand that when the source computer gets the final result, it convert it back to objects but the objects are "dehydrated", and contains a bunch of Note properties and one method - ToString (some "primitive" types, like Int, can be deserialized better than others). As a consequence, if we want to execute methods on the "real" object we need to do that on the remote end. When we want to get hold of the object itself (and it’s members) we invoke the command on the remote end with the Invoke-Command cmdlet:
PS > $identity = 'Mailbox Database 0311695863'
PS > $sb = {(Get-MailboxDatabase -Status –Identity $identity).DatabaseSize.ToBytes()}
PS > Invoke-Command -Session $session -ScriptBlock $sb
Method calls are not allowed in restricted language mode or a Data section.
+ CategoryInfo : ParserError: (ToGB:Token) [], ParseException
+ FullyQualifiedErrorId : MethodCallNotSupportedInDataSection
Another error! We cannot run methods in restricted language mode. What does this mean? The Exchange configuration is locked down (restricted session). By default, only administrators can connect to the end point, but they are restricted as well!
A few words on the LanguageMode property. There are three possible values: NoLanguage, RestrictedLanguage, and FullLanguage. In FullLanguage you can do whatever you want. In NoLanguage mode only commands that are using the Runspace APIs are allowed, and in RestrictedLanguage mode commands that contain scripts that need to be evaluated are not allowed.
This was a bit disappointing. If the server admin cannot have full access to the remote session then who can? I’m not sure why the Exchange team decided to lock the environment. The notion of connecting to any remote server and managing it without having to install local tools is not fulfilled here.
I started to look for a way to bypass that limitation and it appears that I was looking in the wrong direction! Hats off to my friend, MVP Aleksandar Nikolic, for a great tip! We can change the language mode by opening the web.config file in the PowerShell virtual directory:

I changed the value to FullLanguage, saved the file, recycled the MSExchangePowerShellAppPool application pool and re-created a remote session:
PS > $uri = 'http://dc1.homelab.com/PowerShell'
PS > $session = New-PSSession -ConfigurationName Microsoft.Exchange `
-ConnectionUri $uri -Authentication Kerberos
PS > $identity = 'Mailbox Database 0311695863'
PS > $sb = {(Get-MailboxDatabase -Status –Identity $identity).DatabaseSize.ToBytes()}
PS > Invoke-Command -Session $session -ScriptBlock $sb
159449088
And it worked, we can invoke methods in the remote session without having to parse strings. The final step was to create a separate environment, for admins only, one that doesn’t change the original configuration made by the Exchange team. I reverted back the value in the web.config file and wrote the following script to automate the process. Log on to your Exchange server, open PowerShell (not EMS) and run it (comments inline):
# load the IIS module
Import-Module WebAdministration
# get the path to the exchange server installation directory
# and create a new folder for the exadmin application
$path = ‘HKLM:\SOFTWARE\Microsoft\ExchangeServer\v14\Setup’
$exbin = Join-Path (Get-ItemProperty $path).MsiInstallPath ClientAccess
$folder = New-Item -Path $exbin\exadmin -ItemType Directory -Force
# copy the web.config file to the new directory, load it (as xml) and
# change the language mode (from RestrictedLanguage) to FullLanguage
Copy-Item $exbin\PowerShell\web.config $folder.FullName -Force
[xml]$wconfig = Get-Content $exbin\exadmin\web.config
$wconfig.configuration.appSettings.add.value = 'FullLanguage'
$wconfig.Save("$exbin\exadmin\web.config")
# Create a new IIS application pool, and start it
$pool = New-WebAppPool -Name exadmin
# Configure the exadmin app pool to run under the LocalSystem account (0)
Set-ItemProperty IIS:\AppPools\exadmin -Name ProcessModel -Value @{identityType=0}
# start app pool
Start-WebAppPool -Name exadmin
# Create a new IIS Web Application.
$application = New-WebApplication -Name exadmin -Site 'Default Web Site' `
-PhysicalPath "$exbin\exadmin" -ApplicationPool $pool.name
#Set the application SSL settings to accept client certificates (if they are provided)
Set-WebConfigurationProperty -Filter //security/access –Name SslFlags `
-Value SslNegotiateCert -PSPath IIS:\ -Location 'Default Web Site/exadmin'
# create new end point configuration and allow administrators to remotely run commands
# a dialog is shown with the local administrators group selected, and we can add
# users/groups we want to have access to the end point
#Get-PSSessionConfiguration exadmin | Unregister-PSSessionConfiguration -Force
Register-PSSessionConfiguration -Name exadmin -Force
Set-PSSessionConfiguration -Name exadmin -ShowSecurityDescriptorUI -Force
# testing the new environment, uncomment and change database identity
# create a fan-in session (notice we are connecting to exadmin) and try to
# invoke the ToBytes method – it works
#$sb = { (Get-MailboxDatabase -Status -Identity 'Mailbox Database 0311695863').DatabaseSize.ToBytes() }
#$uri = ‘http://dc1.homelab.com/exadmin’
#$session = New-PSSession -ConfigurationName Microsoft.Exchange –ConnectionUri $uri
#Invoke-Command $session –ScriptBlock $sb
Now you can connect from any computer that has PowerShell 2.0 installed to your Exchange server and gain full access. I hope this has been helpful, here’s some related resources you may find useful as well:
How objects are sent to and from remote sessions
Configuring PowerShell for Remoting – Part 1
Configuring PowerShell for Remoting – Part 2 (Fan-In)
Administrator's Guide to Windows PowerShell Remoting
Layman’s Guide to PowerShell 2.0 remoting
Deep Dive video: Constrained PowerShell Endpoints – Aleksandar Nikolic
Book: Microsoft Exchange 2010 PowerShell Cookbook - Mike Pfeiffer
If you're in a mixed-mode environment with both Exchange 2003 and Exchange 2007/2010 you may have noticed this message when using the Get-* cmdlets in the Exchange Management Shell:
WARNING: The object domin.com/Users/UserName has been corrupted, and it's in an inconsistent state. The following validation errors happened:
WARNING: Property expression "xx xxx" isn't valid. Valid values are: Strings formed with characters from A to Z (uppercase or lowercase), digits from 0 to 9, !, #, $, %, &, ', *, +, -, /, =, ?, ^, _, `, {, |, } or ~. One or more periods may be embedded in an alias, but each period should be preceded and followed by at least one of the other characters. Unicode characters from U+00A1 to U+00FF are also valid in an alias, but they will be mapped to a best-fit US-ASCII string in the e-mail address, which is generated from such an alias.
Or one of the following:
WARNING: Object <distinguished name of the recipient> has been corrupted and it is in an inconsistent state. The following validation errors have been encountered:
WARNING: <alias of the recipient> is not valid for Alias.
These messages (there are others as well) appears when you try to manage a recipient with spaces (or any other invalid character) in its alias using the Exchange management tools. For example, in Exchange Server 2003, you could create recipients with spaces in aliases. Exchange Server 2007/2010 does not allow recipients to have spaces in their aliases. The biggest problem with invalid aliases - you will not be able to move a mailbox to an Exchange 2007/2010 server. To mitigate this I've written the following function.
Note: In Exchange 2010, the mailbox's alias is generated based on the Name property. Invalid characters in the name will be replaced with a question mark (?) when the alias is generated.
function Test-ExchangeAlias
{
param(
[Parameter(
Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true
)]
[ValidateLength(1,64)]
[string]$Alias,
[switch]$RemoveIllegalCharacters
)
begin
{
$IllegalCharacters = 0..34+40..41+44,47+58..60+62+64+91..93+127..160
}
process
{
if($RemoveIllegalCharacters)
{
foreach($c in $IllegalCharacters)
{
$escaped = [regex]::Escape([char]$c)
if($Alias -match $escaped)
{
Write-Verbose "illegal character code detected: '$c'"
$Alias = $Alias -replace $escaped
}
}
$Alias
}
else
{
for($c=0; $c -lt $Alias.Length; $c++)
{
$code = [int][char]$Alias[$c]
Write-Verbose "Testing current Alias character code: $code"
if($IllegalCharacters -contains $code)
{
Write-Verbose "Character code: $code is an invalid alias character."
$false
return
}
}
$true
}
}
}
The function supports two parameters, Alias and RemoveIllegalCharacters. In the Begin block we assign a series of numbers to a variable, $IllegalCharacters, using the range operator along with the plus operator (+) to combine a range with a list of elements in an array. These numbers represents the character codes an alias cannot contain.
In the Process block we check if the RemoveIllegalCharacters parameter has been specified. If it was specified, all invalid characters are removed and a fixed alias is returned. Otherwise the function just tests if the alias is valid and returns $true/$false respectively. Invalid characters are removed using the Replace operator. Since we don't know if each invalid character is a regular expression meta character we use the Escape method to convert it so that the regular expression engine will interpret any metacharacters that it may contain as character literals.
With the following command you can fix all invalid aliases on all mailbox objects:
Get-Mailbox –ResultSize Unlimited | Where-Object {-not (Test-ExchangeAlias -Alias $_.Alias)} | Foreach-Object {
$NewAlias = Test-ExchangeAlias -Alias $_.Alias -RemoveIllegalCharacters
$_ | Set-Mailbox –Alias $NewAlias
}
When running the above you’ll get the ‘inconsistent state’ error for each invalid alias mailbox object but if you issue the command again you’ll see that the error has gone and the Aliases have been fixed.
A few days ago, Devfarm Software the makers of PowerWF, has released their commercial PowerShell editor, PowerSE v2.5, as a free community script editor.
PowerSE is an advanced script editor and an interactive console packed with multiple features to help you develop and debug your PowerShell scripts. Now you can download a fully functional FREE version HERE (requires registration).
PowerSE features:
- Complete IntelliSense coverage of PowerShell, DotNet and WMI.
- Real time Syntax Checking instantly lets you see errors in your code and quickly jump to error lines to fix the problem.
- It has an XML editor.
- The ability to do a quick command. Example. Get-process. Then using the grid, you can select columns, rearrange the rows, and sort. Then generate the PowerShell, and insert it into your script. Much faster than typing all those commands.
- Integrated Help.
- Tabbed interface to edit multiple scripts.
- Integrated Console. If you hit F11, it will zoom into full-screen mode (F11 to zoom back). F12 will zoom the highlighted window to full-screen, and vice-versa. F1 full-screen help.
- Command History (combined with the console). So, you can do an interactive console session, to figure out what you need. Then using the Command History, insert those command and create a script. Sort of record/playback.
- Call Stack history, plus complete debugger.
- Search scripts in script repositories like: PoshCode and TechNet Script Center Repository.
Check out this video for a quick overview.
So, give it a spin to see how you like it. Thumbs up for making it free but there's one drawback, the product will expire in 60 days and to continue using it you will have to re-download it!
July 1st is very special day for me. It is the day when I first got the MVP award.
Today I got it again, I'm a PowerShell MVP for the fourth year!
מה זה בכלל PowerShell? למה אני צריך את זה? בנות אוהבות את זה?
מה אם אף פעם לא כתבתי אפילו שורת פקודה אחת? אני בכלל לא מפתח – זה נוגע אלי?
המון שאלות אה?
על כל זאת ועוד נדבר במפגש הבא של קבוצת הדיון שייערך ב- 25/05/2011 בשעה 15:45 במשרדי מיקרוסופט, רעננה.
את יתר הפרטים תוכלו למצוא בהזמנה כאן: http://sbu.co.il/forum_posts.asp?TID=420&PID=1905
אין צורך בידע מוקדם, הביאו רק את עצמכם, ראש פתוח ומצב רוח טוב, השאר עלינו.
נתראה במפגש!
Learn Windows PowerShell in a Month of Lunches is a newly designed tutorial for system administrators. Just set aside one hour a day -- lunchtime would be perfect -- for a month, and you'll be automating administrative tasks in a hurry. Author Don Jones combines his in-the-trenches experience with a unique teaching style to help you master the effective parts of PowerShell quickly and painlessly.
Who Should Read It
The book is written for administrators, not developers.
What's Inside
- Learn PowerShell 2 from the beginning-no experience required!
- Written especially for administrators, not developers
- Practical examples and reusable techniques in every concise 1-hour lesson
About the Author
Don Jones has more than 15 years of IT experience, is the author of more than 35 books, and is a speaker at technology conferences such as Microsoft TechEd and Windows Connections. He's a multiple-year recipient of Microsoft's MVP award and is a technical guide for PowerShell for WindowsITPro.
Only for the next 24 hours you can use the lunchtoday promode and get a 50% discount!
The Get-Date cmdlet lets us create, convert, and format date strings to DateTime .NET objects. However, there’s one thing it cannot do, convert a date string which is not a format it expects (defines by your system locale). For example, if your current culture is en-US you can pass a date string in the format of MM/dd/yyyy to the –Date parameter and Get-date will convert it to a DateTime object:
PS > Get-Date -Date 4/13/2011
Wednesday, April 13, 2011 12:00:00 AM
On the other hand, if we pass a string in the format of dd/MM/yyyy it fails:
PS > Get-Date -Date 13/4/2011
Get-Date : Cannot bind parameter 'Date'. Cannot convert value "13/4/2011" to type "System.DateTime". Error: "String was not recognized as a valid DateTime."
As you can see from the above error, Get-Date complains that "13/4/2011" was not in the correct format. A common case to this kind of date strings is when you have a third party application that writes date strings, not in the format of your locale, to log files. The only way to convert those strings to a valid DateTime object is to use the ParseExact static method of the DateTime .NET class. The ParseExact method is an overloaded member (we can invoke it in three ways, each with its own set of arguments). Instead of using the method directly I wrapped the first overload in an Advanced Function, ConvertFrom-DateString.
function ConvertFrom-DateString
{
[OutputType('System.DateTime')]
[CmdletBinding(DefaultParameterSetName='Culture')]
param(
[Parameter(
Mandatory=$true,
Position=0,
ValueFromPipeline=$true,
HelpMessage='A string containing a date and time to convert.'
)]
[System.String]$Value,
[Parameter(
Mandatory=$true,
Position=1,
HelpMessage='The required format of the date string value'
)]
[Alias('format')]
[System.String]$FormatString,
[Parameter(ParameterSetName='Culture')]
[System.Globalization.CultureInfo]$Culture=$null,
[Parameter(Mandatory=$true,ParameterSetName='InvariantCulture')]
[switch]$InvariantCulture
)
process
{
if($PSCmdlet.ParameterSetName -eq 'InvariantCulture')
{
$Culture = [System.Globalization.CultureInfo]::InvariantCulture
}
Try
{
[System.DateTime]::ParseExact($Value,$FormatString,$Culture)
}
Catch [System.FormatException]
{
Write-Error "'$Value' is not in the correct format."
}
Catch
{
Write-Error $_
}
}
<#
.SYNOPSIS
Converts a string representation of a date.
.DESCRIPTION
Converts the specified string representation of a date and time to its
DateTime equivalent using the specified format and culture-specific format
information. The format of the string representation must match the specified
format exactly.
.PARAMETER Value
A string containing a date and time to convert.
.PARAMETER FormatString
The required format of the date string value. If FormatString defines a
date with no time element, the resulting DateTime value has a time of
midnight (00:00:00).
If FormatString defines a time with no date element, the resulting DateTime
value has a date of DateTime.Now.Date.
If FormatString is a custom format pattern that does not include date or
time separators (such as "yyyyMMdd HHmm"), use the invariant culture
(e.g [System.Globalization.CultureInfo]::InvariantCulture), for the provider
parameter and the widest form of each custom format specifier.
For example, if you want to specify hours in the format pattern, specify
the wider form, "HH", instead of the narrower form, "H".
The format parameter is a string that contains either a single standard
format specifier, or one or more custom format specifiers that define the
required format of StringFormats. For details about valid formatting codes,
see 'Standard Date and Time Format Strings' (http://msdn.microsoft.com/en-us/library/az4se3k1.aspx)
or 'Custom Date and Time Format Strings' (http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx).
.PARAMETER Culture
An object that supplies culture-specific formatting information about the
date string value. The default value is null. A value of null corresponds
to the current culture.
.PARAMETER InvariantCulture
Gets the CultureInfo that is culture-independent (invariant). The invariant
culture is culture-insensitive. It is associated with the English language
but not with any country/region.
.EXAMPLE
ConvertFrom-DateString -Value 'Sun 15 Jun 2008 8:30 AM -06:00' -FormatString 'ddd dd MMM yyyy h:mm tt zzz' -InvariantCulture
Sunday, June 15, 2008 5:30:00 PM
This example converts the date string, 'Sun 15 Jun 2008 8:30 AM -06:00',
according to the specifier that defines the required format.
The InvariantCulture switch parameter formats the date string in a
culture-independent manner.
.EXAMPLE
'jeudi 10 avril 2008 06:30' | ConvertFrom-DateString -FormatString 'dddd dd MMMM yyyy HH:mm' -Culture fr-FR
Thursday, April 10, 2008 6:30:00 AM
In this example a date string, in French format (culture). The date string
is piped to ConvertFrom-DateString. The input value is bound to the Value
parameter. The FormatString value defines the required format of the date
string value. The result is a DateTime object that is equivalent to the date
and time contained in the Value parameter, as specified by FormatString and
Culture parameters.
.EXAMPLE
ConvertFrom-DateString -Value 'Sun 15 Jun 2008 8:30 AM -06:00' -FormatString 'ddd dd MMM yyyy h:mm tt zzz'
Sunday, June 15, 2008 5:30:00 PM
Converts the date string specified in the Value parameter with the
custom specifier specified in the FormatString parameter. The result
DateTime object format corresponds to the current culture.
.INPUTS
System.String
You can pipe a string that contains a date and time to convert.
.OUTPUTS
System.DateTime
.NOTES
Author: Shay Levy
Blog : http://PowerShay.com
.LINK
http://msdn.microsoft.com/en-us/library/w2sa9yss.aspx
#>
}
ConvertFrom-DateString is decorated with Comment Based Help so you can use the Get-Help cmdlet to get help for its parameters as well as code examples. Let’s see how we can use the function to convert a date string to a DateTime object.
PS> 'Tue Mar 29 14:49:04 2011' | ConvertFrom-DateString -FormatString 'ddd MMM dd HH:mm:ss yyyy'
Tuesday, March 29, 2011 2:49:04 PM
The Value parameter accept pipeline input so we can pipe the string to the function. We also specify the format of the string, specifying each element position in the Format-String parameter. We didn’t specify the Culture parameter so the result is a DateTime object in the current culture of the local system. To get more help on .NET format specifiers, see "DateTimeFormatInfo Class" in the MSDN (Microsoft Developer Network) library at http://go.microsoft.com/fwlink/?LinkId=143638
Here’s another example with a French date string. This time we specify the string in the Value parameter and we also use the Culture parameter to tell the function that the string is in the fr-FR culture:
PS > ConvertFrom-DateString –Value 'jeudi 10 avril 2008 06:30' -FormatString 'dddd dd MMMM yyyy HH:mm' -Culture fr-FR
Thursday, April 10, 2008 6:30:00 AM
The function can also be downloaded from the TechNet Script Center Repository.
Enjoy!
When PowerShell starts it creates a bunch of Automatic Variables. One of them is $PWD. $PWD contains a path object that represents the full path of the current directory (provider sensitive). Typically, when you assign a value to a variable, the value is evaluated once and from then on it's "static", each time you call the variable the returned value is always the same. The beauty of $PWD is that its value is calculated each time you call it.
PS> $PWD
Path
----
D:\scripts
PS > Set-Location HKLM:\SOFTWARE
PS > $PWD
Path
----
HKLM:\SOFTWARE
$PWD contains a rich .NET object (System.Management.Automation.PathInfo), not just a string path, so we can also interact directly with its members:
PS > $PWD.Provider.Name
Registry
I was trying to create a variable similar to $PWD ($Now) to get the current date and time, but no matter what I tried, the value of $Now always returned the same date and time. The reason behind creating $Now was this. Let's say you want to get the DayOfWeek value of a DateTime object, what we often do is:
## two lines of code
PS > $date = Get-Date
PS > $date.DayOfWeek
Or
## using a .NET class
PS> [DateTime]::Now.DayOfWeek
Or
## enclosing in parenthesis
PS> (Get-Date).DayOfWeek
I wanted is to use the third example but avoid enclosing Get-Date it in parenthesis. One of the ways I was trying is with a function:
PS > function Now {Get-Date}
It works, I can now get a new fresh DateTime object each time I call the function, but I can't access the result object members without enclosing it in parenthesis:
PS> (Now).DayOfWeek
Ultimately, this is how I wanted it to be:
$Now.DayOfWeek
Simple to use and very short to type. Another thought was to create a new Alias but the result was the same as using a function, parenthesis were required to access object members. So I posted a question to the PowerShell MVP private list and soon enough Lee Holmes, pointed me to this blog post. Here's the code I used to create $Now:
Add-Type -TypeDefinition @"
using System;
using System.Management.Automation;
public class NowVariable : PSVariable
{
public NowVariable ()
: base("Now", 0, ScopedItemOptions.ReadOnly | ScopedItemOptions.AllScope)
{}
public override object Value
{
get
{
return DateTime.Now;
}
}
}
"@
$ExecutionContext.SessionState.PSVariable.Set((New-Object -TypeName NowVariable))
Paste this code into your console and there you have it! A variable that evaluates its value each time you call it.
PS>$Now
Tuesday, April 12, 2011 10:48:41 AM
PS>$Now
Tuesday, April 12, 2011 10:48:43 AM
PS>$Now
Tuesday, April 12, 2011 10:48:45 AM
PS> $Now.DayOfWeek
Tuesday
Now we can access any member of the result DateTime object without parenthesis. Thanks Lee! The next step is to ask the PowerShell team to include $Now in the next version of PowerShell and the way to do that is to file a suggestion on the Microsoft Windows PowerShell Customer Connection website. The PowerShell team review the items suggested by the community and if it has enough votes it will find its (hopefully) way to the next version of PowerShell.
Do you want to have $Now as a new automatic variable in PowerShell 3.0? Vote it up HERE.
UPDATE: Check out this awesome post, by Robert Robelo, where he shows a how to get the same functionality in pure script and it also works in PowerShell v1!
I’m excited to announce that the PowerShell Community Toolbar is now supported on Google Chrome browsers. The new Chrome version is still in beta but is fully available for users who access any custom install page from Chrome (e.g. http://powershell.ourtoolbar.com/). It includes shiny new menus, support for toolbar gadgets, links, apps and much more.

The new version includes enhancements for look and feel for the RSS reader, Menu Buttons and Chevron. Currently, the toolbar does not support the Radio Player (podcasts) and the Weather components.
The PowerShell Community Toolbar has a Facebook group so come join us (if you haven’t done so yet) and get notifications when new stuff is added/removed, send feedback which you may have, technical issues, features you are missing, bugs, questions and any comment at all.
To download, on Google Chrome, go to: http://powershell.ourtoolbar.com/
Enjoy!
The 2011 Scripting Games begin on April 4, 2011 and run through April 15, 2011. What is the Scripting Games, you may ask? Well simply put, the Scripting Games are the premier learning event of the year for IT Pro’s and others who wish to master Windows PowerShell. Comprising 10 events, a registered contestant has seven days to create a solution to a scenario driven problem and post their code to a MVP maintained script repository for evaluation by a panel of internationally recognized judges. Daily leaderboards and prize drawings help to maintain the suspense throughout the two-week international event.
During the 2011 Scripting Games hundreds of contestants will submit thousands of scripts that will be reviewed by dozens of judges. Hundreds of thousands of spectators from all around the world will view the games themselves. Last year, participants from more than 100 countries participated in the Scripting Games. With an emphasis on real world scripting scenarios and problems, the scripts will be of immediate value to both the participants and to the spectators.
Preparation for the 2011 Scripting Games is already underway, with a learning guide, step-by-step tutorials, videos and other resources being generated on a daily basis. The 2011 Scripting Games all in one page is the portal for the games themselves. The 2010 Scripting Games all in one page is still available, as are the events from the 2009 Scripting Games.
Grab the 2011 Scripting Games badge and display it on your blog to show your support for the games.
More Posts
« Previous page -
Next page »