Write a log file - c#

I have a recent problem . I can upload file in my intetpub/wwwrooot/folder
But I can't write a log file in this same folder ...
I have all the permissions for the network service. Everything is on my server.
DirectoryInfo di = new DirectoryInfo(~/);
// Get a reference to each file in that directory.
FileInfo[] fiArr = di.GetFiles();
string strLogText = di;
// Create a writer and open the file:
StreamWriter log;
if (!System.IO.File.Exists("C:\\inetpub\\wwwroot\\logfile.txt"))
{
log = new StreamWriter("C:\\inetpub\\wwwroot\\logfile.txt");
}
else
{
log = System.IO.File.AppendText("C:\\inetpub\\wwwroot\\logfile.txt");
}
// Write to the file:
log.WriteLine(DateTime.Now);
log.WriteLine(strLogText);
log.WriteLine();
// Close the stream:
log.Close();
The error is the access is denied !
It works locally , but on my server it doesnt. On the folder Inetpub , I just need to allow writting for Network service ? That is strange because I can upload file and writting is already enable

Emged in case of exceptions your code does not close the streams on the log file and this is surely not good.
You should use a using statement around the streams so in any case streams are closed and disposed also in case of exceptions.
As Chris has suggested I would absolutely opt for a logging Framework and I would also avoid writing in that wwwroot folder.
ELMAH or NLog or Log4Net are good and easy alternatives far better than any custom logging lie you are doing right now and the big advantage of these technologies/libraries is that you can change the behaviour at runtime simply by editing the configuration file, no need to rebuild or redeploy anything...
my favourite is actually Log4Net, check these ones for a simple example on how to use it:
http://logging.apache.org/log4net/release/manual/configuration.html
Log4Net in App object?

Depending on the version of your server (windows 2008 and above), that directory has additional protection against writes.
I'd highly recommend you look into ELMAH to do your logging. It gives you a number of options including in memory or database backed and collects a LOT of additional data you might want.
Further, opening up various physical directory locations for write access is a HUGE security no-no.

On the server, is the web app running under an Application Pool that has alternate credentials, other than the normal network service account? If you haven't done so already, try turning on Auditing to see what user is trying to access the file.

Related

Writing to a file in Asp.Net

I am trying to write to a file in a Asp.Net form (.aspx). I can create the file fine using,
if (!File.Exists(Settings.Default.FileLocation))
{
File.Create(Settings.Default.FileLocation);
}
But when I go to write to the file using this code:
File.WriteAllBytes(Settings.Default.FileLocation, someByteArray);
I get an exception:
System.IO.IOException: The process cannot access the file 'C:\inetpub\wwwroot\mysite.com\captured\captured.xml' because it is being used by another process.
(in this case 'C:\inetpub\wwwroot\mysite.com\captured\captured.xml' == Settings.Default.FileLocation)
I cant delete or copy the file in Windows Explorer during this time as well. However, if I stop or restart the Application Pool the WebForm is running in, the error goes away. What is the cause of this and how do I prevent it?
This is running on a Win server 2012 R2 and IIS 7.5
Read the documentation on MSDN. You should be using using statements to open the file so that you can make sure any open handles to it are closed.
using(FileStream fs=File.Create(Settings.Default.FileLocation))
{
//manipulate file here
}
Also, File.WriteAllBytes will create the file if it doesn't exist, so there's no need to separately create it.
File.Create opens the file for read/write by default and needs to be closed before it can be used again. From the docs:
By default, full read/write access to new files is granted to all
users. The file is opened with read/write access and must be closed
before it can be opened by another application.
File.WriteAllBytes will create the file if it doesn't exist, so I think your code to check for file existence and creating it is probably overkill.

ERROR: System.Environment.SpecialFolder' does not contain a definition for 'CommonApplicationData'

I have the code to save a file in a folder in directory
string timestamp = DateTime.Now.ToString("MM-dd-yyyy.HH-mm-ss");
var file = File.Create("Owe-Data.txt" + timestamp);
var com = System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase + timestamp + #"\Data" + file;
MessageBox.Show(com);
if (!Directory.Exists(com))
{
Directory.CreateDirectory(com);
}
using (var sw = new StreamWriter(com))
{
sw.WriteLine(InputData);
}
}
i Displayed COM it gives path bt i cant see the Data folder or Owe-Data file at that path
Anybody can tell why this happening, or should i save the Data folder in current directory where this prgram running? bt i dnt know how to reach that path. Any solutions ??
Working on windows phone 5, visual studio 2008 .NET framwork 2.0
As per the Exceptions section of documentation,the above exception is thrown when
ArgumentException ------- folder is not a member of System.Environment.SpecialFolder.
It means the OS where you are running this command does not have Environment.SpecialFolder.CommonApplicationData as one of the special folder.
For knowledge,
Environment.SpecialFolder.ApplicationData is the most common one. This folder holds per-user, non-temporary application-specific data, other than user documents. A common example would be a settings or configuration file.
Environment.SpecialFolder.CommonApplicationData is similar, but shared across users. You could use this to store document templates, for instance.
Environment.SpecialFolder.LocalApplicationData is a non-roaming alternative for ApplicationData. As such, you'd never store important data there. However, because it's non-roaming it is a good location for temporary files, caches, etcetera. It's typically on a local disk.
I think the problem may be that Environment.SpecialFolder.CommonApplicationData is common and shared between different users and the user with which you have logged in is not having rights to access the folder or the Visual Studio has not been started in Admin mode.
EDIT Look at link and try to add a manual registry Common AppData defined in the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders\
Given you are asking about a .NET Windows Phone application as per the tags
I think your problem is that a .NET Windows Phone application does not have direct access to the file system; it can only access IsolatedStorage this is by design.
I would quote a Microsoft source for this but I can't seem to find one!
EDIT
See this article from MSDN

