All posts by brad@wernerconsulting.com

Help Distribution Example

2014w29-GP-PowerShell-Update-Help-exampleEarlier today, I opened the topic of Windows PowerShell Help update distribution. This article continues where that one left off.

Once you have saved help information to a file share, other computers can be updated from that information. Three ways to perform such updates are described herein. They are:

• Manual Update
• Semi-Automatic Updates using a PowerShell Scheduled Job
• Automatic Updates using Active Directory-based Group Policy

The Manual technique simply involves running the Update-Help cmdlet to perform a one-time upon of a machine. The “Semi-Automatic” approach merely creates a new PowerShell scheduled job to periodically run the same update. Finally, the Automatic method uses the Group Policy setting with the path:

‣ Computer Configuration >
‣ Policies >
‣ Administrative Templates >
‣ Windows Components >
‣ Windows PowerShell >
‣ Set the default source path for Update-Help

In all three cases, the source path for the updates need to come from the file share in which you had saved the help information by using Save-Help. When using the Update-Help cmdlet directly for the manual and semi-automatic styles, the -SourthPath parameter is used to provide the appropriate path. For the automatic approach, a Group Policy Object (GPO) could be created with the aforementioned setting enabled and its Default Source Path value assigned the same path. Consider the following snapshot of a script depicting these three techniques, along with the prerequisite creation of the file share and populating it Save-Help.

The comments in the script provide commentary on the different sections and their use relative to the descriptions included above. For your convenience the contents of the script has been retranscribed here with some minor edits. I hope that this helps. Please let me know of any questions or suggestions. Thank you!

# Set up the PowerShell-Help share
New-Item -Path E:PowerShell-Help -ItemType Directory
New-SmbShare -Name PowerShell-Help -Path E:PowerShell-Help

# Update the share. This should be done when additional modules are needed,
# or when new versions are available.
Save-Help -DestinationPath lon-dc1PowerShell-Help

# “MANUAL” method:
# Clients can manually pull down the updates using:
Update-Help -SourcePath lon-dc1PowerShell-Help

# “SEMI-AUTOMATIC” style:
# Clients could alternatively request regularly scheduled updates:
Register-ScheduledJob -Name UpdateHelpJob -Credential ADATUMPSHelpUpdater `
-ScriptBlock { Update-Help -SourcePath lon-dc1PowerShell-Help } `
-Trigger (New-JobTrigger -Daily -At “3 AM”)

# “AUTOMATIC” approach:
# Or, set clients up to get updates via Group Policy
$myGPO = “PowerShell Policy”
$myKey = ‘HKLM:SOFTWAREPoliciesMicrosoftWindowsPowerShellUpdatableHelp’
$myPath = ‘lon-dc1PowerShell-Help’
New-GPO -Name $myGPO
New-GPLink -Name $myGPO -Target “OU=IT,DC=ADatum,DC=com”
Set-GPRegistryValue -Name $myGPO -Key $myKey `
-ValueName ‘EnableUpdateHelpDefaultSourcePath’ -Type DWord -Value 1
Set-GPRegistryValue -Name $myGPO -Key $myKey `
-ValueName DefaultSourcePath -Type String -Value $myPath

Windows PowerShell Help Distribution

2014w29-PS-UpdateHelpScript3
Early versions of Windows PowerShell came bundled with detailed help information (i.e. 1.0 and 2.0). In recent versions—3.0 and 4.0—the help information that is initially installed with Windows PowerShell has been trimmed down to reduce the size of the installation footprint on the many servers and workstations on which much or all of the help information may be construed as unnecessary baggage. PowerShell version 3.0 introduced the Update-Help cmdlet to download the extra detailed help information, and Save-Help was included with version 4.0 to allow downloading once, then updating one or many computers offline from that saved saved repository.

Here are some links to articles from Microsoft on Update-Help and Save-Help, one from Thomas Lee on the topic, and two from Mike F. Robbins that might all be helpful.

Update-Help: <http://technet.microsoft.com/en-us/library/hh849720.aspx>
Save-Help: <http://technet.microsoft.com/en-us/library/hh849724.aspx>
Thomas Lee: <http://tfl09.blogspot.com/2012/03/powershell-version-3updatable-help.html>
Mike F. Robbins: <http://mikefrobbins.com/2012/11/06/powershell-save-help-for-modules-that-arent-installed-on-the-local-computer/> and part 2: <http://mikefrobbins.com/2012/11/08/powershell-save-help-for-modules-that-arent-installed-on-the-local-computer-without-copying-files/>

In particular, I would recommend reading examples four and five from the Update-Help article. These topics relate to scenarios that people often ask about. I suggest deriving your own update scripts and techniques for how you want to run the updates, however the fundamentals are included in those two parts of Microsoft’s documentation (Update-Help link above). I have taken the liberty of quoting those two examples below. Everything below this paragraph is quoted directly from Microsoft’s Update-Help help topic. I hope this helps. Please let me know of any questions. Good luck!

