Add recursive command to set sub directory permissions in C# - c#

I would like to add a recursive command to this script that allows it to loop through a current direcotries sub directory/files and set the permissions on the subfolders/files to whatever I would like. Here is what I have so far which allows for the permissions to be changed on the first set of subdirectories. Obviously, I can add the samecode in to keep diving down through the folder structure, but not every root folder will have the same amount of sub folders within it. I want to add the recursive command to loop through all subdirectories and when there are no more, move on to the next root folder.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Security.AccessControl;
using System.Management;
using System.Management.Instrumentation;
namespace ApplyPermissions
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void label1_Click(object sender, EventArgs e)
{
}
private void selectDirectoryBtn_Click(object sender, EventArgs e)
{
FolderBrowserDialog myFolderBrowserDialog = new FolderBrowserDialog();
myFolderBrowserDialog.ShowDialog();
selectedDirBox.Text = myFolderBrowserDialog.SelectedPath.ToString();
try
{
DirectoryInfo myDirectoryInfo = new DirectoryInfo(selectedDirBox.Text);
foreach (DirectoryInfo currentDir in myDirectoryInfo.GetDirectories())
{
toolStripStatusLabel1.Text = currentDir.Name;
DirectorySecurity DirSecurity = currentDir.GetAccessControl();
DirSecurity.AddAccessRule(new FileSystemAccessRule(“Whatever permissions group I choose”, FileSystemRights.CreateFiles, AccessControlType.Allow));
currentDir.SetAccessControl(DirSecurity);
// Step thru each file within current Directory and assign access
foreach (FileInfo currentFile in currentDir.GetFiles())
{
FileSecurity fileSecurity = currentFile.GetAccessControl();
fileSecurity.AddAccessRule(new FileSystemAccessRule("Whatever permissions group I choose", FileSystemRights.FullControl, AccessControlType.Allow));
currentFile.SetAccessControl(fileSecurity);
}
foreach (DirectoryInfo subDir in currentDir.GetDirectories ())
{
toolStripStatusLabel1.Text = currentDir.Name + "/" + subDir.Name;
DirectorySecurity allsubDirSecurity = subDir.GetAccessControl();
allsubDirSecurity.AddAccessRule(new FileSystemAccessRule("Whatever permissions group I choose ", FileSystemRights.FullControl, AccessControlType.Allow));
subDir.SetAccessControl(allsubDirSecurity);
// Step thru each file within current SubDirectory and assign access
foreach (FileInfo currentFile in subDir.GetFiles())
{
FileSecurity fileSecurity = currentFile.GetAccessControl();
fileSecurity.AddAccessRule(new FileSystemAccessRule("Whatever permissions group I choose", FileSystemRights.FullControl, AccessControlType.Allow));
currentFile.SetAccessControl(fileSecurity);
}
}
}
labelFinished.Text = "Completed Successfully";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + "/////////////////" + ex.StackTrace);
}
}
}
}

First, if your target framework is 4.0, recommend that you use the Directory.EnumerateFiles method (you can also find 3rd code that does the same thing.)
Assuming this is a no-go, you can simplify your recursive processing by using the yield keyword, e.g. make a traverse method based on yield -- I'm showing this with a filter function to since it would often be useful in directory traversal ad should give you ideas.
static IEnumerable<string> traverse(string path, Func<string, bool> filter)
{
foreach (string f in Directory.GetFiles(path).Where(filter))
{
yield return f;
}
foreach (string d in Directory.GetDirectories(path))
{
foreach (string f in traverse(d, filter))
{
yield return f;
}
}
}
Then you use traversal() this way
var files = traverse(PATH, WHERE);
foreach (string f in files) { DoWhatever; }
You will have a more easily reusable directory traversal at your fingertips. I know that I am not yielding directories in the snippet above, but if I wanted to process both files and directory, I would base this on the DirectoryInfo.GetFileSystemInfos method instead.
I forget when the yield feature was added, but it has been available for quite a while.

Related

Move Directory to Google Bucket

