Powershell – WMI: Working with Shares – Part 1: Creating a Share with Custom Permissions

Download Script: zip NewShareWithPermissions-0.0.1.zip 2.3 kB
Downloaded 1816 times

Intro:

Last week, i was teaching a Powershell course (MOC6434), when a student asked me, how to create a share with custom permissions via WMI.

I tried to find an answer for him, but could not really find any examples, cmdlets or functions for it.

I found some examples and help in vbscript, so i decided to make some powershell functions of my own.

I Created these functions that uses the Win32_Share class of WMI. They support remote creation and multiple permissions.

New-Share is for creating a share.

New-ACE is for creating one or more ACEs for use with New-Share

New-SecurityDescriptor is used by New-Share to combine the ACE’s into a SecurityDescriptor for the WMI Method.

Functions:

New-Share

SYNOPSIS
Creates a new Share on local or remote PC. Support for Custom Permissions

SYNTAX
New-Share [-FolderPath] <string> [-ShareName] <string> [-ACEs <Win32_ACE Object>] [-Description <string>] [-Computer] <string>

DETAILED DESCRIPTION
Create new share, either on local or remote PC.

Shares can be created without the use of –ACEs parameter, this will create a share with standard permissions. If the ACEs parameter if used, custom permissions can be added.

PARAMETERS

FolderPath <string>
Specifies the local path for folder that is to be shared.

Required? true
Position? 1
Default value
Accept pipeline input? false
Accept wildcard characters? false

ShareName <string>
Specifies the name of the share.

Please notice that duplicate share names are not supported in windows.

Required? true
Position? 2
Default value
Accept pipeline input? false
Accept wildcard characters? false

ACEs <(Array of) Win32_ACE Objects>
Specifies the custom permissions.
Create the Win32_ACE object by using New-ACE function.
This parameter either support a single object or an array of objects

Required? false
Position? 3
Default value
Accept pipeline input? false
Accept wildcard characters? false

Description <string>
Description for the share

Required? false
Position? 4
Default value
Accept pipeline input? false
Accept wildcard characters? false

Computer <string>
Specify computername for the target computer

Required? false
Position? 4
Default value . (localhost)
Accept pipeline input? false
Accept wildcard characters? false

INPUT TYPE
No Pipe input in version 0.0.1

RETURN TYPE
System.Object
Properties: ReturnCode, Message

————————– EXAMPLE 1 ————————–

$ACE = New-ACE -Name “Domain Users” -Domain “CORETECH” -Permission “Read” -Group
New-Share -FolderPath “C:\Temp” -ShareName “Temp4”  -ACEs $ACE `
–Description “Test Description” -Computer “localhost”

This examples creates one Win32_ACE object that specifies “CORETECH\Domain Users”, to have read permission and use it to share C:\Temp on the local machine.

————————– EXAMPLE 2 ————————–

$ACE = New-ACE -Name “Domain Users” -Domain “CORETECH” -Permission “Read” -Group
$ACE2 = New-ACE -Name “CCO” -Domain “CORETECH” -Permission “Full”
New-Share -FolderPath “C:\Temp” -ShareName “Temp4”  -ACEs $ACE,$ACE2 `
-Description “Test Description” -Computer “localhost”

This examples create both a users ACE and a group ACE, and send them both with the New-Share function

————————– EXAMPLE 3 ————————–

New-Share “C:\Temp” “Temp4”

This is the shortest way to run the function. Using default permissions (which is decided from whom, who run the function). and using position parameters, ignoring all optional parameters

New-ACE

SYNOPSIS
Creates a Win32_ACE object contains permissions for use with New-share (or another function that need Win32_ACE objects)

SYNTAX
New-ACE [-Name] <string> [-Domain] <string> [-Permission] <string> [-Computer <string>] [-Group]

NOTICE

Due to the limitations of the WMI_Account class, it is only possible to get local accounts when connecting to WMI via a remote machine (as far as i know, please contact me if you have input).

This means that usually you should not use the –ComputerName paramter, only use it if you are connecting to a workgroup computer, and using local user/groups for the permissions

PARAMETERS

Name <string>
Specifies the name of the user or group.

Required? true
Position? 1
Default value
Accept pipeline input? false
Accept wildcard characters? false

Domain <string>
Specifies the domain for the user or group.

Required? true
Position? 2
Default value
Accept pipeline input? false
Accept wildcard characters? false

Permission <string>
Specifies the permission granted for the user/group.

Possible values are “Read”, “Change”, “Full”

Required? true
Position? 3
Default value
Accept pipeline input? false
Accept wildcard characters? false

Computername <string>
Specify computername for the target computer to get the user info from.
NB! Please read the Notice above this.

Required? false
Position? 4
Default value . (localhost)
Accept pipeline input? false
Accept wildcard characters? false

