Move a folder on the same volume applying destination permissions - c#

When copying a directory on the same volume (ex. c:) from one folder to another with the .NET DirectoryInfo.MoveTo, the access control are preserved: in other words the destination has the same security has the origin and does not inherit the one of it's new parent.
I would like to be able to move a folder and it's content but replacing the permissions like it was a copy of the folder.
Is there a simple way to achieve this in C#?

const string source = #"C:\test1\test";
const string target = #"C:\test2\test";
Directory.Move(source, target);
// Get Directory Info
var dInfo = new DirectoryInfo(target); // Or FileInfo
var dSec = dInfo.GetAccessControl();
// Set Security to inherit
dSec.SetAccessRuleProtection(false, false);
// Remove Rules/Accounts that are not inherited
var rules = dSec.GetAccessRules(true, false, typeof (NTAccount));
foreach (FileSystemAccessRule rule in rules)
dSec.RemoveAccessRule(rule);
// Commit changes to folder
dInfo.SetAccessControl(dSec);
At first move the folder. Then create a DirectoryInfo and get the AccessControl.
With SetAccessRuleProtection you can reset and inherit security from the parent.
Then remove all accounts/user that are not inherited.
The last line is to commit changes.
Files:
I the folder contains files and other folders, it depends on their security settings.
if they are set to inherit too then they inherit from the folder you changed with the code above (the parent folder)
so if you are not sure what they might be set to you have to do that recursive with all sub-folder and also with all files...
The Code for the Files is the same, except the DirectoryInfo there you have to use FileInfo.
For further information visit File.Move does not inherit permissions from target directory?
// Link for me, to read later: http://support.microsoft.com/kb/320246/de

Related

Determine if the network path targeted by a shortcut is a folder or an archive in C#

I'm trying to determine if the path targeted by a shortcut on Windows is a folder. Let's say I have a test.lnk file on my Desktop which points to the R:\test folder located on a network location. If I also have a shortcut that points to the R:\test.zip archive, I would not want this file to appear in my view.
I currently have the following code which correctly achieves this requirement:
Shell variable = (Shell)Activator.CreateInstance(Marshal.GetTypeFromCLSID(new Guid("13709620-C279-11CE-A49E-444553540000")));
FolderItem variable1 = variable.NameSpace(directoryName).ParseName(fileName);
if (variable1 != null)
{
var shellObject = (ShellLinkObject)variable1.GetLink;
var isShortcutAFolder = shellObject.Target.IsFolder && shellObject.Target.Type == "File folder";
// ...
}
The issue with this approach is that the shellObject.Target.Type property is of type string and its value depends on the language the user has on their machine. The reason I check this property in addition to the IsFolder property of the Target is that archive files (such as .zip and .rar) also have their IsFolder value as true and I do not wish to show such files as directories.
With this said, is there another property I can use of the FolderItem object or some cast that I can make to determine if the target path is actually a file folder?
I do not wish to use the File.GetAttributes or Directory.Exists methods as these result in degraded performance if the network location is offline or inaccessible.

How to create a folder with c# which is NOT read only?