How can we move entire folder(within folder have many sub directory too) to Bucket of google cloud? Can anyone help on this.
Use -r flag in gsutil copy command.
From gsutil documentation:
If you want to copy an entire directory tree you need to use the -r option. For example, to upload the directory tree "dir":
gsutil cp -r mydir gs://my-bucket
The Cloud Storage Client for C # library does not support uploading folders, you must create a function (sync / asynchronous) that gets all the files/subfolders inside your folder and uploads each file.
I found a folder iterator code in this Microsoft Link In my code example I added the GCS library to upload the files, it is not necessary to create a folder structure.
For example
// GCS dependencies
using Google.Apis.Storage.v1;
using Google.Apis.Storage.v1.Data;
using Google.Cloud.Storage.V1;
using Storage;
// GCS dependencies
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
static void WalkDirectoryTree(System.IO.DirectoryInfo root)
{
System.IO.FileInfo[] files = null;
System.IO.DirectoryInfo[] subDirs = null;
// initialize the GCS client library
var storage = StorageClient.Create();
// use this variable to define the upload bucket, please use your bucket name
var bucketName= Myawesomebucket
try
{
files = root.GetFiles("*.*");
}
catch (UnauthorizedAccessException e)
{
}
catch (System.IO.DirectoryNotFoundException e)
{
Console.WriteLine(e.Message);
}
if (files != null)
{
foreach (System.IO.FileInfo fi in files)
{
// If we
// want to open, delete or modify the file, then
// a try-catch block is required here to handle the case
// where the file has been deleted since the call to TraverseTree().
Console.WriteLine(fi.FullName);
// this section is used to upload files to GCS
// the object name includ folder/subfolder structure
objectName = objectName ?? Path.GetFileName(fi.FullPath);
// upload the object to the bucket
storage.UploadObject(bucketName, objectName, null, f);
Console.WriteLine($"Uploaded {objectName}.");
}
// Now find all the subdirectories under this directory.
subDirs = root.GetDirectories();
foreach (System.IO.DirectoryInfo dirInfo in subDirs)
{
// Resursive call for each subdirectory.
WalkDirectoryTree(dirInfo);
}
}
}

Get Absolute Path of file in C# from file name [duplicate]

This question already has answers here:
How to get a path to the desktop for current user in C#?
(2 answers)
Closed 3 years ago.
I have a File on my Desktop and I want to get the full Path of the File in my code, should it be on my Desktop or anywhere
My code is looking like this
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GetFullPath
{
class Program
{
static void Main(string[] args)
{
string filename = "eMemoExpenseApproval.docx";
string fullFilePath = Path.Combine(Directory.GetCurrentDirectory(), filename);
Console.Write("Path : " + fullFilePath);
Console.Read();
}
}
}
Rather than get the full path from Desktop it shows the Path from Visual Studio, which is not suppose to be so, but i get this instead
Path : C:\Users\Administrator\Documents\Visual Studio 2017\Projects\GetFullPath\GetFullPath\bin\Debug\eMemoExpenseApproval.docx
Edit:
this works to get the Path of the file on Desktop
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GetFullPath
{
class Program
{
static void Main(string[] args)
{
string filename = "eMemoExpenseApproval.docx";
string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string fullFilePath = path +"/"+ filename;
Console.Write("Path : " + fullFilePath);
Console.Read();
}
}
}
Fine but How about other directories?
Directory.GetCurrentDirectory() actually returns the directory in which the application is executed.
If you know that the file is located in your Desktop, you can instead do something like this :
string fullFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop, filename));
As I understand you want to search a limited set of folders for a named file. To do that declare a function like this:
IEnumerable<string> FindInMultipleFolders(string[] folders, string filename)
{
var result = new List<string>();
foreach (var folder in folders)
{
var dirs = Directory.GetFiles(folder, filename);
foreach (String dir in dirs)
{
result.Add(dir);
}
}
return result;
}
And call it with the file name and the folders to search like this:
FindInMultipleFolders(
new string[]
{
Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
#"C:\Some\Other\Folder\I\Would\Like\Searched"
},
"eMemoExpenseApproval.docx");
}
The file might be in multiple folders, so the function returns an IEnumerable<string>. FindInMultipleFolders only searches the passed folders, not subfolders. If you want subfolders to be searched you should add SearchOption.AllDirectories as a third parameter to GetFiles. Then you could search the whole hard drive with:
FindInMultipleFolders(
new string[]
{
#"C:\"
},
"eMemoExpenseApproval.docx");
}