Group <switch>
This is a switch parameter, add it if you are creating an ACE for a group instead of a user.

Required? false
Position? 5
Default value
Accept pipeline input? false
Accept wildcard characters? false

INPUT TYPE
No Pipe input in version 0.0.1

RETURN TYPE
Win32_ACE Object

————————– EXAMPLE 1 ————————–

New-ACE -Name “Domain Users” -Domain “CORETECH” -Permission “Read” -Group

This examples creates one Win32_ACE object that specifies “CORETECH\Domain Users”.

————————– EXAMPLE 2 ————————–

$ACE2 = New-ACE -Name “CCO” -Domain “CORETECH” -Permission “Full”

This examples creates a user ACE

New-SecurityDescriptor

SYNOPSIS
Creates a Win32_SecurityDescriptor object from on or more Win32_ACEs, for use by New-Share.

SYNTAX
New-SecurityDescriptor [-ACEs] <[array of] Win32_ACE Object(s)> [-ComputerName <string>]

NOTICE

Due to the limitations of the WMI_Account class, it is only possible to get local accounts when connecting to WMI via a remote machine (as far as i know, please contact me if you have input).

This means that usually you should not use the –ComputerName paramter, only use it if you are connecting to a workgroup computer, and using local user/groups for the permissions

PARAMETERS

ACEs <[Array of] Win32_ACE object(s)>
Specifies one or more Win32ACE object that should be added to the SecurityDescriptor

Required? true
Position? 1
Default value
Accept pipeline input? false
Accept wildcard characters? false

ComputerName <string>
Specify computername for the target computer to get the user info from.
NB! Please read the Notice above this.

Required? false
Position? 2
Default value . (localhost)
Accept pipeline input? false
Accept wildcard characters? false

INPUT TYPE
No Pipe input in version 0.0.1

RETURN TYPE
Win32_SecurityDescriptor Object

————————– EXAMPLE 1 ————————–

$ACE = New-ACE -Name “Domain Users” -Domain “CORETECH” -Permission “Read” –Group
New-SecurityDescriptor $ACE

This examples creates a Win32_SecurityDescriptor from one Win32_ACE object

————————– EXAMPLE 2 ————————–

$ACE = New-ACE -Name “Domain Users” -Domain “CORETECH” -Permission “Read” –Group
$ACE2 = New-ACE -Name “CCO” -Domain “CORETECH” -Permission “Full”
New-SecurityDescriptor $ACE,$ACE2

This examples creates a Win32_SecurityDescriptor from more than one Win32_ACE object

Source:

# //************************************************************************************************************
# // ***** Script Header *****
# //
# // Solution:  Coretech Share Functions
# // File:      NewShareWithPermission.ps1
# // Author:	Jakob Gottlieb Svendsen, Coretech A/S. http://blog.coretech.dk
# // Purpose:
# // New-Share: Creates new Share on local or remote PC, with custom permissions.
# // Required Parameters: FolderPath, ShareName
# //
# // New-ACE: Creates ACE Objects, for use when running New-Share.
# // Required Parameters: Name, Domain
# //
# // New-SecurityDescriptor: used by New-Share to prepare the permissions.
# // Required Parameters: ACEs
#//
# // Usage Examples:
# // New-Share -FolderPath "C:\Temp" -ShareName "Temp" -ACEs $ACE,$ACE2  -Description "Test Description" -Computer "localhost"
# // Sharing of folder C:\Temp, with the Name "Temp". ACE's (Permissions) are sent via the -ACEs parameter.
# // Create them with New-ACE and send one  or more, seperated by comma (or create and array and use that)
# //
# // This is the first in a couple of share-administration scripts i am planning to make and release on the blog.
# //
# // Please comment the blog post, if you have any suggestions, questions or feedback.
# // Contact me if you need us to make a custom script (or cause not for free 😉 )
# //
# // CORETECH A/S History:
# // 0.0.1     JGS 30/06/2009  Created initial version.
# //
# // Customer History:
# //
# // ***** End Header *****
# //**************************************************************************************************************
#//----------------------------------------------------------------------------
#//  Procedures
#//----------------------------------------------------------------------------

Function New-SecurityDescriptor (
$ACEs = (throw "Missing one or more Trustees"),
[string] $ComputerName = ".")
{
	#Create SeCDesc object
	$SecDesc = ([WMIClass] "\\$ComputerName\root\cimv2:Win32_SecurityDescriptor").CreateInstance()
	#Check if input is an array or not.
	if ($ACEs -is [System.Array])
	{
		#Add Each ACE from the ACE array
		foreach ($ACE in $ACEs )
		{
			$SecDesc.DACL += $ACE.psobject.baseobject
		}
	}
	else
	{
		#Add the ACE
		$SecDesc.DACL =  $ACEs
	}
	#Return the security Descriptor
	return $SecDesc
}