——————————————————————————————-
From: Microsoft’s Update-Help PowerShell help topic.

Example 4: Update help automatically
This command creates a scheduled job that updates help for all modules on the computer every day at 3:00 in the morning.
The command uses the Register-ScheduledJob cmdlet to create a scheduled job that runs an Update-Help command. The command uses the Credential parameter to run the Update-Help cmdlet with the credentials of a member of the Administrators group on the computer. The value of the Trigger parameter is a New-JobTrigger command that creates a job trigger that starts the job every day at 3:00 AM.
To run the Register-ScheduledJob command, start Windows PowerShell with the “Run as administrator” option. When you run the command, Windows PowerShell prompts you for the password of the user specified in the value of the Credential parameter. The credentials are stored with the scheduled job; you are not prompted when the job runs.
You can use the Get-ScheduledJob cmdlet to view the scheduled job, use the Set-ScheduledJob cmdlet to change it, and use the Unregister-ScheduledJob cmdlet to delete it. You can also view and manage the scheduled job in Task Scheduler in the following path: Task Scheduler LibraryMicrosoftWindowsPowerShellScheduledJobs.

Windows PowerShell

PS C:> Register-ScheduledJob -Name UpdateHelpJob -Credential Domain01User01 -ScriptBlock {Update-Help} -Trigger (New-JobTrigger -Daily -At “3 AM”)
Id         Name            JobTriggers     Command                                  Enabled
—         —-            ———–     ——-                                  ——-
1          UpdateHelpJob   1               Update-Help                              True

Example 5: Update help on multiple computers from a file share
These commands download updated help files for system modules from the Internet and save them in file share. Then the commands install the updated help files from the file share on multiple computers. You can use a strategy like the one shown here to update the help files on numerous computers, even those that are behind firewalls or are not connected to the Internet.
All of the commands in this example were run in a Windows PowerShell session that was started with the “Run as administrator” option.

The first command uses the Save-Help cmdlet to download the newest help files for all modules that support Updatable Help. The command saves the downloaded help files in the Server01SharePSHelp file share.
The command uses the Credential parameter of the Save-Help cmdlet to specify the credentials of a user who has permission to access the remote file share. By default, the command does not run with explicit credentials and attempts to access the file share might fail.

Windows PowerShell

PS C:> Save-Help –DestinationPath Server01SharePSHelp -Credential Domain01Admin01

The second command uses the Invoke-Command cmdlet to run Update-Help commands on many computers remotely.
The Invoke-Command command gets the list of computers from the Servers.txt file.
The Update-Help command installs the help files from the file share on all of the remote computers. The remote computer must be able to access the file share at the specified path.
The Update-Help command uses the SourcePath parameter to get the updated help files from the file share, instead of the Internet, and the Credential parameter to run the command with explicit credentials. By default, the command runs with network token privileges and attempts to access the file share from each remote computer (a “second hop”) might fail.

Windows PowerShell

PS C:> Invoke-Command –ComputerName (Get-Content Servers.txt) –ScriptBlock {Update-Help –SourcePath Server01ShareHelp -Credential Domain01Admin01}

PowerShell Job Controller

2013w42-6457V-jobcontroller

Do you juggle? I shall always remember a wedding reception at which some of my friends broke out their clubs and balls and began team juggling in the banquet hall. Luckily, they were amazingly good jugglers and not too many in attendance were injured. Now about that lump on the back of my head…

Where was I?

Ah yes, juggling.

Does your shell juggle? Computing environments in the 1960s and 1970s included some beautiful job control languages for juggling computing workloads in timesharing and multiprocessing environments on mainframes and minicomputers. Circa 1978, Bill Joy developed the C shell as a part of the Berkeley UNIX distributions. It is worth noting that /bin/csh and its derivative /bin/tcsh have some fundamental job control features for running some work in the foreground, other work in the background, and switching between jobs. Also intrinsic in nearly any UNIX shell, even shells older than csh, was the ability to easily launch tasks into the background and pick up their output later.

Fast forward to the late 1990s. In PowerShell version 2.0, Microsoft introduced the ability to launch (background) jobs in PowerShell. With PowerShell version 3.0, the need arose to clarify the distinction between these Background Jobs and another new feature called Scheduled Jobs (different than scheduled tasks). PowerShell version 4.0 still supports both types of jobs, background and scheduled.

Although the ability to spawn one pipeline as a background job interactively in PowerShell, and then either launch some more background jobs or do some foreground work may seem natural with some practice, using background jobs inside a script can seem a bit more baroque.

Students in the “Automating Administration with Windows PowerShell” course (GK6457 / M10961A) which includes topics on both kinds of PowerShell jobs often have a question about how useful these features are. In addition, students in dozens of other courses which touch on use of PowerShell, as well as people looking for advice on Windows, System Center, SharePoint, Exchange, SQL, Lync, and other technologies often have a case of perplexion, scratching their heads wondering how jobs really fit into scripting and automation.

