If you’re using certificate-based authentication for your wired or wireless network and have the Lync 2013 client installed then you may find that your users start getting prompted to select a certificate when connecting to the network for the first time. This is because the Lync client issues users certificates with blank Subject fields and Windows can’t work out which certificate to use.

There’s a hotfix available from Microsoft here: http://support.microsoft.com/kb/2710995/en-us but unfortunately it’s not available via WSUS so you’ll have to push it to your clients “manually”. Personally I would have thought that certificate-based wireless authentication in environments running Lync were relatively common, enough to justify a proper patch, but apparently not.



I spent a while recently wondering if it was possible to have certificates follow users between machines, in this case certificates used for 802.1x authentication, because I didn’t want our CA issuing a new certificate every time a user logged onto a new machine. It seemed logical that such a facility must exist but I couldn’t find anything useful until I stumbled upon it almost by accident while looking for something else certificate-related.

What I was after is Credential Roaming, which is basically a roaming profile system for certificates (and saved user credentials but that wasn’t really a consideration). Once enabled, credential roaming will store user credentials attached to their AD account object and download them to the local machine on logon, then on log off sync everything back up to the AD object again. Obviously there are things to consider here, especially if you have a lot of users and they have a lot of certificates, but you can set limits on the maximum store size (the default is 64k) and certificates are pretty small anyway – plus most of the features only work with Vista and later, but frankly if you’re still running XP then you’ve got to expect things not to work properly.



As per http://support.microsoft.com/kb/2921141, you cannot install the Exchange 2013 management tools onto a machine running Terminal Services. It’s unclear why.

Sure, it’s not as important as it used to be, what with the EAC now being a web interface, but it does mean you can’t easily install the Powershell modules and have to rely on Powershell Remoting which works fine but is much more of a pain in the arse to set up.



I’m amazed that I haven’t previously had a need for something like this, but I was looking for some way to visualise AD group memberships, specifically to take into account fairly deeply nested groups. After a fair bit of searching, a lot of dead-ends and some products that seriously over-sold themselves, I came across this little beauty:

https://gallery.technet.microsoft.com/scriptcenter/Graph-Nested-AD-Security-eaa01644

It’s a Powershell module which extracts group memberships for a User, Group or OU (well, everything in that OU anyway) and creates a Graphviz file that gives a functional, if not very pretty, visualisation of the group membership hierarchy. The output looks something like this:

Draw-ADSecurityGroupNesting
Sample output

Extremely handy if you’re trying to get a better idea of how your group nesting shakes out or where you may have circular memberships or redundant groups.



Quick and easy; Exchange creates an environment variable called “ExchangeInstallPath” which holds the install path for Exchange on a given server, this can be accessed via Powershell using $env:ExchangeInstallPath.

This can be useful if you need to call elements such as RemoteExchange.ps1 but aren’t sure if Exchange has been installed to the default location.



Update: Fixed it for a while, then it broke again. Come to the conclusion that the Windows 7 Task Scheduler is just irreparably broken as I’ve had this happen time and time again. Some 3rd party application is interacting with it in a way that reliably breaks it and I’ve never been able to narrow it down.

Yes, this one again.

When you open up the Task Scheduler, you get a message that says:
“The selected task “{0}” no longer exists. To see the current tasks, click Refresh.”

And you can’t view half your tasks any more, though if you run a SCHTASKS /Query /FO LIST you’ll see that they’re all still there and seem to be working.

I’ve toyed around with a lot of different solutions for this, but I’ve finally found one that fixed it for me:

Go to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Tracing\SCM\Regular and set or add REG_DWORD TracingDisabled to 0 and then reboot.

My only concern is that this may be generating a trace log somewhere, but I’ve been unable to find anything that suggests this is the case so far.



Quick and easy one-liner – if you need to know at a glance which DCs in a domain are GCs and which aren’t:

[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().DomainControllers | %{"$($_.Name) : $($_.isglobalcatalog())"}


I saw this in someone’s signature on one of the Technet forums and though it was a really clever idea; nobody wants to put their email address in plaintext on the internet because it’ll just get hoovered up by spammers and most common obfuscation techniques are easily worked around by spambots, so how about…

[string](0..21|%{[char][int](23+("74778682874174878091987477868287237688239484").substring(($_*2),2))})-replace " "

Clever, isn’t it.

You can generate your own with the following code:

$out = $null
$email = "user@example.com"
foreach($char in $($email.tochararray())){$out += @([System.Convert]::ToUInt32($char)-23)}
$string = [string]$out -replace " "
"Your code is: [string](0..$($($out.length)-1)|%{[char][int](23+(`"$string`").substring((`$_*2),2))})-replace `" `""