Function New-ACE (
	[string] $Name = (throw "Please provide user/group name for trustee"),
	[string] $Domain = (throw "Please provide Domain name for trustee"),
	[string] $Permission = "Read",
	[string] $ComputerName = ".",
	[switch] $Group = $false)
{
	#Create the Trusteee Object
	$Trustee = ([WMIClass] "\\$ComputerName\root\cimv2:Win32_Trustee").CreateInstance()
	#Search for the user or group, depending on the -Group switch
	if (!$group)
	{ $account = [WMI] "\\$ComputerName\root\cimv2:Win32_Account.Name='$Name',Domain='$Domain'" }
	else
	{ $account = [WMI] "\\$ComputerName\root\cimv2:Win32_Group.Name='$Name',Domain='$Domain'" }
	#Get the SID for the found account.
	$accountSID = [WMI] "\\$ComputerName\root\cimv2:Win32_SID.SID='$($account.sid)'"
	#Setup Trusteee object
	$Trustee.Domain = $Domain
	$Trustee.Name = $Name
	$Trustee.SID = $accountSID.BinaryRepresentation
	#Create ACE (Access Control List) object.
	$ACE = ([WMIClass] "\\$ComputerName\root\cimv2:Win32_ACE").CreateInstance()
	#Select the AccessMask depending on the -Permission parameter
	switch ($Permission)
	{
		"Read" 		 { $ACE.AccessMask = 1179817 }
		"Change"  {	$ACE.AccessMask = 1245631 }
		"Full"		   { $ACE.AccessMask = 2032127 }
		default { throw "$Permission is not a supported permission value. Possible values are 'Read','Change','Full'" }
	}
	#Setup the rest of the ACE.
	$ACE.AceFlags = 3
	$ACE.AceType = 0
	$ACE.Trustee = $Trustee
	#Return the ACE
	return $ACE
}

Function New-Share (
	[string] $FolderPath = (throw "Please provide the share folder path (FolderPath)"),
	[string] $ShareName = (throw "Please provide the Share Name"),
	$ACEs,
	[string] $Description = "",
	[string] $ComputerName=".")
{
	#Start the Text for the message.
	$text = "$ShareName ($FolderPath): "
	#Package the SecurityDescriptor via the New-SecurityDescriptor Function.
	$SecDesc = New-SecurityDescriptor $ACEs
	#Create the share via WMI, get the return code and create the return message.
	$Share = [WMICLASS] "\\$ComputerName\Root\Cimv2:Win32_Share"
	$result = $Share.Create($FolderPath, $ShareName, 0, $false , $Description, $false  , $SecDesc)
	switch ($result.ReturnValue)
	{
		0 {$text += "has been success fully created" }
		2 {$text += "Error 2: Access Denied" }
		8 {$text += "Error 8: Unknown Failure" }
		9 {$text += "Error 9: Invalid Name"}
		10 {$text += "Error 10: Invalid Level" }
		21 {$text += "Error 21: Invalid Parameter" }
		22 {$text += "Error 22 : Duplicate Share"}
		23 {$text += "Error 23: Redirected Path" }
		24 {$text += "Error 24: Unknown Device or Directory" }
		25 {$text += "Error 25: Net Name Not Found" }
	}
	#Create Custom return object and Add results
	$return = New-Object System.Object
	$return | Add-Member -type NoteProperty -name ReturnCode -value $result.ReturnValue
	$return | Add-Member -type NoteProperty -name Message -value $text
	#Return result object
	$return
}

#//----------------------------------------------------------------------------
#//  Main routines
#//----------------------------------------------------------------------------

#Create ACE's for the securitydescriptor for the share:
#a group ACE, containing Group info, please notice the -Group switch
$ACE = New-ACE -Name "Domain Users" -Domain "CORETECH" -Permission "Read" -Group
#a user ACE.
$ACE2 = New-ACE -Name "CCO" -Domain "CORETECH" -Permission "Full"

#Create the share on the local machine
$result = New-Share -FolderPath "C:\Temp" -ShareName "Temp4"  -ACEs $ACE,$ACE2 -Description "Test Description" -Computer "localhost" 

#Output result message from new-share
Write-Output $result.Message

#Check if the share was succesfully created
If ($result.ReturnCode -eq 0)
{
	#Creation was succesfull, put your next code here.
}

#//----------------------------------------------------------------------------
#//  End Script
#//----------------------------------------------------------------------------

Last Words:

Script is version 0.0.1. Tested on Windows Vista and Windows XP local and remote, in my enviroment.

There might be a lot that i have not thought of yet, please comment this post if you have suggestions/bugs/

Next Part:

Next time i will try to look into changing existing shares, adding and remove permissions to the list.

Replacing the permissions seems easy, but editing the existing ones might be a challenge.

