Elsewhere

I need to enable/ disable the Windows Firewall on a Server 2008R2 core box but didn’t know what the Windows Firewall service name was for use with the sc command. Then I learnt it it has a sub-command called GetKeyName (and corresponding GetDisplayName, for the reverse operation) to get the name from the display name.

1

2

3

C:\>scgetkeyname"Windows Firewall"

[SC]GetServiceKeyNameSUCCESS

Name=MpsSvc

Nice!

Also, as a reminder to myself the sc config command is what you use to change the configuration of a service (make it disabled, manual, etc). When giving the options though be sure to include a space after the option. That is to say, the following works –

Had to update some of my Windows Server Core servers. Just writing these as a note to my future self.

The Windows Update command is wuauclt. I can never get that command name (except that it starts with “wu”, short for “Windows Update”) so I always go into c:\windows\system32 and type “wu” followed by a couple of TABs).

The command doesn’t have any output or help switches. Here’s a post with a list of switches. In my experience none of the switches return any output, even if you enter the wrong switch. Some of the legit switches like /showWindowsUpdate and /showWUAutoScan return an error on Server Core – possibly because the UI doesn’t exist.

To check for new updates the following switch works: /detectNow.

To update the WSUS server with the client’s status the following switch supposedly works: /r /ReportNow.

Windows Update has a log file located at c:\Windows\WindowsUpdate.log. It’s a useful file. For instance, after I applied a policy to change all my domain servers to point to the new WSUS server I could browse this log file to see the results. I could also see on my Server Core installs an error along these lines: “Can not perform non-interactive scan if AU is interactive-only”. This error is because I had set the Windows Update GPOs to be interactive but Server Core didn’t have a GUI for interactive operations.

For Server Core the easiest way to check for updates is via SConfig. Open it and select option 6 (Download and Install Updates). This just runs another script – located in c:\Windows\System32\en-US – called WUA_SearchDownloadInstall.vbs. So one could really run a command like this on Server Core:

This post is about setting up a Server 2012 R2 failover cluster that acts as an iSCSI target server.

I have four servers: WIN-DATA01, WIN-DATA02, WIN-DATA03, WIN-DATA04. I will be putting WIN-DATA03 & WIN-DATA04 in the cluster. As you know clusters required shared storage so that’s what WIN-DATA01 and WIN-DATA02 is for. In a real world setup WIN-DATA01 & WIN-DATA02 are your SAN boxes whose storage you want to make available to clients. Yes you could have clients access the two SAN boxes directly, but by having a cluster in between you can provide failover. Plus, Windows now has a cool thing called Storage Pools which let you do software RAID sort of stuff.

Prepare the iSCSI target server

First step, prepare the iSCSI target servers that will provide storage for the cluster. The steps for this are in my previous post so very briefly here’s what I did:

Repeat the above for the other server (you can login to that server and issue commands, or do remotely like I did below). Everything’s same as above except for the addition of the -ComputerName switch.

Add shared storage to the servers

Here we add the two iSCSI targets created above to the two servers WIN-DATA03 & WIN-DATA04.

Login to one of the servers, open Server Manager > Tools > iSCSI Initiator.

Easiest option is to enter WIN-DATA01 in the Target field and click Quick Connect. That should list the targets on this server in the Discovered targets box. Select the ones you want and click Connect.

Another option is to go to the Discovery tab.

Click Discover Portal, enter the two server names (WIN-DATA01, WIN-DATA02), refresh (if needed), and then the first tab will automatically show all targets on these two servers. Select the ones you want and click Connect as before.

The GUI sets these connections as persistent (it calls them “Favorite Target”) so they are always reconnected when the server reboots.

You can also use PowerShell to add these connections though that isn’t as easy as this point and click. Instructions are in my earlier post so here they are briefly:

Unlike the GUI, PowerShell does not mark these targets as persistent so I have to specify that explicitly when connecting.

Prepare the shared storage

The shared storage we added is offline and needs to be initialized. You can do this via the Disk Management UI or using PowerShell as below. The initializing bits need to be done on any one server only (WIN-DATA03 or WIN-DATA04) but you have to make the disks online on both servers.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

PS>get-disk

Number Friendly Name OperationalStatus Total Size Partition Style

-------------------------------------------------------------

0VMware,VMware VirtualSSCSI Disk De...Online60GB MBR

2MSFT Virtual HD SCSI Disk Device Offline60GB RAW

1VMware,VMware VirtualSSCSI Disk De...Online60GB MBR

3MSFT Virtual HD SCSI Disk Device Offline60GB RAW

PS>Set-Disk-Number2-IsOffline$false

PS>Set-Disk-Number3-IsOffline$false

PS>Initialize-Disk-Number2-PartitionStyleMBR

PS>Initialize-Disk-Number3-PartitionStyleMBR

Create the cluster