Consider the following script, which is one of at least thirty-one flavors of the type of examples I like to present to make the baroque seem more palatable. The goal is to be able to juggle several tasks at once. Juggling pins and balls are optional.

$dirJob = start-job { get-childitem c:,d:,e: }
while( $dirJob.State -eq “Running” ){
Start-Sleep -Milliseconds 500
Write-Warning “Waiting… $(get-date)”
# perhaps start another job, or check another job’s status
}
if( $dirJob.State -eq “Completed” ){
Write-Warning “Directory Listing job completed”
$dirJob | Receive-Job | ConverTo-Html |
out-file C:dirjob-$(get-random).htm
$dirJob | Remove-Job
}

Although this rudimentary example only launches one job, the while loop illustrates that something else can be done while this job is running, even if it is to do something as trivial as waiting, and noting that we are waiting; the comment is the key: “perhaps start another job, or check another job’s status.” The subsequent if statement receives the job output, converts it into HTML format and saves it to a file. Finally, the script removes the record within this shell instance that the job had been running, although the side-effects such as the resultant HTML file are still certainly in force. In reality, this sort of “job controller” script could evolve into something much more elaborate, juggling several balls and clubs at one time, catching each when the time is right. I find it best to introduce the job controller script concept with a simple example.

I will leave you with a slight variation on this theme which is not inordinately more complicated. This script takes a list of paths and searches all subfolders beneath those folders or file systems (drives) for PowerShell scripts. In the end, the output is shown in a PowerShell GridView window rather than sent to an HTML file. Neither of these are production scripts, just educational examples. For instance, in this second one there are several assumptions which are made, such as if the job is not running that it has completed and not failed, and furthermore not actually looking at how the user has answered the “Want output?” question but blindly unconditionally receiving the directory listing of the PowerShell scripts regardless of the answer (although typing Control-C to cancel further execution is an option).

param( $paths )
$j = start-job -ArgumentList $paths {
param( $pathsInside )
get-childitem -Recurse -Path $pathsInside -Filter *.ps1
}
while( $j.State -eq “Running” ){
write-output “Running…”
# launch other jobs, check other job status
start-sleep 5
}
Write-output “Job done”
$answer = read-host “Want output?”
Receive-Job -Job $j | Out-GridView

Windows PowerShell provides a rich set of capabilities for working with background jobs, which are certainly not limited to applicability to interactive shell use, but can be utilized quite powerfully to juggle simultaneous multiprocessing work loads with ease.

Putting SPMS on ISE

2013w39-spms-20331-lab9-ex2

It’s a good thing that there is no stray “A” in the name SharePoint 2013 Management Shell, otherwise I would have to call it “SPAMS”, which would remind me of the old Monty Python sketch with the song refrain “lovely spam, wonderful spam”. For those of you who have a habit of pronouncing your four letter acronyms, I suppose you read the title of this as “putting spams on ice”? But I digress.

However “Putting the SharePoint Management Shell, which runs on the classic PowerShell.exe, onto the Windows PowerShell Integrated Scripting Environment (PowerShell_ISE.exe), so that we can use it more effectively” is a bit long and unwieldy for a title. Have you ever wondered how to put SPMS on ISE? Wonder no more; read on.

The default shortcut for the SharePoint 2013 Management Shell uses PowerShell.exe, however a few small changes can easily yield a SharePoint Management Shell based on the more awesomely powerful PowerShell ISE.

Step 1. Obtain the properties of the existing SharePoint 2013 Management Shell shortcut.

1.a) If you already have the SharePoint 2013 Management Shell shortcut on your Desktop, simply right-click on the shortcut and choose Properties, then move on to step 2. Otherwise, from the Start screen, use steps 1.b through 1.d.

1.b) Assuming that you are staring at the lovely SharePoint 2013 Management Shell tile on your Start screen, there are a few steps to obtain its properties. Start by right-clicking on the SharePoint 2013 Management Shell tile, and continue with steps 1.c through 1.d.

1.c) Note that the SharePoint 2013 Management Shell tile should now have a checkmark overlaid in the corner of the tile. In the Actions tool panel at the bottom of the Start screen, choose “Open file location”. This should show a Windows Explorer window in Desktop mode focused on the SharePoint 2013 Management Shell shortcut in the folder C:ProgramDataMicrosoftWindowsStart MenuProgramsMicrosoft SharePoint 2013 Products.

1.d) Right-click the SharePoint 2013 Management Shell shortcut in this folder and choose Properties.

Step 2. Select all the text in the Target field of the shortcut and Copy it (e.g. Ctrl+C), then Cancel the properties dialog. The text you copied should look like this:

