locked
Errors in New-SMBShare Script RRS feed

  • Question

  • I'm trying to automate the preparation of Server Shares but I ran into a few errors. I'm reading the information from a INI file to form a Hashtable. The variable values are referenced from the Hashtable. Here is the code:

    Get-Content -Path "C:\users\`$jstrode\Configuration2.ini" |
        foreach-object `
            -begin {
                # Create an Hashtable
                $hash=@{}
            } `
            -process {
                # Retrieve line with '=' and split them
                $key = [regex]::split($_,'=')
                if(($key[0].CompareTo("") -ne 0) -and ($key[0].StartsWith("[") -ne $True))
                {
                    # Add the Key, Value into the Hashtable
                    $hash.Add($key[0], $key[1])
                }
            } 

    ## Variables
    $i = 0
    $Server = ($hash.GetEnumerator() | Where-Object {$_.name -match "server$i"}).Value
    $Path = ($hash.GetEnumerator() | Where-Object {$_.name -match "Path$i"}).Value
    $ShareLocation = ((("\\{0}\{1}") -f $Server,$Path).replace(':','$')).replace(' ','')
    $Share = ($hash.GetEnumerator() | Where-Object {$_.name -match "Share$i"}).Value 
    $ShareRead = ($hash.GetEnumerator() | Where-Object {$_.name -match "Read$i"}).Value
    $ShareModify = ($hash.GetEnumerator() | Where-Object {$_.name -match "Modify$i"}).Value
    $ShareFullControl =  ($hash.GetEnumerator() | Where-Object {$_.name -match "FC$i"}).Value
    $NTFS_Permissions = ("Nash\UTLPLN-NAS-PROD-RW","MODIFY","Allow");("Nash\UTLPLN-NAS-PROD-RO","READ","Allow")

    #$Share = 'C_APPSTest2'
    #$Path = 'C:\Test0\Test2'

    ## Create Folder
            IF (!(test-path $path))
                    {
                        write-host "Creating folder: " $path -ForegroundColor green
                        New-Item -Path $path -ItemType directory
                    } 
                    else 
                    {
                        write-host "The folder already exists: "$path -ForegroundColor Yellow
                    }

    ## Create Share
        $Path
            IF (!(Get-SmbShare -Name $share -ErrorAction SilentlyContinue)) 
                    {
                        write-host "Creating share: " $share -ForegroundColor green
                        New-SmbShare –Name $share –Path $path –Description ‘Test Shared Folder’ –FullAccess 'administrators' –ReadAccess 'Everyone','Nash\USWF-DEV-ANNEX-MASNAC' -ChangeAccess 'Authenticated Users'
                        
                    } 
                    else 
                    {
                        write-host "The share already exists: " $share -ForegroundColor Yellow
                    }

    Output



     
    Creating folder:   C:\Test0
    New-Item : Cannot find drive. A drive with the name ' C' does not exist.
    At line:35 char:21
    +                     New-Item -Path $path -ItemType directory
    +                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : ObjectNotFound: ( C:String) [New-Item], DriveNotFoundException
        + FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.NewItemCommand

    Creating share:   C_APPS
    New-SmbShare : One or more parameter values passed to the method were invalid.
    At line:47 char:21
    +                     New-SmbShare –Name $share –Path $path –Descripti ...
    +                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidArgument: (MSFT_SMBShare:ROOT/Microsoft/Windows/SMB/MSFT_SMBShare) 

    [New-SmbShare], CimException
        + FullyQualifiedErrorId : MI RESULT 4,New-SmbShare




    When I put in discrete values it works like a charm. 

    Get-Content -Path "C:\users\`$jstrode\Configuration2.ini" |
        foreach-object `
            -begin {
                # Create an Hashtable
                $hash=@{}
            } `
            -process {
                # Retrieve line with '=' and split them
                $key = [regex]::split($_,'=')
                if(($key[0].CompareTo("") -ne 0) -and ($key[0].StartsWith("[") -ne $True))
                {
                    # Add the Key, Value into the Hashtable
                    $hash.Add($key[0], $key[1])
                }
            } 

    ## Variables
    $i = 0
    $Server = ($hash.GetEnumerator() | Where-Object {$_.name -match "server$i"}).Value
    $Path = ($hash.GetEnumerator() | Where-Object {$_.name -match "Path$i"}).Value
    $ShareLocation = ((("\\{0}\{1}") -f $Server,$Path).replace(':','$')).replace(' ','')
    $Share = ($hash.GetEnumerator() | Where-Object {$_.name -match "Share$i"}).Value 
    $ShareRead = ($hash.GetEnumerator() | Where-Object {$_.name -match "Read$i"}).Value
    $ShareModify = ($hash.GetEnumerator() | Where-Object {$_.name -match "Modify$i"}).Value
    $ShareFullControl =  ($hash.GetEnumerator() | Where-Object {$_.name -match "FC$i"}).Value
    $NTFS_Permissions = ("Nash\UTLPLN-NAS-PROD-RW","MODIFY","Allow");("Nash\UTLPLN-NAS-PROD-RO","READ","Allow")

    #$Share = 'C_APPSTest2'
    #$Path = 'C:\Test0\Test2'

    ## Create Folder
            IF (!(test-path C:\Test0))
                    {
                        write-host "Creating folder: " C:\Test0 -ForegroundColor green
                        New-Item -Path C:\Test0 -ItemType directory
                    } 
                    else 
                    {
                        write-host "The folder already exists: "C:\Test0 -ForegroundColor Yellow
                    }

    ## Create Share
        
            IF (!(Get-SmbShare -Name C_APPS -ErrorAction SilentlyContinue)) 
                    {
                        write-host "Creating share: " C_APPS -ForegroundColor green
                        New-SmbShare –Name C_APPS –Path C:\Test0 #–Description ‘Test Shared Folder’ –FullAccess 'administrators' –ReadAccess 'Everyone','Nash\USWF-DEV-ANNEX-MASNAC' -ChangeAccess 'Authenticated Users'
                        
                    } 
                    else 
                    {
                        write-host "The share already exists: " C_APPS -ForegroundColor Yellow
                    }

    Nash\UTLPLN-NAS-PROD-RO
    READ
    Allow
    The folder already exists:  C:\Test0
    Creating share:  C_APPS

    Name   ScopeName Path     Description
    ----   --------- ----     -----------
    C_APPS *         C:\Test0

    I'm puzzled why I am getting errors when the variables $Share and $Path expand to the proper values.

    Tuesday, July 30, 2019 7:36 PM