Getting a List of all filepaths for Audio Files in a certain directory

I am trying to build my own Music Player android app.
I want it to be very simple, just find all valid music files (perhaps I set file types such as mp3, m4a, wma etc for it to look for?) and play them in order of how they are found.
So far I have it so that I can find the default music folder path using
string musicDirectoryPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryMusic).ToString();
What I now need is to check every file (and folder) inside that folder to see if it is mp3/m4a etc and then add them to the list. I've been messing and trying some foreach loops but cannot get anything useful.
I am very confused and quite new to Android development.
As you will see, if I specify a song that I know is on my phone in the default directory (*/NewPipe/Intergalatic - Beastie.m4a), then the music is playing.
So, how can I get a List of all those strings such as the "NewPipe/Beastie.." etc (along with the other 500+ folders inside my default music directory?
Here is my entire class so far (it's the only class in the project):
using System;
using Android.App;
using Android.OS;
using Android.Runtime;
using Android.Support.Design.Widget;
using Android.Support.V7.App;
using Android.Views;
using Android.Widget;
using Android.Media;
using Xamarin.Android;
using System.IO;
using System.Collections.Generic;
using Android.Util;
namespace Music_Player_v001
{
[Activity(Label = "#string/app_name", Theme = "#style/AppTheme.NoActionBar", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
protected MediaPlayer mediaPlayer;
List<string> filepaths_audio = new List<string>();
public void StartMediaPlayer(String filePath)
{
mediaPlayer.Reset();
mediaPlayer.SetDataSource(filePath);
mediaPlayer.Prepare();
mediaPlayer.Start();
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_main);
Android.Support.V7.Widget.Toolbar toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
SetSupportActionBar(toolbar);
FloatingActionButton fab = FindViewById<FloatingActionButton>(Resource.Id.fab);
fab.Click += FabOnClick;
string musicDirectoryPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryMusic).ToString();
Log.Info("FILEPATHS: ", "music directory path is: " + musicDirectoryPath);
mediaPlayer = new MediaPlayer();
StartMediaPlayer(musicDirectoryPath + "/NewPipe/Intergalactic - Beastie Boys (HD).m4a");
//foreach(AudioTrack track in Android.OS.Environment.DirectoryMusic)
//{
// Log.Info("BULLSHIT TAG","track count =======================" + tracks);
// tracks++;
//}
}
public override bool OnCreateOptionsMenu(IMenu menu)
{
MenuInflater.Inflate(Resource.Menu.menu_main, menu);
return true;
}
public override bool OnOptionsItemSelected(IMenuItem item)
{
int id = item.ItemId;
if (id == Resource.Id.action_settings)
{
return true;
}
return base.OnOptionsItemSelected(item);
}
private void FabOnClick(object sender, EventArgs eventArgs)
{
View view = (View) sender;
Snackbar.Make(view, "Replace with your own action", Snackbar.LengthLong)
.SetAction("Action", (Android.Views.View.IOnClickListener)null).Show();
}
}
}
Additional
I also tried this:
foreach (File f in Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryMusic))
{
}
It sounds like your main issue is recursively iterating through all the files in the directory and its subdirectories. Here are a few relevant links:
How to recursively list all the files in a directory in C#?
Best way to iterate folders and subfolders
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/file-system/how-to-iterate-through-a-directory-tree
The easiest approach is probably Directory.EnumerateFiles, used like this: Directory.EnumerateFiles(musicDirectoryPath, "*", SearchOption.AllDirectories) to ensure that it also enumerates through the sub-directories.
foreach (string musicFilePath in Directory.EnumerateFiles(musicDirectoryPath, "*", SearchOption.AllDirectories)) {
Log.Info("Music File", "Music file path is " + musicFilePath);
// do whatever you want to with the file here
}
Note that this may fail if there is an access-restricted directory (or some other error) somewhere in the tree. If you'd like your solution to work around this, see the links I posted above, particularly the bottom one.
Also note, you can change that "*" (wildcard) in the method call to "*.mp3" or "*.wav" or so on, to only match files with those extensions. However, as the method doesn't support regex, I don't think there's any way to match multiple file extensions (like BOTH mp3 and wav). I think you'd have to use the "*" and then just check within the foreach if the file is a valid music file.

