Creating a Share with Permissions with Windows Powershell

Using Powershell how can I create a share and set access permissions.

For example as follows

  • Create share called "public" that maps to the "path c:\shares\foo"
  • Allow DOMAIN1\Users to have read-only access to the share (this does not mean setting acls on the files, rather on the share)

This should do the trick:

net share "Public=c:\shares\foo" "/GRANT:Users,READ"

Of course, you'll need to launch PowerShell with administrative rights, depending where/how you're doing this.


Use the Win32_Share Create method. Example:

(Get-WmiObject -List -ComputerName . | Where-Object -FilterScript 
{$_.Name -eq "Win32_Share"}).InvokeMethod("Create",
   ("C:\FolderToShare","ShareName",0,100,"Share description"))

You can find the documentation of this method here on MSDN.

uint32 Create(
  [in]  string Path,
  [in]  string Name,
  [in]  uint32 Type,
  [in]  uint32 MaximumAllowed,
  [in]  string Description,
  [in]  string Password,
  [in]  Win32_SecurityDescriptor Access
);

Parameters:

  • Path - Local path of the Windows share. For example, "C:\FolderToShare".
  • Name - Passes the alias to a path set up as a share on a Windows system. Example, "ShareName".
  • Type - Passes the type of resource being shared. Types includes disk drives, print queues, interprocess communications (IPC), and general devices. Can be one of the following values.
    • 0 - Disk Drive
    • 1 - Print Queue
    • 2 - Device
    • 3 - IPC
    • 2147483648 - Disk Drive Admin
    • 2147483649 - Print Queue Admin
    • 2147483650 - Device Admin
    • 2147483651 - IPC Admin
  • MaximumAllowed - Limit on the maximum number of users allowed to concurrently use this resource. Example: 100. This parameter is optional.
  • Description - Optional comment to describe the resource being shared. This parameter is optional. Example: "Share description".
  • Password - Password (when the server is running with share-level security) for the shared resource. If the server is running with user-level security, this parameter is ignored. This parameter is optional.
  • Access - Security descriptor for user level permissions. A security descriptor contains information about the permissions, owner, and access capabilities of the resource.

See this page on MSDN for details how to set access permissions: Win32_SecurityDescriptor Class. This article is also a good starting point: WMI Tasks: Files and Folders.


The function below is an example, and can be adapted to whatever you need. The main restriction is it must be run on the machine where the share is to be hosted (or perhaps using PS Remoting to reach that machine first). The account running the script must also have sufficient permissions to create shares.

As written it expects a DirectoryInfo object as it's argument, but it wouldn't be hard to adapt it for strings. The example includes permissions on the folder for two different objects (one user and one group), each with different kinds of access, so that you can see how to mix and match for complex permission requirements:

# $folder is a DirectoryInfo object
Function Create-FileShare($folder)
{
    $name = $folder.Name
    $path = $folder.FullName
    $description = "$name"
    $domain = "example.com" #AD Domain name here (Optional/Not really used/Here for completeness)

    $Method = "Create"
    $sd = ([WMIClass] "Win32_SecurityDescriptor").CreateInstance()

    #AccessMasks:
    #2032127 = Full Control
    #1245631 = Change
    #1179817 = Read

    #Share with the user
    $ACE = ([WMIClass] "Win32_ACE").CreateInstance()
    $Trustee = ([WMIClass] "Win32_Trustee").CreateInstance()
    $Trustee.Name = $name
    $Trustee.Domain = $Null
    #original example assigned this, but I found it worked better if I left it empty
    #$Trustee.SID = ([wmi]"win32_userAccount.Domain='$domain',Name='$name'").sid    
    $ace.AccessMask = 1245631 
    $ace.AceFlags = 3 #Should almost always be three. Really. don't change it.
    $ace.AceType = 0 # 0 = allow, 1 = deny
    $ACE.Trustee = $Trustee 
    $sd.DACL += $ACE.psObject.baseobject 

    #Share with Domain Admins
    $ACE = ([WMIClass] "Win32_ACE").CreateInstance()
    $Trustee = ([WMIClass] "Win32_Trustee").CreateInstance()
    $Trustee.Name = "Domain Admins"
    $Trustee.Domain = $Null
    #$Trustee.SID = ([wmi]"win32_userAccount.Domain='$domain',Name='$name'").sid    
    $ace.AccessMask = 2032127
    $ace.AceFlags = 3
    $ace.AceType = 0
    $ACE.Trustee = $Trustee 
    $sd.DACL += $ACE.psObject.baseobject        

    $mc = [WmiClass]"Win32_Share"
    $InParams = $mc.psbase.GetMethodParameters($Method)
    $InParams.Access = $sd
    $InParams.Description = $description
    $InParams.MaximumAllowed = $Null
    $InParams.Name = $name
    $InParams.Password = $Null
    $InParams.Path = $path
    $InParams.Type = [uint32]0

    $R = $mc.PSBase.InvokeMethod($Method, $InParams, $Null)
    switch ($($R.ReturnValue))
     {
          0 {Write-Host "Share:$name Path:$path Result:Success"; break}
          2 {Write-Host "Share:$name Path:$path Result:Access Denied" -foregroundcolor red -backgroundcolor yellow;break}
          8 {Write-Host "Share:$name Path:$path Result:Unknown Failure" -foregroundcolor red -backgroundcolor yellow;break}
          9 {Write-Host "Share:$name Path:$path Result:Invalid Name" -foregroundcolor red -backgroundcolor yellow;break}
          10 {Write-Host "Share:$name Path:$path Result:Invalid Level" -foregroundcolor red -backgroundcolor yellow;break}
          21 {Write-Host "Share:$name Path:$path Result:Invalid Parameter" -foregroundcolor red -backgroundcolor yellow;break}
          22 {Write-Host "Share:$name Path:$path Result:Duplicate Share" -foregroundcolor red -backgroundcolor yellow;break}
          23 {Write-Host "Share:$name Path:$path Result:Reedirected Path" -foregroundcolor red -backgroundcolor yellow;break}
          24 {Write-Host "Share:$name Path:$path Result:Unknown Device or Directory" -foregroundcolor red -backgroundcolor yellow;break}
          25 {Write-Host "Share:$name Path:$path Result:Network Name Not Found" -foregroundcolor red -backgroundcolor yellow;break}
          default {Write-Host "Share:$name Path:$path Result:*** Unknown Error ***" -foregroundcolor red -backgroundcolor yellow;break}
     }
}