Not sure how to use SetAccessControll Function - c#

I was trying to make a simple security application that locked my folders when providing that folders path from file explorer. I did this by making a windows forms application in C#. I've managed to get the GetAccessControl(); Function to work by using this line of code.
System.IO.DirectoryInfo directoryInfo = new DirectoryInfo(path);
System.Security.AccessControl.DirectorySecurity s1 = directoryInfo.GetAccessControl();
I'm not sure how to do this with the SetAccessControl(); function as it requires 2 argumanets to work. I tried implementing this code below:
System.Security.AccessControl.DirectorySecurity s3 = directoryInfo.SetAccessControl(path,s1);
I got an error stating: No overload method for 'SetAccessControl' takes 2 arguments
It is obvious to me why this is not working, but I'm not quite sure how to fix it. If anyone would be willing to help, that would be greatly appreciated.

In .Net 5+ :
System.IO.DirectoryInfo directoryInfo = new DirectoryInfo(path);
System.Security.AccessControl.DirectorySecurity s1 = directoryInfo.GetAccessControl();
directoryInfo.SetAccessControl(s1);
or (Changes the security attributes of an existing directory):
FileSystemAclExtensions.SetAccessControl(s1, s2);
In .Net 4.x:
Directory.SetAccessControl(path, s1);
Doc:
https://learn.microsoft.com/en-us/dotnet/api/system.io.directory.setaccesscontrol?view=netframework-4.8.1
https://learn.microsoft.com/en-us/dotnet/api/system.io.filesystemaclextensions.setaccesscontrol?view=net-7.0

Related

Search and return path of given folder name (Windows and Linux)

I want to get the path of an existing folder SeleniumTestData inside the solution.
Why? My selenium tests should create at start of the test, temporary folder which are being ignored in Git, so each of my colleagues has their own TestData folders for their own TestExecutions on their machine (Like Save/Load Cookies) and dont pull TestData from other colleagues.
The folder where i want to create other folder by code is named SeleniumTestData folder and is inside:
..\source\repos\CoffeeTalk\src\Tests
I cant hardcore the path, as i'm facing here 2 problems:
Tests are being ran in Windows and Docker (Linux)
Co-Workers are saving the solution in different windows directories
Now i need a general solution which will work in any of these cases.
I already tried: var currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory());
which returned: D:\source\repos\CoffeeTalk\src\Tests\Web\CoffeeTalk.Client.Selenium.Tests\bin\Debug\net6.0
and then tried to navigate back by executing the codeline currentDirectory?.Parent about 5-6 times. But its then again different in Linux.
Now im looking for a clean way. I suppose the first way i did it was not wrong by getting the CurrentDirectory and navigate back.
I already searched for solutions using stackoverflow, google. Either the solutions are outdated or im not getting the result im expecting.
Here i have the method which creates the folder, but im struggling with the GetFolderPath method.
public static void CreateFolder(string folderName, string newFolderName)
{
var folderPath = GetFolderPath(folderName);
var pathCombined = Path.Combine(folderPath, newFolderName);
var folderExists = Directory.Exists(pathCombined);
if (folderExists) return;
Directory.CreateDirectory(pathCombined);
}
Directory.GetCurrentDirectory isn't the directory with your executable file. It's something else (I don't know) that by the way depends on the OS. You should use this instead:
using System.Reflection;
// ...
string exeDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);
And then go up the folders hierarchy as you want:
string neededFolder = new DirectoryInfo(exeDirectory).Parent.Parent.Parent.ToString(); // Or more "Parent" calls
As far as I know, it works on different OSs.

pyinstaller .exe works locally but fails when called by C#?

I have created a script using Python2.7 and compiled it using pyinstaller into an exe of the same name, in this case "GeneralStats.py" turns into "GeneralStats.exe" using --onefile and -w arguments.
When called with C# I use:
var pythonDirectory = (Directory.GetCurrentDirectory());
var filePathExe1 = Path.Combine(pythonDirectory + "\\Python\\GeneralStats.exe");
Process.Start(filePathExe1);
When called outside of C#, so in my local files I can run the .exe and the result is a text file with lots of values in (Running correctly).
However, when ran with C# in this format, I get an error that "GeneralStats returned -1!"
Which I have had issues with before, but it was a simple python error that when I returned to my code and ran it, I would receive an error that I overlooked.
This time my python code returns no errors and works outside of C#.
Any ideas of why this could be? I can provide any code or file directories necessary, please just ask if you feel it would help with debugging.
EDIT:
Solved by removing:
var filePathExe1 = Path.Combine(pythonDirectory + "\\Python\\GeneralStats.exe");
Process.Start(filePathExe1);
And replacing with:
ProcessStartInfo _processStartInfo = new ProcessStartInfo();
_processStartInfo.WorkingDirectory = Path.Combine(pythonDirectory + "\\Python");
_processStartInfo.FileName = #"GeneralStats.exe";
_processStartInfo.CreateNoWindow = true;
Process myProcess = Process.Start(_processStartInfo);
You need to set the working directory for the Process - it is probably trying to load files from its working directory but isn't finding them.
See, e.g. this:
Use the ProcessStartInfo.WorkingDirectory property to set it prior to starting the process. If the property is not set, the default working directory is %SYSTEMROOT%\system32.
Set it to the path where GeneralStats.exe is.