Login to one of the servers that will form the cluster, open Server Manager, go to Tools > Failover Cluster Manager and click Create Cluster on the right side (the Actions pane). This launches the Create Cluster Wizard.

Click Next on the first screen, enter the server names on the second …

… do or don’t do the validation tests (I skipped as this is a lab setup for me), give a name for the cluster and an IP address, confirm everything (I chose to not add all eligible storage just so I can do that separately), and that’s it.

Couple of things to note here:

If your cluster servers don’t have any interfaces with DHCP configured, you will also be prompted for an IP address. Otherwise a DHCP address is automatically assigned. (In my case I had an interface with DHCP).

A computer object with the cluster server name you specify is created in the same OU as the servers that make up the cluster. You can specify a different OU by giving the full name as the cluster name – so in the example above I would use “CN=WIN-CLUSTER01,OU=Clusters,OU=Server,DC=rakhesh,DC=local” to create the object in the Clusters OU within the Servers OU. Would have been good if the wizard mentioned that.

Later, when you add roles to this cluster server, it creates more virtual servers automatically. These are placed in the same OU where the cluster server object is so you must give this object rights to add/ remove computers in that OU. So it’s best you have a separate OU which you can delegate rights to. I used the Delegation Control Wizard to give the WIN-CLUSTER01 object full control over Computer Objects in the rakhesh.local/Servers/Clusters OU.

Instead of the Create Cluster Wizard one can use PowerShell as below:

1

2

3

4

5

6

7

8

# skip the -NoStorage switch to automatically add storage

# specify a full name for the cluster name if you want to place in a different OU

Configuring the cluster

A cluster has many resources assigned to it. Resources such as disks, networks, and its name. These can be seen in the summary page of the cluster or via PowerShell.

1

2

3

4

5

6

7

# if you have many clusters specify the -Cluster <clustername> switch here

PS>Get-ClusterResource

Name State OwnerGroup ResourceType

-------------------------------

Cluster IP Address Online Cluster GroupIP Address

Cluster Name Online Cluster GroupNetwork Name

Network

I am interested in changing the IP address of my cluster. Currently it’s taken an IP from the DHCP pool and I don’t want that. Being a lab setup both my servers had a NAT interface to connect to the outside world and so the cluster is currently picking up an IP from that. I want it to use the internal network instead.

If I right click on IP address resource I can change it.

In my case I don’t want to use this network itself so I have to go to the Networks section in the UI …

… where I can see there are two networks specified, with one of them having no cluster use while the other is configured for cluster & client use, so I right click on the first network and …

… enable it for cluster access, then I right click on the second network and …

… rename it (for my reference) as well as disable it from the cluster.

Now if I go to the resources section and right click the IP address, I can select the second network and assign a static IP address.

Here’s how to do the above via PowerShell.

To change the network name use the Get-ClusterNetwork to select the network you want (the result is an object) and directly assign the new name as a value:

One would expect to be able to set IP addresses too via this, but unfortunately these are read-only properties (notice it only has the get method; properties which you can modify will also have the set method):

WARNING:The properties were stored,but not all changes will take effect untilCluster IP Address is taken offline and then online again.

To take the Cluster IP Address resource offline & online use the Stop-ClusterResource and Start-ClusterResource cmdlets:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

PS>Stop-ClusterResource"Cluster IP Address"

Name State OwnerGroup ResourceType

-------------------------------

Cluster IP Address Offline Cluster GroupIP Address

PS>Start-ClusterResource"Cluster IP Address"

Name State OwnerGroup ResourceType

-------------------------------

Cluster IP Address Online Cluster GroupIP Address

PS>Get-ClusterResource-Name"Cluster IP Address"|Get-ClusterParameter

ObjectName Value Type

-------------------

Cluster IP Address Network Cluster Network String

Cluster IP Address Address10.50.0.51String

Cluster IP Address SubnetMask255.255.255.0String

Cluster IP Address EnableNetBIOS1UInt32

Cluster IP Address OverrideAddressMatch0UInt32

Cluster IP Address EnableDhcp0UInt32

Cluster IP Address ProbePort0UInt32

Cluster IP Address ProbeFailureThreshold0UInt32

Cluster IP Address LeaseObtainedTime1/1/000112:00:00AM DateTime

Cluster IP Address LeaseExpiresTime1/1/000112:00:00AM DateTime

Cluster IP Address DhcpServer255.255.255.255String

Cluster IP Address DhcpAddress0.0.0.0String

Cluster IP Address DhcpSubnetMask255.0.0.0String

Although it doesn’t say so, you have to also stop and start the Cluster Name resource for the name to pick up the new IP address.

1

2

3

4

5

6

7

8

9

10

11

12

PS>Stop-ClusterResource"Cluster Name"

Name State OwnerGroup ResourceType

-------------------------------

Cluster Name Offline Cluster GroupNetwork Name

