Saturday, May 19, 2018

Free Cheat Sheets, Revision Aids and Quick References

A cheat sheet is a simple short document, typically 1-2 pages of notes designed to aid your memory.  I discovered an interesting site today, https://www.cheatography.com/. This site has over 2500 cheat sheets for all manner of topics, including Office, Business, Technology, kitchen and garden, travel, and a whole lot more.  The site has 17 cheat sheets relating to PowerShell as well as  35 cheat sheets relating to PHP. The most viewed cheat sheet relates to Regular Expressions (a technology I have yet to master).

The site also enables you to create your own cheat sheets.

Friday, April 06, 2018

Method Chaining–A Neat PowerShell Trick

I discovered an interesting  with PowerShell. It’s known as method chaining. Before explaining it – look at an example:

# c:\foo\testit.ps1
# Test of method chaining
$StringBuilder = [System.Text.StringBuilder]::New()
# Build up string contents
[string] $S1 = Get-ChildItem -Path c:\*.pdf | out-string
# Now build the string
$Null = $StringBuilder.
   AppendLine('Using String Builder as opposed to string concatenation').
   AppendFormat('This uses a cool feature: {0}', 'Method Chaining').
   Append([System.Environment]::NewLine).
   AppendLine('.NET has other "builder" classes operate the same way.').
   Append($S1)
# Output the resultant string
$StringBuilder.tostring()

This produces the following output:

2018-04-06_00-38-27


With Method Chaining, you have an object with methods. You specify the object name (i.e. $StringBuilder) followed by a ‘.’ character. On subsequent lines you specify a method call followed by another ‘.’ character. In this case, I created the $StringBuilder object, then chained several method calls. Each method call added lines to the $StringBuilder object. You end the method chaining by omitting the .’ on the final method in the chain (the directory listing).

I’m not too sure I’d advocate using this. It is an obscure trick of the PowerShell parser and as such might fail my “3:00 in the Morning Test” (if woken at 3:00, could you figure this out before a cup of coffee?). But is pretty cool. Yet another example of how awesome the PowerShell parser is!

Wednesday, March 21, 2018

Code Signing Certificates and PowerShell

When creating PowerShell scripts for distribution, it can be useful to digitally sign the script. This ensures the person getting your code knows it has not changed since you sent it, and can verify you as the person signing the code. If you put code on GitHub, for example, a signature might be a great idea. To do this, you need to have a code signing certificate.

In terms of certificates, you have two main options. You can use your own CA to issue the certificate(s) – or use a public CA. The benefit of the public CA is that their root CAs tend to be fully trusted making it more useful. If you issue your own certs, you may have trouble with other people trusting your code signing certificates.