Copying files to a mapped drive while user is not logged in (scheduled task)

I have a job that needs to connect to two fileshares and copy some files for a data feed.
The source server is on our domain's network, and that works fine. The remote server, however, chokes on me and throws a "Could not find part of the path" error. I should add the destination server lives in a different domain than my source server.
The source and destination paths are read out of my app.config file.
I thought persistently mapping a drive would work, but since this is a scheduled task, that doesn't seem to work. I thought about using NET USE, but that doesn't seem to like taking a username and password.
The really weird thing - if I double click on the job while I'm logged into the machine, it'll run successfully.
Sample code:
DirectoryInfo di = new DirectoryInfo(srcPath);
try
{
FileInfo[] files = di.GetFiles();
foreach (FileInfo fi in files)
{
if(!(fi.Name.Contains("_desc")))
{
Console.WriteLine(fi.Name + System.Environment.NewLine);
File.Copy(fi.FullName, destPath + fi.Name, true);
fi.Delete();
}
}
}
Apparently this isn't as simple as copying the files over. Any suggestions on mapping a drive with credentials in C# 4.0?
EDIT
I'm trying to use a batch file called from the console application that maps the drive while the program is running. I'll know for sure whether that works in the morning.
I'd suggest looking into a proper file transfer protocol, like FTP.
Assuming that's out of the question, try using a UNC path like \\servername\path\file.txt. You will still need credentials, but assuming that the account running the application has those permissions you should be fine. Given that you mention a web.config file, I am guessing that would be an ASP.NET application, and therefore I mean the account that runs the Application Pool in IIS. See http://learn.iis.net/page.aspx/624/application-pool-identities/
What I finally wound up doing was mapping the drive in a batch file called by my program. I just launch a NET USE command and pause for a few seconds for the mapping to complete.
It looks like while the user is logged out, there's no context around mapped drives.

Access denied error

