0

I'm trying to figure out a way to script in PowerShell the creation of multiple SMB shares on a file server with different share names pointing to different paths. What I mean is having a variable with share names I want to create and another variable to map those share names to their respective paths, example:

$ShareNames = "Share1","Share2","Share3"
$SharePaths = "C:\Temp1","C:\Temp2","C:\Temp3"

I want to be able to create the shares like so:

Share1 map to C:\Temp1    
Share2 map to C:\Temp2    
Share3 map to C:\Temp3    
and so on...

I know the command to create the SMB shares, see below, but I can't figure out how to map each share name to it's appropriate path with multiple values in each variable.

$Parameters = @{
    Name                  = $ShareName
    ScopeName             = "*"
    Path                  = $SharePath
    FolderEnumerationMode = "AccessBased"
    CachingMode           = "BranchCache"
    ContinuouslyAvailable = $true
    FullAccess            = "Everyone"
}

New-SmbShare @Parameters

I've tried using foreach statements to accomplish what I'm looking to do but just can't seem to figure out how to do the 1 to 1 mapping of share names to share paths.

1 Answer 1

1

There are two approaches depending on your needs or likes.

Stick with two variables using for

If you want to stick with two variables being mapped to each other, you can use the for statement.

But it's important to ensure both variables ($ShareNames, $SharePaths) are of type array (at least when indexing into one) using the PS array subexpression operator @()!

If they're not both of type array and one variable does only contain one string, the current index ($i) of the for iteration will be applied to an char array ([char[]]'Share1'), hence will only return the character at position of $i ('Share1'[0] → 'S' rather than @('Share1')[0] → 'Share1').

To ensure/guarantee an array, read the comments in the code as there are two options:

  1. Enclose the values before the for statement using @()
  2. Enclose the value every time in the iteration with @() (mentioned as # alternative comment in the code).
    Note: Wrapping/Casting a string as array in each iteration could be expensive (performance-wise) for a (very) large list of "Shares".
#! ensure $ShareNames is an array with the array subexpression operator @()
$ShareNames = @('Share1', 'Share2', 'Share3')
#! ensure $SharePaths is an array with the array subexpression operator @()
$SharePaths = @('C:\Temp1', 'C:\Temp2', 'C:\Temp3')

for ($i = 0; $i -lt $ShareNames.Count; $i++) {
    # try/finally to ensure no New-SmbShare gets executed in case of an error in splatting of $parameters
    try {
        $parameters = @{
            Name                  = $ShareNames[$i] # alternative to ensure an array with "@($ShareNames)[$i]"
            ScopeName             = '*'
            Path                  = $SharePaths[$i] # alternative to ensure an array with "@($SharePaths)[$i]"
            FolderEnumerationMode = 'AccessBased'
            CachingMode           = 'BranchCache'
            ContinuouslyAvailable = $true
            FullAccess            = 'Everyone'
        }

        New-SmbShare @parameters
    } finally {}
}

Using a hash table for the share mappings with foreach

No issues here with arrays and there is a clear mapping in the code.
We just need to use the .GetEnumerator() method of the hash table in the foreach statement.

$shares = @{
    #key     = value
    'Share1' = 'C:\Temp1'
    'Share2' = 'C:\Temp2'
    'Share3' = 'C:\Temp3'
}

# we need to use the .GetEnumerator() method to iterate through the hash table
foreach ($share in $shares.GetEnumerator()) {
    # try/finally to ensure no New-SmbShare gets executed in case of an error in splatting of $parameters
    try {
        $parameters = @{
            Name                  = $share.Key
            ScopeName             = '*'
            Path                  = $share.Value
            FolderEnumerationMode = 'AccessBased'
            CachingMode           = 'BranchCache'
            ContinuouslyAvailable = $true
            FullAccess            = 'Everyone'
        }

        New-SmbShare @parameters
    } finally {}
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for this ! Learned something new :). One question in your 2nd example with hash tables. In the parameters for Name and Path, is the $share.Key referencing the first value in the hash and the $share.Value referencing the 2nd value in the hash? I'm just not sure where the .Key and .Value come from. I think I like this method a little better as it more clearly defines the 1 to 1 mapping for the shares, although the 1st example is such a great technical way to do it too.
One advantage of the 1st example is I think I can incorporate a Get-Content of two separate files for the share names and paths so I wouldn't have to type everything out within the script.
@ShaynG: .Key and .Value are properties of the enumerated hash table @{key = value}. As I said, it's necessary to use .GetEnumerator() in the foreach block to enumerate a hash table. I've added a comment in the code above to show you the syntax ;)
thank you so much for this! Really helped, sincerely appreciate your time here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.