PowerShell: Message of the Day


In an effort to be more communicative with our users on changes made to our XenApp servers we decided to create a message of the day.  Here are the criteria we decided on:

  1. The message would show as part of the user’s startup script when logging into XenApp/XenDesktop
  2. The user would have to click a button to remove the message box and the result could be acted on by the script. In one example, if the user pressed the Yes button, then we could open a page to our intranet.
  3. A hidden flag file would be written to a user’s home directory to note that the user had already seen the message.
  4. The Message file itself should be easily edited by any member of the team and not require any scripting knowledge.

I wore Google out looking for various solutions and examples to get the script working the way I wanted. I do not consider myself an expert in PowerShell by any means, but hopefully this post will give you some ideas to try in your environment.


Our environment supports development, staging and production environments along with different XenApp images depending on software being delivered. As a result, the scripts and the text file that is the message of the day are sync’d to the C: drive of the provisioned image. This allows us to tailor messages to different user populations.

While running, the script will archive the existing message, and since the user does not have permission to write to the C: drive (this script runs during a user’s login as the user) I’m using an admin account to write the archive file to the C: drive.

The Script

I’m using Show-Messagebox.ps1 to create the message box provided by Daniel Sörlöv (original link, his new site):

This script is located in the LocalCache folder along with motd.ps1 on the XenApp server.

param ($title,$text,$buttons="OK",$icon="None")