I am trying to delete the excel file from a specipic location . but can't deleting. having error :
Access to the path 'C:\mypath\sample.xlsx' is denied.
I write a code as :
protected void imgbtnImport_Click(object sender, ImageClickEventArgs e)
{
try
{
string strApplicationPath = HttpContext.Current.Request.MapPath(HttpContext.Current.Request.ApplicationPath);
string strXLStoredDirectoryPath = strApplicationPath + "/Information Documents/";
DirectoryInfo di = new DirectoryInfo(strXLStoredDirectoryPath);
string fileName = flUpldSelectFile.FileName;
if (!File.Exists(strXLStoredDirectoryPath))
{
Directory.CreateDirectory(strXLStoredDirectoryPath);
di.Attributes = FileAttributes.Normal;
}
string strCreateXLFileDestinationPath = strXLStoredDirectoryPath + fileName;
if (File.Exists(strCreateXLFileDestinationPath))
{
File.Delete(strCreateXLFileDestinationPath);
}
flUpldSelectFile.SaveAs(strCreateXLFileDestinationPath);
di.Attributes = FileAttributes.ReadOnly;
}
catch (Exception)
{
throw;
}
}
please guide.........
-***********************************************************************
Still problem there . it is not resolved . getting UnauthorizedAccessException. as access denied to deleting file. I m tired now . please help; I tried many things..please help
-***********************************************************************
Is may be iffect of VSS ? i am using that
UPDATE:
Part of your issue might be what is saving/creating this file. If you're using a built in "Save" or "SaveAs" feature the underlying file stream might still have a lock on the file. writing your own save logic with a FileStream wrapped in a Using statement will help dispose the stream right when you're done thus allowing you to further manipulate the file within the same context.
if flUpldSelectFile.SaveAs(strCreateXLFileDestinationPath); is the only logic that saves the file then get rid of the built in SaveAs functionality. write your own save logic using a FileStream wrapped in a Using block.
In your example i can't see what flUpldSelectFile is so i am assuming it is a System.Web.UI.WebControls.FileUpload control. Here is an example of rolling your own save logic.
using (FileStream fs = new FileStream(strCreateXLFileDestinationPath, FileMode.Create))
{
byte[] buffer = flUpldSelectFile.FileBytes;
fs.Write(buffer, 0, buffer.Length);
}
As stated previously, use this tool to find out if there is a lock on the file by another process.
ORIGINAL
Pop open this wonderful tool and search for that file to see who/what has it locked
http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx
(source: microsoft.com)
If your code is working under IIS , Note that ASPNET user doesn't have access to computer files, you should give access to it, that is not recommended, or store you files in the place where ASPNET user have access
see here
Try a combination of these 2 steps:
Set the IIS application pool to run under an account with privileges such as a domain account or local user account (not a default account like local service or local system). Instructions for IIS7.
Turn impersonation on in the web.config file, in the <system.web> section:
<identity impersonate="true"/>
<identity impersonate="true" userName="contoso\Jane" password="password"/>
I think the message is clear, you do not have authorization to delete the file or it is opened by another application. I bet 2$ you can't delete the file manually either.
As others have said, this is because IIS runs your application as a user with restricted access rights. This is a wise security precaution, so that your system is less vulnerable to malicious attacks.
What you need to do is to give the ASPNET user access to the specific folder. You do that from the security tab in the properties of a folder. The user you need to give full control to depends on the version of IIS you are using. In Windows XP it is ASPNET. In Windows Server 2003, 2008 and Windows Vista, 7 it is NETWORK_SERVICE.
See also this question for more details.
Make sure the file isn't opened or
locked by another user/process.
Make sure ASPNET user has access on the file\folder (check the file\folder's property using windows explorer and go to security tab. check if ASPNET user is added there).
One of two things are happening. Either the file is already open, or the permission of the user running IIS does not have the proper permissions.
Either way, this utility ProcMon: Proc Mon
will help you determine the issue. Run ProcMon, kick off your process to try and delete the file. Then go back to procmon. Hit Ctrl-E to turn off the capture, then Ctrl-F to find. Enter the name of the file you're trying to delete. Then once you've found the correct line with the access denied (or similar error) Double click on the the line to get further information. When you click on the Process tab, it will show you the exact user that is trying to delete the file.
So, if it is a file permission issue, you now know the exact user, and can therefore go to the file system right click on the folder that houses the file you are trying to delete, and grant that user permissions to read/write/update that folder.
Second, if the file is locked open instead of a permissions issue, you will have to find out what process is holding open the file. If you are also writing this file in another part of your code, perhaps you are not closing it properly or releasing the object reference.
Have you verified that the file does not have the read-only attribute set?
I don't think we have enough info to be helpful. What is the security context (identity) during the call to Delete? Is the application impersonating the end user? If it is, how are they authenticated? If by Windows / Active Directory, then you'll need to verify that user's access rights to the specific file. If by Forms login, then you should probably not impersonate and verify that the AppPool's security context has the appropriate access rights.

Is FileInfo.Copy accross network good solution? Is CAS required?

Seems that everything I do involves win services copying files across servers. I seem to get a lot of security & securityaccess type exceptions and never fully understand the causes. I am wondering if fileinfo or file.copy is a good solution or if there is a better. Is there a particular attribute I should be using or something to avoid these errors? Issue is not account or password related. example are \ipaddress\sharename \ipaddress\drive\path using domain accounts.
---Added Specific example.---
- I log on to serverA as domain\username. (including domain name)
- I open file eplorer in the address bar enter \\serverB\c$\folder hit enter, I right-click, create new file. No problem.
- I install service, go to properties select Log On, This Account and set the username as domain\username (including the domain name) same password I logged onto serverA with. It accepts it no problem.
Application does a FileSystemWatcher on \\serverA and copy to \\serverB when changed to keep the config files in sync.
private void CopyNewFileToClone()
{
FileInfo OriginalConfigFile = new FileInfo(Path.Combine(ConfigurationManager.AppSettings.Get("directoryToWatch"), ConfigurationManager.AppSettings.Get("fileToWatch")));
FileInfo CloneConfigFile = new FileInfo(Path.Combine(ConfigurationManager.AppSettings.Get("directoryToCopyTo"), ConfigurationManager.AppSettings.Get("fileToCopyTo")));
FileInfo tmp = new FileInfo(Path.Combine(CloneConfigFile.DirectoryName,"~" + CloneConfigFile.Name));
OriginalConfigFile.CopyTo(tmp.FullName, true);
tmp.CopyTo(CloneConfigFile.FullName, true);
tmp.Delete();
}
When I start the service I get Service cannot be started.
System.UnauthorizedAccessException: Access to the path '\\serverB\C$\folder\filename' is denied.
I use fileinfo to copy files from servers and it seems to work fine. If your sure it's not a account or password issue I would start looking at your DNS. If the network can't resolve what account is trying to access the network folder it won't matter if you are using a valid account. You may get lucky some/most of the time with cached accounts but there is no telling when it might not work and when it will work.
I would trace the network if you are getting a lot of broadcast messages for failed responses.
This was due to Code Access Security policy. Ran
c:\Windows\Microsoft.NET\Framework\v2.0.50727\CasPol.exe -af <path\application.exe>
and error resolved.
Adding as a installation step in all apps that need to write to HD, especially accross network via unc such as \server\share\file.

Categories