Treeview search results flat list

How can I make the list on the right populate with only items which meet the search criteria? I'm not asking for the literal code necessarily, but just some general guidance on how to do so.
I've already written the code to populate the list on the left with C#, supplying a directory to populate the list from. I was just not clear on how to get the list to populate correctly when using the search field at the top.
Should I just call another function which researches the directory for the files based on the search criteria? or store the initial file list in a variable and search within that to populate the list?
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace directoryBrowser
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
ListDirectory(treeView1, #"C:\Windows");
}
public void ListDirectory(TreeView treeView, string path)
{
treeView.Nodes.Clear();
var rootDirectoryInfo = new DirectoryInfo(path);
treeView.Nodes.Add(CreateDirectoryNode(rootDirectoryInfo));
}
public static TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo)
{
var directoryNode = new TreeNode(directoryInfo.Name);
foreach (var directory in directoryInfo.GetDirectories())
{
try
{
directoryNode.Nodes.Add(CreateDirectoryNode(directory));
} catch {
// cannot access directory
}
}
foreach (var file in directoryInfo.GetFiles())
{
directoryNode.Nodes.Add(new TreeNode(file.Name));
}
return directoryNode;
}
}
}
Create a parent node that should be global to the form. so that you can use the parent node without searching the directory (folder) on the harddisk every time. lets say
var directoryNode = new TreeNode(directoryInfo.Name);
and add all the subsequent nodes to the directoryNode as your code already performing this. Finally you get the overall structure added to directoryNode. Add this directoryNode to the treeview. your treeview will be populated. when the user provides search parameter, search in the directoryNode not in the actual directory, in memory searching is fast then searching directory on the hardisk, and create list of nodes and assign to the treeview. when the search parameter is removed by the user assign the directoryNode again.
Hope this suggestion will help

Quickest way to use C# to programmatically search entire computer for several dozen unique filenames?

I am writing a program to do compatibility checking... Basically I am going to have a database that contains filenames, and version info for specific file.
This database will store hundreds of unique filenames, and these files could exist in many places on a clients computer.
I could probably do additional work and find out where each file is "suppose" to exist, but obviously that will sometimes be machine dependent, for example 32 bit system files might exist in program files, 64 bit could be either program files or program files (x86).
However, it is also possible that multiple versions of these files exist in different places on the computer, and could be stored in temp data directories like appdata.
So really what I would like to do is search the entire root drive, for all instances of these files, check the file version, and compare that against what is in the database.
Searching the entire root directory and all sub directories for 1 file is time consuming, let alone iterating through hundreds of unique filenames 1 at a time searching entire root.
Would it be easier to just return a list of all files on machine and location, write that to temp table, and then i can iterate through my list of files in sql which would be much quicker?
Dunno, but I would like this search to be fairly quick, not take 2 hours.... ;-)
I just tested this code against my C drive (SSD) with a few files. It found 291,935 files in 14.79 seconds. Now you just need to iterated over your collection of files and match by name - then check versions. The use of the Parallel For / Foreach loop would prove useful here.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var b = new BuildFileList();
var sw = new Stopwatch();
sw.Start();
var files = b.GetFiles();
sw.Stop();
Console.WriteLine("Found {0} files in {1} seconds", files.Count, sw.Elapsed.TotalSeconds);
Console.ReadLine();
}
}
public class BuildFileList
{
public List<FileInfo> GetFiles()
{
var di = new DirectoryInfo(#"C:\");
var directories = di.GetDirectories();
var files = new List<FileInfo>();
foreach (var directoryInfo in directories)
{
try
{
GetFilesFromDirectory(directoryInfo.FullName, files);
}
catch (Exception)
{
}
}
return files;
}
private void GetFilesFromDirectory(string directory, List<FileInfo> files)
{
var di = new DirectoryInfo(directory);
var fs = di.GetFiles("*.*", SearchOption.TopDirectoryOnly);
files.AddRange(fs);
var directories = di.GetDirectories();
foreach (var directoryInfo in directories)
{
try
{
GetFilesFromDirectory(directoryInfo.FullName, files);
}
catch (Exception)
{
}
}
}
}
}

Categories