C# Windows Service Textwriter - c#

I've created a standard windows service that uses the LocalSystem account. For the log files I use textwriter to write to a specified file within C:\Users\useraccount directory. The problem is, when running as a service under LocalSystem, it doesn't want to create or write to the file at all.
string dir = #"C:\Users\useraccount\log.txt";
StreamWriter sw = File.AppendText(dir);
As you can see, the directory is hardcoded in so there isn't any base directory conflicts seeing as LocalSystem would start in System32 or something of that nature. The permissions on the folder lets the System account access it fully (windows 7) so why am I not able to create/write to that file?
Thanks for any input!
Edit:
Apparently the logging program thread is running as LocalSystem as well, when I really need it to be running as a standard user. So how do I execute a threaded process from the service to run under the local user account instead of under LocalSystem.
I use Thread.new(process) where process is an additional program. The process program needs to receive input before it writes anything, and it isn't receiving input because it's on the wrong account. How would I fix this?

Should do the same trick as using(...) but did you try:
sw.Close();
Without it there's just an empty file but it throws no exceptions..

Try this code and check what exception reports:
try
{
using (StreamWriter sw = File.AppendText(dir))
{
sw.WriteLine("test");
}
}
catch (Exception ex)
{
Debug.Print(ex.Message);
}
Just a note: it's a good idea to use using(...) with all classes implementing IDisposable interface, so you can be sure they are freed when exiting block!

First of all I would use Log4Net instead of rolling your own logging mechanism, unless there is a good reason not to. This way you can create the log file you want but also (via a config or code) add log appenders such as windows event log. Then I would make sure I log any and all exceptions. You say no exception is being thrown, I expect there is an exception being thrown on the logging thread which is not 'bubbling' up, so catch it and log it (Log.Error(ex)). You can then see these exceptions in your event log if you have configured an event log appender.
Lastly, I'm not sure how you would assume the security context of the logged on user. Sounds like that would be a big securtity hole, unless you write something that prompts the user to enter their credentials or grant the process the right to impersonate/assume the user security context.. Perhaps that is the answer, the service responds to a user logon by prompting the user to grant this right. I'll have a look around for a better answer to this point.

Related

Service not running application

I am creating a service which runs an .exe file on Windows 7. It must be done as a service due to complex requirements, so a console application is not possible.
I have written the following code, which works perfectly in a console application, however when placed in the service, the executable is never run.
ProcessStartInfo startInfo = new ProcessStartInfo();
try
{
startInfo.WorkingDirectory = "C:\\Folder";
startInfo.FileName = "MyApp.exe";
Process myProcess = Process.Start(startInfo);
}
catch (Exception ex)
{
using (StreamWriter writer = File.AppendText(path))
{
writer.WriteLine(ex.Message);
}
}
}
No errors are being thrown, but the application is simply not starting.
I have read that services cannot run an executable in a straightforward manner, and have modified the above code based on suggestions, however it does not work.
EDIT: I have configured the service manually as follows:
This question has been the cause of great frustration, and I have finally solved my problem. Yes, I have managed to make a service load a GUI application, even though everyone says that it is impossible. There is a warning though - the "fix" can be considered as exploiting a loophole in Windows, as the code which I used basically passes the Vista and Windows 7 UAC. Essentially, the application is always executed with full rights and bypasses the UAC.
If anyone has this same problem, what you need to do is iterate through a list of logged in users on the PC, and choose to open the UI application in this session (which has the user's desktop), rather than in session 0 where the service is supposed to be running (and which does not have a desktop).
For some people, this might not be a solution as it is not secure. But in my case, security is not a main concern, and I just needed it to work (had to be a service by force).
Hope this helps anyone who has the same problem that I had.

Write a log file

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.

Determining Write Permissions to the Application Folder

I have a C# application, and I need to dump some output to a log file during operation. I am wanting to give the user the option of where to locate the log file, but by the client request it needs to default to the current application location, which is normally /Program Files/.
When I deploy my application on a Win7/Vista machine, though, the application does not write the log file unless I run the program as an Administrator. At the same time, it seems to be silently handling the case where it cannot write the file, as I am currently handling all exceptions being thrown during the file creation and writing process.
I am currently trying to detect lack of write permission by both:
A) Creating a DirectorySecurity object by calling "Directory.GetAccessControl()" and
B) Checking security priviledges with the "SecurityManager.IsGranted(permissions)" method,
but A does not throw an exception when I expect it to, and B returns true every time.
I have seen numerous posts related to this topic, but they all give the solution of just writing to Application.UserAppDataFolder or some variation of it. My client has specifically asked to default to the current Application path, so I need to at least find a way to gracefully warn them when writing the log file is going to silently fail.
Note: My current code works find on Windows XP (since there are no UAC, I assume). Basically all I need to know is why all my calls are telling me that writing the file is going fine, when the file is never created at all unless I am running as Admin.
Thanks!
Windows Vista and 7 will write files to the Program Files directory just fine.
Well, not really, but the program thinks it's just fine. In reality, the file is written to the current user's VirtualStore directory; that is, in %userprofile%\AppData\Local\VirtualStore\Program Files
You can include a manifest file to disable this behavior for your application to get the results you expect.
You can force the os to run your app as Admin.
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
There are three ways your app can run - elevated, deliberately not elevated (manifest saying asInvoker), or accidentally not elevated (no manifest). Elevated apps will be able to write to Program Files. Deliberately not elevated apps will get access denied. Accidentally not elevated apps will succeed but the file will be written elsewhere. This last case is what's happening to you. It didn't silently fail. You just don't know where the files are. See http://www.gregcons.com/KateBlog/FindingFilesYoureSureYouWrote.aspx for screenshots.
Therefore if the users insist on the current directory, you should add a manifest requesting asInvoker. You will then get AccessDenied and they will see the error message. I think they are odd for wanting this. Ask them if they are ok with one extra click to find them: if so, keep your app using virtualization (I really disapprove) by having no manifest and then train them to click the Compatibility Files button.
My preference: write elsewhere and manifest to asInvoker. My second choice: stick with current directory, no manifest, train them to find virtualized files. My third choice: stick with current directory, manifest to asInvoker, users see error messages when log files are not written, but logs are lost.
I am experiencing the same problem. I have an xml file that i am writing to...When I install the app(C sharp) and try to run the application am getting an exception due to write permission. When I change the file permission (give read permission to users) it is working ok..
The ultimate test for whether you have the rights to write a file is to open it for writing.
I.e.
try
{
File.Open(path, FileMode.OpenOrCreate);
...
}
catch(SecurityException)
{
... it failed for security reasons
}
catch(Exception)
{
... it failed for other reasons
}
Besides Stefan P.'s suggestion to elevate the app to run as admin, you could also modify the installation folder permission on install to to add the Users group to have write access. Then the application would work as well.
Moving the log file location would be the best option though.