Get rights on folder

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

Get directory where executed code is located

I know that in the same directory where my code is being executed some files are located. I need to find them and pass to another method:
MyLib.dll
Target1.dll
Target2.dll
Foo(new[] { "..\\..\\Target1.dll", "..\\..\\Target2.dll" });
So I call System.IO.Directory.GetFiles(path, "*.dll"). But now I need to get know the path:
string path = new FileInfo((Assembly.GetExecutingAssembly().Location)).Directory.FullName)
but is there more short way?
You may try the Environment.CurrentDirectory property. Note that depending on the type of application (Console, WinForms, ASP.NET, Windows Service, ...) and the way it is run this might behave differently.
Environment.CurrentDirectory returns the current directory, not the directory where the executed code is located. If you use Directory.SetCurrentDirectory, or if you start the program using a shortcut where the directory is set this won't be the directory you are looking for.
Stick to your original solution. Hide the implementation (and make it shorter) using a property:
private DirectoryInfo ExecutingFolder
{
get
{
return new DirectoryInfo (
System.IO.Path.GetDirectoryName (
System.Reflection.Assembly.GetExecutingAssembly().Location));
}
}

Error in Process.Start() -- The system cannot find the file specified

I am using the following code to fire the iexplore process. This is done in a simple console app.
public static void StartIExplorer()
{
var info = new ProcessStartInfo("iexplore");
info.UseShellExecute = false;
info.RedirectStandardInput = true;
info.RedirectStandardOutput = true;
info.RedirectStandardError = true;
string password = "password";
SecureString securePassword = new SecureString();
for (int i = 0; i < password.Length; i++)
securePassword.AppendChar(Convert.ToChar(password[i]));
info.UserName = "userName";
info.Password = securePassword;
info.Domain = "domain";
try
{
Process.Start(info);
}
catch (System.ComponentModel.Win32Exception ex)
{
Console.WriteLine(ex.Message);
}
}
The above code is throwing the error The system cannot find the file specified. The same code when run without specifying the user credentials works fine. I am not sure why it is throwing this error.
Can someone please explain?
Try to replace your initialization code with:
ProcessStartInfo info
= new ProcessStartInfo(#"C:\Program Files\Internet Explorer\iexplore.exe");
Using non full filepath on Process.Start only works if the file is found in System32 folder.
You can't use a filename like iexplore by itself because the path to internet explorer isn't listed in the PATH environment variable for the system or user.
However any path entered into the PATH environment variable allows you to use just the file name to execute it.
System32 isn't special in this regard as any directory can be added to the PATH variable. Each path is simply delimited by a semi-colon.
For example I have c:\ffmpeg\bin\ and c:\nmap\bin\ in my path environment variable, so I can do things like new ProcessStartInfo("nmap", "-foo") or new ProcessStartInfo("ffplay", "-bar")
The actual PATH variable looks like this on my machine.
%SystemRoot%\system32;C:\FFPlay\bin;C:\nmap\bin;
As you can see you can use other system variables, such as %SystemRoot% to build and construct paths in the environment variable.
So - if you add a path like "%PROGRAMFILES%\Internet Explorer;" to your PATH variable you will be able to use ProcessStartInfo("iexplore");
If you don't want to alter your PATH then simply use a system variable such as %PROGRAMFILES% or %SystemRoot% and then expand it when needed in code. i.e.
string path = Environment.ExpandEnvironmentVariables(
#"%PROGRAMFILES%\Internet Explorer\iexplore.exe");
var info = new ProcessStartInfo(path);
Also, if your PATH's dir is enclosed in quotes, it will work from the command prompt but you'll get the same error message
I.e. this causes an issue with Process.Start() not finding your exe:
PATH="C:\my program\bin";c:\windows\system32
Maybe it helps someone.
I had the same problem, but none of the solutions worked for me, because the message The system cannot find the file specified can be misleading in some special cases.
In my case, I use Notepad++ in combination with the registry redirect for notepad.exe. Unfortunately my path to Notepad++ in the registry was wrong.
So in fact the message The system cannot find the file specified was telling me, that it cannot find the application (Notepad++) associated with the file type(*.txt), not the file itself.
I know it's a bit old and although this question have accepted an answer, but I think its not quite answer.
Assume we want to run a process here C:\Program Files\SomeWhere\SomeProcess.exe.
One way could be to hard code absolute path:
new ProcessStartInfo(#"C:\Program Files\SomeWhere\SomeProcess.exe")
Another way (recommended one) is to use only process name:
new ProcessStartInfo("SomeProcess.exe")
The second way needs the process directory to be registered in Environment Variable Path variable. Make sure to add it in System Variables instead of Current User Variables, this allows your app to access this variable.
You can use the folowing to get the full path to your program like this:
Environment.CurrentDirectory

Categories