Download Script: [download id=”12″]
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 ————————–
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 ————————–
$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 ————————–
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 ————————–
This examples creates one Win32_ACE object that specifies “CORETECH\Domain Users”.
————————– EXAMPLE 2 ————————–
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 ————————–
New-SecurityDescriptor $ACE
This examples creates a Win32_SecurityDescriptor from one Win32_ACE object
————————– EXAMPLE 2 ————————–
$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. https://blog.ctglobalservices.com # // 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!
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
Great to hear that someone is using my script 😉
and thanks alot for the bug fix! 🙂
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
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([email protected]) 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] “\$ComputerNamerootcimv2: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] “\$ComputerNamerootcimv2: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] “\$ComputerNamerootcimv2:Win32_Account.Name=’$Name’,Domain=’$Domain'” }
else
{ $account = [WMI] “\$ComputerNamerootcimv2:Win32_Group.Name=’$Name’,Domain=’$Domain'” }
#Get the SID for the found account.
$accountSID = [WMI] “\$ComputerNamerootcimv2: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] “\$ComputerNamerootcimv2: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] “\$ComputerNameRootCimv2: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
#//—————————————————————————-
thnx alot!
i havent had time myself to do it, its great to see other helping out!
merry christmas to you all.
Thank you so much for this script. It saved me a lot of time.
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!
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
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
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
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
}
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
Hello Jakob!
Thanks for this great Example! I tried it but it’s not working.
I get the following Error
“Cannot convert value “\Serverrootcimv2: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
Hello again!
I’ve found the solution and maybe you can explain me. The computername in function New-Ace hast to be “.” Why?
regards
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
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.
Did you ever write Part 2?
@Greg: Thnx for your reply!
@Chris: Sorry no, i did not .. i will try to soon 🙂
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? 🙂
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
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.
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.
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] “\$ComputerNamerootcimv2:Win32_Trustee”).CreateInstance()
if (!$group) { $account = [WMI] “\$ComputerNamerootcimv2:Win32_Account.Name=’$Name’,Domain=’$ComputerName'” }
else
{ $account = [WMI] “\$ComputerNamerootcimv2:Win32_Group.Name=’$Name’,Domain=’$ComputerName'”}
$accountSID = [WMI] “\$ComputerNamerootcimv2:Win32_SID.SID=’$($account.sid)'”
$Trustee.Domain = $Domain
$Trustee.Name = $Name
$Trustee.SID = $accountSID.BinaryRepresentation
$ACE = ([WMIClass] “\$ComputerNamerootcimv2: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
function new-acelocal is not working for Administrators or any local group.
Cannot convert value “\host1rootcimv2:Win32_Group.Name=’Administrators’,Domain=’host1’” to type “System.Management.ManagementObject”. Error: “Invalid pa
rameter ”
At C:UsersTEMPAppDataLocalTemp5867c7417-4389-4f78-a564-90bac98ab8d6.ps1:123 char:20
+ { $account = [WMI] <<<< “\$ComputerNamerootcimv2:Win32_Group.Name=’$Name’,Domain=’$ComputerName’”}
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
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:SistemaScriptsShareFunctions.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).
Thanks a lot for your work, guys!
For those who copy&paste script gets errors like
“Cannot convert value “\host1rootcimv2:Win32_Group.Name=’Administrators’,Domain=’host1’” to type ”System.Management.ManagementObject”. Error: “Invalid pa
rameter ”
At C:UsersTEMPAppDataLocalTemp5867c7417-4389-4f78-a564-90bac98ab8d6.ps1:123 char:20
+ { $account = [WMI] <<<< “\$ComputerNamerootcimv2:Win32_Group.Name=’$Name’,Domain=’$ComputerName’”}
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException"
do not forget to find and replace ’ ” on the ' "
Part2 any time “soon” ???
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
}
I can make the share but it will not add the Administrators Group? i get this error?
Cannot convert value “\.rootcimv2:Win32_Group.Name=’Administrators’,Domain=’Domain'” to type “System.
Management.ManagementObject”. Error: “Not found ”
At C:SupportNew-APPS-Share.PS1:75 char:19
+ { $account = [WMI] <<<< "\$ComputerNamerootcimv2:Win32_Group.Name='$Name',Domain='$Domain'" }
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
Cannot convert value “\.rootcimv2:Win32_Group.Name=’Administrators’,Domain=’Domain'” to type “System.
Management.ManagementObject”. Error: “Not found ”
At C:SupportNew-APPS-Share.PS1:75 char:19
+ { $account = [WMI] <<<< "\$ComputerNamerootcimv2:Win32_Group.Name='$Name',Domain='$Domain'" }
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
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.
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
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.
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
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
newel post austin texas
Coretech Blog » Blog Archive » Powershell â WMI: Working with Shares – Part 1: Creating a Share with Custom Permissions
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.
Works fine, but does not work for hidden shares, how to create hidden shares like admin$.