Windows 10 Console

Best New Feature of Windows 10?

Well for me, it has to be the proper standard support for text selection, copy (CTRL+C), cut (CTRL+X) and paste (CTRL+V) in the Command and PowerShell windows. Finally, Microsoft has gotten rid of the completely unintuitive and non-standard method employed for the last 20 or so years. What took them so long?

Although I still don’t like the fact that copying text in a console window de-selects it. This is not standard behaviour anywhere else. Perhaps they’ll fix this too?


Get DSC Configuration from a Remote Host using an SSL Connection

I’ve spent the last day or so working on a module to help with managing DSC Pull Servers and other functions to help making DSC a little bit easier to get up and running. This module isn’t quite finished yet, but I thought I’d share a quick code snippet that I’ve been using a lot to get the DSC configuration from a remote machine when credentials and special port details are required.

Normally, if you want to pull the DSC configuration for a remote computer that won’t require credentials or SSL WSMan then you can just execute:

Get-DSCConfiguration -CimSession 'DSCSVR01'

This cmdlet just pulls the DSC configuration from the remote host using any existing credentials and using HTTP instead of HTTPS.

But if you want to use any alternative connection information – such as forcing the use of SSL WSMan – you need to add some CIM Options:

$cimOption = New-CimSessionOption -UseSsl
 $cimSession = New-CimSession -ComputerName 'DSCSVR01' -Credential (Get-Credential) -SessionOption $cimOption
 Get-DSCConfiguration -CimSession $cimSession
 Remove-CimSession -CimSession $cimSession

That is about all I’ve got for today. Hope this helps someone.

Clear All Windows Event Logs

Just a quick one this time.

One thing I often like to do on my lab machines (servers and clients) is clear out all event logs. Not just the older style Windows Logs, but the newer Applications and Services Logs as well:
Event Viewer Logs

The easiest way I’ve found to do this is just run the following PowerShell command in an Administrator PowerShell console:

get-winevent -ListLog * | % { [System.Diagnostics.Eventing.Reader.EventLogSession]::GlobalSession.ClearLog($_.LogName) }

This will dump the content of every Windows Log and Applications and Services log in one go.

Be aware, this is a one-way ticket – you can’t recover the content of these logs after they’ve been deleted!

So if you’re a bit concerned and want to archive the content before it gets deleted use this command instead:

get-winevent -ListLog * | % { [System.Diagnostics.Eventing.Reader.EventLogSession]::GlobalSession.ClearLog($_.LogName,"d:\LogArchive\$($_.LogName -replace '/','.').evtx") }

You’ll want to configure the d:\ArchiveLog to set the path you want the old events saved to. All the events will be saved into this folder with one file for each event log:

Events after they've been archived

Simple as that!


Multiple VHD/VHDx Optimization using PowerShell Workflows

Like most tech people I have lots of Hyper-V VM’s scattered across various computers at home. Some of these VM’s are running on Server OS hosts (Server 2012 R2) and some running on client OS hosts (Windows 8.1) on my desktop or laptop. These VMs also get varying amount of use – lab and dev machines getting used most of the time while “experimentation” machines getting booted only rarely.

I also like to run my heavily used VMs on fast SSD drives to keep them “snappy”. But like most people I have only a limited amount of SSD space. I’m also quite an obsessive neat freak. These two things combined means I like to keep the VHD/VHDx files used by my VMs as small as possible.

Keeping VHD/VHDx files trim is can easily be performed inside the Hyper-V management tool by clicking the Edit Disk… button and using the Edit Virtual Hard Disk Wizard to Compact the desired VHD/VHDx file:

Compact a VHD using the Edit Virtual Hard Disk wizard

This of course is all a bit manual and can be really time-consuming when performing this on lots of virtual hard disks. This sounds like it could be performed by a PowerShell command.

After about 5 minutes of investigation I came up with this simple PowerShell command:

Get-VM | Where { $_.State -eq 'Off' } | Get-VMHardDiskDrive | Optimize-VHD -Mode Full

It basically performs a full optimization on all VHD/VHDx files attached to all Virtual Machines that are in the Off state on the host the command is run on. This does the job quite well but has a few annoyances:

  • The optimization is performed in series.
  • Running guests won’t be optimized.
  • The command only works on VMs on the host the command is run on.

Looking at the list of annoyances it seems a PowerShell workflow might be a good solution. So, after a few hours coding and testing (I can’t tell the number of times my VMs were rebooted and optimized over the day) I managed to complete a module containing a PS Workflow that was up to the task (documentation contained in the link):

Optimize Hyper-V VHDs using PowerShell Workflow

The module can be installed into a PowerShell modules folder (or imported from any location) and the workflow called like in the same way a normal cmdlet would be called:

Optimize-VHDsWorkflow -ComputerName HV-01,HV-02 -VMName NTB01,NTB02,NTB03 -Mode Quick

