More $profile madness
As usual, a minor glitch in my workflow has me mucking around with my $profile. It all started because I normally run Word, Excel, and other Office applications from the command line (as I do many non-MS applications.) To do this, I have functions and aliases in my $profile. These let me start Word, for example, by typing “word” on the PowerShell command line along with any filenames I want to open. So far, so good. But I recently started using Office 2013 on some machines, and this broke my functions for those machines. And at least one of them is running the 640-bit version of office. Hmmm. That could just be a problem. Now I could manually edit the functions in those $profiles, but that’s just kludgy. I like to have a single $profile that I load on any new machine I work on. So, rather than the hard-coded paths, which were never really elegant, but worked fine when I only had one version running, it’s time to be a bit more general. So, I added the following function to my $profile:
Function Find-Office { # if on 32-bit, or running 64-bit office on 64-bit machine, this will find office $Global:[[code]]czo2Olwib2ZmaWNlXCI7e1smKiZdfQ==[[/code]] = Get-ChildItem ` -file "Outlook.exe" ` -path "C:\Program Files\Microsoft Office\" ` -recurse if (! $office) { # If we didn't find it there, look down the (x86) path. But only if we didn't find it $Global:[[code]]czo2Olwib2ZmaWNlXCI7e1smKiZdfQ==[[/code]] = Get-ChildItem ` -file "Outlook.exe" ` -path "C:\Program Files (x86)\Microsoft Office\" ` -recurse } }
Now, a couple of comments here — I made the $Office variable Global so that I could get at the value outside of my profile, since there’s a fair amount of information and properties in it. The other thing is that while I’m searching for Outlook, it really could have been any of the core Office apps that I know get installed every time I install Office. If you’re running Office Home & Student edition, however, you’d best choose a different executable, such as “winword.exe”.
So, now that we know where Office is, we can extract the path to it:
$OffPath = (Find-Office).DirectoryName
(note, we’re still inside my $profile, but we won’t bother to make $OffPath global, since we can easily get it again if we need it. )
Finally, the functions that our aliases will call to start the core Office applications:
function Run-Word { & "$OffPath\WinWord.exe" $args} function Run-Excel { & "$OffPath\Excel.exe" $args } function Run-OneNote { & "$OffPath\OneNote.exe" $args } function Run-Outlook { & "$OffPath\Outlook.exe" $args }
The aliases are simply calls to these functions in the form:
set-alias word Run-Word
Nothing fancy there. But now I’ve got easy command line access to my core Office applications. (As you can see, I don’t use PowerPoint any more than I have to.
)
OneNote 2010 and Windows Server 2012 RD Session Host
You can install Office 2010 in an RD Session Host (ie, Terminal Server), if you have a volume license version. (If you’re using MSDN versions for testing, there’s a special key for use in an RD Session Host environment see: http://support.microsoft.com/kb/983443.)
Great, and you can go ahead and use all the various features of Office. Except OneNote, which fails with an error message telling you to install the Desktop Experience Feature since you’re on Windows Server. Well, that’s great, and if you’re on Server 2008 R2, that’s the solution. BUT, if you’re running on Windows Server 2012, there is no longer a Desktop Experience Feature. It’s GONE. However, what OneNote is looking for is “Ink and Handwriting Services “.
To solve the problem, and install the necessary feature, run:
PS C:\> Add-WindowsFeature InkAndHandwritingServices
This will automatically load the ServerManager module (isn’t PowerShell v3 cool?!) and add the necessary feature. This WILL need a reboot, so be prepared.
Charlie.
Windows Azure PowerShell
For those of you using Windows Azure, we finally have official PowerShell support for managing your Azure subscriptions. With the CTP release of the 1.7 SDK, you can install the Windows Azure PowerShell cmdlets. The download is here.
Keep in mind that this is a CTP, and the first version of the cmdlets released, so there are a few rough edges and missing functionality still. But they are already very usable and a big improvement if you need to manage more than a single image in Windows Azure. As I get time, I’ll be posting more stuff here, but I also recommend you add Michael Washam’s blog to your favourites.
Charlie.
PowerShell v3 – Using PSDrive to Replace Net Use
I routinely have to map drives across domain boundaries, or to/from non-domain and domain machines. In the old days, I used NET USE commands, which were OK, but there were some issues. Besides, it’s time to move to away from legacy commands such as NET. PowerShell v3 includes an updated set of PSDrive cmdlets (Get, New, Remove) that have added the ability to create persistent mappings to a drive letter. Plus, unlike NET USE commands, I can pass a single credential to connect to multiple machines, and prompt for the password. Ah, HA. Now that’s useful. Here’s my drive mapping script for connecting to three different machines with my domain credentials, even though I’m actually connecting from a non-domain joined machine.
# PowerShell script to map drives using New-PSDrive command.
# Prompts once for credentials, then uses them. Or so we hope.
#
# Initial: 10 June, 2012
## Start by checking for already mapped drives. We’ll use Get-WMIObject to query Win32_LogicalDisk.
# A drivetype of 4 means that the drive is a network drive.
$NetDrives = Get-WMIObject Win32_LogicalDisk | Where-Object { $_.DriveType -eq 4 }
# Check which servers have drives mapped to them.
$Srv1Mapped = $NetDrives | Where-Object {$_.ProviderName -match "srv1" }
$wssMapped = $NetDrives | Where-Object { $_.ProviderName -match "wss-100" }
# Prompt for credentials and store in a variable.
$Contoso = Get-Credential -Cred "CONTOSO\Charlie"# Now, map drives based on that credential
# First, drives on SRV1. These are general Contoso resources
if ($Srv1Mapped ) {
Echo "Skipping core maps on SRV1"
} else {
New-PSDrive -Name I –root \\srv1\install -scope Global -PSProv FileSystem -Cred $Contoso –Persist
New-PSDrive -Name J -root \\srv1\Download -scope Global -PSProv FileSystem -Cred $Contoso -Persist
}# Now, shared drives for the home resources
if ($wssMapped ) {
Echo "Skipping Home maps on Windows Storage Server WSS-100"
} else {
New-PSDrive -Name M -root \\wss-100\Music -scope Global -PSProv FileSystem -Cred $Contoso -Persist
New-PSDrive -Name P -root \\wss-100\Pictures -scope Global -PSProv FileSystem -Cred $Contoso -Persist
New-PSDrive -Name V -root \\wss-100\Videos -scope Global -PSProv FileSystem -Cred $Contoso -Persist
}# Finally, some specialized resources
New-PSDrive -Name W -root \\srv1\Working -scope Global -PSProv FileSystem -Cred $Contoso -Persist
New-PSDrive -Name U -root \\srv1\Charlie -scope Global -PSProv FileSystem -Cred $Contoso -Persist
New-PSDrive -Name Y -root \\hp180-ts-17\RemoteApps -scope Global -PSProv FileSystem -Cred $Contoso -Persist
}
There we go, and I can run this from both elevated and standard user PowerShell windows. The best part is, these mapped drives are visible in that PowerShell window, but also in Windows Explorer, and anywhere else I need a mapped drive.
Charlie.
Windows MultiPoint Server 2012 Beta Available
Some of you know I’m a huge fan of Windows MultiPoint Server, and the next release is due out “soon”. I’ve been testing it here and I’m really excited about the new features, especially the built in VDI support for both Win7 and Win8 clients. This will solve issues around power users in business environments where WMS has been limited by the Remote Desktop Protocol (RDP). With direct support for virtual desktops using VDI, that should be a non-issue.
To learn more about Windows MultiPoint Server 2012, check out the official blog post here. To join the public beta, go to the Connect directory at https://connect.microsoft.com/directory/ and click on the Join link for Windows MultiPoint Server 2012 Public Beta. (It’s right at the top, at least for the moment. )
Stopping All Running Virtual Machines (Hyper-V)
So, a good friend and fellow MVP asked me for a script to shut down all running virtual machines on a server so she could do cold backups of them. This seemed like a perfectly reasonable request, and my first thought was “Well, this gets really obvious and easy in Windows Server 8” since we have a full set of Hyper-V cmdlets there. But then I sort of remembered doing something like this before, and hunted around and found this old TechNet Wiki article I wrote over a year ago. It wasn’t a full fledged script, but had all the pieces I needed to put together a simple script to stop all the VMs on the local Hyper-V host:
# This is a simple script to stop all the currently running VMs on the local
# Hyper-V host. It could easily be extended to accept a command line
# argument of the name of a remote yper-V hosts or a list of hosts into an array$VMs = Get-WmiObject MSVM_ComputerSystem -computer "." -namespace "root\virtualization"
ForEach ($vm in $VMs) {
if ( $vm.name -ne $vm.elementname ) { # skip the parent’s name
if ( $vm.EnabledState -eq 2 ) { # If the VM is running
$shutdown = Get-WmiObject MSVM_ComputerSystem -namespace "root\virtualization" –query “Associators of {$vm} where ResultClass=Msvm_ShutdownComponent”$shutdown.iniateShutdown($true,”System Maintenance”)
sleep 5
}
}
}
So, what’s happening in that script? Well, Get-WmiObject grags a list of all the VMs on the local Hyper-V Host (-computer “.”), then we simply loop through the list (skipping host itself ($vm.name -ne $vm.elementname), and for each VM that is running ($vm.EnabledState -eq 2), we get a shutdown object for that specific VM and then call the initiateShutdown method on that object.
Note that this is a “forced shutdown”, so is equivalent to “shutdown –s –f” at the command line. Some processes may not get politely shutdown. Too bad, so sad. Since we need this to work regardless of what else is happening, that’s a necessary risk.
Charlie.
Remote Desktop Protocol Vulnerability
I don’t usually bother to write about Microsoft patches. After all, they happen every month, and we all are in the habit of patching (updating) moderately regularly. However, the update in MS12-020, described in this post, is both serious, and very likely to be a target in the very near future, though there aren’t any known exploits. Yet.
First, download and install the patch. That’s the obvious fix. However, if there is some particular reason why you can’t install the patch immediately, then you should configure all clients and servers that have Remote Desktop enabled to require Network Level Authentication (NLA). Microsoft has even made it easy for you. At the bottom of the TechNet post are links to apply a registry change to enforce Network Level Authentication. If you’ve got Windows XP or Windows Server 2003 clients, there’s even a Fix-It to turn on CredSSP so that they can connect using NLA.
Finally, you can configure group policy to require NLA on your network (and really, isn’t it about time you did?) Instructions are here: http://technet.microsoft.com/en-us/library/cc732713.aspx.
I know I was lazy about it for a long time, even after pretty much all my downlevel clients were long gone. But now that GPO is set and enabled. And my SBS WSUS server is sending that patch to every computer in my network. No playing around with this one, folks.
Mapping Drives
My standard environment expects to have several drive mappings wherever I’m logged in to my network. Even when I’m running on a computer that isn’t joined to the domain. To facilitate that, I have a simple “mapdrives.cmd” file that has the necessary net use commands in it to map them. Then my default PowerShell $profile calls mapdrives.cmd. This works well, except that the result is fairly messy if there’s a problem.
Problem? Sure. For example, if my laptop isn’t in the office, then it won’t be able to map the drives on my office network. Or, if the dries are already mapped as part of a group policy, I’ll get an error when I try to map them. So, I decided to get smarter about it. Here’s the relevant section of my $profile:
$InOffice = test-connection -quiet 192.168.50.3
$isMapped = Get-WMIObject -query "Select * from Win32_LogicalDisk where DeviceID=’A:’"
if ($InOffice -and ! $isMapped ){
$maps=’C:\Windows\system32\mapdrives.cmd’
if ($maps) {& $maps }
}
Now there may be even better ways to do this, but for me this works well. The $InOffice test checks for the presence of a server that should be reachable if I’m in the office, but that will not be reachable anywhere else. The $isMapped test checks to see if one of my standard drive mappings has already been done.
The result? If I’m not in the office, it won’t bother mapping drives and thus save some significant startup time while it tried to map them and then failed. And if I’m in the office, but they’ve already been mapped, it won’t bother either, saving no time but keeping my PowerShell window from echoing all those errors as it tries to map something that is already mapped.
Find this useful? Got a better way to do it? Leave a comment, please.
Charlie.
Windows MultiPoint Server 2011 UR 1.1 Released
Microsoft has released an update rollup to WMS. This update rollup replaces UR1, which had an installation order problem when installed on an SBS Essentials network (or with Windows Storage Server 2008 R2 Essentials). The details of the update are covered in MS KnowledgeBase article 2626067. UR1.1 is cumulative, so you can install it over the top of UR1 if you already have that installed, or you can install it on a plain RTM system. It will supersede UR1 on WU/MU/WSUS.
(note: if you already have problems because of installing the existing UR1, you need to re-install the SBS Essentials to correct the issue — just connect to http://sbseservername/connect and re-install.)
Charlie.
RemoteFX and Windows MultiPoint Server 2011
Windows MultiPoint Server 2011 (WMS) has an option to “Enable RemoteFX” under Server Settings
.
But what does that option actually do? And what IS RemoteFX anyway?
RemoteFX is technology that was included in Windows Server 2008 R2 that is designed to make virtual machines and remote sessions work better. When used with Windows 7 VDI sessions, and with the appropriate graphical hardware, it can leverage that hardware to create a virtual GPU for the VDI session. However, that isn’t something that WMS can take advantage of. However, another piece of the RemoteFX story is an improved codec for RDP sessions, and that is something that WMS can use. The RemoteFX codec is designed to handle video and mixed video and text better across RDP sessions than the native NScodec. When you enable RemoteFX under Server Settings, WMS switches from using the NScodec to using the RemoteFX codec for encoding content that is rendered on the server and sent over the wire via RDP.
To take advantage of it, however, your WMS station needs to be running RDP version 7.1, which means your client needs to be running Windows 7 SP1, Windows ThinPC, Windows 7 Embedded, or one of the third party RDP clients that are 7.1 compliant. I’ve enabled this on my WMS, and it definitely helps with streaming video to an RDP session. It won’t help to a zero USB client, unfortunately, but works well with my repurposed old laptop that is running Windows ThinPC.
Finally, if you have a lot of multimedia needs for WMS, and your physical layout allows it, I suggest using directly connected video for your client stations. This is the best video solution, and with a couple of modern video cards in your WMS server you can easily get 8-10 stations directly connected. If you need more stations than that, using RemoteFX and a client running an version 7.1 compliant RDP client will provide a quite acceptable experience.
(Thanks to Dean Paron at Microsoft for clarifying some key points around RemoteFX. Any errors are my mine, not his.)
Charlie.