PS>Start-ClusterResource"Cluster Name"

Name State OwnerGroup ResourceType

-------------------------------

Cluster Name Online Cluster GroupNetwork Name

Lastly, to change whether a particular network is used for cluster communication or not, one can do the same technique that was used to change the host name. Just use the Role property. I am not sure what the values for it are, but from my two networks I can see that a value of 0 means it is not used for cluster communication, while a value of 3 means it is used for cluster communication and client traffic.

1

2

3

4

5

6

PS>Get-ClusterNetwork|ftName,Role

Name Role

--------

Cluster Network3

NAT Network0

The GUI is way easier than PowerShell for configuring this network stuff!

Storage (Disks)

Next I want to add disks to my cluster. Usually all available disks get added by default, but in this case I want to do it manually.

Right click Failover Cluster Manager > Storage > Disk and select Add Disk. This brings up a window with all the available disks. Since this is a cluster not every disk present on the system can be used. The disk must be something visible to all members of the cluster as it is shared by them.

Via PowerShell:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

PS>Get-ClusterAvailableDisk

Name:Cluster Disk1

Number:2

Size:64424509440

Id:0x9B9C9B12

Cluster:WIN-CLUSTER01

Partitions:{}

Name:Cluster Disk2

Number:3

Size:64424509440

Id:0x9B9C9B17

Cluster:WIN-CLUSTER01

Partitions:{}

To add these disks to the cluster pipe the output to the Add-ClusterDisk cmdlet. There’s no way to select specific disks so you must either pipe the output to a Where-Object cmdlet first to filter the disks you want, or use the Get-Disk cmdlet (as it lets you specify a disk number) and pipe that to the Add-ClusterDisk cmdlet.

(I won’t be adding these disks to my cluster yet as I want to put them in a storage pool. I’ll be doing that in a bit).

Quorum

Quorum is a very important concept for clusters (see an earlier post of mine for more about quorum).

1

2

3

4

5

6

PS>Get-ClusterQuorum|fl*

Cluster:WIN-CLUSTER01

QuorumResource:

QuorumType:NodeMajority

The cluster which I created is currently in the Node Majority mode. (Because I haven’t added and Disk or File Share witnesses to it). That’s not a good mode to be in so let’s change that.

Go to the Configure Cluster Quorum Settings as in the screenshot below, click Next …

… choose the second option (Select the quorum witness) and click Next …

… in my case I want to use a File Share witness so I choose that option and click Next …

… create a file share someplace, point to that, and click Next …

… click Next and then Finish.

Now it’s configured.

1

2

3

4

5

6

PS>Get-ClusterQuorum|fl*

Cluster:WIN-CLUSTER01

QuorumResource:File Share Witness

QuorumType:NodeAndFileShareMajority

Storage (Pool)

(If you plan to create a storage pool add an extra shared disk to your cluster. I created a new target on the WIN-DATA02 & WIN-DATA01 server (no need for doing on both but I just did so it’s consistent), mapped another virtual disk to it, and used the iSCSI initiator on WIN-DATA03 & WIN-DATA04 to map it. Storage Pools on Failover Clusters require a minimum of three disks).

I want to use Storage Spaces (they are called Storage Pools in Failover Cluster Manager). Storage Spaces is a new feature in Server 2012 (and Windows 8) and it lets you combine disks and create virtual disks on them that are striped, mirrored, or have parity (think of it as software RAID).

We can create a new Storage Pool by right clicking on Failover Cluster Manager > Storage > Pools and select New Storage Pool.

Click Next, give the Pool a name …