I have recently obtained a new code signing certificate from DigiCert (https://www.digicert.com). It was really very easy:

1. Open an account and order your cert.

2. Validate you are who you say you are. This involves sending DigiCert some documentation (eg your Passport) to prove you are who you way you are.

3. Do a Skype call, where they watch you sign their Identify Verification and Authorization document.

4. Generate, download, and install the certificate.

The validation process was easy although I had issues with the Skype call, initially. Mainly because I was flat out ill for weeks. Then when I was better, I had some difficulty getting the Skype call going. Entirely my issue, although it has to be said, Digicert support are really very, very, very busy. Between being ill and their overload, it took a bit longer to organise – but today it’s done. I did the call, they saw me sign the form and within an hour or so, the cert was working.

To use the cert to sign something is pretty easy. First you start with the script you want to sign:

# C:\Foo\Certs\Cert1.ps1
Write-Host "I got my cert from DigiCert"

A simple script saved as C:\Foo\Certs\cert1.ps1. To sign it it is simple:

$Cert = Get-ChildItem -Path Cert:\CurrentUser\My\ –CodeSigningCert
Set-AuthenticodeSignature -Certificate $Cert -FilePath C:\Foo\Certs\Cert1.ps1

Once signed, you can verify the signature by using Get-AuthenticodeSignature, like this:

2018-03-21_16-39-30

Very simple and very straightforward. If you, for some reason, have multiple signing certificates then you’d need to adjust call to Get-ChildItem to ensure you get the right certificate.


Friday, February 23, 2018

PowerShell’s $OFS built-in Variable And What It Does

The other day, I was working on converting some C'# to PowerShell. 95% was trivial and almost muscle memory. Then I came to this block of C#

char[] chars = { 'w', 'o', 'r', 'd' };
string string1 = new string(chars);
Console.WriteLine(string1);

The output is:

word

So I initially translated it as:

[char[]] $Chars =  ('w', 'o', 'r', 'd' )
[String $String1 = $Chars
Write-Host $String1

But that produced:

w o r d

The same characters but with spaces between which seemed illogical (at first!). I scratched my head, and did a bit of digging over at Spiceworks, where I was introduced to the $OFS PowerShell Variable. $OFS holds a string, known as the Output Field Separator.   PowerShell uses this character string to separate array elements when it coverts the array to the string, PowerShell has a default value of  ” ”, but you can change at the command line, in a script, or in your Profile. The issue here is that PowerShell is doing the array to string conversion and separates each character in the char array with the separator (“ “). You can read a bit more about this in an old blog post by Jeffrey Snover:

This gave rise to two solutions. The first is to let .NET do the conversion and the second was to leverage $OFS. Here  are two ways to do it: https://blogs.msdn.microsoft.com/powershell/2006/07/15/psmdtagfaq-what-is-ofs/


# Leveraging $OFS
[char[]] $Chars =  ('w', 'o', 'r', 'd' )
$OFS = ''  # Set separator to null
[String] $String1 = $Chars
Write-Host $String1
# Or using .NET directly
[char[]] $chars =  ('w', 'o', 'r', 'd' )
$String2 = [System.String]::New($Chars)
Write-Host $string2

This is interesting, but there is a highly practical solution to an issue I’ve seen brought up in several PowerShell support places. The issue if how to construct a comma separated string of words. So if you had an array of several words such as (‘X423q420’, ‘JG75-01-27’,”PCNY”) you could easily concatenate them as follows:

$Array = (‘X423q420’, ‘JG75-01-27’,”PCNY”)
[string] $Array

Which produces:


X423q420,JG75-01-27,PCNY

You could also create the array from properties then force it to be separated by $OFS, like so:

$F = Get-ChildItem –Path X.XML
$OFS = ','
$Sring3 = [string] ($F.Fullname, ($f.length/1kb).ToString('n3'))
Write-Host $String3

Which produces this:

C:\foo\X.XML,0.317

You learn something nearly every day!




Sunday, February 18, 2018

Using Azure PowerShell and PowerShell 3 or 4? You need to update PowerShell SOON (probably).

I recently saw a GitHub Pull Request (https://github.com/Azure/azure-powershell/issues/5149) for the Azure PowerShell cmdlets (the PR was merged into Version 5.3.0 of the Azure cmdlets). Besides from the continuing improvements that each version brings, I noted one very interesting sentence: 'PowerShell version 3 and 4 will no longer be supported starting in May 2018. Please update to the latest version of PowerShell 5.1 '

What does this mean? Well – it means that after May this year, if you are running either PowerShell V3 or V4, new versions of the Azure cmdlets may not longer work – and are not supported in any case. That is not to say that either the sky is going to fall in! Older versions of the cmdlets should continue to work and most of the newer cmdlets should work too. Note the ‘should’. But why take the risk. You have several months before the lack of support begins. But you should start to plan now if you are still using PowerShell V3 or V4 to manage Azure.

So what should you do? The answer should be fairly obvious – if you are using Azure and the Azure cmdlets, just upgrade to the latest version of PowerShell (i.e. 5.1). This new version of PowerShell should work just fine on all supported versions of Windows. Of course, if you are still using XP to manage Azure then you may have some issues trying to upgrade, although an OS upgrade to Windows 10 would fix this problem.

The upgrade of PowerShell should be a no brainer. I suspect many (most?) readers here are already running later versions!  There should be no issue, but if you are using Exchange, tread carefully to ensure that the version of PowerShell you are thinking of upgrading to is going to work with and is supported by your version of Exchange.  This is probably not going to be an issue if you using hosted Exchange (O365).

It seems to me that this is the start of removing all support for PowerShell V3 and V4. V5 and V5.1 are sufficiently better to make the upgrade most welcome. Loads more cmdlets, improvements in workflows etc are all goodness that comes from the Upgrade.

What is your take?

Saturday, January 20, 2018

Power-User–a great productivity add-in for PowerPoint

I do a lot of PowerPoint presentation – I train on a variety of technical subjects and PowerPoint has been my ‘friend’ for as long as I can remember! Over the years, PowerPoint has evolved, but I still prefer the older menu structure vs the ribbon. But such is life – with the menu or ribbon, PowerPoint is an awesome product. With that said, I do find remembering where the key features are to be found.

I’ve just started using a new tool, Power-User (https://www.powerusersoftwares.com/) which is an add-in for both PowerPoint or Excel. When you open PowerPoint, once this add-in is installed, you get a new ribbon item with great tools, which looks like this:

image

Thus, you see all the useful PowerShell features all in one place. Power-User helps with creating a variety of effects including icons, diagrams, colour management etc., etc., etc. And as if that were not enough, Power-User also has some cool Excel tools as well, like this:

image

I love this tool and would not be without it!  For more details on this cool product, see the presentation video at: https://youtu.be/xtFGSnQnWpE.

Power-User is, however, a commercial product. Students and teachers can get this for free, but for commercial use individual licenses are €198/year. For larger companies, a bulk license can reduce the cost per user. So not free, but well worth the fee if you are doing a lot of PowerPoint. My only regret is that I did not find this tool years ago!

Friday, November 10, 2017

Major updates to PowerShell Azure Module

Like the rest of Azure, the Azure PowerShell cmdlets are truly a work in progress. I've written many times before about the cmdlets, including details of the great cmdlet renaming (https://tfl09.blogspot.co.uk/2015/09/azure-powershell-some-changes-and-some.html). I've also demoed these cmdlets on a variety of occasions.

Microsoft has just released a major new revision to these cmdlets, version 5.0.0. The details can be found over on GitHub at: https://github.com/Azure/azure-powershell/releases/tag/v5.0.0-November2017.

This is a major update, as evidenced by the major version number change (from 4.x.x to 5.x.x). Additionally, there are several breaking changes - changes that could break your code if you update just the module itself.  You can see a list of updates at: https://github.com/Azure/azure-powershell/blob/release-5.0.0/documentation/release-notes/migration-guide.5.0.0.md.

If you are using Azure cmdlets - then you probably have some work to do to update to the new cmdlets. But all in all, such is the price of progress.

Monday, October 16, 2017

A Cool Azure Resource

I spent the weekend attending a Train-The-Trainer event at Microsoft UK (Thanks Ed Baker!). The event was focused on Azure and both what it was and how to teach it. A cool event which led to a lot of sharing of tips, tricks, and cool links.

One particularly cool link I discovered was to https://azureplatform.azurewebsites.net/. When you navigate there, you see a page like this:


Each tile on the page represents one Azure service. Click on a service and a neat pop-up appears providing more details of that service. Clicking on Virtual Machines, for example, shows this:

A great launching pad for discovering more about Azure.


Thursday, October 12, 2017

Events in the Security Event Log

I was answering a question in the Spiceworks PowerShell Forum concerning the event log. The poster was looking for how to find out who had logged on to a particular computer. The answer was to use Get-WinEvent and search the Security log for the relevant event. Easy.

But how do you know which event to look for? There are so many events! Well, there's a PowerShell script for that. To find the different event codes and roughly what they mean looks like this:

# Get all the security even  
$e = Get-WinEvent -LogName Security
# Get the different message kinds:
$ids = $e | Sort-Object Name |Group-Object -property id
# And print the event types 
Foreach ($id in $Ids) {
$m = ($id.Group[0].Message).SPLIT("`n")[0] 
" {0:N5}    {1}" -f ($id.NAME), $m }
This code first gets all the security events and sorts them by Event ID. Then the code extracts the first line of the Event Log message and displays the event ID and that first line. On my the output looks like this:
 4624    An account was successfully logged on.
 4672    Special privileges assigned to new logon.
 4634    An account was logged off.
 4648    A logon was attempted using explicit credentials.
 5058    Key file operation.
 5061    Cryptographic operation.
 4798    A user's local group membership was enumerated.
 4799    A security-enabled local group membership was enumerated.
 4904    An attempt was made to register a security event source.
 4905    An attempt was made to unregister a security event source.
 4907    Auditing settings on object were changed.
 5059    Key migration operation.
 4688    A new process has been created.
 4608    Windows is starting up.
 4902    The Per-user audit policy table was created.
 1100    The event logging service has shut down.
 4616    The system time was changed.
 4826    Boot Configuration Data loaded.
 5033    The Windows Firewall Driver started successfully.
 5024    The Windows Firewall service started successfully.
 4647    User initiated logoff:
So knowing this, finding out who logged in is simple, right? You might think. It takes a bit of tinkering with the object, but here's my code:

# Get logon users
$le = $e | where id -eq 4624
$x =
foreach ($event in $le) {
$time = $event.timecreated
$username = $event.properties[5].value
$domain = $event.Properties[6].value
If (($username -ne '') -or ($Username -ne 'System')) {
$ht = @{}
$ht.time = $time
$ht.user = "$domain/$username"
New-object psobject -property $ht
# And display the results:
$x | group user | sort count -desc| ft name, count
This code creates a simple object for each event log entry for the relevant ID. This object just has the time, username and domain name from the event log entry. I create an object to, at the end, group then sort the logon events. The result is almost like this:
Name                                                    Count
----                                                    -----
COOKHAM.NET/JerryGarcia                                  7576
NT AUTHORITY/SYSTEM                                       746
COOKHAM.NET/COOKHAM24$                                     73
COOKHAM/BobWeir                                            36
NT VIRTUAL MACHINE/27A96661-D855-4286-81D6-BBB32172CCED     6
COOKHAM.NET/MickyHart                                       5
Window Manager/DWM-1                                        2
NT AUTHORITY/NETWORK SERVICE                                1
NT VIRTUAL MACHINE/55C8EC55-6D2B-421D-A454-28FCF4680366     1
NT VIRTUAL MACHINE/53EC57B5-BAB2-4A29-A34B-19A8BB857C42     1
NT VIRTUAL MACHINE/45FF27A5-C133-4213-9A4A-DBF4317D55D0     1
NT VIRTUAL MACHINE/4459B92D-0476-4815-B2DE-C3243CD2D82B     1
NT VIRTUAL MACHINE/3D886F3D-B8BD-41A0-8B05-B82AEB2FE99D     1
NT VIRTUAL MACHINE/370E6442-86B5-4310-BDAB-1882DAE4E5C6     1
NT VIRTUAL MACHINE/33872EB0-2259-4312-83F4-AE783B9D817C     1
NT VIRTUAL MACHINE/2FF8C7E0-CB1E-46E1-9C53-7DEFF18FB488     1
NT VIRTUAL MACHINE/289DD95C-0454-4D51-93FC-F4D7502D894B     1
NT VIRTUAL MACHINE/596834C2-6B40-47E6-9EC5-3231BAD2C01B     1
NT VIRTUAL MACHINE/125EFD6E-2F88-4E2E-A0F2-BDA9516B2B59     1
NT VIRTUAL MACHINE/0C77EC57-8A20-4533-A4E1-5CDB93CB1DC2     1
NT AUTHORITY/ANONYMOUS LOGON                                1
NT AUTHORITY/LOCAL SERVICE                                  1
NT VIRTUAL MACHINE/2FAD3305-C65D-4304-AFF1-F4CFC0C96381     1
NT VIRTUAL MACHINE/64D69931-57FE-491F-96C8-215DE6B3D3FC     1
NT VIRTUAL MACHINE/880CD2FD-7304-4CE1-B831-87ED01DD0BD7     1
NT VIRTUAL MACHINE/7A4205E9-D2C6-466C-82BE-80CFF9947738     1
NT VIRTUAL MACHINE/FA3ADF88-EA85-43A4-AE49-5551186977DB     1
NT VIRTUAL MACHINE/EBF0AAF0-2300-4CD3-9B92-BCA29896DD90     1
NT VIRTUAL MACHINE/E4B8AA47-B256-4918-9098-A80C09DC91ED     1
NT VIRTUAL MACHINE/DD8F6DE3-5F65-4990-B0DD-BF328BFB47BE     1
NT VIRTUAL MACHINE/DC824601-E4F9-445D-BFE4-44FB83D7B733     1
NT VIRTUAL MACHINE/DA85B909-A42E-400F-96CB-340BBB6E0DC0     1
NT VIRTUAL MACHINE/D5420357-DF18-4140-B986-B85CF25D8FF1     1
NT VIRTUAL MACHINE/C66F22AD-DF26-4ED3-A555-9FDDE0588EE4     1
NT VIRTUAL MACHINE/6A8984FD-8774-447A-9F35-4FD97766E303     1
NT VIRTUAL MACHINE/BFDAC935-60ED-4CF9-BE1C-FC12DC47EBB2     1
NT VIRTUAL MACHINE/BE427F4F-C3AC-4086-B58D-8B5B8B8C7863     1
NT VIRTUAL MACHINE/A20EA3B5-7926-4AE4-96D7-4AFE2E34D80A     1
NT VIRTUAL MACHINE/9C00DC59-E565-4B88-88D0-CEE2AC08E870     1
NT VIRTUAL MACHINE/95D96D7E-9A2F-46D8-8E02-0FC0B2F9E594     1
NT VIRTUAL MACHINE/953BFF3A-A3EA-4567-ABAD-2A7337CE3B26     1
NT VIRTUAL MACHINE/9353F711-F39C-47E0-B41A-9E85D70997D8     1
NT VIRTUAL MACHINE/88536766-EF5D-4AE9-A343-B3713EA912DF     1
Font Driver Host/UMFD-1                                     1
NT VIRTUAL MACHINE/BFAFEC2C-5565-4458-A359-A4EC6F62079C     1
Font Driver Host/UMFD-0                                     1
Fun and games with the event log!

Wednesday, October 04, 2017

Free Microsoft Azure Symbol/Icon Set

Over the years, many Microsoft groups have created sets of downloadable symbols and icons so you can create nice diagrams to represent your Azure service architecture. The latest set of tools includes Azure services which can be used in PowerPoint or Viso making it easy to create professional looking content.

You can get this icon pack at: https://www.microsoft.com/en-us/download/details.aspx?id=41937. Note the download is 23.3MB.


Wednesday, September 20, 2017

The PowerShell Book Is Complete

Since late last year, I have been working on a book. Titled  Windows Server 2016 Automation with PowerShell Cookbook (ISBN: 978-1-78712-204-8), it was finally completed and sent to the printers. The book is published by Packt Publishers.

It's taken 10 months to complete and we face some serious issues during the writing. We had been using a neat web portal, but it suddenly started 'eating' bits of code. It was a nightmare and cost weeks of extra effort to fix (and we'd fix it only for the portal to eat the code again). 

Then disaster struck in the form of my co-author having to drop out for personal reasons. This is never nice. I ended up picking up the extra chapters, but due to time, space and personal commitments, we did have to drop some of the chapters.  And during the final chapter reviews, we found that code that looked great in the Word Documents had been badly borked in the final PDFs (so HOURS or detailed proofreading). I just hope I picked up all the errors.

But it's done. The printers are doing their best now to print it, and Amazon is now selling the book. I have to say I get a kick out of seeing that page.

The code is planned to be uploaded to a GITHUB repository, so you can download and leverage it. This should happen soon!

So with this book done, my fifth, I am never going to do this again. Way too much work, way too many late nights and early mornings, way too much stress. Never again. But having said that, my super-star tech reviewer, Mike Robbins, has suggested another book. Hmmm.

In any event, let me know if you get this book and what you think!

Wednesday, August 30, 2017

VSCode as a replacement for the ISE

VSCode is a free source code editor developed by Microsoft and aimed at WIndows, Linux, and MACOS. VScode includes support for various languages, such as PowerShell, as well as embedded GIT control, syntax highlighting, code completion, and more.

Mike Robbins has produced a nice video, which you can find at http://mikefrobbins.com/2017/08/24/how-to-install-visual-studio-code-and-configure-it-as-a-replacement-for-the-powershell-ise/. This video takes you through the process of downloading VSCode, and setting it up as a replacement for the ISE.

It turns out to be remarkably simple to do this. Downloading is easy - and the installation process the normal clickercise approach. Once you get VS Code installed, you can easily configure it to act as the replacement for the ISE.

Once you have your settings configured, you end up with something that looks like this:



It looks and feels almost like the ISE, but with a lot of extra features above and beyond the basics provided by the ISE. These include the ability to determine aliases (and replace them with full cmdlet names), GIT hub/VSTeam Services/Hg integration and a lot more.

If you like the ISE, you are likely to enjoy VS Code!



Wednesday, August 16, 2017

Creating a SHA1 Hash - Using PowerShell

I recently saw a query about how to create a SHA1 hash, using Powershell. The post was looking at using a web site for this and accessing it via PowerShell's web processing. But there is a much simpler way - just using the .NET Framework. Here's a simple script that hashes a string:


# Create Input Data 
$enc      = [system.Text.Encoding]::UTF8
$string   = "This is a string to hash< $data     = $enc.GetBytes($string)
# Create a New SHA1 Crypto Provider
$sha1 = New-Object System.Security.Cryptography.SHA1CryptoServiceProvider
# Now hash and display results 
$ResultHash = $sha1.ComputeHash($data)
$ResultHash

The trick to this approach is to convert the string into a byte array and then pass the byte array to the ComputeHash method.


Saturday, July 15, 2017

Managing Azure with PowerShell - A Spiceworks Blog Series

One of my fun tasks these days is being a group administrator and moderator on Spiceworks community forums. The forums are IT Pro focused and include a great group dedicated to all things PowerShell. If you have issues or questions, you are most welcome to come on over and post away. If you know PowerShell, we'd love to have more folks answering the torrent of questions we get.

In that role, Spiceworks asked me to create a series of blog posts on the Spiceworks Cloud blog which covers PowerShell and how you use it in the context of Azure. I offered to update some of the content in my upcoming book (See http://tfl09.blogspot.co.uk/2017/04/my-next-powershell-book.html for details). The publisher (Packt Publishing) kindly agreed.

The first article, Introduction to Managing Azure Services Using Windows PowerShell, was posted this week. The next blog post, which looks at getting the modules you need to manage  Azure whould be posted sometime next week. A third article on the basics of Azure storage and how to create an SMB share (and access the share across the Internet) is planned and should follow on in due course.

I have a number of additional posts to create, including one on building a Virtual Machine, and another on virtual networks and creating a P2S VPN into the VM. I am very much open to suggestions for more in this series.


Thursday, July 13, 2017

Hyper-V and PowerShell - A Tale of Two Modules

I've been working on a book project (see: http://tfl09.blogspot.co.uk/2017/04/my-next-powershell-book.html for details!) and have been working a lot with Hyper-V. I've built a nice farm of VMs (18 or so) representing a bunch of server roles and features. Then, I've been using PowerShell to exercise those roles and features.

These VMs all run on client Hyper-V, on a Windows 10 (AU) host that has 96gb or ram, 2x6-core XEON processors, and loads of disk. The VMs are nearly all running Windows 2016 Server. The chapters all utilise AD/DNS/DHCP/CA etc. A nice setup for writing a book.

In writing, I've noticed that Windows 10 as well as Windows Server 2016 both ship with two Hyper-V modules. The two modules are version 1.1 and 2.0.0.0, as you can see here:


The version 2.0.0.0 module is a superset of the version 1.1 module. Version 1.1 contains 178 cmdlets, while  version 2.0.0.0 contains 235. Both modules have display XML included. Both versions use the same file name, but the Version 2.0.0.0 copy is larger.

You could, or course, manually load version 1.1 module like this:
Import-Module -Name Hyper-V -MaximumVersion 1.1
So long as you just use the cmdlets in the 1.1 version, you would be safe, but if your script did load 1.1, then trying to use cmdlets in the 2.0.0.0 module generates what at first sight is a curious message:


The error message is also both wrong and, if taken, confusing. Importing the module as suggested by the error message generates more error messages. The error messages (Error in TypeData, etc) occur because Powershell is trying to load the version 2.0.0.0 copy of the display XML, and most of the components were already loaded from the 1.1 version. And even if you ignore the display XML errors, the suggested solution still fails with the same error message.

The solution to this error is easy: update your scripts to not explicitly load v1.1. OR, if you do need for some reason to use the 1.1 version and use cmdlets in 2.0.0.0, then pressed them with a 'Get-Module Hyper-V | Remove-Module Hyper-V' and then follow the 2.0.0.0 cmdlet with commands to remove the module and reload the 1.1 version. Personally, while that could work, it's awfully messy and possibly not needed.

Does having two versions really matter?  If you just use cmdlet names in the Hyper-V module, such as Get-VM, then PowerShell by default loads version 2.0.0.0.  If your script uses Import-Module to load the Hyper-V module explicitly, then again by default, PowerShell loads 2.0.0.0.  Having written over 100 scripts across a dozen different Server 2016 features and roles - I never noticed any problems. My scripts, with a few exceptions, relied on PowerShell's module autoload feature - I called the cmdlet and PowerShell loaded one.

If your scripts, on the other hand, explicitly load V 1.1 (as shown above), then you may get a strange error. But in most cases, that can be avoided by simply not explicitly loading version 1.1 of the module. Now I know there may be cases where you may need to use a V 1.1 cmdlet, but those cases should be pretty rare.


Monday, June 26, 2017

Setting Application Pool Recycling Values with PowerShell

As I mentioned a while ago, I'm working on a new PowerShell book (See http://tfl09.blogspot.co.uk/2017/04/my-next-powershell-book.html for details! In writing the book, I've been creating simple scripts to do useful things. In researching them, I found a number of aspects really well covered, reference wise. Other things were not covered well if at all. I hope to post some things I've discovered in the coming months.

With IIS, you can create applications that run in application pools. An application is some set of web pages (with related executables). An application pool is a process, or processes, that run this application. This provides process isolation between applications reducing the impact a badly behaved application can have on other applications running on the same server. Resource leaks can bring an entire web server down, for example.

One way to minimise these sorts of issues is to recycle the application pool - just stop then restart the processes running the application. A neat trick that reduces the risks of resource leaks. One downside is that any state within the application is lost. Needless to say, there are other ways to save state that are not affected by an application pool restart. For a fuller look at the things you can do to configure application pools, see: https://technet.microsoft.com/en-us/library/cc745955.aspx. This document is old, but is a good starting point (and worked fine on IIS 10 for my needs).

You set application pool recycling values, using PowerShell, by setting item properties on certain items within the WebAdministration provider (the IIS: drive). This is simple, but the property names are not all that obvious at first.

What I wanted to do was:

  • Set specific times at which to recycle the application pool
  • Set the pool to automatically if private memory rises beyond a limit, say 1GB.
  • Set the pool to recycle the pool after the pool processes a certain number of requests, say 1 million.

In PowerShell, once you know where to look, this is simple:

# Set Application Pool Restart time
Clear-ItemProperty IIS:\AppPools\WWW2Pool -Name Recycling.periodicRestart.schedule
$RestartAt = @('07:55', '19:55') 
New-ItemProperty -Path 'IIS:\AppPools\WWW2Pool' -Name Recycling.periodicRestart.schedule -Value $RestartAt

# Set Application Pool Maximum Private memory
Clear-ItemProperty IIS:\AppPools\WWW2Pool -Name Recycling.periodicRestart.privatememory
[int32] $PrivMemMax = 1GB
Set-ItemProperty -Path "IIS:\AppPools\WWW2Pool" -Name Recycling.periodicRestart.privateMemory -Value $PrivMemMax

# Set max requests before a recycle
Clear-ItemProperty IIS:\AppPools\WWW2Pool -Name Recycling.periodicRestart.requests
[int32] $MaxRequests = 100000
Set-ItemProperty -Path "IIS:\AppPools\www2POOL" -Name Recycling.periodicRestart.requests -Value $MaxRequests

Some things that caught me out a bit:
1. Finding out the property names. In the case of recycling after 1m hits, the property name is 'Recycling.periodicRestart.PrivateMemory'. I suspect this naming is used by the provider to access the underlying XML that IIS actually uses to hold configuration information.
2. Finding values is easy, if there is one. I found the easitest way to set these values was to first clear the property, then set it.
3. Some item properties take properties of a certain type. It helps to specify the type (as shown above) as some times PowerShell tries to be helpful which can confuse the provider.


Tuesday, May 02, 2017

AD User Properties In PowerShell

I spend a lot of time as a Group Administrator looking after the PowerShell forum over on Spiceworks. The PowerShell group has an active forum  which you can find over at https://community.spiceworks.com/programming/powershell,

One issue that arises often is around getting properties back from a user object in Windows Active Directory. Typically we see posters knowing the GUI interface in Active Directory Users and Computers (ADUC), and wanting to get the same details. Although it is NOT new, I found a great resource the other day: Mappings for the Active Directory Users and Computers Snap-in.

This page, which has numerous subpages, maps the fields you find on the property sheets inside the ADUC MMC snap-in to the properties names you get/set using the Microsoft provided AD cmdlets.

For example, if you have set an Office address on the OU Managed By property sheet, you need to use the Physical-Delivery-Office-Name property from Get-Organizational unit to obtain that information. Likewise, the General Property Page for a user object shows First Name (property givenName), Last Name (sn), and the Display Name (displayName).

This page has links for:

  • Computer Object User Interface Mapping
  • Domain Object User Interface Mapping
  • Group Object User Interface Mapping
  • Object Property Sheet
  • Organizational Unit User Interface Mapping
  • Printer Object User Interface Mapping
  • Shared Folder Object User Interface Mapping
  • User Object User Interface Mapping
If you are working with the AD cmdlets and you need to map what you see in the ADUC GUI to what you need to use in PowerShell.

Saturday, April 29, 2017

Top 50 PowerShell Blogs

I just got e-mail that this blog has been included in the Feedspot.Com's Top 50 PowerShell Blogs list. You can see this list over at http://blog.feedspot.com/powershell_blogs/

I started this blog in 2003 - and first blogged about PowerShell (well, it was called Monad in those days) on 1 Nov 2003. It's been a long run with PowerShell - since that first day when Jeffrey Snover presented 'Batch Scripting, what you can do in 7 lines of code' to PDC 2003.

As Robert Hunter once wrote (and the Grateful Dead sang) "What a long strange trip it's been".

My Next PowerShell Book

I'm working on a new PowerShell book. The book's title is Windows Server 2016 Automation with PowerShell Cookbook (ISBN: 978-1-78712-204-8).  The focus of the book is showing how to manage key Windows Server 2016 features using the latest versions of PowerShell. For each area covered, I show how to do things using Powershell, in the form of recipes. The intention is to both teach a bit about the feature itself, and show you how to manage the feature using built-in and add-on modules.

In a few cases, there is no built-in way to perform some operation using PowerShell. My favourite example is that the Printing cmdlets provide no way to create a printer pool, but you can in the UI. In that case, and others, the book shows useful Win32 console applications. In the case of printer pools, we show how to use PrintUI.DLL and RunDll32.EXE to set up a printer pool. IT pros can't yet do everything with PowerShell, out of the box - but in many cases, that's just not a problem.

The book has 13 chapters, as follows:
  • What’s New in PowerShell
  • Implementing NanoServer
  • Managing Windows Updates
  • Managing Printers
  • Managing Server Backup
  • Managing Performance
  • Troubleshooting Servers
  • Managing Windows Network Services
  • Managing Network Shares
  • Managing IIS
  • Managing Hyper-V
  • Managing Azure
  • Using Desired State Configuration
At the time of this post, I'm nearly done the drafting of the book's contents, and entering into the slow, tedious, and boring part: the editing and final proofing. It may be slow, tedious, and boring, but it's very important, as any writer knows.

There were several hiccoughs with the writing, but it's looking now like this book will be published in the autumn. As soon as I have a more definitive date, I'll post it.

[Later]
Publication should be early October. Sadly, my planned co-author had to drop out of the writing due to personal commitments. Additionally, I had to scale back a bit on the contents. The original plan was to write 450 pages. The book ended up something like 650!

Saturday, January 28, 2017

Nested Hyper-V with Windows 10

I've been away all week, teaching in Trondheim Norway. A nice place, great students and a useful Microsoft training course. In the course, Hyper-V features quite a lot - one cool feature discussed in nested Hyper-V.

Nested Hyper-V is a feature that enables you to create a virtual machine, and then load Hyper-V into that machine. So you can have a VM running VMs. This feature is cool, certainly at a technical level. No doubt someone is going to point out that VMware supports this, but the feature is new in Hyper-V on Server 2016. And interestingly enough, it works in Windows 10 Anniversary Update too!

Why does it matter?  For me, it matters since I am writing a book on PowerShell showing its range and depth. One chapter covers Hyper-V and having Nested Hyper-V means I can create two VMs (HV1, HV2) cluster the VMs, then create clustered virtual machines, The chapter is now easier to write.

The feature matters for customers too.  This enables you to use Hyper-V containers within a VM on a VM. And, it's a fantastic training tool when using on-line labs. The lab vendor, such as Virsoft (a great hosted labs experience!), to provide a student with a VM, in which they can load and use Hyper-V. Previously that was unsupported.

Getting nested Hyper-V to work is great news. For some time, I believed that this would not work on my systems. I have three big Dell Precision 7500 systems. When I tried this during the beta of Windows Server 2016, Coreinfo.exe suggested that my system did not support SLAT. And that meant I could not use nested Hyper-V. But it was wrong!

Here's a picture of a VM hosting a nested VM:
As you can see, a VM running a nested VM. The nested VM, which I called 'embedded' is in the midst on installation.

It turns out that the fix was pretty simple. In the host VM, I just had to issue a simple PowerShell command:

Set-VMProcessor -VMname DC1-ExposeVirtualizationExtensions $True
I had to shut down the  VM first, then reboot. Once rebooted, I was able to bring up the Hyper-V console and create the embedded VM.