Introduction
As the title of the article describes this article is going to describe a very simple but very helpful topic. Every now and then we are faced with a situation where we have to fix a file or folder's permissions to add or remove a user. The perfect example is installation of an ASP.Net application. If you have a folder in that application which needs write permissions for ASPNET user account then your custom installer may need to add a new ACE that gives ASPNET user the required permissions.
The Code
You can make use of DirectoryServices
classes to accomplish this task. Technically speaking, the techniue does not use the classes defined in System.DirectoryServices
namespace at all. It uses Interop to access ADSI
objects to get the job done. The reason for using Interop is the same as we described in our earlier article, How to get file security information, DirectoryServices
classes does not fully implement all the features present in ADSI
.
using System;
using System.Collections;
using ActiveDs;
namespace PardesiServices.FixFilePermission
{
class FileSecurity
{
[STAThread]
static void Main(string[] args)
{
string strFile = @"D:\mmcInst.log";
try
{
ADsSecurityUtilityClass secuUtil = new ADsSecurityUtilityClass();
object ob = secuUtil.GetSecurityDescriptor(
strFile,
(int)ActiveDs.ADS_PATHTYPE_ENUM.ADS_PATH_FILE,
(int)ActiveDs.ADS_SD_FORMAT_ENUM.ADS_SD_FORMAT_IID);
if (null != ob)
{
ActiveDs.IADsSecurityDescriptor sd =
(IADsSecurityDescriptor)ob;
ActiveDs.IADsAccessControlList obDacl =
(ActiveDs.IADsAccessControlList)sd.DiscretionaryAcl;
bool bAddAce = true;
IEnumerator obAceEnum = obDacl.GetEnumerator();
while (obAceEnum.MoveNext())
{
IADsAccessControlEntry obAce =
(IADsAccessControlEntry)obAceEnum.Current;
Console.WriteLine("Trustee: {0}", obAce.Trustee);
if (obAce.Trustee.IndexOf("ASPNET") != -1)
{
if (obAce.AceType ==
(int)ADS_ACETYPE_ENUM.ADS_ACETYPE_ACCESS_ALLOWED)
{
bAddAce = false;
}
}
}
if (bAddAce)
{
AccessControlEntryClass obNewAce =
new AccessControlEntryClass();
obNewAce.AceType =
(int)ADS_ACETYPE_ENUM.ADS_ACETYPE_ACCESS_ALLOWED;
obNewAce.Trustee = @"ASPNET";
obNewAce.AccessMask = -1;
obDacl.AddAce(obNewAce);
sd.DiscretionaryAcl = obDacl;
secuUtil.SetSecurityDescriptor(
strFile,
(int)ADS_PATHTYPE_ENUM.ADS_PATH_FILE,
sd,
(int)ADS_SD_FORMAT_ENUM.ADS_SD_FORMAT_IID);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
If you notice, at the top of the code we have referenced ActiveDs
namespace. This namespace is included into the project by referencing to Active DS Type Library COM object in your project. If you use Visual Studio .NET IDE, then you can right click on the project and choose Add Reference menu option to add the required COM object refrence. If you are using command line compiler then use tlbimp utility to import activeds.tlb.