All replies

  • You seem to be getting multiple values in your variables.

    This:

    $Server = ($hash.GetEnumerator() | Where-Object {$_.name -match "server$i"}).Value

    Should be this:

    $Server = $hash["server$i"]

    Hash keys are directly addressable.


    \_(ツ)_/

    Tuesday, July 30, 2019 8:06 PM
  • It would be much better to use a data file which is just like an ini file but readable by PowerShell.

    # create a text file with this content called "config.data"
    Name1=Value1
    Name2=Value2
    Name3=Value3

    Now just run this code.

    PS D:\scripts> $config = Get-Content config.data | ConvertFrom-StringData
    PS D:\scripts> $config.Name1
    Value1
    PS D:\scripts> $config.Name2
    Value2
    PS D:\scripts>

    All of your config is now available and directly accessible.

    You can also do this so you can use reference or created variables:

    PS D:\scripts> $name = 'Name3'
    PS D:\scripts> $config.$name
    Value3
    PS D:\scripts>

    You can also use this to load an INI file into a hash in one line.

    $config = Get-Content config.ini |
         Where{$_ -match '='} |
         ConvertFrom-StringData
    The plus with this is that it doesn't screw up the data while loading and parsing.


    \_(ツ)_/


    Tuesday, July 30, 2019 9:04 PM
  • John,

    Easy oversight, but it seems that you have a leading space character in the path.

    This is from your error output:

    Creating folder:   C:\Test0
    New-Item : Cannot find drive. A drive with the name ' C' does not exist.

    I suspect that the leading space is being treated as part of the drive letter.  maybe do a $path.Trim() call to remove any leading/trailing whitespace?


    -Eriq VanBibber, CTO, Priasoft Inc.

    Tuesday, July 30, 2019 9:18 PM
  • John,

    Easy oversight, but it seems that you have a leading space character in the path.

    This is from your error output:

    Creating folder:   C:\Test0
    New-Item : Cannot find drive. A drive with the name ' C' does not exist.

    I suspect that the leading space is being treated as part of the drive letter.  maybe do a $path.Trim() call to remove any leading/trailing whitespace?


    -Eriq VanBibber, CTO, Priasoft Inc.

    That is what ConvertFrom-StringData prevents as it removes all leading and trailing spaces.  It is designed just for this kind of situation.


    \_(ツ)_/

    Tuesday, July 30, 2019 9:42 PM
  • I ran the first part of fourth suggestion. 

    $config = Get-Content "C:\Users\`$jstrode\Config.ini" | Where-Object {$_ -match '='}
    $config = Get-Content "C:\Users\`$jstrode\Config.ini" | Where-Object {$_ -match '='}
    
    PS C:\> $config
    Server0 = NIM12345.HOSTS.Nash.COM
    Server1 = NIM12345.HOSTS.Nash.COM
    Server2 = NIM12345.HOSTS.Nash.COM
    Path0 = 'C:\Test0'
    Path1 = 'C:\Test0\test1'
    Path2 = 'C:\Test0\test2'
    Share0 = 'C_APPS'
    Share1 = 'C_APPSTest1'
    Share2 = 'C_APPSTest2'
    FC0 = "administrators"
    FC1 = "administrators"
    FC2 = "administrators"
    Read0 =  "Everyone","Nash\USWF-DEV-ANNEX-MASNAC"
    Read1 = "EveryOne"
    Read2 = "Everyone","Nash\USWF-DEV-ANNEX-MASNAC"
    Modify0 = "Authenticated Users"
    Modify1 =  "Everyone","Nash\USWF-DEV-ANNEX-MASNAC"
    Modify2 = "Authenticated Users"
    NTFS0 = "Nash\UTLPLN-NAS-PROD-RW","MODIFY","Allow";"Nash\UTLPLN-NAS-PROD-RO","READ","Allow"
    NTFS1 = "Nash\UTLPLN-NAS-PROD-RW","MODIFY","Allow";"Nash\UTLPLN-NAS-PROD-RO","READ","Allow"
    NTFS2 = "Nash\UTLPLN-NAS-PROD-RW","MODIFY","Allow";"Nash\UTLPLN-NAS-PROD-RO","READ","Allow"
    

    When I piped the above to ConvertFrom-StringData I got errors.

    ConvertFrom-StringData : parsing "C:\Test0" - Unrecognized escape sequence \T.
    At line:21 char:97
    + ... ";"Nash\UTLPLN-NAS-PROD-RO","READ","Allow" } | ConvertFrom-StringData
    +                                                    ~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [ConvertFrom-StringData], ArgumentException
        + FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.ConvertFromStringDataCommand

    Tuesday, July 30, 2019 10:03 PM
  • You can't have tabs in n INI file or a data file. "\t" is a tab. Filter them out after  the "Where".


    \_(ツ)_/

    Tuesday, July 30, 2019 10:19 PM
  • It looks like your text file has backslashes in it.  A backslash is an escape character for many scripting and code languages, including powershell.

    The ConvertFrom-StringData is interpreting those as codes and not literal text.

    i think you might either have to pre-parse the file to "double up" the backslashes (Nash\\UTLPLN, for example), or use a different method of parsing the file.

    also, generally an INI formatted file should not have whitespace on either side of the equal sign, but since you are not using any Microsoft APIs for parsing it, its really just a text file.

    If you know the contents of this data and are in control of its production, then you might be able to pre-format it at creation.  but then everyone else (assuming any reuse) would need to know to use ConvertFrom-StringData, or at least that the double backslashes are intended.

    i think your first approach could work, just add the string.Trim() method to your strings to drop any unintended whitespace on the value.

    here is my suggested edit to your original script:

    # Retrieve line with '=' and split them
                $key = [regex]::split($_,'=')
                if(($key[0].CompareTo("") -ne 0) -and ($key[0].StartsWith("[") -ne $True))
                {
                    # Add the Key, Value into the Hashtable
                    $hash.Add($key[0].Trim(), $key[1].Trim())
                }

    This will make sure that both the key and the value have no leading or trailing whitespace.

    There are many other ways to handle this too, including making Regex do all this work, but for the simplest answer for a script that you seem to have mostly working for your tastes, the Trim() method seems best.

    The .NET String class has several other 'helper' methods too, like StartsWith, TrimEnd, TrimStart, etc.

    Here's a reference to them:  System.String Methods


    -Eriq VanBibber, CTO, Priasoft Inc.

    Tuesday, July 30, 2019 11:31 PM
  • I removed Path0=C:\Test0 from the Config.data file.

    Server0 = NIM12345.HOSTS.Nash.COM
    Server1 = NIM12345.HOSTS.Nash.COM
    Server2 = NIM12345.HOSTS.Nash.COM
    Path1 = C:\Test0\test1
    Path2 = C:\Test0\test2
    Share0 = C_APPS
    Share1 = C_APPSTest1
    Share2 = C_APPSTest2
    FC0 = "administrators"
    FC1 = "administrators"
    FC2 = "administrators"
    Read0 = "Everyone","Nash\USWF-DEV-ANNEX-MASNAC"
    Read1 = "EveryOne"
    Read2 = "Everyone","Nash\USWF-DEV-ANNEX-MASNAC"
    Modify0 = "Authenticated Users"
    Modify1 =  "Everyone","Nash\USWF-DEV-ANNEX-MASNAC"
    Modify2 = "Authenticated Users"
    NTFS0 = "Nash\UTLPLN-NAS-PROD-RW","MODIFY","Allow";"Nash\UTLPLN-NAS-PROD-RO","READ","Allow"
    NTFS1 = "Nash\UTLPLN-NAS-PROD-RW","MODIFY","Allow";"Nash\UTLPLN-NAS-PROD-RO","READ","Allow"
    NTFS2 = "Nash\UTLPLN-NAS-PROD-RW","MODIFY","Allow";"Nash\UTLPLN-NAS-PROD-RO","READ","Allow"

    When I ran the following sequence:

    PS C:\> $config = $config | ConvertFrom-StringData
    ConvertFrom-StringData : parsing "C:\Test0\test1" - Unrecognized escape sequence \T.
    At line:1 char:21
    + $config = $config | ConvertFrom-StringData
    +                     ~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [ConvertFrom-StringData], ArgumentException
        + FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.ConvertFromStringDataCommand
    I now get another error so I just think ConvertFrom-StringData can't handle \T. How can I get the cmdlet to ignore the backslashes in Paths? 


    Tuesday, July 30, 2019 11:47 PM
  • To include "c:\Test0" use this "c:\\Test0".

    Doubling the backslash escapes it.

    From the help:

    Example 8: Use backslash escape character to correctly render a file path
    
    PowerShell = Copy 
    PS C:\> ConvertFrom-StringData "Message=Look in c:\\Windows\\System32"
    Name                           Value
    ----                           -----
    Message                        Look in c:\Windows\System32
    


    \_(ツ)_/

    Tuesday, July 30, 2019 11:50 PM