I need compact all the folders of my E:\ But when i try with this code, i get this access exception.
I'm new on programming and are trying learn how a i can do this work.
I'm using the dotnetzip for compact the directories inside E:.
Some parts of the code are just copied, i know that... but i'm trying learn how to do work.
I already tried some others solution for solve the problem answered here.
Like add a manifest to the project who requeireAdministrator permissions to run and insert a Access Control Rule to modify the security of E:\ Something that i notice when do this is my user have permissions removed from the subfiles and directories of E:\ But without this access rule the same exception keep existing.
try
{
ZipFile zip = new ZipFile();
zip.AddDirectory(#"E:\");
zip.Save(#"C:\Users\vitorbento\Desktop\backup.zip");
Console.WriteLine("Compactação concluída");
Console.WriteLine("Done.");
}
catch (UnauthorizedAccessException)
{
FileAttributes attr = (new FileInfo(DirectPath)).Attributes;
Console.Write("UnAuthorizedAccessException: Unable to access file. ");
if ((attr & FileAttributes.ReadOnly) > 0)
Console.Write("The file is read-only.");
}
Related
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 :-)
First, let me begin by saying I know this appears to be a commonly asked question, but trust me, I've searched extensively and I couldn't find the answer to my question specifically. IF you do happen to know where this specific question was asked, by all means, mark it as a duplicate and reference me there, and accept my apologies for not finding it.
Now, I have a simple if function in my code:
if (!Directory.Exists(FileDirectory))
{
Directory.CreateDirectory(FileDirectory);
}
However, upon running this if Function, I get this error code:
System.UnauthorizedAccessException: 'Access to the path 'C:\Program Files\LockingProgram\Password.txt;' is denied.'
Now, obviously the problem is that the access is denied. How would I gain access?
I have tried simply writing the file instantly, however then it won't find the path
File.WriteAllText(FileDirectory, Password);
throws this error:
System.IO.DirectoryNotFoundException: 'Could not find a part of the path 'C:\Program Files\LockingProgram\Password.txt;'
The FileDirectory string is:
string FileDirectory = "C:\\Program Files\\LockingProgram\\Password.txt;";
Currently, what the program is trying to do is get a password from the user when they click a button, and then saves that password to a txt file located at the file directory for future reference. When they open the program, it checks if the file exists. If it exists, it sets the password to that file, and if it doesn't it forces the user to enter a string into a text box and from there, I am trying to save it. However, that's where I'm having the problem.
Any help would be greatly appreciated!
Edit: I now understand it's generally a bad idea to save it to Program Files, and you should use AppData instead. I'll try that and update you if it works that time.
Edit 2: It now works. I changed the file directory to:
string FileDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "LockingApp";
And I added a new variable:
string FileName = "Password.txt";
And I modified where the directory is created to:
if (!Directory.Exists(FileDirectory))
{
Directory.CreateDirectory(FileDirectory);
}
File.WriteAllText(Path.Combine(FileDirectory, FileName), Password);
Thanks for your help guys! Hopefully I formatted this question well.
C:\\Program Files\\LockingProgram\\Password.txt;
is not a directory, use
FileDirectory = #"C:\Program Files\LockingProgram";
Directory.CreateDirectory(FileDirectory);
Also there is a probably a good chance you will need to run your program at an elevated privilege or with the appropriate permissions, i.e as an administrator
However there are better places to store data
Where Should I Store my Data and Configuration Files if I Target Multiple OS Versions?
ie AppData, for example
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
You can use Isolated Storage for saving files (Seems the easiest and least tasking to use).
Check this code sample below
using System;
using System.IO;
using System.IO.IsolatedStorage;
public class CreatingFilesDirectories
{
public static void Main()
{
using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Domain | IsolatedStorageScope.Assembly, null, null))
{
isoStore.CreateDirectory("TopLevelDirectory");
isoStore.CreateDirectory("TopLevelDirectory/SecondLevel");
isoStore.CreateDirectory("AnotherTopLevelDirectory/InsideDirectory");
Console.WriteLine("Created directories.");
isoStore.CreateFile("InTheRoot.txt");
Console.WriteLine("Created a new file in the root.");
isoStore.CreateFile("AnotherTopLevelDirectory/InsideDirectory/HereIAm.txt");
Console.WriteLine("Created a new file in the InsideDirectory.");
}
}
}
Any way to check if write permissions are available on a given path that could be either a local folder (c:\temp) or a UNC (\server\share)? I can't use try/catch because I might have write permissions but not delete so I wouldn't be able to delete created file...
Yes you can use the FileIOPermission class and the FileIOPermissionAccess enum.
FileIOPermissionAccess.Write:
Access to write to or delete a file or directory. Write access includes deleting and overwriting files or directories.
FileIOPermission f = new FileIOPermission(FileIOPermissionAccess.Write, myPath);
try
{
f.Demand();
//permission to write/delete/overwrite
}
catch (SecurityException s)
{
//there is no permission to write/delete/overwrite
}
You use a permissions demand, thus:
FileIOPermission f2 = new FileIOPermission(FileIOPermissionAccess.Read, "C:\\test_r");
f2.AddPathList(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, "C:\\example\\out.txt");
try
{
f2.Demand();
// do something useful with the file here
}
catch (SecurityException s)
{
Console.WriteLine(s.Message);
// deal with the lack of permissions here.
}
specifying the permissions you want and the file system object(s) desired. If you don't have the demanded permission, a Security exception is thrown. More details at
http://support.microsoft.com/kb/315529
http://msdn.microsoft.com/en-us/library/system.security.permissions.fileiopermission.aspx
For a variety of reasons — race conditions being one of them — it's more complicated than it might seem to examine NTFS file system permissions.
Apparently, we figured out a while back that this is a no-op for UNC paths. See this question, Testing a UNC Path's "Accessability", for detials.
A little google-fu suggests that this CodeProject class might be of use, though: http://www.codeproject.com/Articles/14402/Testing-File-Access-Rights-in-NET-2-0
I'm a bit confused here. I wrote the following script to add files of a certain extension type to a List and it DOES work, just not for the root of C: Here's the code first...
// Create an empty list
List<string> scanFiles = new List<string>();
// Split possible extention list into array
string[] scanExtensions = #"exe,com".Split(',');
try
{
foreach (string extension in scanExtensions)
{
// Add collection for this filetype to the list of files
scanFiles.AddRange(Directory.GetFiles("C:\\", "*." + extension, SearchOption.AllDirectories));
}
}
catch (Exception ex)
{
Console.WriteLine("ERROR: " + ex.Message);
}
// Display results
foreach(string sf in scanFiles)
{
Console.WriteLine(sf);
}
So if I run the above code, I get an error - but not the error I expect. It displays the following...
ERROR: Access to the path 'C:\Documents and Settings\' is denied.
I'd understand this if I hadn't specified 'C:\' as the directory path! If I change this to any valid directory (such as C:\Program Files), the code works fine. Can anyone explain this?
Thanks,
Simon
SearchOption.AllDirectories means your code will drill down into (forbidden) territory.
Better be prepared to handle this kind of error. For a solution without catching exceptions you'll need DirectoryInfo.GetFiles() to get FileInfo objects instead of strings and verify your access rights ahead of time.
But you will still need to handle exceptions (File/Dir not found) because of concurrency so you might as well forget about the FileInfos.
Well, the cause of the error message called "Access denied" is ... that you don't have access to that folder!
Try clicking on it in Windows Explorer. You will notice that, in fact, you can't access it. What a surprise ;-) The message told you exactly that.
SearchOption.AllDirectories means that GetFiles will recursively enumerate all files. If it hits an error somewhere it will throw an exception. There is no way to change that.
You cannot make Directory.GetFiles ignore access denied errors. So you have to code your own file-system enumeration code. It will probably be a recursive function with some error-handling code in it.
You're specifying SearchOption.AllDirectories which according to the documentation means
AllDirectories Includes the current directory and all the subdirectories in a search operation. This option includes reparse points like mounted drives and symbolic links in the search.
In other words, your search is recursive and walks down into Documents and Settings where you have no read permission.
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.