Which should give an output that looks something like:

[string](0..15|%{[char][int](23+("94927891417897748689857823768886").substring(($_*2),2))})-replace " "

Email addresses with certain symbol characters may not encode properly.



Bit of an esoteric one this, but might be helpful to someone anyway. If you’ve worked with Out-Gridview before you may have also made use of the NoteProperty property to collate your results prior to output; today I ran into an issue where I knew some of my output objects had 2 NoteProperties and some had 2+x NoteProperties where x was more than 0. When output to Out-Gridview or Export-CSV it was only showing the number of properties that the first object had, irrespective of how many subsequent objects had.

For example:

User Property1 Property2 Property3
Dave 43
Steve 25 62 23
John 23 263

In this scenario, all results would be output with just the User & Property1 NoteProperty displayed because Dave’s Property2 and Property3 don’t exist. You could work around this by sorting on “Property 3” so that it’s the first object in the output and thus includes all columns like so:

User Property1 Property2 Property3
Steve 25 62 23
Dave 43
John 23 263

However, this obviously only works if you know how many properties there are and I didn’t. So, I had to find a further workaround and came up with this:

$count = @()
foreach($output in $useroutput){$count += $(($output | gm).count)-5}
$max = $($count | measure -maximum).maximum
$useroutput | Sort-Object "Property$max" | Out-GridView

This iterates through your array of objects ($useroutput), counts the properties on each (minus the 4 base methods on a System.Object and the known “User” property) and then finds the highest count and sorts the output based on that highest value, ensuring that it always outputs every column even when it’s empty for most of the results.

Obviously, even this method is only useful if your properties are titled numerically, if you’re just pulling an unknown list of properties with arbitrary names, you’re probably going to have to dig a bit deeper.



You know how it is, you don’t pay attention to the management of your domain for just 5 or 6 years and suddenly you have hundreds of GPOs with no idea what half of them do or even if they’re actually linked somewhere. For some reason, the Powershell GPO module doesn’t have a simple cmdlet or property that lets you tell if a GPO is linked or not, because that would be far too helpful, but it’s not too hard to do if you don’t mind parsing some XML.

This code is based on a much more complicated script from here, designed to let you search for individual settings within a GPO. It will accept a number of arguments, but run without any it will simply output to the console a list of all of the unlinked GPOs in the current domain.

<#
Copyright (c) 2014, Adam Beardwood
All rights reserved.
 
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: 
 
1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer. 
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution. 
 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#>
 
#Find Unlinked Linked GPOs in a domain
#Adam Beardwood 20/05/2014
#v1.0 - Initial Release
 
param (
[Parameter(Mandatory=$false)]
[boolean] $outfile=$false,
[Parameter(Mandatory=$false)]
[string] $filename="UnlinkedGPO-$(get-date -f HHmmss).txt",
[Parameter(Mandatory=$false)]  
[string] $DomainName = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
)
 
Import-Module GroupPolicy;
 
[string] $Extension="Enabled"
 
$allGposInDomain = Get-GPO -All -Domain $DomainName | Sort DisplayName;
 
$xmlnsGpSettings = "http://www.microsoft.com/GroupPolicy/Settings";
$xmlnsSchemaInstance = "http://www.w3.org/2001/XMLSchema-instance";
$xmlnsSchema = "http://www.w3.org/2001/XMLSchema";
 
$QueryString = "gp:LinksTo";
 
$host.UI.WriteLine();
 
foreach ($Gpo in $allGposInDomain)
{				
	$xmlDoc = [xml] (Get-GPOReport -Guid $Gpo.Id -ReportType xml -Domain $Gpo.DomainName);		
	$xmlNameSpaceMgr = New-Object System.Xml.XmlNamespaceManager($xmlDoc.NameTable);
 
	$xmlNameSpaceMgr.AddNamespace("", $xmlnsGpSettings);
	$xmlNameSpaceMgr.AddNamespace("gp", $xmlnsGpSettings);
	$xmlNameSpaceMgr.AddNamespace("xsi", $xmlnsSchemaInstance);
	$xmlNameSpaceMgr.AddNamespace("xsd", $xmlnsSchema);
 
	$extensionNodes = $xmlDoc.DocumentElement.SelectNodes($QueryString, $XmlNameSpaceMgr);
 
	$stringToPrint = $($Gpo.DisplayName) + " is not linked in this domain";
 
	if($extensionNodes[0] -eq $null){
		if($outfile -eq $true){
			$stringToPrint | Out-File $filename -Append
		}else{
			write-host $stringToPrint -foregroundcolor red
		}
	}
}