Get rights on folder - c#

I'm trying to get right for a folder. The purpose is to create a file inside this folder when i ask my program to create this file. I tried almost everything and it still don't work.
try
{
DirectorySecurity ds = Directory.GetAccessControl(path);
foreach (FileSystemAccessRule rule in ds.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier)))
{
if ((rule.FileSystemRights & FileSystemRights.CreateFiles) > 0 /*== FileSystemRights.CreateFiles)*/)
return true;
}
}
catch (UnauthorizedAccessException e)
{
return false;
}
return false;
My problem is: The FileSystemAccessRule said that I have the permissions but when I want to create my file, "unauthorizedexception" exception appears.
I tried to use a DirectoryInfo, like that:
DirectoryInfo di = new DirectoryInfo(path);
DirectorySecurity ds = di.GetAccessControl();
instead of to use the "Directory" object directly. Plus, i was thinking that my problem was concerning the GetAccessRules, so I tried to use the SecurityIdentifier and also NTAccount, both said that I have all the right on this folder (FullControl) whereas at the end, i don't have any right. And of course my path is good, I checked it.
Someone knows another method to get the right on a folder, or if I do something wrong, a bit of help will be a pleasure.

I think the problem with your code is that is does not check on the specific users which have access. GetAccessControl gets a list of ALL users that have any access rule applied to the folder, not just YOU.
There is an excellent answer already here how to do the proper checking: Checking for directory and file write permissions in .NET

Related

Directory exists is producing inconsistant results on desktop vs server

I have a C# program which checks if a specific directory exists.
It is simply doing:
Directory.Exists(path).
I tried other ways as well. Using DirectoryInfo and using AlphaFS
On my local machine, the path exists. When I run the same program on a server with the same credentials it doesn't exist.
I wonder if it is a group policy issue. But I am able to go up one level and see it.
\server\volume\share\sub directory - Doesn't exist remotely but on my desktop it does
\server\volume\share - Does exist both on my desktop and remote server
Update
I forgot to mention, that since I had access to my desktop, I got the ACL information.
None of the groups were able to translate.
I really just want to get this application to behave the same way is on the server and find out why it is behaving differently.
Update 2
These are physical servers.
My desktop is Liquid VDI
Below is the code:
var path = txtPath.Text;
using (var user = new Impersonation(fuserdomain, fc_user, fc_pass))
{
var alphaExists = Alphaleonis.Win32.Filesystem.Directory.Exists(path);
var alphaDIExists = new Alphaleonis.Win32.Filesystem.DirectoryInfo(path).Exists;
var SystemExists = System.IO.Directory.Exists(path);
var SystemDIExists = new System.IO.DirectoryInfo(path).Exists;
var AlphaHasFiles = false;
var AlphaDIHasFiles = false;
var SystemHasFiles = false;
var SystemDIHasFiles = false;
try
{
Directory.GetFiles(path);
AlphaHasFiles = true;
}
catch { }
try
{
new DirectoryInfo(path).GetFiles();
AlphaDIHasFiles = true;
}
catch { }
try
{
System.IO.Directory.GetFiles(path);
SystemHasFiles = true;
}
catch { }
try
{
new System.IO.DirectoryInfo(path).GetFiles();
SystemDIHasFiles = true;
}
catch { }
MessageBox.Show(string.Format("alphaExists: {0}\nalphaDIExists: {1}\nSystemExists: {2}\nSystemDIExists: {3}\nAlphaGetFiles: {4}\nAlphaDIGetFiles: {5}\nSystemGetFiles: {6}\nSystemDIGetFiles: {7}\n", alphaExists, alphaDIExists, SystemExists, SystemDIExists, AlphaHasFiles, AlphaDIHasFiles, SystemHasFiles, SystemDIHasFiles));
}
Update 3
Although I have workaround this issue; I am still not sure why I would have a difference between my desktop and server. Is there any tool that can help me see where the issue may be?
I've seen the same thing with File.Exists. I never found an answer and finally threw in the towel, I simply try to use it and catch the exception.
Robust code has to catch it anyway, all the test does is avoid trying if the file or directory is not there. (And the PITA that Visual Studio no longer as any way to ignore an exception on a certain line. No problem runtime, annoying in development.)
This is a complete shot in the dark, since we don't have any specific details to go on. e.g. Is the server you're talking about physically yours, or is it a cloud-based server service?
I'd guess that your machine is an older operating system than the server, and the folder that you're trying to access is one of those special folders that has become more locked down with more recent operating systems (particularly on server operating systems) like the "Program Files" folder. So even though the folder exists on both, the method works on your machine but not on the server, due to permissions.
Hope this helps.
As far as I can tell, the Impersonation class in your code is not part of the dot net framework. Googling finds a couple of implementations. Where does it come from and How confident are you that it actually works in your scenario?
For example, if you remove the Impersonation code, and actually run it as that user, does that make it work?
One other clarification... When you say
\server\volume\share
Do you mean this is a network location (e.g. a UNC location), so is the same network path you are trying to access from both machines? If so, this would open up new possibilities for problems like firewalls, etc... Is that location on either of the two machines that we know about from the question, or a different location?

