Tuesday, 15 May 2012

Programmatically sharing a windows directory in C#


Sometime you are in a situation where you want to programmatically share a path and unshared it after use. This was a challenge I was faced with while working on an application that accepted user input, and then it would trigger a different process on another terminal.  The second application would then process and save the output on a path selected by the user. After going through the MSDN and a few google searches, here is what I developed

This article demonstrates how to share a directory and set NTFS permissions on it. start by importing the following library and namespaces.

using System.Security.Permissions;
using System.Security;
using System.Security.AccessControl;
using System.Security.Principal;


Create an instance of the group or user you want to share to, in my case here I want to share to everyone.

NTAccount ntAccount = new NTAccount("Everyone");

Get the group’s Security Identifier (SID).

SecurityIdentifier oGrpSID = (SecurityIdentifier)ntAccount.Translate(typeof(SecurityIdentifier));
byte[] utenteSIDArray = new byte[oGrpSID.BinaryLength];
oGrpSID.GetBinaryForm(utenteSIDArray, 0);

Create a trustee instance from the group SID above

ManagementObject oGrpTrustee = new ManagementClass(new ManagementPath("Win32_Trustee"), null);
oGrpTrustee["Name"] = "Everyone";
oGrpTrustee["SID"] = utenteSIDArray;

Create an Access Control Entry object. Give full access to the folder and allow sub folder to inherit

ManagementObject oGrpACE = new ManagementClass(new ManagementPath("Win32_Ace"), null);
oGrpACE["AccessMask"] = 2032127;//Full access
oGrpACE ["AceFlags"] = AceFlags.ObjectInherit | AceFlags.ContainerInherit; //propagate the AccessMask to the subfolders
oGrpACE["AceType"] = AceType.AccessAllowed;
oGrpACE["Trustee"] = oGrpTrustee;

Create a security descriptor; this will contain the security information for the group

ManagementObject oGrpSecurityDescriptor= new ManagementClass(new ManagementPath("Win32_SecurityDescriptor"), null);
oGrpSecurityDescriptor["ControlFlags"] = 4; //SE_DACL_PRESENT
oGrpSecurityDescriptor["DACL"] = new object[] { oGrpACE };

Lastly Share the directory in question and upgrade the security permissions. In my case is C:\testShare\, the Share Name is Test Share

string FolderPath=”c:\testshare\”;
string ShareName=”Test Share”;
string Description=”This save output”;
ManagementClass mc = new ManagementClass("win32_share");
ManagementBaseObject inParams = mc.GetMethodParameters("Create");
inParams["Description"] = Description;
inParams["Name"] = ShareName;
inParams["Path"] = FolderPath;
inParams["Type"] = 0x0; //Disk Drive
inParams["MaximumAllowed"] = null;
inParams["Password"] = null;
inParams["Access"] = oGrpSecurityDescriptor; 
ManagementBaseObject outParams = mc.InvokeMethod("Create", inParams, null);


Unshare the Directory
Create an Object to query the WMI Win32_Share API for shared files

ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from win32_share");
ManagementBaseObject outParams;
ManagementClass mc = new ManagementClass("Win32_Share"); //for local shares

Loop through all the local shares,

foreach (ManagementObject share in searcher.Get())
{
string type = share["Type"].ToString();

if (type == "0"// Check if it’s a DiskDrive                 {
string path = share["Name"].ToString(); //getting share path name

if (path == "testshare"){ //if it’s the testshare folder

outParams = share.InvokeMethod("delete"nullnull); //Delete the shares

if ((uint)(outParams.Properties["ReturnValue"].Value) != 0)
   {
      // unsuccessful do something

   }
else
   {
     // unsharing successful do something
   }
  }
 }
}


                                                                                

8 comments:

  1. but could you do something out of window?

    ReplyDelete
    Replies
    1. I'll see how that works out on a different post.

      Delete
  2. Thank you! Works from the first try!

    ReplyDelete
  3. Hi,
    I Encorporated ur code in my application but I get the Access denied status in
    ManagementBaseObject outParams = mc.InvokeMethod("Create", inParams, null);
    uint ReturnStatus = Convert.ToUInt32(outParams.Properties["ReturnValue"].Value);

    Dont know whats wrong. Plz help!!

    ReplyDelete
  4. This is a permission issue. Try using and administrator account.

    ReplyDelete
  5. Hey guys, how can I set the shared folder permission to READ ONLY instead of Full Control? Thanks!

    ReplyDelete
    Replies
    1. You need to use the access mask of 1179817 for the Access Control Entry (from Win32_Ace)

      Delete
  6. This code show how to create and delete a shared folder. Is it possible to change the permissions on an already existing share to have something like Full Access to Read or Read to Read and Modify?

    ReplyDelete

Comment