C:WindowsSystem32WindowsPowerShellv1.0PowerShell.exe -NoExit ” & ‘ C:Program FilesCommon FilesMicrosoft SharedWeb Server Extensions15CONFIGPOWERSHELLRegistrationsharepoint.ps1 ‘ ”

(Note: Don’t worry about the “v1.0” in the middle of the path to PowerShell.exe; that is normal for PowerShell versions 1.0, 2.0, 3.0, and 4.0.)

Step 3. Right-click on the Desktop (or other folder of your choice, such as the ProgramData…Start Menu folder) and choose New > Shortcut.

Step 4. In the Create Shortcut dialog’s “Type the location of the item” text box, Paste the text from the old shortcut into the new one, and before hitting the Next button, Edit the new shortcut’s path as follows.

To change this to use the PowerShell_ISE.exe, we can perform the following edits:
Change the command name to PowerShell_ISE.exe
Remove the -NoExit option, as this is not relevant to the ISE.
Remove the ampersand (&).
Remove both of the apostrophes (‘), but keep the quotation marks (“). Note, it is also advisable to eradicate some of the extra spaces around those apostrophes, yet be careful to retain at least one space before the opening quotation mark (after the PowerShell_ISE.exe part).

The result should look like this:
C:WindowsSystem32WindowsPowerShellv1.0PowerShell_ISE.exe “C:Program FilesCommon FilesMicrosoft SharedWeb Server Extensions15CONFIGPOWERSHELLRegistrationsharepoint.ps1”

Step 5. Now hit the Next button in the Create Shortcut wizard. On the “What would you like to name the shortcut?” / “Type a name for this shortcut” step, change the name “powershell_ise.exe” to something more administrator-friendly and functionally descriptive, such as “SharePoint 2013 on ISE” or “SharePoint 2013 Management ISE”. Then, hit the Finish button to finish creating the new shortcut.

That’s it. Note that when you open this shortcut, it shows the “sharepoint.ps1” script in the script editor pane of the PowerShell ISE, but does not actually run it. You can run it by typing <F5> on the keyboard, pressing the “play” (green triangle) icon titled “Run Script (F5)” in the ISE toolbar, or choosing either File > Run or Debug > Run/Continue from the menus.

Here is the contents of that script (sans signature block):
$ver = $host | select version
if ($ver.Version.Major -gt 1) {$Host.Runspace.ThreadOptions = “ReuseThread” }
Add-PSSnapin Microsoft.SharePoint.PowerShell
Set-location $home

Two side notes:
You could easily include this script in a PowerShell profile script (e.g. profile.ps1, Microsoft.PowerShellISE_profile.ps1, etc.) so that you don’t need to explicitly run it every time you launch a new SharePoint 2013 on ISE session.
From the Start screen, right-clicking on either the original “SharePoint 2013 Management Shell” tile or the new “SharePoint 2013 Management ISE” tile and choosing “Pin to taskbar” from the Start screen Actions tool panel is a great way to make these shortcuts available in Desktop mode.

Now, back to our story about the SharePoint 2013 Management ISE. The critical line of that script, namely: Add-PSSnapin Microsoft.SharePoint.PowerShell simply imports many cmdlets for management SharePoint Server 2013 farms. Once those cmdlets have been imported, try each of the following.

(a) At the shell prompt, type:
Get-Command -Module Microsoft.SharePoint.PowerShell

(b) Hit the Refresh button in the ISE Commands panel, then in the Modules menu choose “Microsoft.SharePoint.PowerShell”. Note, both the Modules menu and Refresh button are at the top of the Commands panel (use View > Show Command Add-on if that panel is not visible).

These cmdlets for managing SharePoint 2013 environments are immensely powerful, yet hopefully the ability to use them within the Integrated Scripting Environment instead of just that classic PowerShell interface is helpful for both interactive management and composing SharePoint management scripts.

NOTE: An edited version of this article was posted on January 7, 2014 to the Global Knowledge Training Blog at <http://blog.globalknowledge.com/technology/microsoft/putting-the-sharepoint-management-shell-on-ise/>

Late Night with System Center Management

It’s 3:30 a.m. and your trusty mobile phone on your nightstand buzzes a hideous, nasty, telltale racket. You pick up the smartphone and squint in the darkness at the glowing message that informs you that one of the e-mail servers at work is down. As you’re about to dismiss the nasty-gram in your still-half-asleep daze (who would need e-mail at 3:30 in the morning?), you bolt up wide-eyed! You suddenly realize the server that’s down serves critical e-mail services for a team three time zones east of you. And, at 6:30 a.m. their time, a downed server spells near-immediate and definitely impending doom as the workforce at that facility is about to start their shift.