The above command would optimize all VHD/VHDx files attached to VMs called NTB01, NTB02 or NTB03 on hosts HV-01 and HV-02. It would perform this optimization in parallel meaning all VHDs would be optimized at the same time. Care obviously needs to be taken here, because optimizing too many VHDs running off the same data store could saturate the IO leading to performance of the data store being crippled.

When this workflow is run, any VMs that are running will not have their VHDs optimized. This is probably a good thing for production guests, but for my test lab guest, I want them to be shutdown automatically, have their VHDs optimized and have them automatically started back up. So I implemented a switch called AllowRestart:

Optimize-VHDsWorkflow -AllowRestart -Mode Full -Verbose

The AllowRestart switch will allow a guests that are in a running state to be shut down (not turned off or forced), an optimization performed and then started back up. If a guest is not in a running state it will just be optimized. If the guest can’t be shut down using a normal shut down (because the guest doesn’t have Hyper-V tools running or installed or isn’t running a compatible OS) then it won’t be optimized.

You can also use the Verbose switch to show more information about the workflow process:

The Optimize Verbose Process

There really isn’t much to the process and it could even be scheduled via Task Manager to be performed automatically. If anyone has any comments or feature requests, please let me know – I’m always enjoy a challenge!

\m/ \m/


Using PowerShell to Install/Uninstall Microsoft Office Products by Group Policy

I’ve been recently doing some experimentation with AD RMS templates and AD FS integration in my lab environment. Clearly, I lead a very exciting life. Of course to test AD RMS templates one needs a copy of Office installed into the lab environment. This, I thought, would be a good opportunity to configure Office (Office 2013 Pro Plus to be precise) to be installed via Group Policy.

I of course read the Deploy Office 2013 by using Group Policy computer startup scripts documentation on TechNet, which directed me to use GPOs which called batch files on computer start-up. This is all simple enough and works well, but being a bit of a PowerShell fiend I’d prefer to use it whenever I can. Since Windows Server 2008 R2 and above supports PowerShell scripts for GPO startup and shutdown I thought I’d write some general purpose PowerShell scripts that could be used in place of the old batch file scripts:

PowerShell Scripts to Install/Uninstall Office 2013 products using GPO

As a side note – I wonder why Microsoft doesn’t support installing Office 2013 products using the standard Software Deployment policies in GPO (assigning, publishing etc). But that is a question only Microsoft can answer.

These PowerShell scripts accept parameters that allow key elements of the installation process (product, source folder, config file, log file location) to be specified in the GPO Script parameters themselves:

GPO PowerShell Startup Script

For example, to install a copy of Microsoft Office 2013 Pro Plus from the \\server\software$\Office15.ProPlus\ share using the file \\server\software$\Office15.ProPlus\ProPlus.ww\SilentInstall.xml to control the configuration the following parameters could be used:

-ProductId "Office15.ProPlus" -SourcePath "\\server\software$\Office15.ProPlus\" -ConfigFile "\\server\software$\Office15.ProPlus\ProPlus.ww\SilentInstall.xml"

The full script parameters are documented in the PowerShell scripts as well as on the Microsoft Script Repository page along with additional examples. The scripts can also accept a parameter for controlling where a brief log file can be written to so that it is easy to see if the product has been successfully installed on each machine that has been assigned the GPO.

Creating a GPO using the PowerShell Scripts

  1. In Group Policy Management Console, create a new GPO:ss_gpmc_new_gpo
  2. Enter a name for the installation policy and click OK.ss_gpmc_new_gpo_name
  3. Right click on the new policy and select Edit:ss_gpmc_gpo_edit
  4. Select the Computer Configuration\Policies\Windows Settings\Scripts (Startup/Shutdown) node:ss_gpmc_edit_startup_script
  5. Double click the Startup item:ss_gpmc_startup_properties_scripts
  6. Select the PowerShell Scripts tab:ss_gpmc_startup_powershell_scripts
  7. Click Add to add a new startup script:ss_gpmc_startup_powershell_addascript
  8. Click the Browse button to locate the folder where the policies scripts should be stored:ss_gpmc_startup_scripts_location
  9. You will need to copy the PowerShell scripts downloaded from the Microsoft Script Repository into this folder and select the one that should be used with this policy.
  10. Enter the PowerShell script parameters into the Script Parameters box:ss_gpmc_startup_powershell_script_properties
  11. Click OK to save the PowerShell startup script:ss_gpmc_startup_powershell_scrpts_configured
  12. Click OK to save the Startup Properties.
  13. Close the GPME and apply the new GPO.

Important Note about PowerShell Script Parameters

There appears to be a limit to the maximum number of characters supported in the GPO Startup/Shutdown PowerShell script parameters. This limit seems to be 207 characters, but I haven’t been able to confirm this anywhere. Although more than this number of characters can be entered into the Parameter text box, anything above 207 does not get passed through to the script, which either causes the script to run incorrectly or not at all.

If you do encounter this limit, but still need additional parameters passed, you could use positional parameters to reduce the overhead or create another script that calls these scripts with the defined parameters.

Hopefully, someone will find this useful. If you have any comments or requests for improvements of the scripts, don’t hesitate to let me know.