… select the disks that will make up the pool (notice that the disks shown below are the iSCSI disk that are visible to both nodes; neither disk is actually on the local computer, they are both from a SAN box someplace (in this case the WIN-DATA01 & WIN-DATA02 servers from where we created these before) …

… and click Create.

Right click on the pool that was created and make virtual disks on that. These virtual disks are software RAID equivalents. (The pool is a placeholder for all your disks. The virtual disks are the logical entities you create out of this pool). Here’s the confirmation page of the pool I created:

Once the disk is created, be sure to not uncheck the “Create a volume when this wizard closes” check box. If you did uncheck, you’ll have to go to Server Manager > File and Storage Services > Volumes, click on TASKS and select New Volume. The virtual disk is just a disk, what we have to do now is create volumes on it.

Below is a screenshot of the volume I created. I chose ReFS for no particular reason, and assigned the full space to the volume. Also, the screenshot shows that I didn’t assign a drive letter. That’s incorrect. I did just that I forgot to do that when taking this screenshot. (Note that I assigned the drive letter R. This will be used later).

As with the GUI, once the disk is created a cmdlet has to be run to create a volume on the disk. It’s probably the New-Volume cmdlet, but it’s throwing errors in my case and I am too tired to investigate further so I’ll skip it for now.

Add Roles

Click Next, select iSCSI Target Server, and click Next. This steps assumes the iSCSI Target Server role is installed on both nodes of the cluster. If not, install it via Server Manager or PowerShell.

Give the role (the virtual server that hosts the role) a name and IP address …

… select storage (the previously created volume; if you missed out on creating the volume go back and do it now), click Next, Next, and that’s it.

At this point it’s worth taking a step back to understand what we have done. What we did just now is create a virtual server (a role in the cluster actually) and assigned it some storage space. One might expect this storage to be the one that’s presented by the iSCSI server as a target, but no, that’s not the case. Think of this server and its storage as similar to the WIN-DATA01 and WIN-DATA02 servers that we dealt with initially. What did we do to set these as an iSCSI target? We created a target, created virtual iSCSI disks, and assigned mappings to them. That’s exactly what we have to do here too!

Ideally one should be able to use the GUI and do this, but Server Manager seems to have trouble communicating with the newly created WIN-DATA server. So I’ll use PowerShell instead.

And that’s it! Now I can add this target back to the WIN-DATA01 & WIN-DATA02 servers if I want (as those are the Initiator IDs I specified) and whatever I write will be written back to their disks via this clustered iSCSI target. I am not sure if the mirroring will happen across both servers though, but this is all just for fun anyways and not a real life scenario.

Lastly …

Before I conclude here’s something worth checking out.

The WIN-DATA virtual server is currently on the WIN-DATA04 node. This means WIN-DATA04 is the one who is currently providing this role, WIN-DATA03 is on standby.

If I login to WIN-DATA04 and check its disks I will see the mirrored volume I created:

If I right click on the role in Failover Cluster Manager, select Move > Select Node, and select the new node as WIN-DATA03, then this becomes the new active node. Now if I check the volumes and disks of both servers the information will be the other way around. WIN-DATA03 will have the volume and disk, WIN-DATA04 won’t have anything!

This is how clustering ensures both servers don’t write to the shared storage simultaneously. Remember, the shared storage is just a block device. It doesn’t have any file locking nor is it aware of who is writing to it. So it’s up to the cluster to take care of all this.

Also …

Be sure to add WIN-CLUSTER01 and WIN-DATA to DNS with the correct IPs. If you don’t do that Server Manager and other tools won’t be able to resolve the name.

There’s more …

This post is just a tip of the iceberg. There’s so many more cool things you can do with iSCSI, Clustering, and Storage Spaces in Server 2012 so be sure to check these out elsewhere!

When creating the target it is very important to specify the initiator IDs. The cmdlet doesn’t prompt for these if you don’t mention (unlike the UI which doesn’t go ahead unless initiator IDs are specified). If the initiator IDs are missing no one can see this target.

Initiator IDs can be specified via IQNs, IP addresses, IPv6 addresses, DNS name, and MAC addresses. Notice the ‘IPN:xxx’ bit above? Replace IQN with IPAddress, IPv6Address, DNSName, and MACAddress if you are specifying initiator IDs using these, followed by the address or name. For instance:

If there’s only one initiator ID it can be specified as it is. If there multiple, separate them with commas. There’s no need to put them inside @(…) as above – that’s just to make it explicit to the reader that the input is an array. Separating by commas will have the same effect irrespective of the @(…) notation.

It’s also worth pointing out that if multiple initiators are allowed to access a target, they will all be able to read/write to the target, but expect corruption. There are exceptions of course.

Create an iSCSI virtual disk which will back the LUN presented by the target.

Update: Rename the computer & join the domain (thanks to Daniel Streefkerf (check out his blog, if you like my blog posts you’ll surely enjoy his!) for pointing this out – since PowerShell 3.0 the Add-Computer cmdlet has a -NewName switch that lets you rename and add/ move a computer):

I have a Server Core 2012 that has two BitLocker encrypted disks on it. When I encrypted those disks the server had the full GUI but after I converted to Core there’s obviously no GUI to just double click and be prompted for a password etc. So need to use the command line tools.

There seems to be two ways.

First are the BitLocker command line tools. Manage-bde looks like the most useful command here. Using this one can see the status of all the drives on the machine, lock, unlock, set auto-lock auto-unlock, and also turn on or off BitLocker encryption on a drive.

Typing manage-bde in the command prompt gives you all the options. Each of these options have further switches which you can discover by typing manage-bde <option-name> -?.

To view the status of all drives on the machine:

1

C:\>manage-bde-status

To unlock an encrypted drive (with drive letter D:) to use with the system:

1

C:\>manage-bde-unlockD:-pw

I use passwords, hence the -pw switch. If you use recovery keys or certificates there are switches for that too. manage-bde prompts for a password and unlocks the drive, mounting it on the specified drive letter.

To set the drive (with drive letter D:) as auto-unlocked:

1

C:\>manage-bde-autounlock-enableD:

That’s all. From now on the drive will be automatically unlocked when attached to the system.

The syntax for disabling auto-unlock and locking a drive are pretty obvious from the examples above. The thing to remember is you always specify the manage-bde command followed by a dash switch specifying what you want to do, and after that you specify the drive letter.

There are two other commands: Repair-Bde for repairing corrupted BitLocker encrypted drives and BdeHdCfg for setting up a drive with BitLocker encryption (though it doesn’t seem to be required any more as Manage-Bde includes some of this functionality).

Apart from the BitLocker command line tools you can also manage BitLocker via PowerShell. This is only for Windows 8/ Windows Server 2012 and is available via the BitLocker module (requires RSAT on Windows 8).

To view the available drives on a system and their BitLocker status do:

1

PS>Get-BitLockerVolume

You can also check the status of a specific drive with the above cmdlet by passing it the drive letter with the -MountPath switch.

The cmdlet does not prompt for a password. You have to pass it via the -Password switch. You can’t pass the password as plain text either, so have to convert it to a secure string. Use the ConvertTo-SecureString cmdlet for that or just use Read-Host and convert the inputted text to secure string on the fly.

To set auto-unlock on a drive (with letter D:) do:

1

PS>Enable-BitLockerAutoUnlock-MountPointD:

Similar cmdlets exist for locking and auto-locking drives.

After writing this post I discovered a TechNet article that goes into more detail on the above command line tools and cmdlets. Go check it out.

setx is built into cmd.exe. It can be used to make changes to a remote computer too.

setx modifies the “persistent” store though, not the “active” store (to borrow a terminology from netsh. What this means is that the changes by setx only take place when you open a new command prompt, it doesn’t affect the existing one.

After writing yesterday’s post I wondered what switches DISM would have to install a new feature from a specified source. I played around a bit with DISM and realized that the version (6.2.9200.16384) in Server 2012 has more features compared to the version (6.1.7600.16385) in Server 2008. I haven’t obviously explored them all out, but as and when I do I’ll make subsequent posts to document them.

An interesting new feature that stands out for me is the fact that the /enable-feature switch now supports an /all switch that automatically installs all the needed dependency features.

Arequired parent feature may not be enabled.You can use the/enable-feature/all option to automatically enable each parent feature from the following list.Ifthe parent feature(s)are already enabled,refer to the log file forfurther diagnostics.

NetFx3ServerFeatures

The DISM log file can be found atC:\Windows\Logs\DISM\dism.log

Unfortunately the /disable-feature doesn’t have a corresponding switch to remove all the automatically installed dependencies so be sure to keep track of these.

The /disable-feature does have a /remove switch though which can be used to disable a package and remove all its binaries. This is one step ahead of what the /disable-feature in the previous DISM version offers. There you could only disable the feature but the binaries (the installed files) would still be on the system; now you have an option to remove them too.

Features whose binaries are thus removed (or were never installed in the first place) are marked differently when you use /get-features:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

C:\Users\Administrator.CONTOSO>dism/online/get-features|more

Deployment Image Servicing and Management tool

Version:6.2.9200.16384

Image Version:6.2.9200.16384

Features listing forpackage:Microsoft-Windows-ServerCore-Package~31bf3856ad364e35~amd64~~6.2.9200.16384

Feature Name:NetFx3ServerFeatures

State:Disabled

Feature Name:NetFx3

State:Disabled with Payload Removed

...

Feature Name:AdminUI

State:Disabled with Payload Removed

...

Note the “Disabled with Payload Removed” status.

If you are trying to install a feature whose binaries (the payload) are not present /enable-features complains about that. You can use the /Source switch to specify a source for these binaries.

Use the"source"option to specify the location of the files that are required to restore the feature.Formore information on specifyingasource location,see http://go.microsoft.com/fwlink/?LinkId=243077.

The DISM log file can be found atC:\Windows\Logs\DISM\dism.log

The /Source switch must point to a path similar to the one required by the -Source switch of the Add-WindowsFeature (see my previous blog post or this TechNet article). It must be the C:\Windows folder in a WIM file image or on a running Windows installation anywhere else on the network.

I think I’ll stick to DISM instead of PowerShell for a while while managing features. PowerShell has a DISM module now and hence a subset of the DISM commands, but it’s easier working with DISM exclusively for these sort of tasks as DISM has more features and eventually you will need to depend on DISM for some of these features (managing WIM images, for instance) and so I feel sticking with it exclusively will help breed more familiarity with DISM.

DISM mounted images are persistent across reboots so be sure to /unmount-wim them. You can get a list of mounted WIM images via the /get-mountedwiminfo switch.

The /discard switch is required while un-mounting to tell DISM it doesn’t need to save any changes (not that we made any changes in this case, but one could potentially make changes and save them using DISM). If you wanted to save changes instead use the /commit switch.

Inspired by this great post on improvements in Windows Server 2012 I decided to give MinShell a go.

Unlike that post, however, I was starting from Server Core and wanted to add on MinShell (not start with Server regular and remove the additional components to be left with just MinShell). Not a problem, PowerShell can be used to install the “Graphical Management Tools and Infrastructure” feature.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

PSC:\>Add-WindowsFeatureServer-Gui-Mgmt-Infra

Add-WindowsFeature:The request to add or remove features on the specified server failed.

Installation of one or more roles,role services,or features failed.

The source files could not be downloaded.

Use the"source"option to specify the location of the files that are required to restore the feature.Formore

In retrospect this is not surprising. It happens because (obviously) the binaries for the Server Manager GUI bits are not present in the installed system and so one must point the Add-WindowsFeature cmdlet to a source where it can get these from.

Had it been a non-GUI feature such as DNS or DHCP, the binaries would already be installed as part of Server 2012 Core – but not enabled – and so all the cmdlet needed to do would be to enable the feature. (However: if it were a non-GUI feature whose binaries were removed via the Uninstall-WindowsFeature cmdlet with the –Remove switch, then we would have had to point Add-WindowsFeature to a source if we wanted to install these features later).

The Add-WindowsFeature cmdlet has a –Source switch which lets you specify a path from where it can pick up the binaries. This must point to the c:Windows folder and that’s where the binaries are copied over from. If you have another Windows Server 2012 (non-Core) you can share its c:Windows folder and point –Source to that. Or you can mount the Windows Server 2012 (non-Core) install image from WIM file in the installation DVD and point –Source to that. If you have the WIM file from the installation DVD on a network location, you can also point to the Windows Server 2012 (non-Core) install image in that by prefixing the path with WIM: like this: –Switch wim:pathtowimfile.wim:2 (where 2 is the index of the image in this WIM file).

WIM files are sort of like containers for disk images. A single WIM file can contain many disk images – often with overlapping files – and so the size of the WIM file isn’t necessarily equal to the size of all the disk images combined. It is also a file based disk image format – meaning the images contain the actual file system and files within, not just binary data like a sector based format (such as ISO or VHD files). This is why you can actually “mount” an image from the Windows Server 2012 DVD on a folder and then browse this image as a regular file system – because it is a regular file system! The Windows installation DVDs usually contain the installation WIM file – called install.wim – in the Sources folder.

The DISM (Deployment Image Servicing and Management) command is your friend when it comes to WIM files. We met DISM earlier in the context of enabling/ disabling features and while it has a pretty straight-forward syntax it’s kind of ugly. Apart from enabling/ disabling features, you can also use DISM to inspect WIM files, mount the images within them, make changes to these images, and so on.

Before mounting an image in a WIM file, we need to inspect it to see what images are present. The /getwiminfo switch is your friend for that:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

C:\>dism/get-wiminfo/wimfile:z:\sources\install.wim

Deployment Image Servicing and Management tool

Version:6.2.9200.16384

Details forimage:z:\sources\install.wim

Index:1

Name:Windows Server2012SERVERSTANDARDCORE

Description:Windows Server2012SERVERSTANDARDCORE

Size:7,195,580,708bytes

Index:2

Name:Windows Server2012SERVERSTANDARD

Description:Windows Server2012SERVERSTANDARD

Size:11,999,848,937bytes

Index:3

Name:Windows Server2012SERVERDATACENTERCORE

Description:Windows Server2012SERVERDATACENTERCORE

Size:7,176,243,455bytes

Index:4

Name:Windows Server2012SERVERDATACENTER

Description:Windows Server2012SERVERDATACENTER

Size:11,995,224,677bytes

The operation completed successfully.

As you can see, there are four images in this WIM file. Two of these images are 7GB in size, two are nearly 12GB in size. So one would expect the WIM file containing these images to be around (7*2+12*2=)36GB in size, but in reality the WIM file is just 3.1GB. This is because all these images share the files within them and in addition to that the files are compressed. We want to install the “Graphical Management Tools and Infrastructure” feature which is present in the Windows Server 2012 Standard image (index : 2) and so that’s the image we are interested in.

To mount this image, create a folder and invoke DISM with the /mount-wim switch:

Mind you, DISM is very finicky when it comes to syntax. There is no space between the /wimfile: switch and its arguments; similarly no space between /mountdir and its arguments.

If we navigate to the c:\Offline folder we can see a regular file system with a Windows folder. Navigate through this and you’ll see its just like the Windows folder in a live Windows system. This is the folder we are interested in.

So back to Add-WindowsFeature we now pass the above mentioned folder via the -Source switch:

Added a Server 2012 Core machine as DC to my existing (virtual) domain today. Did it using PowerShell.

First up, add the AD-Domain-Services (and DNS if you plan on using that) features:

1

2

3

4

5

6

7

PS>Add-WindowsFeatureAD-Domain-Services,DNS

SuccessRestartNeededExitCodeFeatureResult

--------------------------------------------

TrueNoSuccess{Active Directory Domain Services,DNS Ser...

WARNING:Windows automatic updating is not enabled.To ensure that your newly-installedrole or feature is

automatically updated,turn on Windows Update.

Curious about what the Active Directory related cmdlets are? This will help:

1

2

3

4

5

6

7

8

9

10

11

12

PS>Get-Command-NounAD*|more

CommandType Name ModuleName

-------------------------

Cmdlet Add-ADCentralAccessPolicyMemberActiveDirectory

Cmdlet Add-ADComputerServiceAccountActiveDirectory

Cmdlet Add-ADDomainControllerPasswordReplicationPolicyActiveDirectory

Cmdlet Add-ADDSReadOnlyDomainControllerAccountADDSDeployment

Cmdlet Add-ADFineGrainedPasswordPolicySubjectActiveDirectory

Cmdlet Add-ADGroupMemberActiveDirectory

Cmdlet Add-ADPrincipalGroupMembershipActiveDirectory

...

Three commands are to do with installing domain controllers:

The Install-ADDSDomain cmdlet installs a new Active Directory domain configuration.

The Install-ADDSForest cmdlet installs a new Active Directory forest configuration.

The Install-ADDSDomainController cmdlet installs a domain controller in Active Directory.

In my case the Install-ADDSDomainController cmdlet is what’s of interest.

This cmdlet has many switches, some of the regularly used ones are:

-Credential to specify the credentials of the account used to install the DC. Use -Credential (Get-Credential) to be prompted for the password;

-DatabasePath (default: %SYSTEMROOT%NTDS) and -LogPath (default: %SYSTEMROOT%NTDS) and -SysvolPath (default: %SYSTEMROOT%SYSVOL) to specify the location where you want the database and log files and SYSVOL to be (%SYSTEMROOT is C:Windows usually);

-DomainName to specify the name of the domain; and

optionally -SiteName to specify a site name and -SafeModeAdministratorPassword to specify a safe mode administrator password (use this switch if you’d like to specify a password; if you skip you are prompted for a password anyways)

Once your Server Core network etc are configured it’s time to enable/ disable Windows features and roles.

To enable/ disable/ list Windows features and roles it’s probably easiest to import the ServerManager module into PowerShell and use the three cmdlets provided. But just in case you are not into PowerShell, or don’t want to install PowerShell and it’s dependency .NET (you are on Server Core and PowerShell & .NET aren’t installed by default there) there are two alternatives.

DISM

DISM is short for Deployment Image Servicing and Management. As the name suggests, it’s a tool for managing the disk image using which you deploy Windows. Starting with Windows Vista the installation files of Windows are stored in a (file based) disk image called the Windows Imaging Format (WIM). DISM is a tool that can manage this disk image before it’s deployed to a computer. But DISM is not just about managing disk images before they are deployed; it can be used also to manage a running instance of a deployed image. The latter is what we are interested here.

Disk images prior to deployment are known as offline images. Disk images that are currently running as the OS within which DISM is invoked are called online images. When you are dealing with an online image you also pass the switch /online to DISM.

DISM was introduced with Windows 7/ Windows Server 2008 R2 and has a pretty straight-forward syntax:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

C:\Users\Administrator>dism/online/?

Deployment Image Servicing and Management tool

Version:6.1.7600.16385

Image Version:6.1.7600.16385

The following commands may be used to service the image:

...

PACKAGE SERVICING COMMANDS:

/Add-Package-Adds packages to the image.

/Remove-Package-Removes packages from the image.

/Enable-Feature-Enablesaspecific feature inthe image.

/Disable-Feature-Disablesaspecific feature inthe image.

/Get-Packages-Displays information about all packages in

the image.

/Get-PackageInfo-Displays information aboutaspecific package.

/Get-Features-Displays information about all features in

apackage.

/Get-FeatureInfo-Displays information aboutaspecific feature.

/Cleanup-Image-Performs cleanup and recovery operations on the

image.

...

The switches of interest to use are /Enable-Feature, /Disable-Feature, and /Get-Features.

To get a list of available features:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

C:\Users\Administrator>dism/online/get-features/?

Deployment Image Servicing and Management tool

Version:6.1.7600.16385

Image Version:6.1.7600.16385

/Get-Features[/Format:][/PackagePath:]

[/PackageName:]

Displays information about all features found inaspecific package.Ifyou

As you can see, feature names are case sensitive (eugh!!), and DISM doesn’t automatically enable dependent features – we have to enable them ourselves (good in a way coz DISM won’t enable a whole bunch of dependencies without me realizing, but I wish there were a way to say go ahead and enable whatever’s required). In contrast, if you try enabling a feature using PowerShell with the ServerManager module, dependencies are automatically taken care of.

(Update: DISM in Windows Server 2012 and Windows 8 has a /all switch that automatically installs all the dependencies.)

The feature names are also not very intuitive – for instance to enable AD DS you need to enable the DirectoryServices-DomainController-ServerFoundation feature but that’s not very obvious coz of the ServerFoundation tacked at the end of the feature name, which makes you think it might be a scaled down version of AD DS. (Just as an aside: in the specific case of AD DS, even if you don’t enable the afore-mentioned feature yourself, dcpromo automatically enables it as part of its tasks). This TechNet article is helpful in understanding what the feature names are.

I also hate the fact the fact that there are so many switches to type, but hey, at least the names are logical and I am glad DISM doesn’t have any dependencies and works out of the box on Server Core too. PowerShell has much better switches, but you need DISM sort of to enable PowerShell and the ServerManage module features.

Apart from enabling and disabling features, it’s worth knowing that DISM can be used to upgrade between editions. Say if you are running Server Core Standard and want to move to Server Core Enterprise, DISM can do that.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

C:\Users\Administrator>dism/online/?

Deployment Image Servicing and Management tool

Version:6.1.7600.16385

Image Version:6.1.7600.16385

The following commands may be used to service the image:

WINDOWS EDITION SERVICING COMMANDS:

/Set-ProductKey-Populates the product key into the offline image.

/Get-TargetEditions-Displaysalist of Windows editions that an

image can be upgraded to.

/Get-CurrentEdition-Displays the editions of the specified image.

/Set-Edition-Upgrades the Windows image toahigher edition.

...

C:\Users\Administrator>dism/online/get-currentedition

Deployment Image Servicing and Management tool

Version:6.1.7600.16385

Image Version:6.1.7600.16385

Current edition is:

Current Edition:ServerStandardCore

The operation completed successfully.

C:\Users\Administrator>dism/online/get-targeteditions

Deployment Image Servicing and Management tool

Version:6.1.7600.16385

Image Version:6.1.7600.16385

Editions that can be upgraded to:

Target Edition:ServerDataCenterCore

Target Edition:ServerEnterpriseCore

The operation completed successfully.

Read more about DISM and upgrading images at this TechNet article and blog post.

Lastly, DISM can also be used to query the installed drivers:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

C:\Users\Administrator>dism/online/get-drivers

Deployment Image Servicing and Management tool

Version:6.1.7600.16385

Image Version:6.1.7600.16385

Obtaining list of3rdparty drivers from the driver store...

Driver packages listing:

Published Name:oem0.inf

Original File Name:vboxguest.inf

Inbox:No

Class Name:System

Provider Name:Oracle Corporation

Date:10/26/2012

Version:4.2.4.0

Published Name:oem1.inf

Original File Name:vboxvideo.inf

Inbox:No

Class Name:Display

Provider Name:Oracle Corporation

Date:10/26/2012

Version:4.2.4.0

Published Name:oem2.inf

Original File Name:netkvm.inf

Inbox:No

Class Name:Net

Provider Name:Red Hat Inc.

Date:2/13/2012

Version:61.63.103.2200

The operation completed successfully.

Unfortunately while there is a /Add-Driver switch for adding drivers, it doesn’t work against an online image.

OCSetup

OCSetup is short for Optional Components Setup. This tool was introduced in Windows Vista/ Server 2008 specifically for Server Core. Windows Vista/ Server 2008 had the new modular architecture of roles and features, along with the Server Manager tool (GUI and command line) to manage these. However, Server Manager depends on .NET which is not enabled by default on Server Core, and so the OCSetup tool was provided for Server Core. This tool has a counterpart called OCList that gets a list of the optional components.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

C:\Users\Administrator>oclist|more

Use the listed update names with Ocsetup.exe to install/uninstallaserver role or optional feature.

Adding or removing the Active Directory role with OCSetup.exe is not supported.It can leave your server inan unstable

Once you’ve identified the features you’d like, enable them using OCSetup:

1

2

3

4

5

6

7

8

9

C:\Users\Administrator>oclist|find"Cmdlets"

||---Not Installed:BestPractices-PSH-Cmdlets

||---Installed:ServerManager-PSH-Cmdlets

C:\Users\Administrator>ocsetup BestPractices-PSH-Cmdlets

C:\Users\Administrator>oclist|find"Cmdlets"

||---Installed:BestPractices-PSH-Cmdlets

||---Installed:ServerManager-PSH-Cmdlets

Similar to DISM, OCSetup too is case sensitive and doesn’t automatically install dependent features. Moreover, it doesn’t give any output. To see whether the feature was enabled, you run OCList again and verify that it’s installed.

OCSetup has a much simpler syntax than DISM, but also doesn’t have the additional features that DISM has. Moreover, DISM is a useful tool to know for creating offline images for deploying on other machines, so it’s worth familiarizing oneself with DISM.