Create a folder without read-only using c# [duplicate]

I was successfully able to remove read only attribute on a file using the following code snippet:
In main.cs
FileSystemInfo[] sqlParentFileSystemInfo = dirInfo.GetFileSystemInfos();
foreach (var childFolderOrFile in sqlParentFileSystemInfo)
{
RemoveReadOnlyFlag(childFolderOrFile);
}
private static void RemoveReadOnlyFlag(FileSystemInfo fileSystemInfo)
{
fileSystemInfo.Attributes = FileAttributes.Normal;
var di = fileSystemInfo as DirectoryInfo;
if (di != null)
{
foreach (var dirInfo in di.GetFileSystemInfos())
RemoveReadOnlyFlag(dirInfo);
}
}
Unfortunately, this doesn't work on the folders. After running the code, when I go to the folder, right click and do properties, here's what I see:
The read only flag is still checked although it removed it from files underneath it. This causes a process to fail deleting this folder. When I manually remove the flag and rerun the process (a bat file), it's able to delete the file (so I know this is not an issue with the bat file)
How do I remove this flag in C#?
You could also do something like the following to recursively clear readonly (and archive, etc.) for all directories and files within a specified parent directory:
private void ClearReadOnly(DirectoryInfo parentDirectory)
{
if(parentDirectory != null)
{
parentDirectory.Attributes = FileAttributes.Normal;
foreach (FileInfo fi in parentDirectory.GetFiles())
{
fi.Attributes = FileAttributes.Normal;
}
foreach (DirectoryInfo di in parentDirectory.GetDirectories())
{
ClearReadOnly(di);
}
}
}
You can therefore call this like so:
public void Main()
{
DirectoryInfo parentDirectoryInfo = new DirectoryInfo(#"c:\test");
ClearReadOnly(parentDirectoryInfo);
}
Try DirectoryInfo instead of FileInfo
DirectoryInfo di = new DirectoryInfo(#"c:\temp\content");
di.Attributes = FileAttributes.Normal;
To clean up attrbutes on files-
foreach (string fileName in System.IO.Directory.GetFiles(#"c:\temp\content"))
{
System.IO.FileInfo fileInfo = new System.IO.FileInfo(fileName);
fileInfo.Attributes = FileAttributes.Normal;
}
The dialog just works in a fairly bizarre way. It always shows up the way you see it in your screen shot, whatever the state of the ReadOnly attribute. The checkbox is in the 'indetermined' state. You have to click it and either clear or check it to make it perform its action. And in spite of the prompt text (but not the hint next to the checkbox), it only changes the ReadOnly attribute on the files in the directory, not the directory itself.
Use the attrib command line command to see what is really going on. In all likelihood, your code fails because the directory contains files that have their ReadOnly attribute set. You'll have to iterate them.
The read-only flag on directories in Windows is actually a misnomer. The folder does not use the read-only flag. The issue is going to be with the customization. The flag is used by Windows to identify that there are customizations on the folder.
This is an old post, with an issue that is sunsetting, but, figured people might still run into it, as it is pretty annoying when you hit it.
Microsoft's Explanation
IEnumerable / Lambda solution for recursively removing readonly attribute from directories and files:
new DirectoryInfo(#"some\test\path").GetDirectories("*", SearchOption.AllDirectories).ToList().ForEach(
di => {
di.Attributes &= ~FileAttributes.ReadOnly;
di.GetFiles("*", SearchOption.TopDirectoryOnly).ToList().ForEach(fi => fi.IsReadOnly = false);
}
);
Set the Attributes property on the original dirInfo:
dirInfo.Attributes = FileAttributes.Normal;
FileSystemInfo[] sqlParentFileSystemInfo = dirInfo.GetFileSystemInfos();
foreach (var childFolderOrFile in sqlParentFileSystemInfo)
{
RemoveReadOnlyFlag(childFolderOrFile);
}
Just in case any one happens across this later...
ALL of the other answers posted before mine are either wrong or use unnecessary recursion.
First of all the "Read Only" check box in the property dialog of windows always has the tri-state marker for folders. This is because the folder itself is not read only but the files inside can be.
If you want to set/unset read only flag for ALL files. you can do it simply as follows:
void SetReadOnlyFlagForAllFiles(DirectoryInfo directory, bool isReadOnly)
{
// Iterate over ALL files using "*" wildcard and choosing to search all directories.
foreach(FileInfo File in directory.GetFiles("*", SearchOption.All.Directories))
{
// Set flag.
File.IsReadOnly = isReadOnly;
}
}
I see that #DotnetDude said in comments that solutions of guys don't work. To my mind it is happens because guys don't mentioned that need to use File.SetAttributes method to apply new attributes.
This may or may not be directly related, but the root issue in your case may be caused by the underlying files. For example, I ran into this issue trying to delete a directory:
System.IO.Directory.Delete(someDirectory, true)
This results in "Access to the path 'blah' is denied". To resolve this underlying problem, I removed the read-only attribute on sub-files and was then able to remove the parent directory. In my case, I was using powershell, so you can use the .NET equivalent.
dir -r $PrePackageDirectory |% {if ($_.PSIsContainer -ne $true){$_.IsReadOnly = $false}}
Shell("net share sharefolder=c:\sharefolder/GRANT:Everyone,FULL")
Shell("net share sharefolder= c:\sharefolder/G:Everyone:F /SPEC B")
Shell("Icacls C:\sharefolder/grant Everyone:F /inheritance:e /T")
Shell("attrib -r +s C:\\sharefolder\*.* /s /d", AppWinStyle.Hide)
this code is working for me.. to share a folder to every one with read and write permission

Directory.CreateDirectory access to path is denied?

I have server-client application, it's a file manager
my problem is when I go inside a folder which requires access control like system folders, it becomes to read-only, but I need to move/delete or create new folder, how can I get the permission to do that?
here's how I create a new folder at the server side
public void NewFolder(string path)
{
try
{
string name = #"\New Folder";
string current = name;
int i = 0;
while (Directory.Exists(path + current))
{
i++;
current = String.Format("{0} {1}", name, i);
}
Directory.CreateDirectory(path + current);
Explore(path); //this line is to refresh the items in the client side after creating the new folder
}
catch (Exception e)
{
sendInfo(e.Message, "error");
}
}
There are often directories on a drive that even a user with administrator privileges cannot access. A directory with a name like "HDDRecovery" is quite likely to be troublesome like this. Surely it contains sensitive data that helps the user recover from disk failure. Another directory that fits this category is "c:\system volume information", it contains restore point data.
An admin can change the permissions on folders like this. But of course that doesn't solve the real problem nor is it a wise thing to do. Your user can't and shouldn't. Be sure to write code that deals with permission problems like this, simply catch the IOExeption. Keep the user out of trouble by never showing a directory that has the Hidden or System attribute set. They are the "don't mess with me" attributes.
If you want to remove directory read-only attribute use this: http://social.msdn.microsoft.com/Forums/en/vblanguage/thread/cb75ea00-f9c1-41e5-ac8e-296c302827a4
If you want to access system folders you can run your program as local administrator.
I had a similar problem (asp.net MVC vs2017) with this code:
Directory.CreateDirectory("~/temp");
Here is my solution:
// Create path on your web server
System.IO.Directory.CreateDirectory(System.Web.HttpContext.Current.Server.MapPath("~/temp"));
I also ran into an issue similar to this, but I was able to manually navigate through Windows Explorer and create directories.
However, my web app, running in VS on my laptop, hosted through my local IIS and not the built-in IIS deal for VS, was triggering the Access Denied issue.
So when I was hitting the error in code, I drilled down to glean more data from the System.Environment object and found the user, which of course was the App Pool that my app was running under in IIS.
So I opened IIS and opened the Advanced Settings for the app pool in question and changed the Identity to run under Network Service. Click OK. "cmd -> iisreset" for good measure. Try the app again, and SUCCESS!!!!
I had the same issue when creating a directory. I used DirectorySecurity as shown below:
DirectorySecurity securityRules = new DirectorySecurity();
securityRules.AddAccessRule(new FileSystemAccessRule(#"Domain\AdminAccount1", FileSystemRights.Read, AccessControlType.Allow));
securityRules.AddAccessRule(new FileSystemAccessRule(#"Domain\YourAppAllowedGroup", FileSystemRights.FullControl, AccessControlType.Allow));
DirectoryInfo di = Directory.CreateDirectory(path + current, securityRules);
Also keep in mind about the security as explained by Hans Passant's answer.
Full details can be found on MSDN.
So the complete code:
public void NewFolder(string path)
{
try
{
string name = #"\New Folder";
string current = name;
int i = 0;
while (Directory.Exists(path + current))
{
i++;
current = String.Format("{0} {1}", name, i);
}
//Directory.CreateDirectory(path + current);
DirectorySecurity securityRules = new DirectorySecurity();
securityRules.AddAccessRule(new FileSystemAccessRule(#"Domain\AdminAccount1", FileSystemRights.Read, AccessControlType.Allow));
securityRules.AddAccessRule(new FileSystemAccessRule(#"Domain\YourAppAllowedGroup", FileSystemRights.FullControl, AccessControlType.Allow));
DirectoryInfo di = Directory.CreateDirectory(path + current, securityRules);
Explore(path); //this line is to refresh the items in the client side after creating the new folder
}
catch (Exception e)
{
sendInfo(e.Message, "error");
}
}
My suspicion is that when you are running the application in client/server mode, the server portion needs to be running as Administrator, in addition to possibly removing read-only or system flags, to be able to do what you want.
That said, I agree with #HansPassant- it sounds like what you are trying to do is ill-advised.
Solved:
Directory created on remote server using below code & setting.
Share folder and give the full permission rights also in Advance
setting in the folder.
DirectoryInfo di = Directory.CreateDirectory(#"\\191.168.01.01\Test\Test1");
Test is destination folder where to create new Test1 folder(directory)

Remove Read-Only Attribute On FOLDER On A Network Share

I am having an issue that is really killing me.
I have a directory that when I go to the properties window, shows Read-Only as partially checked (not a full check box, but the box is filled).
So I looked in the directory and I checked all the files, none of them have the read-only attribute. Only the folder has it, and only partially.
I tried the following code:
if (directoryInfo.Exists)
{
try
{
directoryInfo.Attributes &= ~FileAttributes.ReadOnly;
foreach (FileInfo f in directoryInfo.GetFiles())
{
f.IsReadOnly = false;
}
}
catch (Exception e)
{
throw e;
}
}
It still did not work. I can right click on the folder and manually remove the read-only permissions but I need to be able to do this in code. The code executes but does not error.
Anyone have any idea what the issue could be? My only guess is because the folder is on a network share (in the form of \\computer\folder\subfolder), that I might need special rights in order to change permissions on a folder?
Please someone help.
Thanks in advance
readonly on folders is used by Windows internally... if you really need to change it then is some work involved (Registry and changing alot of folders)... see http://support.microsoft.com/kb/256614/en-us
Why do you need to make that change ?
EDIT - some information on Powershell and TFS:
http://codesmartnothard.com/ExecutingPowerShellScriptsOnRemoteMachinesWithTFS2010AndTeamDeploy2010.aspx
http://blogs.msdn.com/b/yao/archive/2011/06/15/tfs-integration-pack-and-scripting-using-powershell.aspx
or try a normal "batch file" (.bat) with "attrib -r" on the folder

Copy ACL information like XCopy

We recently were forced to move to a new domain server half-way around the world. This may not seem like much of a change, but one of the processes that we run frequently has suddenly gone form a 2-second command to a 5-minute command.
The reason? We are updating the permissions on many directories based on a "template" directory structure.
We've discovered that XCOPY can update the majority of these settings in the same-old-two-second window. The remaining settings, of course, get left off.
What I'm trying to figure out is, how can XCopy do faster what .NET security classes should do natively? Obviously I'm missing something.
What is the best method for copying a directory's ACL information without pinging (or minimal pinging) the domain/Active Directory server?
Here's what I have:
...
DirectorySecurity TemplateSecurity = new DirectorySecurity(TemplateDir, AccessControlSections.All);
...
public static void UpdateSecurity(string destination, DirectorySecurity TemplateSecurity)
{
DirectorySecurity dSecurity = Directory.GetAccessControl(destination);
// Remove previous security settings. (We have all we need in the other TemplateSecurity setting!!)
AuthorizationRuleCollection acl_old = dSecurity.GetAccessRules(true, true, typeof(NTAccount));
foreach (FileSystemAccessRule ace in acl_old)
{
// REMOVE IT IF YOU CAN... if you can't don't worry about it.
try
{
dSecurity.RemoveAccessRule(ace);
}
catch { }
}
// Remove the inheritance for the folders...
// Per the business unit, we must specify permissions per folder.
dSecurity.SetAccessRuleProtection(true, true);
// Copy the permissions from TemplateSecurity to Destination folder.
AuthorizationRuleCollection acl = TemplateSecurity.GetAccessRules(true, true, typeof(NTAccount));
foreach (FileSystemAccessRule ace in acl)
{
// Set the existing security.
dSecurity.AddAccessRule(ace);
try
{
// Remove folder inheritance...
dSecurity.AddAccessRule(new FileSystemAccessRule(
ace.IdentityReference, ace.FileSystemRights,
InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
PropagationFlags.None,
ace.AccessControlType));
}
catch { }
}
// Apply the new changes.
Directory.SetAccessControl(destination, dSecurity);
}
Okay... I have a working prototype after A TON OF DIGGING on the internet. Needless to say, there's alot of mis-information about ACL online. I'm not exactly certain if this bit of info will be a godsend, or more mis-information. I'll have to leave that for you, the user, to decide.
What I ended up with is clean, slick, and very, very fast since it doesn't ever TOUCH the domain server. I'm copying the SDDL entries directly. Wait, you say... you can't do that on a directory because you get the dreaded SeSecurityPrivilege error!
Not if you restrict the copy to ONLY the Access Control Lists (ACL).
Here's the code:
public static void UpdateSecurity(string destination, DirectorySecurity templateSecurity)
{
DirectorySecurity dSecurity = Directory.GetAccessControl(destination);
string sddl = templateSecurity.GetSecurityDescriptorSddlForm(AccessControlSections.Access);
try
{
// TOTALLY REPLACE The existing access rights with the new ones.
dSecurity.SetSecurityDescriptorSddlForm(sddl, AccessControlSections.Access);
// Disable inheritance for this directory.
dSecurity.SetAccessRuleProtection(true, true);
// Apply these changes.
Directory.SetAccessControl(destination, dSecurity);
}
catch (Exception ex)
{
// Note the error on the console... we can formally log it later.
Console.WriteLine(pth1 + " : " + ex.Message);
}
// Do some other settings stuff here...
}
Note the AccessControlSections.Access flags on the SDDL methods. That was the magic key to make it all work.

Categories