six demon bag

Wind, fire, all that kind of thing!


Migration of SMB Shares

Share migration is a common (if not integral) part of a file server migration. If you just move the shares from one host to another host the process is pretty straightforward as described in MSKB article 125996:

  1. Export [HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Shares] on the old file server to a file:

    reg export HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Shares shares.reg
  2. Copy the file to the new file server and import it:

    reg import shares.reg
  3. Restart the Server service:

    net stop server && net start server
  4. Done.

You could also use the of the Win32_Share WMI class to enumerate the shares and re-create them using its Create() method:

# create Everyone ACL with full control using the well-known SID of the
# Everyone security principal
# <>
$trustee = ([wmiclass]'Win32_Trustee').CreateInstance()
$trustee.SID = ([wmi]"Win32_SID.SID='S-1-1-0'").BinaryRepresentation

$ace = ([wmiclass]'Win32_ACE').CreateInstance()
$ace.AccessMask = 2032127  # full control
$ace.AceFlags   = 3
$ace.AceType    = 0
$ace.Trustee    = $trustee

$sd = ([wmiclass]'Win32_SecurityDescriptor').CreateInstance()
$sd.ControlFlags = 4
$sd.DACL         = $ace

# get WMI object providing Create() method
$wmi = Get-WmiObject Win32_Share -List

# enumerate shares on old server and re-create them on the local host
# filtering on Type=0 excludes administrative shares from the list
Get-WmiObject Win32_Share -Computer oldserver -Filter 'Type=0' | % {
  $wmi.Create($_.Path, $_.Name, 0, $null, $_.Description, '', $sd) | Out-Null

Unfortunately things aren't quite as simple when the new server is actually a clustered file server. While there is a (poorly documented) WMI class Win32_ClusterShare with a Create method inherited from Win32_Share, that method simply doesn't work.

However, the new SMB share cmdlets in Windows Server 2012 provide an alternative way for creating shares on a clustered file server. You can even enable access-based enumeration while you're at it.

Get-WmiObject Win32_Share -Computer oldserver -Filter 'Type=0' | % {
  New-SmbShare -CimSession clusteredserver -Name $_.Name -Path $_.Path `
    -Description $_.Description -FolderEnumerationMode AccessBased

Why Microsoft decided to name the parameter for running the cmdlet on remote computers -CimSession when it's named -ComputerName in the cmdlets of all other modules is beyond me, though. Perhaps someone thought life would be too boring if they used the same name for the same thing all the time. Who needs consistency anyway? *sigh*

Posted 21:09 [permalink]