SixOrNot linked from Mozilla blog entry

World IPv6 launch day got me a nice bump in the user count for SixOrNot, my IPv6 status indicator addon for Firefox. Looks like Mozilla linked to it from a blog entry they made which I imagine helped a lot with that!

Pushing up toward 2000 users now. It’s an incredible feeling seeing so many people using software I’ve written. Definitely time to work on some new features for it.

Facebook IPv6 live on main domain?


It appears that everyone’s favourite $100bn social network have enabled IPv6 on their main domain, jumping the gun on World IPv6 Launch Day.

This is rather good news, possibly the highest traffic site aside from Google to have done this so far.

World IPv6 launch – 6th June

I like to think of myself as an IPv6 expert, sadly it isn’t hard to be when so few people even know it exists!

I try and raise awareness through work, and through development of software which highlights IPv6. My Firefox extension Sixornot was one of the first to do this, and has inspired several others. I’m also using some of the unique features of v6 (multicast and scope identifiers) at work in building an innovative test management system.


I’m glad to see that (at least for me, using AAISP) Google has got most of the domains blogger uses IPv6 enabled. One of the cool features Sixornot has over its competitors is the ability to see whether each component of a remote website is being loaded using IPv6. Quite a lot of sites who claim to be IPv6 ready use CDNs or advertising networks which do not support the new protocol!

You can find more information on IPv6 via the launch day website – it’s well worth finding out about this crucial next-generation Internet technology. You’ll be one of a select few who know what they’re talking about!

Hyper-V and Azman for delegated VM access (using PowerShell!)

There’s an excellent article about delegating Hyper-V permissions using Azman (Authorization Manager) which has recently proven invaluable for me. We’ve been using VMM for a while, but the only real use case we have is to impose a simple segregation between our “production” development systems and our test systems (to avoid testers accidentally powering off the CI server, for example).

VMM is really overkill for this, and after upgrading to VMM 2012 I found that it no longer even managed to set permissions properly. (All our users hate the VMM self-service portal and want to use the Hyper-V MMC anyway…)

One part of the process detailed in that article which I wanted to improve on was the VBS scripts used to set the Scope for VMs. The permission model relies on assigning VMs to scopes (and then assigning users to those scopes with particular permissions profiles). The latter can be done with the Azman UI (or, I am sure, via scripting of some kind via WMI). The former can only be done via scripting. Since I do most of my Hyper-V management using PowerShell I wanted a simple solution to keep it all in one place.

