Finding A Dynamic Folder - c#

So I am trying to find a Dynamic folder. We have made a game and the game has a sound driver which we provided for the players which is optional. When they download the new patch the driver also gets downloaded and put into a folder called Driver. It is a optional driver to install if one would like. I have the installation Registry Key of where it should be installed. I am asking how can I find the folder called Driver that is in the Game Folder that is downloaded but not ran because its optional. I am curios of how can I find that folder and than running the exe file inside that folder. The catch is, not everyone is going to have the folder installed in the same place. Some may have it on the C Driver, other maybe on the D drive and so on. So I am here to ask for some help. The Code is all being written in C#.

First off scanning the drives for a folder is very inefficient, so you may want to come up with a better way to limit your scan set. One way would be determine a relative path to search within. Following is my quick and dirty [NOTE: Please handle exceptions in a better way], also if possible concatenate your installation path to each local drive (this is assuming that you may only want to install your game on local drives) to limit the scan set.
static void Main(string[] args)
{
var myDrives = DriveInfo.GetDrives().Where(x => x.DriveType == DriveType.Fixed);
foreach (var drive in myDrives)
{
var outp = GetAllSubFolders(drive.Name,#"\Driver");
foreach (var folder in outp)
{
Console.WriteLine(folder);
}
}
}
static IEnumerable<string> GetAllSubFolders(string folder, string pathSubString)
{
try
{
var dirInfo = new DirectoryInfo(folder);
return dirInfo.GetDirectories().SelectMany(x => GetAllSubFolders(x.FullName, pathSubString))
.Concat(dirInfo.GetDirectories().Select(x => x.FullName).Where(x => x.Contains(pathSubString)));
}
catch
{
return new List<string>();
}
}

Related

Read all files and folders in C drive via c#

I want to get all files and folders in Drive C.
In fact, I want a list of all the files on the drive. All the files along with their path.
I use this code .but encounters an error.
static void Main(string[] args)
{
System.IO.DriveInfo di = new System.IO.DriveInfo(#"C:\");
System.IO.DirectoryInfo dirInfo = di.RootDirectory;
System.IO.FileInfo[] fileNames = dirInfo.GetFiles("*.*");
System.IO.DirectoryInfo[] dirInfos = dirInfo.GetDirectories("*.*");
foreach (System.IO.DirectoryInfo d in dirInfos)
{
string[] filePaths = Directory.GetFiles(d.FullName, "*.*",
SearchOption.AllDirectories);
}
}
You can simply exclude directories that you can't access by searching them one by one and surrounding all of the searches with a try-catch block. Here is an example:
Console.WriteLine("Input search pattern (or empty to search all):");
string pattern = Console.ReadLine();
if (pattern == "")
{
pattern = "*";
}
List<string> allDirectories = new List<string>{ #"C:\" });
Stack<string> directories = new Stack<string>(allDirectories);
List<string[]> allFiles = new List<string[]>();
while (directories.Count > 0)
{
try
{
Console.WriteLine("Searching " + directories.Peek() + " for " + pattern);
foreach (string dir in Directory.GetDirectories(directories.Pop()))
{
directories.Push(dir);
allDirectories.Add(dir);
try
{
allFiles.Add(Directory.GetFiles(dir, pattern, SearchOption.TopDirectoryOnly));
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine(e.Message);
}
}
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine(e.Message);
}
}
Console.WriteLine("FINISHED");
This will collect all files into the allFiles list (as paths) and directories into the allDirectories list.
This runs for ~10 minutes for me, so don't debug to many times.
First thing you need to do is compiling your C# app with a manifest file that asks for root privileges (follow instructions from: How do I force my .NET application to run as administrator?).
Next, What you should do is achieve any kind of a user/running-app with admin permissions and let it start your C# app.
I think that if you'll do the above via an app with root privileges then no UAC will pop-up to the user when the C# app will start.
If your app don't have root permission you won't be able to read the directory tree of unauthorized folders.
C# is a managed language, which means C# counts on the operating system to run and for that reason it can't bypass the operating system. Even with root permission, the operating system will be aware of your app actions.
BUT if your target is to figure out if a C# dll can maliciously read the folder tree of C drive, I think it's possible:
You need to compile your C# code into a exe file with a manifest as I've described above.
Then, create a batch file that will start a CLR process with root privileges (it'll probably alert the user with a UAC prompt but a common user won't suspect the CLR).
Make sure your batch will run with the user privileges and not the default ones or the next step won't work.
Your batch should tell the clr to load C# exe and I believe either no UAC will be prompted or either the batch could accept on behalves of the user without any prompt.
4'. If I'm wrong, perhaps the article https://www.codeproject.com/Articles/607352/Injecting-NET-Assemblies-Into-Unmanaged-Processes#PuttingItAllTogether will help you inject the exe into the clr without a UAC prompt.
Let me know if you continued the research by my suggestion and what was the results :-)

C# Saving files on different PC's

The program I am writing is a stock inventory system.
So the PC I wrote the program on can locate the files and folders to update on the PC as necessary as the path is valid.
string path = "C:\\Users\\ThisPC\\Documents\\Stock Documents\\Reciepts";
if (!Directory.Exists("C:\\Users\\ThisPC\\Documents\\Stock Documents\\Reciepts"))
{
Directory.CreateDirectory(path);
}
var fileName = #"c:\Users\ThisPC\Documents\Stock Documents\Tyre_File.xml";
This line is also used when I am updating quantities when an order is taken.
So obviously when I run this program in visual studio on another PC this path isn't recognized.
Is there a way that I can add a pointer to create and store my folder and documents in the My Documents on any pc the program loads in?
UPDATE-------------------------------------------------------
string path = "C:\\Users\\ThisPC\\Documents\\Stock Documents\\Customer Reciepts";
if (!Directory.Exists("C:\\Users\\ThisPC\\Documents\\Stock Documents\\Customer Reciepts"))
{
Directory.CreateDirectory(path);
}
This is the only one it wont work for, it creates a folder within a folder when the form is loaded, but your method doesnt work for that?
I believe that
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
is what you are looking for
You want the environment variable for MyDocuments, which will be unique for each user/computer.
String path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

How to get the folder path using folder name c#

I'm using C# to get the exact path of the specific folder in windows system by giving the folder name. Is their any way to get the folder path by giving the folder name, where the folder name will be unique.
Update:
Folder is created at run time with current time as the name. This
process is done by the application. Here i know the folder name but i
didn't know path, because path is selected by the user during
installation and installation is done before very long time.
That changes the question considerably. Why not use the application to tell you where it lives:
http://msdn.microsoft.com/en-us/library/system.windows.forms.application.startuppath.aspx
I had a similar idea ages ago and wrote about it as a Code Project Tip:
http://www.codeproject.com/Tips/132804/Open-folders-using-a-Run-Command
Otherwise you would need to index every folder on the PC and make them unique names and look up the full path that way.
The other suggestion I have is using LogParser as the Most efficient way to find all exe files on disk using C#? Its a free Microsoft product but I'm not sure about re-dist permissions, I had to include it in my package separately last time I used it. It full on flys, faster than a speeding train!
I found a Log Parser example that finds folders, you could try it out and adapt it if its useful:
SELECT TOP 1 * FROM C:\TFS\Project\*.* WHERE INDEX_OF(Path, 'Database') > 0
The good folks over at http://visuallogparser.codeplex.com/ have
provided us with the source code.
Open the VisualLogParser solution in VS2010, ignore the prompt about debugging, after the solution loads, F5, set the combo-box to FS (FileSystem), paste in this query and press go.
You could probably use something like this, but it'll be rather slow, depending on how many folders needed to be looked through.
Use it like FindFullPath(rootFolder, folderNameToLookFor)
public static string FindFullPath(string path, string folderName)
{
if (string.IsNullOrWhiteSpace(folderName) || !Directory.Exists(path))
{
return null;
}
var di = new DirectoryInfo(path);
return findFullPath(di, folderName);
}
private static string findFullPath(DirectoryInfo directoryInfo, string folderName)
{
if (folderName.Equals(directoryInfo.Name, StringComparison.InvariantCultureIgnoreCase))
{
return directoryInfo.FullName;
}
try
{
var subDirs = directoryInfo.GetDirectories();
return subDirs.Select(subDir => findFullPath(subDir, folderName)).FirstOrDefault(fullPath => fullPath != null);
}
catch
{
// DirectoryNotFound, Security, UnauthorizedAccess
return null;
}
}
See following link
string dirName = new DirectoryInfo(#"c:\projects\roott\wsdlproj\devlop\beta2\text").Name;

Copy all files in directory

How can I copy all of the contents in one directory to another with out looping over each file?
You can't. Neither Directory nor DirectoryInfo provide a Copy method. You need to implement this yourself.
void Copy(string sourceDir, string targetDir)
{
Directory.CreateDirectory(targetDir);
foreach(var file in Directory.GetFiles(sourceDir))
File.Copy(file, Path.Combine(targetDir, Path.GetFileName(file)));
foreach(var directory in Directory.GetDirectories(sourceDir))
Copy(directory, Path.Combine(targetDir, Path.GetFileName(directory)));
}
Please read the comments to be aware of some problems with this simplistic approach.
Msdn has guidance on this - How to:Copy Directories
You can use VB’s FileSystem.CopyDirectory method to simplify the task:
using Microsoft.VisualBasic.FileIO;
foo(){
FileSystem.CopyDirectory(directoryPath, tempPath);
}
using System.IO;
string sourcePath = #"D:\test";
string targetPath = #"D:\test_new";
if (!Directory.Exists(targetPath))
{
Directory.CreateDirectory(targetPath);
}
foreach (var srcPath in Directory.GetFiles(sourcePath))
{
//Copy the file from sourcepath and place into mentioned target path,
//Overwrite the file if same file is exist in target path
File.Copy(srcPath, srcPath.Replace(sourcePath, targetPath), true);
}
KISS – Keep It Simple Stupid… is a good rule of thumb for any situation, including programming.
Here is the simplest method of copying all files, folders, sub-folders and all their files and folders while keeping the original hierarchy. It also displays a nice Microsoft Windows progress dialog box.
Simply follow these basic instructions:
1: Open a new C# console application in Visual Studio – version (whatever)
2: From the menu bar; go to “Tools – Nuget Package Manager – Manage Nuget Packages for Solution” In the Nuget package manager search box, type – “Microsoft.VisualBasic” and select the “.Net” package.
3: Back on the “Program.cs” page, add the following “using” statements:
• Using System;
• Using Microsoft.VisualBasic.FileIO;
4: Inside the “Main” method, type the code provided below, replacing the source and destination paths with your folder/drives.
5: The “Console.WriteLine” line simply displays a message that it is copying and to “Please Stand by”. This line of code is completely optional. Not needed for this process to work.
6: The “FileSystem.CopyDirectory” command is a basic copy function to copy the folder and contents to the new destination. The only real difference is that the “UIOption.AllDialgs” command is added to the end of the copy command. This is the part that generates the Microsoft Windows Progress Dialog box.
Now, add the following code to your C# “Program.cs” page.
using System;
using Microsoft.VisualBasic.FileIO;
namespace ProgressDialogBox
{
class Program
{
static void Main(string[] args)
{
string sourcePath = #"c:\TestA\TestNew3";
string destinationPath = #"c:\TestB\TestNew4";
Console.WriteLine(#"Copying... {0} ... Please stand by ", sourcePath);
FileSystem.CopyDirectory(sourcePath, destinationPath, UIOption.AllDialogs);
}
}
}
This whole process takes less than 3 minutes to create. It actually takes longer to read this posting than to create and execute the program.
Enjoy.
Hope this helps someone in the future.
Here is the link from Microsoft that I used for reference:
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/file-system/how-to-provide-a-progress-dialog-box-for-file-operations
This works great! It will copy sub directories or you can just dump all the files from all subdirectories into one location.
/// AUTHOR : Norm Petroff
/// <summary>
/// Takes the files from the PathFrom and copies them to the PathTo.
/// </summary>
/// <param name="pathFrom"></param>
/// <param name="pathTo"></param>
/// <param name="filesOnly">Copies all files from each directory to the "PathTo" and removes directory.</param>
public static void CopyFiles(String pathFrom, String pathTo, Boolean filesOnly)
{
foreach(String file in Directory.GetFiles(pathFrom))
{
// Copy the current file to the new path.
File.Copy(file, Path.Combine(pathTo, Path.GetFileName(file)), true);
}
// Get all the directories in the current path.
foreach (String directory in Directory.GetDirectories(pathFrom))
{
// If files only is true then recursively get all the files. They will be all put in the original "PathTo" location
// without the directories they were in.
if (filesOnly)
{
// Get the files from the current directory in the loop.
CopyFiles(directory, pathTo, filesOnly);
}
else
{
// Create a new path for the current directory in the new location.
var newDirectory = Path.Combine(pathTo, new DirectoryInfo(directory).Name);
// Copy the directory over to the new path location if it does not already exist.
if (!Directory.Exists(newDirectory))
{
Directory.CreateDirectory(newDirectory);
}
// Call this routine again with the new path.
CopyFiles(directory, newDirectory, filesOnly);
}
}
}
Execute xcopy source_directory\*.* destination_directory as an external command. Of course this will only work on Windows machines.
You can't. But you can use some sort of succinct code like Directory.GetFiles(mydir).ToList().ForEach(f => File.Copy(f, otherdir + "\\" + Path.GetFileName(f));
While the C# approach works well, it's not always the best answer. A simple DOS batch script works much better by ignoring the 256 character limit found in the C# approach.
robocopy C:\myFiles D:\masterBackup\myFiles /E /V
The only draw back I have found with the DOS batch script is that it will not (in some cases) copy SQL Server "mdf" data files and "ldf" log files using the "robocopy" command. But that's a permissions issue.
Otherwise, I have relied more on the DOS batch script for my incremental and full backups.
Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory + #"resources\html")
.ToList()
.ForEach(f => File.Copy(f, folder + "\\" + f.Substring(f.LastIndexOf("\\"))));

UnauthorizedAccessException trying to delete a file in a folder where I can delete others files with the same code

I'm getting a Unauthorized Access Exception
in a file which I can delete manually.
in a folder where I'm able to delete by code other files
and the file isn't marked as read only
besides, I'm using Windows XP in a standalone PC and I have not assigned any permissions to the folder or the file.
no other process is using the file
If it helps, this is the code where the exception ocurrs:
protected void DeleteImage(string imageName)
{
if (imageName != null)
{
string f = String.Format("~/Images/{0}", imageName);
f = System.Web.Hosting.HostingEnvironment.MapPath(f);
if (File.Exists(f))
{
if (f != null) File.Delete(f);
}
}
}
Why could this happen?
I encountered the same problem, and found that writing my own Directory.Delete wrapper fixed it up. This is recursive by default:
using System.IO;
public void DeleteDirectory(string targetDir)
{
File.SetAttributes(targetDir, FileAttributes.Normal);
string[] files = Directory.GetFiles(targetDir);
string[] dirs = Directory.GetDirectories(targetDir);
foreach (string file in files)
{
File.SetAttributes(file, FileAttributes.Normal);
File.Delete(file);
}
foreach (string dir in dirs)
{
DeleteDirectory(dir);
}
Directory.Delete(targetDir, false);
}
If the directory contains a read only file, it won't delete that using Directory.Delete. It's a silly implementation by MS.
I am surprised no one suggested this method on the internet, which deletes the directory without recursing through it and changing every file's attributes. Here's that:
Process.Start("cmd.exe", "/c " + #"rmdir /s/q C:\Test\TestDirectoryContainingReadOnlyFiles");
(Change a bit to not to fire a cmd window momentarily, which is available all over the internet)
If it's not read-only it's possible that it is currently in use by another process.
Checking the obvious first...
When you open the file property and take a look at its security settings. Does the user running the code (i.e. if this is ASP.NET, Network Services / Domain Service Account) has access to actually delete the file?
If it is not, then change it and try again.
Are you running as administrator when trying to delete this manually?
If you are, then that's probably why you are able to delete it manually. Try deleting it as the account running your ASP.NET (I'm assuming it is ASP.NET since you are using System.Web.Hosting.HostingEnvironment.MapPath.)
If both failed, try to see if any other process is actually currently using this file. Good tool to find out is SysInternal Process Monitor. Filter it by path containing your filename and you should see if anything is using it. Terminate the process and try again.
I too faced the Same Problem but eventually came up with a Generic Approach. Below are my codes.
String pathfile = "C:\Users\Public\Documents\Filepath.txt" ;
if (!Directory.Exists(pathfile))
{
File.SetAttributes(pathfile, FileAttributes.Normal);
File.Delete(pathfile);
}
using (FileStream fs = File.Create(pathfile))
{
Byte[] info = new UTF8Encoding(true).GetBytes("What Ever Your Text is");
fs.Write(info, 0, info.Length);
File.SetAttributes(pathfile, FileAttributes.ReadOnly);
}
You, the human user, have a login with certain rights. The Web server might have a different login with different rights. A user starting with IUSR_XXXX or some such thing. Make sure that user has rights to the directory.
Without more info on the context in which you are deleting the file, I assume that the Web server user has different rights to a file than you do.

Categories

Resources