How to log user operations for a asp.net application?

How can we log user operations for a asp.net application. Further what is the approach for saving the log data ? Kindly guide.
I recommend to use a logging framework like log4net or NLog. These frameworks allow you to log to many destinations and more importantly they allow you to make the decision after you finished your application i.e. you can configure where the log messages are written.
Personally I would log to a database in case of web applications.
or, you could use the Common Logging infrastructure to hide the implementation and switch between loggers at will
http://netcommon.sourceforge.net
Where you store the logging is largely dictated by how you will consume the logging data(i.e. read and interpret the logging data, take action if needed). If the person who analyzes the logging data has access to the machine and it's not business-critical, just log to file. If the machine is critical to your business you probably have some sort of monitoring software and publishing the logging to event logs or WMI becomes interesting.
If you log to file, consider how long you need the logging data and how much of it you need at one time. You can use rolling log files to make sure they don't become gigantically large and consume half your hard disk space. You can also use filters or priorities to log only errors when there is nothing wrong, and open the filter to debug or verbose when investigating a problem.
IIRC log4net and/or enterprise library can log to a format that is readable by the WCF service trace viewer, see http://msdn.microsoft.com/en-us/library/ms732023.aspx (but i'm not sure about that one). Log4net has a dashboard, though.
There are two methods: either you save the log details into the database or create a simple text file so that you can track the events.
Here I am the giving just simple code to how to track the event and maintain the log details and save the log details into the text file. It may help you solve your problem.
First of all you have to import name space:
using System.IO;
I had created the small function to track the log details-
public void LogEntry(string msg, string path)
{
try
{
//It will open the file, append the your message and close the file
File.AppendAllText(path,msg);
}
catch (Exception ex)
{
ex.GetBaseException();
}
}
In this function you have to pass the two parameters
Message
Path of your text File
For example
string logmsg;
logmsg = "** " + DateTime.Now.ToString() + "||" + "User:" + UserName + "||" + " EventDesc: Login Attempt Failed";
l1.LogEntry(logmsg, Server.MapPath("LoginEvent.txt"));
Here the LoginEvnet.txt is the name of the text file where I am storing the log details.
logmsg-It is the message you have to track the or store in the log file

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.

Categories