I'm using transactional NTFS wrapper that is available on msdn here to support atomic transactions of file system operations, the available example only shows how to work with transactedFiles but I need also to create, move and copy transacted Directories, I don't know how to use TransactedDirectory Class, can you please help?
I tried this code but it doesn't seem to be correct:
if (Transaction.Current == null)
{
throw new Exception("Must be within a transaction scope");
}
using (TransactionScope folderTransaction = new TransactionScope(Transaction.Current))
{
TransactedDirectory.StartTxFResource("D:\\New");
folderTransaction.Complete();
TransactedDirectory.StopTxFResource("D:\\New");
}
it gives an error "access denied, the folder is being used by another process".
Under which User Account is your process running? Check if it has access to the D:\New folder.
For a quick check, run the process as Administrator (Right click myprocess.exe > Run As Administrator), and if it works then, you should either set the correct permissions, or setup your code to require admin level access.
Related
In Windows other than the registry -localmachine where can I place common user data that could be accessed by all users.
i need to do this without requesting elevation of admin rights
You can store it in the Application data folder. which you can get from Envorinment:
var appDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.CommonDocuments);
To determine if you can access the folder without admin right, run Visual Studio, without admin rights, and see if this code executes successfully.
class Program
{
static void Main(string[] args)
{
var folder = Environment.GetFolderPath(Environment.SpecialFolder.CommonDocuments);
var file = Path.Combine(folder, "testfile.txt");
File.WriteAllText(file, " Test Settings");
Console.ReadLine();
}
}
No such location is available by default. Regular (i.e., non-administrative users) do not have the requisite privileges to mess with system files or files that belong to other users—that would be a security issue. As such, they would not be able to write to a "common" directory.
If you need all users to be able to write to some type of common area, you need to set it up yourself. Generally, this is done by an installer application. The installer application will need to request elevation so that it has administrative privileges in order to write to restricted folders and alter security rights. If you're using a standard installer utility, then this is usually a built-in feature. If you're writing your own, you arrange for it to have administrative privileges by embedding a manifest with level set to requireElevation (search Stack Overflow for details).
The installer it will create a sub-directory of the common application data folder (the enumerated value Environment.SpecialFolder.CommonApplicationData in the .NET world) for your application's use. By default, of course, that sub-directory will inherit the restrictions of its parent folder, so the installer will also need to explicitly set the ACL (access control list) on that sub-directory to grant all users write access. This can be done in the .NET Framework using the Directory.SetAccessControl method.
Then, after installation is complete, administrative privileges will not be required to run your application. The application can just save into its own sub-directory of the common application data folder, which its installer has ensured that all users have read/write access to.
I have a code which is similar this:
string file;
using (StreamReader r = new StreamReader("xml.xml"))
{
file = r.ReadToEnd();
}
XElement xml = XElement.Parse(file);
using (XmlWriter w = XmlWriter.Create("xml.xml")) //The point of problem!
{
w.WriteStartDocument();
...;
w.WriteEndDocument();
}
When I try run it like a console application is everything all right. But problems start when I want to use it in an ASP.NET application. At the using line it throws UnauthorizedAccessException exception with a description "access to the path is denied". Why?
You need to check which account your application Pool is using to access your server files/folders, for example, make one code to copy one file to application folder, check all security info, copy and paste on this problem folder, normally use this account "IIS_IURRS" give full control to test only...
If IIS/the web server is configured correctly, an account with a very limited set of permissions is used. As your path points to the application directory, it is very likely that the application pool account is not allowed to write to this location.
If you run the code in a console application, your user's permissions are applied and it is more than likely that you are allowed to write to the output folder of the project as Visual Studio writes the build output there under your account.
I would not recommend to change the application pool account or the permissions of the application folder in the file system - it is a very sensible limitation that limits the amount of trouble an attacker can possibly make.
Therefore I'd recommend to either move the file to a folder that the account can write to without changing permissions or define a special one outside of the application folder hierarchy that the account is given permissions to.
Also keep in mind that multiple users might access the file at the same time, so a database might be a better choice to store the data.
I am trying to take ownership and change the ACL of a file in C#, but even as an administrator I am getting the exception:
System.UnauthorizedAccessException: Attempted to perform an unauthorized operation.
The user running the program has the ability to take ownership and change permissions through Windows interface.
My code:
string fileName = #"C:\temp\mount\Windows\System32\Boot\en-US\winload.exe.mui";
FileSecurity fileSec = File.GetAccessControl(fileName);
fileSec.SetOwner(WindowsIdentity.GetCurrent().User);
File.SetAccessControl(fileName, fileSec); //exception thrown here
I even added a check to make sure the current user is member of administrator group:
WindowsIdentity wi = WindowsIdentity.GetCurrent();
WindowsPrincipal wp = new WindowsPrincipal(wi);
bool isAdmin = wp.IsInRole(WindowsBuiltInRole.Administrator); //returns true
Background information: I am creating a WinPE image and need to replace the winload.exe.mui file.
Also, the current permissions on this file only give full access to "Trusted Installer".
I am running on Windows 7
I solved this issue by running takeown in a command shell using a System.Diagnostics.Process. Then I was able to set the access control without error.
Strange that takeown works but the equivalent .NET libraries don't.
You can still use File.SetAccessControl() in your new method in place of FileStream.SetAccessControl(). I'd be willing to bet it works, too. MSDN actually recommends this practice:
"While the FileStream class and SetAccessControl can be used on an existing file, consider using the File.SetAccessControl method as it is easier to use."
http://msdn.microsoft.com/en-us/library/system.io.filestream.setaccesscontrol.aspx[^]
I work on a thick-client app that often runs into "issues" accessing network shares. Before doing any IO with the server, my app tests whether the share (usually of the form \\server\share$) exists. This works fine for detecting those scenarios in which the client has lost its connection to the server, but there are still those odd scenarios where the hidden share exists but the user does not have the rights to read from the within the share. Can someone share (no pun intended) the C# code required to test whether the current user can read files on a share? Should I be querying the share's ACL or the files within the share? What if the share is empty? What if the user is a local non-admin in a mixed environment (XP Pro workstation, Windows 2003 server without a domain on a Novell network)?
The easiest way is to just do it (i.e. try to read a file, for example). As Jared mentioned, there is no way to make sure that you will be able to read in the future (network failure, change of permissions, etc).
As far as code goes, you could use the DirectoryInfo class for some attempts at an answer:
string remotePath = #"\\server\share$";
bool haveAccess = false;
DirectoryInfo di = new DirectoryInfo(remotePath);
if (di.Exists)
{
try
{
// you could also call GetDirectories or GetFiles
// to test them individually
// this will throw an exception if you don't have
// rights to the directory, though
var acl = di.GetAccessControl();
haveAccess = true;
}
catch (UnauthorizedAccessException uae)
{
if (uae.Message.Contains("read-only"))
{
// seems like it is just read-only
haveAccess = true;
}
// no access, sorry
// do something else...
}
}
There are many shortcomings in the above code (such as the hard-coded "read-only" test), but it is just an example used to illustrate what you could do. DirectoryInfo has a few other helper methods that you can use to list the files in the folder. If you don't have access, the methods will throw an UnauthorizedAccessException exception which you can use to test why the access failed. Check out the info on GetAccessControl for further details on the exceptions it throws.
The #1 most reliable way to determine if you used to have permission to read from the share is to
Try and read from the share
Handle errors that could occur while reading and consider that a failed attempt
Unfortunately though based on your description you are trying to determine if you will have read permission to the share. There is no way to reliably determine this.
No matter how many ACLs, directories, etc ... you look at the moment you're done looking at them you could lose access to the share via any number of mechanisms. The most obvious one is the network share going down. All you can determine is that you used to have permission to the share.
This snippet works well if I try to write in a user directory but as soon as I try to write in Program Files, it just executes silently and the file has not been copied (no exception). If I try to copy the file in C:\ or in C:\Windows I catch an UnauthorizedAccessException.
Do you know another way to get the permissions to write in that directory or to make it work another way?
Any help greatly appreciated! Thanks
using(FileStream fs=File.Open(source, FileMode.Open)){ }
try
{
FileIOPermission fp = new FileIOPermission(FileIOPermissionAccess.Write,
AccessControlActions.Change, "C:\\Program Files\\MyPath");
fp.Demand(); //<-- no exception but file is not copied
File.Copy("C:\\Users\\teebot\\Documents\\File.xml","C:\\Program Files\\MyPath\\File.xml",true);
}
catch(SecurityExceptions)
{
throw(s);
}
catch(UnauthorizedAccessException unauthroizedException)
{
throw unauthroizedException;
}
If you are running under Vista then the system just redirects writes to the program files folder, this is done so old program that keep their configuration in the program directory will continue to work when the user is not an Admin (or UAC is enabled).
All you have to do is add a manifest to your program that specify the required access level, then the system assume your program is Vista-aware and turns off all those compatibility patches.
You can see an example of a manifest file on my blog at:
http://www.nbdtech.com/blog/archive/2008/06/16/The-Application-Manifest-Needed-for-XP-and-Vista-Style-File.aspx
(the focus of the post is on getting the right version of the common controls, but the Vista security declarations are also there)
Don't write in the Program Files folder.
That's a big no-no, and will especially cause problems when the day comes where your code runs in Vista or on a machine at a company where users only get standard security rather than admin rights. Use the Application Data folder instead.
Are you running on Vista? If so then you may be running into file system virtualization. This is a feature in 32 bit versions of Vista which allows a normal user to write to protected parts of the file system. It's a shim introduced to reduce the pain of the LUA features of Vista.
The short version is that the operating system will create a virtual file system for certain protected roots (such as program files). When a non-admin attempts to write to it, a copy will be created an editted instead of the original. When your user account attempts to look at the file it will see the edit.s Other user accounts will only see the original.
Longer Version: http://thelazyadmin.com/blogs/thelazyadmin/archive/2007/04/26/file-system-virtualization.aspx
Code access security grants or denies permissions to your code.
It can't be used to override permissions that are granted/denied to the current user.