A few years ago, with car keys in hand, you would have been racing for the door to get to work. Last year, you might have fired up the laptop or tablet, gotten on the VPN, and performed a bit of remote management magic to try to remedy the situation. But now, you read the choices presented on your phone: Restore Server, Switch to DR Site, Restart Server. You make your selection, receive near-instant confirmation and a new health update, and begin fantasizing about starring in yet another Walter Mitty-esque “Masters of System Center 2012″ episode as you drift back into dreamland.
A student in one of my Microsoft System Center 2012 Private Cloud courses recently asked about the ability to receive notifications regarding system health on his smartphone. It started off as a question that dozens of others have asked. One easily answered and easily handled by System Center 2012’s Operations Manager. However, this person pointed out that he also wanted to go beyond merely receiving a notification of the alert. He wanted to initiate a change from his phone that would either simply acknowledge the alert or initiate corrective actions. One of the goals was to be able to clear an alert on his phone and have both System Center Operations Manager (SCOM) close the alert and System Center Service Manager (SCSM) resolve the related incident. Having SCOM and SCSM work together to couple actions on alerts and incidents is a feature supported on the connectors in System Center 2012. The system management magic is getting the mobile phone involved as desired.

Of course, I mentioned that Windows PowerShell or System Center Orchestrator could be used to help accomplish this, but then a discussion started around using third-party tools to provide this sort of automation as another approach. After a bit of research, I provided them with the link to an April 2012 article by Peter Stevens, “Enterprise Alert and System Center 2012,” that describes such a product called Enterprise Alert 2012 from Derdack of Berlin, Germany.

In the article, Stevens includes a description of the add-on product to System Center. While you could write your own System Center 2012 Orchestrator runbooks and PowerShell scripts and configure the appropriate notification channels in SCOM and SCSM to accomplish much of what this product does, this product delivers an off-the-shelf foundation enabling you to focus on how you want to manage your systems rather than having to create the magic glue and integration between Orchestrator and other key System Center components.

But as pointed out in the YouTube video that Stevens included in his article, one of the best features of this product is its Enterprise Alert Integration Pack for System Center 2012 Orchestrator. Some of the activities included in the integration pack are:
• E-Mail Notification
• Flag for Mobile Execution
• Instant Message Notification (Lync)
• Multi-Channel Notification
• Smartphone Push Notification
• SMS Text Notification
• Voice Call Notification

Of these different Orchestrator activities, the most exciting is Flag for Mobile Execution. When you add that activity into a runbook, without even connecting it with links to other activities (it can just sit next to the Initialize Data activity if you want), the runbook becomes registered as available to mobile devices in response to a notification! I suggest watching the demonstration video to see how easy avoiding a late-night drive to work could be. Of course, Orchestrator can accomplish other magic on its own, but for remote smartphone management, this is an immensely powerful toolkit.

How much would your organization be willing to spend for this sort of functionality? According to the Derdack site, a license to their Enterprise Alert® System Center Edition retails for US $7,995. Each Alert User Client Access License runs US $399 at the time of this writing. Note also that they offer an Open API Edition, also for $7,995, that allows systems, including but not limited to Nagios, Solarwinds, CA, and BMC, to leverage off their notification and action infrastructure. Enterprise Alert makes this kind of notify-and-respond functionality available on smartphones such as iPhone, Windows Phone, Blackberry, and Android. The integration with System Center 2012 Orchestrator, Operations Manager, and Service Manager affords auditing, integration with other processes, and extensibility. This technology can be utilized in private cloud deployments and any other environments that use System Center 2012.

They say that a good night’s sleep is priceless, but with Enterprise Alert there may be a nominal price! What other suggestions do you have for providing such System Center 2012 remote management functionality? I’m sure there are other solutions out there, and I’d love to hear from you.

NOTE: This article was posted on September 20, 2013 to the Global Knowledge Training Blog at <http://blog.globalknowledge.com/technology/microsoft/late-night-with-system-center-management/>

PowerShell Data Type Basics

Yellow Binary Byte 42

A year ago? A year and a half ago? Yes, that is how old some of the notes are that I left myself, after students asked for a list of the basic data types available in Windows PowerShell. I honestly thought I had blogged about this long ago. This article provides a foundation for several others. The question which has prompted this is one of several which people tend to ask during PowerShell courses.

What data types are available in Windows PowerShell?

Is there a list of these?

The quick answers to these are yes there is a list, and then I typically direct students to the Microsoft Developer Network (MSDN) .NET type reference pages. Here, we shall look at more specific answer which hopefully ties together several aspects of PowerShell and .NET data types that might not be clear from reading any one particular page on MSDN, TechNet, or various other PowerShell blogs or references. I hope that this helps. Please let me know if you would like any additional information.

If you are interested in PowerShell but either have no background or no interest in programming in C#, F#, J#, Visual Basic (VB), or any other the other lovely .NET programming languages, you may find that much of the .NET type information is not exactly Greek, but tends to be C# oriented, which many people have told me is disconcerting when they really just want to focus on Windows PowerShell.