So I wrote a simple PowerShell module with two methods, Get-VMScope and Set-VMScope. Get-VMScope lists the scope for the given VM (either pass a string with the name or a wildcard pattern, or pipe in an object with either a “VMName” or “ElementName” property – e.g. you can pipe in the VM objects which are returned by the psHyperV module. Set-VMScope takes a (single) VMName/ElementName and you set the Scope using the -Scope parameter.

No documentation (yet), but it’s fairly self-explanatory!

One issue I found while migrating from VMM 2012 to using this was that snapshots contain a scope property which will override the global one whenever the machine is reverted. This can be overcome by re-snapshotting, or manually editing the snapshot XML file, or running a script/task to set the scope whenever the machines are reverted automatically. This problem will gradually go away as the machines get rebuilt of course.

PXE configuration

(This is just a random braindump, no real structure!) Directory structure:

RemoteInstall/ - Base folder, shared using TFTP, HTTP and SMB
Boot/ - No reason for this subfolder (hang over from using WDS initially)
abortpxe.0 - Permits exit from PXE process via menu
boot.gpxe - Initial boot file for gPXE, see below
gpxe-1.0.1-gpxe.kpxe - Initial file used to boot gPXE
gpxe-1.0.1-undionly.kpxe - Same, but using UNDI only (I found this doesn't work with a lot of older NICs)
ifcpu.c32 - CPU feature detection, use for menus
ifcpu64.c32 - CPU feature detection, use for menus
LiteTouchPE_x86.iso - Images produced using MDT, and then booted using memdisk - see notes
memdisk - Used to boot from an ISO image - Turn off machine
pxelinux.0 - This is loaded by gPXE to provide the menus
vesamenu.c32 - Provides menu system
Linux/ - Place to put Linux files (and things like memtest)
pxelinux.cfg/ - Configuration for pxelinux
default - Default menu loaded for all clients
graphics.conf - Configuration for menu graphics

DHCP configuration: I’m using the Windows DHCP server. You need to configure some server options at the root of your scope:

Option Name Value Class
066 Boot Server Host Name None
067 Bootfile Name http:///reminst/Boot/boot.gpxe gPXE
067 Bootfile Name Boot\gpxe-1.0.1-gpxe.kpxe None

You’ll need to create a custom class called gPXE to specify one of the options inside. Right-click on “IPv4” under your DHCP server -> “User Classes” -> Add Name: gPXE Description: gPXE Clients ASCII: gPXE Other than that set up DHCP as normal. You don’t need to configure option 60. More details on chainbooting gPXE can be found here. boot.gpxe:

chain http:///reminst/Boot/pxelinux.0

This is simple, but can be made much more complex (see gPXE command line reference). MDT notes: Generating the MDT images is fairly straightforward, though obviously you need to configure MDT first (outside the scope of this article). The .iso MDT produces contains a WIM image, boot.sdi and bootmgr etc. This can be used to boot windows PE, which then triggers OS deployment. One little thing to mention here is that for this process to work you need to disable the “Press any key to boot from CD/DVD” option which comes up. This is done by removing the bootfix.bin file from the generated ISO. Delete it from: C:\Program Files\Windows AIK\Tools\PETools\x86\boot\ C:\Program Files\Windows AIK\Tools\PETools\amd64\boot\ And MDT won’t copy it into the ISOs it generates. Menu entries for MDT:

MENU LABEL ^Windows Deployment Services (x86)
LINUX http:///reminst/Boot/memdisk
APPEND iso raw
INITRD http:///reminst/Boot/LiteTouchPE_x86.iso

MENU LABEL ^Windows Deployment Services
LINUX http:///reminst/Boot/memdisk
APPEND iso raw
INITRD http:///reminst/Boot/LiteTouchPE_x64.iso

Selecting either option will download memdisk and the iso, then boot from the ISO (which takes you into the MDT wizard, or if you configure a default task sequence per machine it’ll automatically begin to deploy). gPXE: You can get gPXE ROMs from here. I chose to use the all drivers one for simplicity, and because I found the UNDI-only one didn’t work with some NICs. The “PXE bootstrap loader” option is the right one (.kpxe) Other notes: Menu item for booting from local disk should be…

LABEL local
MENU LABEL Boot from ^Harddisk


SQL 2012 unattended install + command line options

Here’s the help output from the SQL 2012 setup.exe:

setup.exe /[option]={value} /[option]={value} ...

ACTION Specifies a Setup work flow, like INSTALL,
UNINSTALL, or UPGRADE. This is a required
ADDCURRENTUSERASSQLADMIN Provision current user as a Database Engine
system administrator for SQL Server 2012 Express.
AGTDOMAINGROUP Either domain user name or system account
AGTSVCACCOUNT Either domain user name or system account
AGTSVCPASSWORD Password for domain user name. Not required for
system account
AGTSVCSTARTUPTYPE Startup type for the SQL Server Agent service.
Supported values are Manual, Automatic or
ALLINSTANCES Specifies that all instances are to be included
in the Setup operation. This parameter is
supported only when applying a patch.
ASBACKUPDIR The location for the Analysis Services backup
ASCOLLATION The collation used by Analysis Services.
ASCONFIGDIR The location for the Analysis Services
configuration files.
ASDATADIR The location for the Analysis Services data
ASLOGDIR The location for the Analysis Services log files.
ASPROVIDERMSOLAP Specifies if the MSOLAP provider can run in
ASSERVERMODE Specifies the server mode of the Analysis
Services instance. Valid values are
ASSVCACCOUNT The account used by the Analysis Services
ASSVCPASSWORD The password for the Analysis Services service
ASSVCSTARTUPTYPE Controls the service startup type setting for the
ASSYSADMINACCOUNTS Specifies the list of administrator accounts to
ASTEMPDIR The location for the Analysis Services temporary
BROWSERSVCSTARTUPTYPE Startup type for Browser Service.
CLTCTLRNAME The computer name that the client communicates
with for the Distributed Replay Controller
CLTRESULTDIR The result directory for the Distributed Replay
Client service.
CLTSTARTUPTYPE The startup type for the Distributed Replay
Client service.
CLTSVCACCOUNT The account used by the Distributed Replay Client
CLTSVCPASSWORD The password for the Distributed Replay Client
service account.
CLTWORKINGDIR The working directory for the Distributed Replay
Client service.
CLUSTERPASSIVE Specifies that SQL Server Setup should not manage
the SQL Server services. This option should be
used only in a non-Microsoft cluster environment.
CONFIGURATIONFILE Specifies the configuration file to be used for
CONFIRMIPDEPENDENCYCHANGE Indicates that the change in IP address resource
dependency type for the SQL Server multi-subnet
failover cluster is accepted.
CTLRSTARTUPTYPE The startup type for the Distributed Replay
Controller service.
CTLRSVCACCOUNT The account used by the Distributed Replay
Controller service.
CTLRSVCPASSWORD The password for the Distributed Replay
Controller service account.
CTLRUSERS The Windows account(s) used to grant permission
to the Distributed Replay Controller service.
ENABLERANU Set to "1" to enable RANU for SQL Server Express.
ENU Detailed help for command line argument ENU has
not been defined yet.
ERRORREPORTING Specify if errors can be reported to Microsoft to
improve future SQL Server releases. Specify 1 or
True to enable and 0 or False to disable this
FAILOVERCLUSTERDISKS Specifies a cluster shared disk to associate with
the SQL Server failover cluster instance.
FAILOVERCLUSTERGROUP Specifies the name of the cluster group for the
SQL Server failover cluster instance.
FAILOVERCLUSTERIPADDRESSES Specifies an encoded IP address. The encodings
are semicolon-delimited (;), and follow the
format ;
mask>. Supported IP types include DHCP, IPV4, and
FAILOVERCLUSTERNETWORKNAME Specifies the name of the SQ LServer failover
cluster instance. This name is the network name
that is used to connect to SQL Server services.
FAILOVERCLUSTERROLLOWNERSHIP Specifies whether the upgraded nodes should take
ownership of the failover instance group or not.
Use 0 to retain ownership in the legacy nodes, 1
to make the upgraded nodes take ownership, or 2
to let SQL Server Setup decide when to move
FEATURES Specifies features to install, uninstall, or
upgrade. The list of top-level features include
SQL, AS, RS, IS, MDS, and Tools. The SQL feature
will install the Database Engine, Replication,
Full-Text, and Data Quality Services (DQS)
server. The Tools feature will install Management
Tools, Books online components, SQL Server Data
Tools, and other shared components.
FILESTREAMLEVEL Level to enable FILESTREAM feature at (0, 1, 2 or
FILESTREAMSHARENAME Name of Windows share to be created for
FTSVCACCOUNT User account for Full-text Filter Daemon Host.
FTSVCPASSWORD User password for Full-text Filter Daemon Host
FTUPGRADEOPTION Full-text catalog upgrade option.
HELP Displays the command line parameters usage
IACCEPTSQLSERVERLICENSETERMS By specifying this parameter and accepting the
SQL Server license terms, you acknowledge that
you have read and understood the terms of use.
INDICATEPROGRESS Specifies that the detailed Setup log should be
piped to the console.
INSTALLSHAREDDIR Specify the root installation directory for
shared components. This directory remains
unchanged after shared components are already
INSTALLSHAREDWOWDIR Specify the root installation directory for the
WOW64 shared components. This directory remains
unchanged after WOW64 shared components are
already installed.
INSTALLSQLDATADIR The Database Engine root data directory.
INSTANCEDIR Specify the instance root directory.
INSTANCEID Specify the Instance ID for the SQL Server
features you have specified. SQL Server directory
structure, registry structure, and service names
will incorporate the instance ID of the SQL
Server instance.
INSTANCENAME Specify a default or named instance. MSSQLSERVER
is the default instance for non-Express editions
and SQLExpress for Express editions. This
parameter is required when installing the SQL
Server Database Engine (SQL), Analysis Services
(AS), or Reporting Services (RS).
ISSVCACCOUNT Either domain user name or system account.
ISSVCPASSWORD Password for domain user.
ISSVCSTARTUPTYPE Automatic, Manual or Disabled.
NPENABLED Specify 0 to disable or 1 to enable the Named
Pipes protocol.
PID Specify the SQL Server product key to configure
which edition you would like to use.
QUIET Setup will not display any user interface.
QUIETSIMPLE Setup will display progress only, without any
user interaction.
ROLE Detailed help for command line argument ROLE has
not been defined yet.
RSCATALOGSERVERINSTANCENAME The SQL Server server for the report server
catalog database.
RSINSTALLMODE RSInputSettings_RSInstallMode_Description
RSSHPINSTALLMODE RSInputSettings_RSInstallMode_Description
RSSVCACCOUNT Specify the service account of the report server.
This value is required. If you omit this value,
Setup will use the default built-in account for
the current operating system (either
NetworkService or LocalSystem). If you specify a
domain user account, the domain must be under 254
characters and the user name must be under 20
characters. The account name cannot contain the
following characters:
" / \ [ ] : ; | = , + * ?
RSSVCPASSWORD Specify a strong password for the account. A
strong password is at least 8 characters and
includes a combination of upper and lower case
alphanumeric characters and at least one symbol
character. Avoid spelling an actual word or name
that might be listed in a dictionary.
RSSVCSTARTUPTYPE Specifies the startup mode for the Report Server
service. Valid values include Manual, Automatic,
and Disabled. The default value for StartupType
is Manual, where the server is started when a
request is received.
RSUPGRADEDATABASEACCOUNT RSInputSettings_RSInstallMode_Description
RSUPGRADEPASSWORD RSInputSettings_RSInstallMode_Description
RULES Specifies the list of rule IDs or rule group IDs
to run.
SAPWD Password for SQL Server sa account.
SECURITYMODE The default is Windows Authentication. Use "SQL"
for Mixed Mode Authentication.
SQLBACKUPDIR Default directory for the Database Engine backup
SQLCOLLATION Specifies a Windows collation or an SQL collation
to use for the Database Engine.
SQLSVCACCOUNT Account for SQL Server service: Domain\User or
system account.
SQLSVCPASSWORD A SQL Server service password is required only
for a domain account.
SQLSVCSTARTUPTYPE Startup type for the SQL Server service.
SQLSYSADMINACCOUNTS Windows account(s) to provision as SQL Server
system administrators.
SQLTEMPDBDIR Directory for Database Engine TempDB files.
SQLTEMPDBLOGDIR Directory for the Database Engine TempDB log
SQLUSERDBDIR Default directory for the Database Engine user
SQLUSERDBLOGDIR Default directory for the Database Engine user
database logs.
SQMREPORTING Specify that SQL Server feature usage data can be
collected and sent to Microsoft. Specify 1 or
True to enable and 0 or False to disable this
TCPENABLED Specify 0 to disable or 1 to enable the TCP/IP
UIMODE Parameter that controls the user interface
behavior. Valid values are Normal for the full
UI,AutoAdvance for a simplied UI, and
EnableUIOnServerCore for bypassing Server Core
setup GUI block.
UpdateEnabled Specify whether SQL Server Setup should discover
and include product updates. The valid values are
True and False or 1 and 0. By default SQL Server
Setup will include updates that are found.
UpdateSource Specify the location where SQL Server Setup will
obtain product updates. The valid values are "MU"
to search Microsoft Update, a valid folder path,
a relative path such as .\MyUpdates or a UNC
share. By default SQL Server Setup will search
Microsoft Update or a Windows Update service
through the Window Server Update Services.
X86 Specifies that Setup should install into WOW64.
This command line argument is not supported on an
IA64 or a 32-bit system.

Full unattended installation example, showing all required parameters:

/AGTSVCACCOUNT="MyDomain\MyAccount" /AGTSVCPASSWORD="************"
/ASSVCACCOUNT="MyDomain\MyAccount" /ASSVCPASSWORD="************"
/RSSVCACCOUNT="MyDomain\MyAccount" /RSSVCPASSWORD="************"
/ISSVCAccount="MyDomain\MyAccount" /ISSVCPASSWORD="************"

Answer files are still supported, so you can specify /ConfigurationFile on the command line and then use an answer file to set most of the other options, or set them on the command line. E.g. the answer file for a fairly default install would be:


Save it as %TEMP%\SQL2012.ini and then run:

setup.exe /ConfigurationFile=%TEMP%\SQL2012.ini

I tend to put the passwords on the command line, to avoid having them sitting around in temporary files (same for PIDKEY).

Useful links:

Configuration file syntax
Configuration parameters

Modifying embedded properties in WMI using PowerShell

This isn’t immediately obvious. Say you have a WMI class, e.g. SMS_SCI_Component from the SCCM WMI provider (root\SMS\site_XXX). You can obtain a PowerShell object representing the various instances of this class easily enough:

$SiteCode = "XXX"
$WmiObjectNamespace = "root\SMS\site_$($SiteCode)"
$WmiObjectClass = SMS_SCI_Component
$WmiObjectFilter = "ComponentName='SMS_AD_SECURITY_GROUP_DISCOVERY_AGENT'"

$WmiObject = Get-WmiObject -Namespace $WmiObjectNamespace -Class $WmiObjectClass -Filter $WmiObjectFilter

$WmiObject will now be an instance of the [System.Management.ManagementObject] class, with properties similar to:

PS S:\SCCM2012> $WmiObject

__GENUS : 2
__CLASS : SMS_SCI_Component
__SUPERCLASS : SMS_SiteControlItem
__DYNASTY : SMS_BaseClass
__DERIVATION : {SMS_SiteControlItem, SMS_BaseClass}
__NAMESPACE : root\SMS\site_D71
__PATH : \\DEVXX-CM01\root\SMS\site_D71:SMS_SCI_Component.FileType=2,ItemName="SMS_AD_SECURITY_GROUP_DISCOVER
FileType : 2
Flag : 2
ItemType : Component
Name : DEVXX-CM01.DEVXX.local
PropLists : {AD Accounts:test2, AD Attributes, AD Containers, Search Bases:blah...}
Props : {Days Since Last Logon, Days Since Last Password Set, Discover DG Membership, Enable Filtering Expir
ed Logon...}
SiteCode : XXX

Pretty much everything in SCCM WMI is like this, an object with a list of embedded SMS_EmbeddedPropertyList objects.

Accessing these is fairly simple, just access the PropLists member of the $WmiObject instance. E.g. to remove one:

$Name = "Testing"
$PropListName = "Search Bases:$($Name)"

# Apply filter
$proplists = $WmiObject.PropLists
$proplists = $proplists | where {$_.PropertyListName -ne $PropListName}

# Finally write changes back to the object
$WmiObject.PropLists = $proplists
$WmiObject.put() > $null

But how about adding one? Well we need to create an instance of an SMS_EmbeddedPropertyList and then add it to the parent object’s list. To create an instance we use:

$new = [WmiClass] "$WmiObjectNamespace:SMS_EmbeddedPropertyList"
$embeddedproperylist = $new.CreateInstance()

This will give you an instance of the [System.Management.ManagementObject] class with the following properties:

PS S:\SCCM2012> $embeddedproperylist

__GENUS : 2
__CLASS : SMS_EmbeddedPropertyList
__DYNASTY : SMS_EmbeddedPropertyList
__PATH :
ItemType :
PropertyListName :
Values :

So you fill in the required parameters, and then add it to the $proplists array for writing back…

$embeddedproperylist.PropertyListName = "testname"
$embeddedproperylist.Values = @("value1", "value2")

$WmiObject.PropLists += $embeddedproperylist



PS S:\SCCM2012> $WmiObject.PropLists += $embeddedproperylist
Exception setting "PropLists": "Unable to cast object of type 'System.Management.Automation.PSObject' to type 'System.M
At line:1 char:12
+ $WmiObject. <<<< PropLists += $epl
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException

It seems that if you make any modifications to the instance it can no longer automatically convert it into its base type for writing back to WMI. The trick is to perform the cast manually:

$embeddedproperylist = [System.Management.ManagementBaseObject] $embeddedproperylist

$WmiObject.PropLists += $embeddedproperylist