Creating and saving a text file to the server - c#

In C# ASP.Net, I would like to create and save a text file to a server. This will be happening daily (by a user action, not scheduled).
I would like the location to not be in the application path but in a separate folder (for this question, lets say the folder is off the root).
I am new to this site and if this question is too "open", feel free to let me know.
Thanks for your assistance.

I agree with Dan Herbert. Put the path in web.config and make sure the permissions for the folder are correct.
Also, make sure that path is not on the C drive. That way, if something goes wrong, or if the site is attacked, the c drive won't fill up and crash the server.
Be careful with the permissions; even a simple text file can be dangerous if a hacker can muck with the path somehow. Think about someone overwriting the server's hosts file, for example.

One good practice to follow is to use a web.config app setting key to define the output path of your application.
You'd use the ConfigurationManager.AppSettings class for retrieving values from a web.config. You can read how to do this here:
http://msdn.microsoft.com/en-us/library/system.configuration.configurationmanager.appsettings.aspx

Here is an example:
// Pass a path and filename to the StreamWriter's
// constructor. The path must already exist but the
// file will be created if it does not already exist.
using (TextWriter tw = new StreamWriter("c:\\foo\\bar.txt"))
{
tw.WriteLine("hello world");
}

You can use System.IO classes to save to a file on the local filesystem.
using(var w = new StreamWriter(filename))
{
w.WriteLine("Hello world!");
}

Just to add on what others have said, when writing to a file in a multi-threaded application, you need to synchronize the access to this resource. You could use ReaderWriterLockSlim to achieve this:
// Make this a static field
ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
_lock.EnterWriteLock();
try
{
File.WriteAllText(#"c:\test.txt", "some info to write");
}
finally
{
_lock.ExitWriteLock();
}

I don't see any specific issue in doing so. You just need to make sure the user running ASP.NET is granted the required permissions to write to the output folder.

You'll want to use Server.MapPath to get to the physical path of your folder.
using (TextWriter tw = new StreamWriter(Server.MapPath("Folder1")))
{
tw.WriteLine("hello world");
}

Related

what process is preventing my file from getting deleted in C#

I have a C# single thread application that creates a file. Uses that file and then deletes it. Some times the app has trouble deleting that file. The error I get is:
"The process cannot access the file --file path and file name-- because it is being used by another process."
How can I find out what process has a hold on this file and how can I make that process to let go so that the file can be deleted.
This thing rocks for that very "gotcha".
http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx
Process Monitor v3.05
It has a "Filter" submenu so you can fine tune it to the file that is locked.
You need to post the relevant code so we can see.
It is however always important to make sure that your app close the file that it has opened.
usually something like this will ensure that:
using(var f = File.OpenRead("myfile")) {
...
}
or the equivalent:
try {
var f = File.OpenRead("myfile");
} finally {
f.close()
}
Make sure that you are closing file before delete.
if you are using StreamWriter class make sure that you are closing with its variable
Ex. StreamWriter sw = new StreamWriter();
// some writing operation
sw.Close();

Path to read file from inside www folder

I have a binary reader to read a file
BinaryWriter bw2 = new BinaryWriter(File.Open(#"c:\test\test6.xml", FileMode.OpenOrCreate));
the path i have set to is c:\test\test.xml
However it needs to read the file from www folder hosted site
so www\test\test.xml
should it be ~\test\test.xml?
Not sure.
Thanks for your help
Check out Server.MapPath() http://msdn.microsoft.com/en-us/library/ms524632(v=VS.90).aspx
So in your case, you're after this:
using (BinaryWriter bw2 = new BinaryWriter(File.Open(Server.MapPath(#"~\test\test6.xml", FileMode.OpenOrCreate)))
{
...
}
Notice I added the using() which is a best-practice for working with expensive resources like files.
Of course, you really should seperate out file opening from object creation so you can have better diagnostics in your code.
Probably you need this function: http://msdn.microsoft.com/en-us/library/ms524632(v=vs.90).aspx

How to Determine If a Word Document Is Read-Only?

I use Word.Interop to work with Word Document and let user to open a file from hard disk.
Sometimes I get error saying that the file that user has chosen is readonly.
How can I check if a file is readonly or not?
Are you sure you are actually talking about the File attribute (that can be set via the Windows file properties dialog)? If so, you can use FileInfo.IsReadOnly:
FileInfo fileInfo = new FileInfo(#"path\to\file");
if (fileInfo.IsReadOnly)
{
// do something
}
otherwise, refer to this answer if another process is using the file.

Securely enforcing user-input file paths within subdirectories

I know the solid security recommendation of avoiding accepting user input that you then use to choose a path to read/write a file. However, assuming you have a base directory you want to keep within (such as the root of an ftp folder), how do you best ensure that a given user input keeps us within that folder?
For instance,
Path.Combine(_myRootFolder, _myUserInput)
could still take us outside of _myRootFolder. And this could also be dodgy
newPath = Path.Combine(_myRootFolder, _myUserInput)
if (newPath.StartsWith(_myRootFolder))
...
given something like "/back/to/myrootfolder/../../and/out/again" from the user. What are the strategies for this? Am I missing a blindingly obvious .NET method I can use?
Within ASP.NET applications you can use Server.MapPath(filename) which will throw an exception if the path generated goes outside of your application root.
If all you want is a safe file name and you just want all files in there it becomes simpler;
FileInfo file = new FileInfo(
Server.MapPath(
Path.Combine(#"c:\example\mydir", filename)));
If you're outside of ASP.NET like you indicate then you could use Path.GetFullPath.
string potentialPath = Path.Combine(#"c:\myroot\", fileName);
if (Path.GetFullPath(potentialPath) != potentialPath)
// Potential path transversal
Or you call Path.GetFullPath and then check the start of it matches the directory you want locked to.
I know, that this thread is quiet old, but to prevent following readers from writing code with potential security errors, I think I should point out, that using Path.Combine(arg1, arg2) isn't save when arg2 is directly based on user input.
When arg2 is for example "C:\Windows\System32\cmd.exe" the arg1 parameter will be completely ignored and you grant the users of your API or server application full access to the whole file system.
So please be very careful with using this method!
I came up with this solution that should (afaik) be secure:
public static string SecurePathCombine(params string[] paths)
{
string combinedPath = "";
foreach (string path in paths)
{
string newPath = Path.Combine(combinedPath, path);
if (!newPath.StartsWith(combinedPath))
return null;
combinedPath = newPath;
}
if (Path.GetFullPath(combinedPath) != combinedPath)
return null;
return combinedPath;
}
Edit: There is a new Path.Join() method now. Please use that one instead of the code above.
I believe Path.FullPath will do what you need (I didn't test this though):
string newPath = Path.Combine(_myRootFolder, _myUserInput);
string newPath = Path.FullPath(newPath);
if (newPath.StartsWith(_myRootFolder)) ...
Well, in your example of an FTP server, you should set the users home-directory, and permissions appropriately, such that they can't navigate out of the folder. Any reason you can't do that?
You can parse input string and cut ../ with regex.

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