First, it is good to note, before we get mired in details, that PowerShell typically does not require you to specify data types, but will automagically coerce values into the necessary underlying data types. Later, we’ll look at PowerShell as a Calculator, which strives to drive home this point. In summary, you usually don’t need to worry about data types in PowerShell, as they are handled transparently so that us humans do not have to be concerned with those gory details.

If you are concerned with the gory details for whatever reason, read on!

In Windows PowerShell, data types can be explicitly specified in several scenarios:

  • After the New-Object cmdlet name, a data type name can be given to create an instance (object) of that type.
  • Inside square brackets, a type name could be used to access a static (class) method or property.
  • Inside square brackets, a type name could be used to cast (convert) a value into that data type.

One of the first data types that people like to introduce is the integer data type, which in .NET is called Int32 starting with a capital I, in C# this is simply int with a lowercase i, and in the class method and casting uses in PowerShell is most often written in square brackets as lowercase int similar to C#, as follows: [int].

Note that PowerShell is flexible, and instead of using the C# notation int in square brackets, [int], you could refer to the .NET name within the System namespace by using the notation: [System.Int32], or even without the System namespace explicitly identified, as just [Int32]. Notice the capital I again in Int32. Also, because PowerShell is particularly forgiving with respect to case sensitivity, being largely case insensitive, unlike C#, we would also use [int32] or [system.int32] as well, or even [INT], [INT32], or [SYSTEM.INT32].

Real numbers which have a fractional part after the decimal point are a different data type, as shown by the result of the following logical expression:

PS C:> 42 -eq 42.1234
False

The -eq operator checks for equality of the operands, 42 on the left, and 42.1234 on the right. They are not equal, thus the result of the -eq operator is the boolean value False.

If we include a cast of the right-hand side to an integer value prior to the comparison, we have equality. Let’s look at this using two similar ways of specifying an integer cast in PowerShell:

PS C:> 42 -eq [int]42.1234
True
PS C:> 42 -eq [System.Int32]42.1234
True

Rather than dive deeper into casting, operators, expressions, and scenarios of when and how we could use explicit data types in Windows PowerShell, let’s get back to the original questions.

What are the data types available in Windows PowerShell? There are thousands by default, and you can easily add dozens, hundreds, or thousands more by bringing in additional software to be accessed and/or managed via PowerShell. Here is a brief and by no means exhaustive list of a small very few of the primitive types in PowerShell with a few commonly used non-primitive ones thrown in at the end of the list. Note that the use of the System namespace and the dot which separates that from the class/type name for the first two was used intentionally.

[System.Object]
[System.ValueType]
[void]
[bool]
[enum]
[byte]
[sbyte]
[int16]
[uint16]
[char]
[int]
[int32]
[uint32]
[float]
[single]
[long]
[int64]
[uint64]
[double]
[DateTime]
[decimal]
[guid]
[array]
[string]
[hashtable]
[random]
[regex]
[XML]
[WMI]
[WMICLASS]
[ADSI]

Consider the following PowerShell command snapshot, which is transcribed beneath the graphic and rendered as text for clarity.

2013w10-PowerShell-Types

Here is the same thing in a larger typeface (font) as text, just the one-line command first.

PS C:> [object],[valuetype],[void],[bool],[byte],[int],[long],[single],[double],[datetime],[decimal],[guid],[array],[string],[hashtable],[random],[regex],[PSObject],[XML],[WMI],[WMICLASS],[ADSI],[Diagnostics.Process],[ServiceProcess.ServiceController],[IO.FileInfo],[IO.DirectoryInfo] | FT Name,IsClass,IsValueType,UnderlyingSystemType,BaseType -auto

Note that in this example, we did not include the System namespace before each of the data types. Now, let’s look at the results.

Name IsClass IsValueType UnderlyingSystemType BaseType
Object True False System.Object 
ValueType True False System.ValueType System.Object 
Void False True System.Void System.ValueType
Boolean False True System.Boolean System.ValueType
Byte False True System.Byte System.ValueType
Int32 False True System.Int32 System.ValueType
Int64 False True System.Int64 System.ValueType
Single False True System.Single System.ValueType
Double False True System.Double System.ValueType
Decimal False True System.Decimal System.ValueType
Guid False True System.Guid System.ValueType
Array True False System.Array System.Object 
String True False System.String System.Object 
Hashtable True False System.Collections.Hashtable System.Object 
Random True False System.Random System.Object 
Regex True False System.Text.RegularExpressions.Regex System.Object 
PSObject True False System.Management.Automation.PSObject System.Object 
XmlDocument True False System.Xml.XmlDocument System.Xml.XmlNode 
ManagementObject True False System.Management.ManagementObject System.Management.ManagementBaseObject 
ManagementClass True False System.Management.ManagementClass System.Management.ManagementBaseObject 
DirectoryEntry True False System.PSObject System.Object 
Process True False System.PSObject System.Object 
ServiceController True False System.PSObject System.Object 
FileInfo True False System.PSObject System.Object 
DirectoryInfo True False System.PSObject System.Object