In my C# forms application, I try to download the data in a directory of my SFTP Server. The data should be stored in a folder which I want to create in "MyDocuments". When the folder is created, I receive an Renci error "failure" because the folder is "read-only".
I tried many ways to create a folder, but I in most ways I used I either got an error, that I don't have the permission to create a folder, or I got an empty file instead of a folder. Right now I got a folder, but unluckily it is read only.
String localPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\MyNewFolder\\";
if (Directory.Exists(localPath))
{
Console.WriteLine("Folder already exists");
}
if (!Directory.Exists(localPath))
{
Directory.CreateDirectory(localPath);
DirectoryInfo directory = new DirectoryInfo(localPath);
DirectorySecurity security = directory.GetAccessControl();
}
I expect the folder not to be read only, so that I can safe data in it using my programm. Anyone knows why my code still creates a read only one?
I believe you have to set the following using the DirectorySecurity object:
DirectorySecurity securityRules = new DirectorySecurity();
securityRules.AddAccessRule(new FileSystemAccessRule(#"Domain\Account", FileSystemRights.FullControl, AccessControlType.Allow));
Then you can create the directory using the following:
DirectoryInfo di = Directory.CreateDirectory(#"directoryToCreatePath", securityRules);
EDITED:
Once you've created the directory using Directory.CreateDirectory(), you can then apply the following to the folder. This will allow the user you've specified to have FullControl of the folder. You can check the permissions for that user via Properties > Security
DirectoryInfo directory = new DirectoryInfo("C:\\CreatedFolder");
DirectorySecurity security = directory.GetAccessControl();
security.AddAccessRule(new FileSystemAccessRule(#"USERNAME",
FileSystemRights.FullControl,
AccessControlType.Allow));
directory.SetAccessControl(security);

FolderBrowserDialog add Custom Root Name

FolderBrowserDialog fd = new FolderBrowserDialog();
fd.RootFolder = string.Format("D:\\Project\\folder1\\folder2\\ Results\\{0}", FolderName);
in FolderBrowserDialog the Rootfolder Expects a type of environment.specialfolder
but i want to add my folder as root folder.
i dont want to set the SelectedPath as my custom path.
is there any way to do so.
thanks in advance.
There is no way to change the RootFolder to a custom folder because this is used as a fallback, which I think is what's happening in your code. .Net knows that special folders exist, whereas your custom directory may not.
It looks like you need to remove the space in here ...folder2\\ Results\\... and/or check the FolderName variable as this is producing a directory string that doesn't exist, therefore your dialog is using the RootFolder instead.
Default the RootFolder to Desktop
Set your custom folder as the SelectedPath property
fd.SelectedPath = string.Format("D:\Project\folder1\folder2\ Results\{0}", FolderName);
Call Show method of dialog
fd.ShowDialog();
Note that order of these settings need to be preserved, else will lead to wrong result.
More detail in following answered question
Set folder browser dialog start location
I've dropped a folder browser on a form called "folderBrowserDialog1" and the below seems to work. The special folder option is simply an option to allow the browsing to start in a "Special" folder. E.g. Windows etc.. and it provides a neat mechanism to set it without typing the full path. If you need a custom path, then set the SelectedPath property.
folderBrowserDialog1.RootFolder = Environment.SpecialFolder.MyComputer;
//The above is optional. You don't need to set it.
folderBrowserDialog1.SelectedPath = #"C:\"; //Your path here
folderBrowserDialog1.ShowDialog();
Hope that helps

Notify the change in directory in a website asp.net with c#

I want to implement OBSERVER pattern for a website to raise a event if the content of a particular server directory (including sub directory) is changed (files added or deleted or modified). Moreover the directory can't be accessed via mapping in the website url.
Firstly if you want to check if inside a folder has been added or deleted an item you might use:
List<DirectoryInfo> allSubDirectories = new List<DirectoryInfo>();
DirectoryInfo myDir = new DirectoryInfo("/Path/To/Base/Directory/Here");
foreach(DirectoryInfo di in myDir.GetDirectories())
{
allSubDirectories.Add(di);
}
Now allSubDirectories holds info of all directories inside the base directory, and in the same manner you can retrieve the inner directories.
So now we should check if something is added or removed like so:
int numberOfFiles = someDir.GetFiles().Length; // This will retrieve how much files are there at the start
Then you can easly check if the length is different from some DateTime or depending on your needs
Now to check if a file has been modified, check the examples here
https://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.changed(v=vs.110).aspx
The class FileSystemWatcher has event Changed wich will give information if the file was opened, changed, modified size, modified file name and other info.

How get file from a directory using relative path?

I am pretty new in C# and I am finding some difficulties trying to retrieve a jpg file that is into a directory of my project.
I have the following situation:
I have a Solution that is named MySolution, inside this solution there are some projects including a project named PdfReport. Inside this project there is a folder named Shared and inside this folder there is an header.jpg file.
Now if I want to obtain the list of all files that are inside the Shared directory (that as explained is a directory inside my project) I can do something like this:
string[] filePaths = Directory.GetFiles(#"C:\Develop\EarlyWarning\public\Implementazione\Ver2\PdfReport\Shared\");
and this work fine but I don't want use absolute path but I'd rather use a relative path relative to the PdfReport project.
I am searching a solution to do that but, untill now, I can't found it. Can you help me to do that?
Provided your application's Executable Path is "C:\Develop\EarlyWarning\public\Implementazione\Ver2", you can access the PdfReport\Shared folder as
string exePath = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
string sharedPath = Path.Combine(exePath, "PdfReport\\Shared\\");
string[] filePaths = Directory.GetFiles(sharedPath);
Try to get the current folder by using this
Server.MapPath(".");
In a non ASP.NET application but WinForms or Console or WPF application you should use
AppDomain.CurrentDomain.BaseDirectory
If you want root relative, you can do this (assuming C:\Develop\EarlyWarning is site root)
string[] filePaths = Directory.GetFiles(Server.MapPath("~/public/Implementazione/Ver2/PdfReport/Shared"));
Or if you want plain relative,
//assuming you're in the public folder
string[] filePathes = Directory.GetFiles(Server.MapPath("/Implementazione/Ver2/PdfReport/Shared"));
Root relative is usually best in my experience, in case you move the code around.
You can right click on your file header.jpg, choose Properties, and select for example the option Copy always on the property "Copy to Output Directory".
Then a method like this, in any class that belongs to project PdfReport:
public string[] ReadFiles()
{
return Directory.GetFiles("Shared");
}
will work well.
Alternatively, if you have files that never change at runtime and you want to have access to them inside the assembly you also can embed: http://support.microsoft.com/kb/319292/en-us

Categories