I will look at it as soon as i have some spare time :)

As usual, please contact me/us if you need any help on a custom scripting project (at standard price rate of cause).

I hope you all have a nice summer!


Comments (39):

  1. James says:

    Nice script. I had to modify it slightly for my env though.

    This line:
    $result = $Share.Create($FolderPath, $ShareName, 0, $false , $Description, $false, $SecDesc)

    Changed to this:
    $result = $Share.Create($FolderPath, $ShareName, 0, $null , $Description, $null, $SecDesc)

    The $null’s work better for the optional arguments. Especially argument 4. Maximum users. I found $false was setting it to 0. So nobody could connect to the share.

    James

  2. Jakob Gottlieb Svendsen Jakob says:

    Great to hear that someone is using my script 😉

    and thanks alot for the bug fix! :)

  3. Tom says:

    Hello!

    Thanks!!! Your script rescued my goal to create a script for sharing folders remote.

    But I’ve two problems.
    – How can I change the “user limit” in the creating share from now 1 user to “maximum allowed”?
    – How can I grant access to the created share to the “Authenticated Users”?

    Maybe you have an idea….

    thanks a lot
    Tom

  4. Jonathan Warnken says:

    Nice work!!
    I added support for setting permissions for Everyone and Authenticated users. Also Updated the New-Share function to address the bug James found.

    # //************************************************************************************************************
    # // ***** Script Header *****
    # //
    # // Solution: Coretech Share Functions
    # // File: NewShareWithPermission.ps1
    # // Author: Jakob Gottlieb Svendsen, Coretech A/S. http://blog.coretech.dk
    # // Purpose:
    # // New-Share: Creates new Share on local or remote PC, with custom permissions.
    # // Required Parameters: FolderPath, ShareName
    # //
    # // New-ACE: Creates ACE Objects, for use when running New-Share.
    # // Required Parameters: Name, Domain
    # //
    # // New-SecurityDescriptor: used by New-Share to prepare the permissions.
    # // Required Parameters: ACEs
    #//
    # // Usage Examples:
    # // New-Share -FolderPath “C:\Temp” -ShareName “Temp” -ACEs $ACE,$ACE2 -Description “Test Description” -Computer “localhost”
    # // Sharing of folder C:\Temp, with the Name “Temp”. ACE’s (Permissions) are sent via the -ACEs parameter.
    # // Create them with New-ACE and send one or more, seperated by comma (or create and array and use that)
    # //
    # // This is the first in a couple of share-administration scripts i am planning to make and release on the blog.
    # //
    # // Please comment the blog post, if you have any suggestions, questions or feedback.
    # // Contact me if you need us to make a custom script (or cause not for free )
    # //
    # // CORETECH A/S History:
    # // 0.0.1 JGS 30/06/2009 Created initial version.
    # //
    # // Customer History:
    # // 0.0.2 – Jonathan Warnken(jon.warnken@gmail.com) 16/12/2009
    # // – Added logic to all permissions to be set using Everyone and Authenticated Users. These use well known SIDs and are easier to hard code then lookup.
    # // – Usage Examples:
    # // – (Everyone) $ACE = New-ACE -Name “Everyone” -Domain “.” -Permission “Read” -Group
    # // – (Authenticated Users) $ACE = New-ACE -Name “Authenticated Users” -Domain “NT AUTHORITY” -Permission “Read” -Group
    # // –
    # // – Updated New-Share so that -MaxUsers and -Password are optional parameters. The default values are $null.
    # // – Updated the Main Code examples to use an Array for the Access Control objects
    # //
    # // ***** End Header *****
    # //**************************************************************************************************************
    #//—————————————————————————-
    #// Procedures
    #//—————————————————————————-

    Function New-SecurityDescriptor (
    $ACEs = (throw “Missing one or more Trustees”),
    [string] $ComputerName = “.”)
    {
    #Create SeCDesc object
    $SecDesc = ([WMIClass] “\\$ComputerName\root\cimv2:Win32_SecurityDescriptor”).CreateInstance()
    #Check if input is an array or not.
    if ($ACEs -is [System.Array])
    {
    #Add Each ACE from the ACE array
    foreach ($ACE in $ACEs )
    {
    $SecDesc.DACL += $ACE.psobject.baseobject
    }
    }
    else
    {
    #Add the ACE
    $SecDesc.DACL = $ACEs
    }
    #Return the security Descriptor
    return $SecDesc
    }

    Function New-ACE (
    [string] $Name = (throw “Please provide user/group name for trustee”),
    [string] $Domain = (throw “Please provide Domain name for trustee”),
    [string] $Permission = “Read”,
    [string] $ComputerName = “.”,
    [switch] $Group = $false)
    {
    #Create the Trusteee Object
    $Trustee = ([WMIClass] “\\$ComputerName\root\cimv2:Win32_Trustee”).CreateInstance()
    #Check for Special cases Everyone and Authenticated Users)
    switch ($Name.ToUpper()) {
    “EVERYONE” {
    $Trustee.Domain = $Null
    $Trustee.Name = “EVERYONE”
    $Trustee.SID = @(1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0)
    }
    “AUTHENTICATED USERS” {
    $Trustee.Domain = “NT AUTHORITY”
    $Trustee.Name = “Authenticated Users”
    $Trustee.SID = @(1, 1, 0, 0, 0, 0, 0, 5, 11, 0, 0, 0)
    }
    default {
    #Search for the user or group, depending on the -Group switch
    if (!$group)
    { $account = [WMI] “\\$ComputerName\root\cimv2:Win32_Account.Name=’$Name’,Domain=’$Domain'” }
    else
    { $account = [WMI] “\\$ComputerName\root\cimv2:Win32_Group.Name=’$Name’,Domain=’$Domain'” }
    #Get the SID for the found account.
    $accountSID = [WMI] “\\$ComputerName\root\cimv2:Win32_SID.SID=’$($account.sid)'”
    #Setup Trusteee object
    $Trustee.Domain = $Domain
    $Trustee.Name = $Name
    $Trustee.SID = $accountSID.BinaryRepresentation
    }
    }
    #Create ACE (Access Control List) object.
    $ACE = ([WMIClass] “\\$ComputerName\root\cimv2:Win32_ACE”).CreateInstance()
    #Select the AccessMask depending on the -Permission parameter
    switch ($Permission)
    {
    “Read” { $ACE.AccessMask = 1179817 }
    “Change” { $ACE.AccessMask = 1245631 }
    “Full” { $ACE.AccessMask = 2032127 }
    default { throw “$Permission is not a supported permission value. Possible values are ‘Read’,’Change’,’Full'” }
    }
    #Setup the rest of the ACE.
    $ACE.AceFlags = 3
    $ACE.AceType = 0
    $ACE.Trustee = $Trustee
    #Return the ACE
    return $ACE
    }

    Function New-Share (
    [string] $FolderPath = (throw “Please provide the share folder path (FolderPath)”),
    [string] $ShareName = (throw “Please provide the Share Name”),
    $ACEs,
    [string] $Description = “”,
    [string] $ComputerName = “.”,
    $MaxUsers = $null,
    $Password = $null)
    {
    #Start the Text for the message.
    $text = “$ShareName ($FolderPath): ”
    #Package the SecurityDescriptor via the New-SecurityDescriptor Function.
    $SecDesc = New-SecurityDescriptor $ACEs
    #Create the share via WMI, get the return code and create the return message.
    $Share = [WMICLASS] “\\$ComputerName\Root\Cimv2:Win32_Share”
    $result = $Share.Create($FolderPath, $ShareName, 0, $MaxUsers, $Description, $Password, $SecDesc)
    switch ($result.ReturnValue)
    {
    0 {$text += “has been success fully created” }
    2 {$text += “Error 2: Access Denied” }
    8 {$text += “Error 8: Unknown Failure” }
    9 {$text += “Error 9: Invalid Name”}
    10 {$text += “Error 10: Invalid Level” }
    21 {$text += “Error 21: Invalid Parameter” }
    22 {$text += “Error 22 : Duplicate Share”}
    23 {$text += “Error 23: Redirected Path” }
    24 {$text += “Error 24: Unknown Device or Directory” }
    25 {$text += “Error 25: Net Name Not Found” }
    }
    #Create Custom return object and Add results
    $return = New-Object System.Object
    $return | Add-Member -type NoteProperty -name ReturnCode -value $result.ReturnValue
    $return | Add-Member -type NoteProperty -name Message -value $text
    #Return result object
    $return
    }

    #//—————————————————————————-
    #// Main routines
    #//—————————————————————————-

    #Create ACE’s for the securitydescriptor for the share:
    #a group ACE, containing Group info, please notice the -Group switch
    $ACE = @(New-ACE -Name “Domain Users” -Domain “CORETECH” -Permission “Read” -Group)
    $ACE += New-ACE -Name “Authenticated Users” -Domain “NT AUTHORITY” -Permission “Read” -Group
    $ACE += New-ACE -Name “everyone” -Domain “.” -Permission “Read” -Group
    #a user ACE.
    $ACE += New-ACE -Name “CCO” -Domain “CORETECH” -Permission “Full”

    #Create the share on the local machine
    $result = New-Share -FolderPath “C:\Temp” -ShareName “Temp4” -ACEs $ACE -Description “Test Description” -Computer “localhost”

    #Output result message from new-share
    Write-Output $result.Message

    #Check if the share was succesfully created
    If ($result.ReturnCode -eq 0)
    {
    #Creation was succesfull, put your next code here.
    }

    #//—————————————————————————-
    #// End Script
    #//—————————————————————————-

  5. Jakob Gottlieb Svendsen Jakob says:

    thnx alot!

    i havent had time myself to do it, its great to see other helping out!

    merry christmas to you all.

  6. Joe says:

    Thank you so much for this script. It saved me a lot of time.

  7. name required says:

    anyone copy/pasting this script be aware the content has funky single and double quotes that will need to be converted back to regular old keyboard quotes. Otherwise works g-r-e-a-t!

  8. Jakob Gottlieb Svendsen Jakob says:

    Hello

    Yes sometimes the browsers change the chars.

    use the download link in the top of the page to download a zip file containing the script :)

    Best Regards
    Jakob

  9. eric says:

    Very new(1 week) to PowerShell but I got your code working in XP-Pro-32bit and I love it.

    Any chance that all will work in XP-Pro-64bit as well as Windows7?

    thank you very much…eric

  10. Jakob Gottlieb Svendsen Jakob says:

    Hello eric!

    Nice to know it is working for you!

    I don’t see any reason it shouldnt work in Win XP PRo 64bit. but I have not tested it myself, if it does not work, please post your feedback/problems :)

    Best regards
    Jakob

  11. eric says:

    Jakob,
    Old version(0.0.1) works fine for me. The new version(0.0.2) fails on New-ACE.
    Can you spot what I am doing wrong or is the new version ready to download???
    Thank you-eric

    #Delete the Folder
    Remove-Item “C:\PowerShellTest\*” -recurse

    #Create the Folder/Directory
    New-Item “C:\PowerShellTest” -type directory -force

    #Create permission to the AccessControlEntry(ACE)
    $ACE = @(New-ACE -Name “ericg” -Domain “cbo” -Permission “Read”)
    $ACE += New-ACE -Name “peggyg” -Domain “cbo” -Permission “Read”
    $ACE += New-ACE -Name “georgiab” -Domain “cbo” -Permission “Read”

    #Create the New Share
    $result = New-Share -FolderPath “C:\PowerShellTest” -ShareName “PSTestShare” -ACEs $ACE -Descrition “TestDescription” -Computer “w-66898”

    Write-Output $result.Message

    if ($result.ReturnCode -eq 0)
    {
    #Creation was succesfull
    }

  12. Jakob Gottlieb Svendsen Jakob says:

    Hello Eric

    i cannot see anything wrong in your syntax, i could be wrong tho.

    It is really hard, next to impossible to help you, when you have not included the error message you are getting.

    unfortunately there is no new version in development at the moment, i have too many other projects that need my work at the moment.

    Best regards
    Jakob

  13. Juergen says:

    Hello Jakob!

    Thanks for this great Example! I tried it but it’s not working.

    I get the following Error
    “Cannot convert value “\\Server\root\cimv2:Win32_Group.Name=’Domain Users’,Domain=’dom'” to type “System.Management.ManagementObject”. Error: “Not found ” ”

    As you can see it’s in the line for getting the $account object.

    As Domain Users really exists I do not understand the error.
    maybe you can help me.

    Thanks and regards
    Juergen

  14. Juergen says:

    Hello again!

    I’ve found the solution and maybe you can explain me. The computername in function New-Ace hast to be “.” Why?

    regards

  15. Jakob Gottlieb Svendsen Jakob says:

    Hello Juergen!

    you are correct, there is a problem there.

    i have also described it in the post

    “NOTICE

    Due to the limitations of the WMI_Account class, it is only possible to get local accounts when connecting to WMI via a remote machine (as far as i know, please contact me if you have input).”

    I don’t know why, and unfortunately i have not had time to do more powershell scripts with shares.

    Best regards
    Jakob

  16. Greg McCarty says:

    I used the scripts to successfully create a share on a remote server using a local group from that remove servers. To do so, I specified the domain name as the server name.

    This was on a win2008 r2 box.

  17. Chris says:

    Did you ever write Part 2?

  18. Chris Smith says:

    I have made a change to my script that adds a way to modify existing share permissions.

    #Start the Text for the message.
    $text = “$ShareName ($FolderPath): ”
    #Package the SecurityDescriptor via the New-SecurityDescriptor Function.
    $SecDesc = New-SecurityDescriptor $ACEs

    #Check to see if the share already exists – This is to modify Permissions
    $CheckShare = (Get-WmiObject Win32_Share -comp $Computername -Filter “Name=’$ShareName'”)
    if ($CheckShare -ne $null) {
    # “Share exists and will now be modified!!!”
    $result = $CheckShare | foreach-object { $_.SetShareInfo(0, $Description, $SecDesc) }

    I hope this helps other people use your script.

    • Hi Chris!

      I was actually working on part 2, but i had to do work instead! .. thanks alot for your script.
      It is pretty cool that powershell 2.0 has the New-SecurityDescriptor, which didnt exist when i wrote this blog post :)

      although i havent tested, i would guess that your script replace all exiting permissions, i might use it in a part 2, makin it able to add them to the exiting.

      Or am i wrong? :)

      • Tom says:

        Jakob,

        Could you explain this code that Chris added? I am putting it in but I am not having any luck. I am also not programmer. I am trying to learn Powershell and only a year into it. What I am trying to do is set permissions on a share.

        • please look at Rudy’s great example below. I think that does the job for you

          • Tom says:

            Ok, been trying to with no luck so far. But you think that will allow me to set the permissions periodically? My end goal is to create a share with the right accounts, which is what your script does for me. The second part is that I want the script to re-apply the permissions if they have changed.

          • Tom says:

            Ok, got it to work and it is beautiful. Could you suggest a way to remove all users from a share? While this script re-adds people if they were removed, lets say someone adds the Everyone group. This script will not remove everyone. So I am thinking if I could have the script run to remove all groups, then the section to add the group I want it would be great.

  19. David Daniels says:

    To add local groups from the remote computer I added an addition modified function and performed a call appropriately.

    Function New-ACELocal (
    [string] $Name = (Write-Host “Please provide user/group name”),
    [string] $Permission = “Read”,
    [string] $ComputerName = “.”,
    [switch] $Group = $false)
    { $Trustee = ([WMIClass] “\\$ComputerName\root\cimv2:Win32_Trustee”).CreateInstance()
    if (!$group) { $account = [WMI] “\\$ComputerName\root\cimv2:Win32_Account.Name=’$Name’,Domain=’$ComputerName'” }
    else
    { $account = [WMI] “\\$ComputerName\root\cimv2:Win32_Group.Name=’$Name’,Domain=’$ComputerName'”}
    $accountSID = [WMI] “\\$ComputerName\root\cimv2:Win32_SID.SID=’$($account.sid)'”
    $Trustee.Domain = $Domain
    $Trustee.Name = $Name
    $Trustee.SID = $accountSID.BinaryRepresentation
    $ACE = ([WMIClass] “\\$ComputerName\root\cimv2:Win32_ACE”).CreateInstance()
    switch ($Permission) {
    “Read” { $ACE.AccessMask = 1179817 }
    “Change” { $ACE.AccessMask = 1245631 }
    “Full” { $ACE.AccessMask = 2032127 }
    default { Write-Host “$Permission is not a supported permission value. Possible values are ‘Read’,’Change’,’Full'” }}
    $ACE.AceFlags = 3
    $ACE.AceType = 0
    $ACE.Trustee = $Trustee
    return $ACE}

    $ACE2 = New-ACELocal -Name “Administrators” -ComputerName “$Repository” -Permission “Full” -Group

    • kiran says:

      function new-acelocal is not working for Administrators or any local group.

      Cannot convert value “\\host1\root\cimv2:Win32_Group.Name=’Administrators’,Domain=’host1’” to type “System.Management.ManagementObject”. Error: “Invalid pa
      rameter ”
      At C:\Users\TEMP\AppData\Local\Temp\5\867c7417-4389-4f78-a564-90bac98ab8d6.ps1:123 char:20
      + { $account = [WMI] <<<< “\\$ComputerName\root\cimv2:Win32_Group.Name=’$Name’,Domain=’$ComputerName’”}
      + CategoryInfo : NotSpecified: (:) [], RuntimeException
      + FullyQualifiedErrorId : RuntimeException

  20. Alvaro Rodrigues says:

    I’ve try to use the script and i get the error:

    The term ‘Throw’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
    At E:\Sistema\Scripts\ShareFunctions.psm1:122 char:29
    + [string] $ShareName = (Throw <<<< "Please provide the Share Name"),
    + CategoryInfo : ObjectNotFound: (Throw:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    I change throw to read-host and works! Why throw can't be works?

    Thanks! (Sorry by english. Im brazilian).

  21. eXo says:

    Thanks a lot for your work, guys!
    For those who copy&paste script gets errors like
    “Cannot convert value “\\host1\root\cimv2:Win32_Group.Name=’Administrators’,Domain=’host1’” to type ”System.Management.ManagementObject”. Error: “Invalid pa
    rameter ”
    At C:\Users\TEMP\AppData\Local\Temp\5\867c7417-4389-4f78-a564-90bac98ab8d6.ps1:123 char:20
    + { $account = [WMI] <<<< “\\$ComputerName\root\cimv2:Win32_Group.Name=’$Name’,Domain=’$ComputerName’”}
    + CategoryInfo : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException"
    do not forget to find and replace ’ ” on the ' "

  22. Xavier Merlin says:

    Part2 any time “soon” ???

    • rudy devires says:

      Dear Xavier “the Wizard” Merlin, your name could be used for a x-men character

      Maybe this will help you:

      Function Set-SharePermission{

      param ([string]$Sharename, [string] $User)

      $strsid= ConvertTo-Sid $User $ADname
      $accountSID = [WMI] “Win32_SID.SID=’$($strsid.value)'”
      $t = ([WMIClass]”Win32_Trustee”).CreateInstance()
      $t.Domain =$ADname; $t.Name = $User; $t.SID =$accountSID.BinaryRepresentation
      #initialize ACE
      $ACE = ([WMIClass]”Win32_Ace”).CreateInstance()
      $ACE.AccessMask = 2032127; $ACE.AceFlags = 3; $ACE.AceType = 0; $ACE.Trustee = $t

      # Get SD for share
      $SD = (Get-WMIObject Win32_LogicalShareSecuritySetting -Filter “Name=’$Sharename'”).GetSecurityDescriptor().Descriptor
      # add new ace
      $SD.DACL+=$ACE.psobject.baseobject
      # put the share info
      Get-WMIObject Win32_Share -Filter “Name LIKE ‘$Sharename'” | %{
      $_.SetShareInfo(“”,””,$SD)
      }
      }
      function ConvertTo-Sid($UserName,$domain = $env:Computername) {

      $ID = New-Object System.Security.Principal.NTAccount($domain,$UserName)
      $SID = $ID.Translate([System.Security.Principal.SecurityIdentifier])
      $SID.Value
      }

  23. Greg Theron says:

    I can make the share but it will not add the Administrators Group? i get this error?
    Cannot convert value “\\.\root\cimv2:Win32_Group.Name=’Administrators’,Domain=’Domain'” to type “System.
    Management.ManagementObject”. Error: “Not found ”
    At C:\Support\New-APPS-Share.PS1:75 char:19
    + { $account = [WMI] <<<< "\\$ComputerName\root\cimv2:Win32_Group.Name='$Name',Domain='$Domain'" }
    + CategoryInfo : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException

  24. Greg Theron says:

    Cannot convert value “\\.\root\cimv2:Win32_Group.Name=’Administrators’,Domain=’Domain'” to type “System.
    Management.ManagementObject”. Error: “Not found ”
    At C:\Support\New-APPS-Share.PS1:75 char:19
    + { $account = [WMI] <<<< "\\$ComputerName\root\cimv2:Win32_Group.Name='$Name',Domain='$Domain'" }
    + CategoryInfo : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException

  25. Greg: there is no chance of me helping without more info. What OS? are you running as admin?

    thnx :)

    Xavior: sorry i have never done a follow up on this… no timeplan as we speak.

  26. Greg Theron says:

    We are running Server 2008 R2, i am logged in as administrator running Power Shell as administrator.

    i am trying to add the Administrators Group to a share.

    #Create ACE’s for the securitydescriptor for the share:
    #a group ACE, containing Group info, please notice the -Group switch
    $ACE = New-ACE -Name “Administrator” -Domain “My.domain” -Permission “Full”
    #a user ACE.
    $ACE2 = New-ACE -Name “Administrators” -Domain “My.domain” -Permission “Full” -Group

    Thanks for the Fast Responce

  27. Jon Almada says:

    I had to make a slight change in this script to allow it to work on Windows 2008

    At line 113 in the New-Share function:

    From

    $result = $Share.Create($FolderPath, $ShareName, 0, $false, $Description, $false , $SecDesc)

    To
    $result = $Share.Create($FolderPath, $ShareName, 0, 16777216 , $Description, $false , $SecDesc)

    This had to do with the number of connections allowed for the share and I set it to the default setting of 16777216 so that the share could be browsed once the share was created.

  28. Verdural says:

    Hi Jakob,

    Thanks for your great script.
    Who can i set the Cache to “No files or programs from the shared folder are available offline’?

    Thanks in advance,

    Regards,
    Verdural

  29. John-Rock Bilodeau says:

    Hi,

    I just wanted to thank you for your function. I used bits and pieces of it as well as a few other functions for creating shares and developed my own version. I built it the creation of share and building the security permissions all in one function that validate if an account is a user or group against AD or the specified computer. I just published it in the MS script gallery. Have a peek. hopefully it will help others.

    http://gallery.technet.microsoft.com/scriptcenter/Create-Shared-Folder-with-79fce495

  30. newel post austin texas

    Coretech Blog » Blog Archive » Powershell – WMI: Working with Shares – Part 1: Creating a Share with Custom Permissions

  31. varapraveen says:

    when i ran the script,the user setting got set properly which i came to know after seeing the properties of the file which i tried to share.But when i tried to access the folder from the user which i granted,I am not able to access.

Leave a Reply