PowerShell and GUIDs

Interdum at. Eget habitasse elementum est, ipsum purus pede porttitor class, ut adipiscing, aliquet sed auctor, imperdiet arcu aliquam maecenas ligula nostra tempor fermentum. Ligula suspendisse nulla pretium, rhoncus tempor placerat. Lorem ipsum dolor sit amet, ligula suspendisse nulla pretium, rhoncus tempor placerat fermentum, enim integer ad vestibulum volutpat. Nisl rhoncus turpis est, vel elit, congue wisi enim nunc ultricies sit, magna tincidunt. Maecenas aliquam maecenas ligula nostra, accumsan taciti.

Sociis mauris in integer, a dolor netus non dui aliquet, sagittis felis sodales, dolor sociis mauris, vel eu libero cras. Interdum at. Eget habitasse elementum est, ipsum purus pede porttitor. Interdum at. Eget habitasse elementum est, ipsum purus pede porttitor class, ut adipiscing, aliquet sed auctor, imperdiet arcu aliquam maecenas ligula nostra tempor fermentum. Ligula suspendisse nulla pretium, rhoncus tempor placerat.

Lorem ipsum dolor sit amet, ligula suspendisse nulla pretium, rhoncus tempor placerat fermentum, enim integer ad vestibulum volutpat. Nisl rhoncus turpis est, vel elit, congue wisi enim nunc ultricies sit, magna tincidunt. Maecenas aliquam maecenas ligula nostra, accumsan taciti. Sociis mauris in integer, a dolor netus non dui aliquet, sagittis felis sodales, dolor sociis mauris, vel eu libero cras. Interdum at. Eget habitasse elementum est, ipsum purus pede porttitor. Interdum at. Eget habitasse elementum est, ipsum purus pede porttitor class, ut adipiscing, aliquet sed auctor, imperdiet arcu aliquam maecenas ligula nostra tempor fermentum. Ligula suspendisse nulla pretium, rhoncus tempor placerat. Lorem ipsum dolor sit amet, ligula suspendisse nulla pretium, rhoncus tempor placerat fermentum, enim integer ad vestibulum volutpat. Nisl rhoncus turpis est, vel elit, congue wisi enim nunc ultricies sit, magna tincidunt. Maecenas aliquam maecenas ligula nostra, accumsan taciti. Sociis mauris in integer, a dolor netus non dui aliquet, sagittis felis sodales, dolor sociis mauris, vel eu libero cras. Interdum at. Eget habitasse elementum est, ipsum purus pede porttitor.

More on multiple elements per ASP.NET Web Form

2013w06-WebFormPlurality-bothServerCode

I recently wrote a note about several possible solutions to simulating multiple web forms on the same page when using ASP.NET Web Forms, to work around the restriction of one active (visible) ASP.NET <form> per .aspx page. Although a good article by Kirk Evans titled “Neat ASP.NET Trick: Multiple Forms on a Page” shows the technique, I wanted to elaborate with some more step-wise details.

First, what I had described earlier as option #2, is shown in the listing at the top of this page. Note that the <form id=”form2”> has only classic HTML <input> items used literally. Although these are the exact kinds of elements that ASP.NET will generate in the rendering phase for “form1” in that example, ASP.NET does not allow multiple server-side forms on the same Web Form (i.e. .aspx file). This yields the following visual result, which unfortunately does not functionally do what the button text implies.

2013w06-WebFormPlurality-shot2

Rather than focusing on making that functional via JavaScript or other techniques, let us focus on what I had described as option #1 in the earlier blog post, with a step-wise approach.

Although having two or more <form> elements on the same ASP.NET Web Form throws an exception if two or more server-side <form> elements are visible, as Evans had pointed out, we can make all but one of those forms invisible as follows:

2013w06-WebFormPlurality-bothServerOneVisibleCode

This results in only the first form being visible, but it loads without the exception.

2013w06-WebFormPlurality-bothServerOneVisibleFirst

If you add behavior to the button to switch the visibility of both forms, then you can switch from form1 to form2 at the press of a button.

2013w06-WebFormPlurality-bothServerOneVisibleCode1

Of course, in a real form, you would likely have logic to process the information from the form, however only the visibility switching code is shown here for clarity. Pressing the button makes form1 disappear and form2 magically appears (it isn’t really magic, it’s just the changing in the rendering based on those two form1.Visible and form2.Visible properties above).

2013w06-WebFormPlurality-bothServerOneVisibleSecond

You could add exactly the reverse action into the Button2_Click event handler wired up to this button as follows:

2013w06-WebFormPlurality-bothServerOneVisibleCode2

The WebPlurality.aspx markup shows the onclick wiring of the event handlers to these events for the appropriate buttons.

2013w06-WebFormPlurality-bothServerOneVisibleCode3