$FormsAssembly = [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

$dialogButtons = @{
 "RetryCancel"=[Windows.Forms.MessageBoxButtons]::RetryCancel }

$dialogIcons = @{

$dialogResponses = @{

return $dialogResponses[[Windows.Forms.MessageBox]::Show($text,$title,$dialogButtons[$buttons],$dialogIcons[$icon])]

The Get-Checksum function is from Moe Winnett at the TechMumboJumblog. I use this function to generate a checksum of the current message.txt file that will be displayed to the user. Once the message is displayed, a hidden .flag file is written to the user’s home directory containing the message.txt checksum. When the script checks to see if the user has seen the message, a checksum is generated of the current message.txt and compared to the checksum written to the .flag file. If they match, the script assumes that the user has already seen the message and will not display it.

### Get-Checksum function #############################################

function Get-Checksum($file, $crypto_provider) {
 if ($crypto_provider -eq $null) {
 $crypto_provider = new-object 'System.Security.Cryptography.MD5CryptoServiceProvider';

$file_info = get-item $file;
 trap { ;
 continue } $stream = $file_info.OpenRead();
 if ($? -eq $false) {
 return $null;

$bytes = $crypto_provider.ComputeHash($stream);
 $checksum = '';
 foreach ($byte in $bytes) {
 $checksum += $byte.ToString('x2');

$stream.close() | out-null;

return $checksum;
### Main Code #########################################################

##Set env variables
$hostname = gc env:computername
$lc = (get-item env:localcache).value
$usrname = [Environment]::UserName
$usrprofile = (get-item env:userprofile).value
$usrPath = "$usrprofile\$usrname"

##Set credentials
$Passwd = "PASSWORD1"

## Set file paths
$MsgBox = "$lc\scripts\Show-MessageBox.ps1"
$MsgPath ="$lc\message"
$MsgFile = "message.txt"
$MsgFilePath = $MsgPath + '\' + $MsgFile
$userhome = (get-item env:USERHOME).Value
$debug = $true

##Check if there is a message file and get its checksum, if not exit the script
if (!(test-path $MsgFilePath)) {
 if ($debug) {write-host "No MOTD file"}
} else {
##Check whether Message has been archived
 if (Get-Content -LiteralPath $MsgFilePath | Select-String -Pattern "ARCHIVE" -Quiet)
 if ($debug) {write-host "MOTD file was already archived"}
 } else {
 if (!(test-path $MsgPath\archive)) {
 md $MsgPath\archive | out-null
 if ($debug) {write-host "Created archive folder"}
 $ArchiveNote="`r`nARCHIVE - Delete this line if editing file"
 net use \\$Hostname\c$ /user:$username $Passwd
 add-content $tmppath $ArchiveNote
 net use \\$Hostname\c$ /delete
 copy $MsgPath\$MsgFile "$MsgPath\archive\MOTD_$((get-date).toString('yyyyMMdd')).txt"
 if ($debug) {write-host "Archived $MsgFilePath to $MsgPath\archive\MOTD_$((get-date).toString('yyyyMMdd')).txt"}
 $MsgChecksum = get-checksum($MsgFilePath)

##Check if the user has already seen the message
if (test-path $flexpath\.flag) {
 if ($debug) {write-host "User has seen a message - check if it's current message"}
 $a = get-item $flexpath\.flag -Force
 $flgchecksum = Get-Content $a
 if ($flgchecksum -eq $MsgChecksum) {
 if ($debug) {write-host "User has seen today's message - exit"
 } else {
 del $a -force
 $flagfile = new-item $flexpath\.flag -type file
 Add-Content $flagfile $MsgChecksum
 Set-ItemProperty -Path $flagfile -Name Attributes -Value ([System.IO.FileAttributes]::Hidden)
 if ($debug) {write-host "User's old .flag file deleted"}
 if ($debug) {write-host "Created hidden flag file: $flagfile and wrote checksum: $MsgChecksum"}
} else {
 $flagfile = new-item $flexpath\.flag -type file
 Add-Content $flagfile $MsgChecksum
 Set-ItemProperty -Path $flagfile -Name Attributes -Value ([System.IO.FileAttributes]::Hidden)
 if ($debug) {write-host "User has not seen the message"}
 if ($debug) {write-host "Created hidden flag file: $flagfile and wrote checksum: $MsgChecksum"}

## Create Window Title with date
$dt = get-date -format D
$tit = "Message of the Day for " + $dt

## Display MessageBox
$Msg = [string]::join([environment]::newline, (get-content -LiteralPath $MsgFilePath))
$MsgB = $Msg.Replace("ARCHIVE - Delete this line if editing file","")

$result = & $MsgBox $tit $MsgB "YesNo" "Information"

## Act on result
if ($result -eq "No") {
 Write-Host "User Pressed: $result"

if ($result -eq "Yes") {
 Write-Host "User Pressed: $result"


Message.txt is the file that is read by the MOTD.ps1 script and displayed to the user.  If you edit the file and see the archive message in the file, you must delete the archive message…

This will ensure the new message is archived by the script.  Currently the script assumes there will be only one message a day, so if a change is made to the script it will overwrite that day’s archived message.  The message.txt is stored in the localcache folder on the server in the Message folder.  The script will create an Archive folder under the Message folder if none is present.

Script Logic Flow




Article: 10 best new features of Windows Server 8

An Article by Doug Dineley on the Good Gear Guide: 10 best new features of Windows Server 8 – Good Gear Guide.

10 best new features of Windows Server 8

With Windows Server 8, Microsoft has outdone itself, from a revamped UI to hundreds of new features, including vastly improved virtualization management

Microsoft claims 300 new and improved features in Windows Server 8, but after a few days in Redmond watching demos and stepping through lab sessions, we wonder whether the marketing guys accidentally left off a zero. It’s hard to name a Windows Server feature that hasn’t been tweaked, streamlined, wizardized, or completely revamped. Whatever grudge you may hold against Windows Server 2008, Windows Server 8 will almost certainly make amends.

If you’re a large shop struggling to manage hundreds of Windows servers, Windows Server 8 should ease the job. If you’re a small shop trying to squeeze high-end capability from a low-end budget, Windows Server 8 has plenty for you, too. With Windows Server 8, everything from server deployment to high availability becomes smoother and more automated.

In fact, there’s so much of note in the new OS, it’s almost a crime to stop at the top 10, listed below in no particular order. Believe it or not, data deduplication for production file servers, native PowerShell support in Hyper-V, and virtual Active Directory didn’t even make the list. Look at it this way: There will be even more surprises in store when you finally get your hands on a Windows Server 8 beta.

Multiserver management. Server Manager not only gets a face-lift in Windows Server 8, donning the superclean Metro look, but opens the management horizon to the entire server environment. Pull in new servers (physical or virtual) to manage through Active Directory or DNS lookup, and Server Manager will inventory the server and add a new tile to the dashboard displaying its state. Other tiles roll up aggregates of information across multiple servers by server role and various attributes.

Views are search driven, so it’s easy to pull up matching values across all rows. Search filters can be saved, so it’s easy to create personalized dashboards or standard views for selected sets of machines. Instead of reaching across the screen to ye olde Task pane (RIP), you perform all actions directly on specific elements, by right-clicking and choosing from a contextual menu. Naturally, all of this remote, multiserver management goodness is built on PowerShell and WMI (Windows Management Interface). Considering Microsoft’s boasts of 2,300 new PowerShell cmdlets, wizards should become more commonplace throughout the Windows Server ecosystem.

Friction-free server deployment. Windows Server 8 inherits Windows Server 2008’s wizards for installing roles and features, but combines them in what Microsoft calls “scenario-based deployment.” Installs can target local machines, remote machines, or virtual hard disks, with deployment to multiple machines automated through PowerShell cmdlets, WMI APIs, and “workflows” that handle suspending and resuming batch operations. Plus, you no longer have to second-guess that Server Core install. Instead of starting over from scratch, Windows Server 8 lets you move between Server Core and a full server simply by installing or removing components. You can even install the full server without the graphical shell because real servers don’t have GUIs.

IP address management. Odds are you’re using a spreadsheet or homegrown cobbleware to track your IP address allocations, and it’s no fun at all. Windows Server 8 introduces a full-featured IP address manager that combines network discovery, static and dynamic address allocation, DNS and DHCP monitoring, and network auditing capabilities all in one place. Logging actual address usage, identifying conflicts, cross-referencing with hardware inventory, and providing an audit trail of all changes, the Windows IP Address Management Center goes way beyond record keeping. It has the potential to eliminate a huge time suck from your to-do list.

Dynamic Access Control. Today’s folder-centric model for access control makes it all too easy for permissions to get garbled — and auditing is a horror. Dynamic Access Control doesn’t replace your current file and folder permissions, but allows you to layer global policies and claims-based access controls on top of them. For example, you might create a rule to ensure that only members of the finance group can access finance department files and strictly from a managed device — and this rule could be enforced by all Windows Server 8 file servers (and only Windows Server 8 file servers) in your organization.

Dynamic Access Control uses tags applied to the files by users, supporting applications (think Microsoft Office), and Windows Server 8 itself (automatic classification). To implement, you create claims definitions and file property definitions in Active Directory; any Active Directory attribute can be used for access control. Claims travel with the user’s security token. In a nice touch, the system now goes beyond the annoying “access denied” message. Instead of the stone wall, denied users can be presented with a remediation link to open a help ticket or contact the administrator or file owner to request access.

Large Hyper-V clusters. Windows Server 8 leaps into VMware territory and beyond with support for as many as 63 hosts and 4,000 VMs per cluster. Backing up the raw numbers are a slew of features that improve performance, manageability, availability, and security in large environments: cluster-aware patching, storage resource pools, thin provisioning, storage offload for data transfers, BitLocker encryption for cluster volumes, data deduplication, and live storage migration.

For the first time, you can team NICs from different vendors, with or without LACP support on your upstream switch. Windows Server 8 also brings Fibre Channel support to Hyper-V guests. You can configure multipath I/O or cluster guests with Fibre Channel for high availability, yet still make use of live migration.

Flexible live migration. Windows Server 8 introduces live storage migration, the ability to migrate virtual hard disks or configuration files for a running VM without interruption. And it removes shared storage as a requirement for migrations. You can now migrate VMs using nothing more than an Ethernet cable; first, the virtual disk is moved, then the running VM. The only requirement is that the hosts belong to the same domain.

There’s no longer a cap on the number of migrations you can perform simultaneously, apart from the limitations of your hardware. Windows Server 8 also lets you queue migrations in a single operation that moves VMs one at a time. And you can specify priority VMs to avoid failures when a cluster becomes oversubscribed. If a cluster is loaded with more VMs than it can handle in a failover scenario, Windows Server 8 will shut down low-priority VMs to allow high-priority VMs to run.

Advanced virtual networking. If you’ve chafed against the lack of promiscuous mode in the Hyper-V virtual switch or pined for the virtual networking capabilities in VMware, you’ll be happy to know that Microsoft has dived in with both feet in Windows Server 8. Microsoft seems to have matched the VMware vSwitch feature for feature — port ACLs, private VLANs, per-vNIC bandwidth reservations, QoS, metering, OpenFlow support, VN-Tag support, network introspection — all without requiring expensive network devices. The switch will support third-party extensions for inspecting, filtering, modifying, sampling, and inserting packets, with management of the extensions integrated into Hyper-V.

Hyper-V Replica. One of the best features of virtualization is easy disaster recovery, but this isn’t as simple as it could be in Windows Server 2008 R2 Hyper-V. The clumsy process for setting up virtual machine replication in R2 gives way to a simple wizard in Windows Server 8. After you choose the virtual disks to replicate and the location for the replicas, you have the option of syncing immediately, scheduling the sync, or writing the replica to a local disk — if you want to bring up the replica on a big USB drive and ship it to the other end for the initial load. The result is an asynchronous, application-consistent snapshot that’s no more than five minutes behind the primary VM. You can even specify the IP settings for the failover environment within the replica, and failback is supported.

SMB for server apps. Windows Server 8 gives a big boost to small businesses and branch offices by extending support for Hyper-V virtual hard disks and SQL Server database files to SMB2 file shares. Translation: You can run your virtual machines and SQL database from a commodity file server, no special storage system required. To protect your Hyper-V and SQL workloads, you can create “continuously available” SMB file server clusters that provide transparent failover. That’s high availability made very cheap and very easy.

VDI for the rest of us. Virtual Desktop Infrastructure will change the world — but not until it becomes a whole lot simpler to do. Setting up and managing virtual desktops on Windows Server 2008 R2 pales miserably to Citrix XenApp/XenDesktop, for example, and implementing Citrix is no walk in the park. Windows Server 8 takes a big step forward toward reducing the complexity and costs of a VDI deployment.

RemoteFX no longer requires a hardware GPU, and remote connections appear to be much lighter-weight than in R2 (about 10 percent of R2 bandwidth in Microsoft’s demo). Admins have per-user control over RDSH (aka Terminal Server) resource allocations. They have a single admin tool for full deployment, as well as a single unified way to deploy RDSH sessions, pooled (stateless) virtual desktops, and personalized (stateful) virtual desktops.

The virtual hard disks — a new format called vhdx — are specifically designed to store the changes and customizations users might want to make to the “gold image” that IT provides them. Although you can still store the virtual hard disk files on just about any SMB share, Microsoft is promising considerably better performance than the previous methods of storing roaming profiles that have given this technology a black eye. Bravo, and let the VDI wars begin … again.

This article, “10 best new features of Windows Server 8,” was originally published at InfoWorld.com. Follow the latest developments on Microsoft Windows at InfoWorld.com. For the latest business technology news, follow InfoWorld.com on Twitter.

Article: More PowerShell modules than you know what to do with

More PowerShell modules than you know what to do with – Richard Siddaway’s Blog.

More PowerShell modules than you know what to do with

After building a PowerShell Windows 8 server I naturally started to look at PowerShell

Click the icon and it loads

PS C:\Users\Administrator> $psversiontable

Name                           Value
—-                           —–
PSVersion                      3.0
PSCompatibleVersions           {1.0, 2.0, 3.0}
BuildVersion                   6.2.8102.0
CLRVersion                     4.0.30319.17020
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.103

Compare with current details from PowerShell v2

PS> $psversiontable

Name                           Value
—-                           —–
CLRVersion                     2.0.50727.5446
BuildVersion                   6.1.7601.17514
PSVersion                      2.0
WSManStackVersion              2.0
PSCompatibleVersions           {1.0, 2.0}
PSRemotingProtocolVersion      2.1


The biggest change is that PowerShell 3 uses .NET 4.0 and WSMan has moved on a version.

Without loading any features or roles the following 56 modules are available

ADDeploymentWF                           AppLocker
Appx                                     BestPractices
BitsTransfer                             BranchCache
CimCmdlets                               ClusterAwareUpdating
DirectAccessClientComponents             Dism
DnsClient                                DnsConfig
DnsLookup                                DnsNrpt
FailoverClusters                         FileServer
iSCSI                                    KdsCmdlets
Microsoft.PowerShell.Core                Microsoft.PowerShell.Diagnostics
Microsoft.PowerShell.Host                Microsoft.PowerShell.Management
Microsoft.PowerShell.Security            Microsoft.PowerShell.Utility
Microsoft.WSMan.Management               MicrosoftiSCSITarget
MsDtc                                    NetAdapter
NetLbfo                                  NetQos
NetSwitchTeam                            NetTCPIP
netwnv                                   NetworkConnectivityStatus
NetworkSecurity                          NetworkTransition
PKIClient                                PrintManagement
PS_MMAgent                               PSDiagnostics
PSScheduledJob                           PSWorkflow
RDManagement                             ScheduledTasks
SecureBoot                               ServerManager
ServerManagerShell                       SmbShare
SmbWitness                               Storage
TelemetryManagement                      TroubleshootingPack
TrustedPlatformModule                    UserAccessLogging
Wdac                                     Whea

These modules are auto loaded when PowerShell starts

AppLocker                                Appx
BestPractices                            BitsTransfer
BranchCache                              CimCmdlets
ClusterAwareUpdating                     DirectAccessClientComponents
Dism                                     DnsClient
DnsConfig                                DnsLookup
DnsNrpt                                  FailoverClusters
FileServer                               iSCSI
KdsCmdlets                               Microsoft.PowerShell.Core Microsoft.PowerShell.Diagnostics         Microsoft.PowerShell.Host
Microsoft.PowerShell.Management          Microsoft.PowerShell.Security
Microsoft.PowerShell.Utility             Microsoft.WSMan.Management
MicrosoftiSCSITarget                     MsDtc
NetAdapter                               NetLbfo
NetQos                                   NetSwitchTeam
NetTCPIP                                 netwnv
NetworkConnectivityStatus                NetworkSecurity
NetworkTransition                        PKIClient
PrintManagement                          PS_MMAgent
PSDiagnostics                            PSScheduledJob
PSWorkflow                               RDManagement
ScheduledTasks                           SecureBoot
ServerManager                            ServerManagerShell
SmbShare                                 SmbWitness
Storage                                  TelemetryManagement
TroubleshootingPack                      TrustedPlatformModule
UserAccessLogging                        Wdac

Thats all of them!

To paraphrase a slogan from a well known software company – what do you want to automate today?

Remember – thats before we add any roles or features.

This going to be fun

Published Thu, Sep 15 2011 20:09 by RichardSiddaway