Now, the user of the web form can switch from form1 to form2 and back as many times as are necessary to the same URL for the WebFormPlurality.aspx and they alternate between the two ASP.NET server-side forms. Certainly, other events besides buttons firing could be used to trigger the alternation between the forms.

Perhaps you are wondering what benefits are afforded by sharing the same .aspx file (ASP.NET Web Form) for two forms. Consider that the view state and use of one Page class is used. Although different instances of that class may be used for each postback, however having the same class code loaded into the web host has its benefits. But the benefits of sharing the same view state for two or more forms within the same ASP.NET Web Form has many implications for JavaScript scripting and AJAX interactions as well, not just better continuity for processing postbacks. The topic of benefits of doing this deserves its own topic. Let me know if you’re interested in more details. For now, let’s get back to the mechanics of switching between web forms sharing the same .aspx file.

Again, there are many ways in which the switching between the forms could be accomplished. One technique shown thus far is to have the onclick event handlers for the buttons do the visibility switcheroo of the forms. One of the possible alternatives is to have the Page_Load method switch them, as Mr. Evans’ article had suggested. The result would resemble the listing below.

2013w06-WebFormPlurality-bothServerOneVisibleCode4

As written, this code will switch between two forms, where one had been visible previous and the other not visible, it simply inverts the visible of each. For three or more forms this would need to be modified with some sort of signal, request or pecking order, thus the button-driven approach can have its advantages for three or more forms. One problem with this Page_Load visibility swap technique even for two forms. Because form1 was initially visible and form2 was not, this Page_Load method implementation depicted above actually shows form2 first, then allows switching to form1, which might not be what had been intended by the designer who had set up form1 to be visible in the .aspx markup. Luckily, there is a simple fix for that feature.

2013w06-WebFormPlurality-bothServerOneVisibleCode5

Before discussing that fix, let’s clean up the code by removing the Button1_Click and Button2_Click methods, and then scrubbing the wiring of the onclick= attribute to those from each of the buttons in the markup. The above version of the WebFormPlurality.aspx shows this. Now, on to that other fix with the Page_Load method.

2013w06-WebFormPlurality-bothServerOneVisibleCode6

Note that the above version of WebFormPlurality.aspx.cs has an if( IsPostBack ) clause with the body being the swapping of the visibility. This accomplishes the goal of retaining the states of the visibility set in the .aspx markup file upon initial load, and inverts only on postbacks, whether they are caused by button actions or other events which trigger postbacks to the page.

As in Mr. Evans’ example, the last two listings would be sufficient to illustrate that the visibility can be swapped between two <form runat=”server”> elements on the same .aspx Web Form. However, the sequence shown in this article has given us the opportunity to mention some of the other possible ways of implementing something similar as well as hint at some of the ramifications and related tangential possibilities. What might you use such a technique for? Or what have you used such a technique to accomplish already?

ASP.NET: A page can have only one server-side Form tag

2013w06-WebFormPlurality-bothServerErrorSmall

A student in a Microsoft ASP.NET web development class recently asked the following question:

 I have a Perl webpage that has multiple forms on it, like this:

<body>
    <form id=forma1></form>
    <form id=form2></form>
</body>

I have tried to do the same thing in ASP.NET and C# with the runat=”server” attribute in the forms, and cannot get it to run.

That’s an excellent question. There is bad news and good news; first, the bad. Unfortunately, ASP.NET “owns” the form so that only one *VISIBLE* server-side form can be on any one .aspx file’s Web Form at a time.

Luckily, there are several workarounds or solutions which might give you what you want.

(1) Here is an article <http://blogs.msdn.com/b/kaevans/archive/2005/10/19/482778.aspx> by Kirk Evans titled “Neat ASP.NET Trick: Multiple Forms on a Page”. There are many references at other web sites as well which convey the fact that you can’t have more than one HTML <form> with the runat=”server” on the same page, however Kirk Evans presents an example where you could Switch Between Two Forms, as opposed to some other authors who simply say it is impossible.

(2) You could have one ASP.NET <form id=”form1″ runat=”server”></form> and another one or more without the runat=”server” such as <form id=”form2″></form>, however you can’t effectively have ASP.NET elements which are processed on the server-side in the second or subsequent forms. It depends on your needs and what you wanted to do with those forms with respect to client-side and server-side processing as to whether that solution is viable.

(3) You could use User Controls with .ascx files and have more than one of them composed on the same ASP.NET Web Form (.aspx file). This technique is pretty straight forward, and is one of my preferred methods for solving this sort of problem.

(4) You could use multiple buttons which act as submit buttons for different sets of controls/fields on the same form, but the C# (or other) code behind the markup treats the fields in distinct sets so that it is almost like having two forms.

(5) You could use update panels with ASP.NET AJAX.

I hope that helps. To all you in the blogosphere, do these options make sense?

Thanks,
++brad;