views:

104

answers:

5

I have a class library which is deployed on an ISP server to be consumed by an ASP.NET web service. I'd like to keep track of any errors and in this case the windows event log is inaccessible to me. So I thought I'd write to a txt file using the StreamWriter class. Problem is if I don't give an absolute path and just a file name it tries to write to C:\Windows\System32, and that's no good to me. How can I tell it to use maybe the data directory or the application root? Any thoughts?

A: 

Try checking out:

Application.StartupPath;

Here's a link to the docs

Gets the path for the executable file that started the application, not including the executable name.

string path = Application.StartupPath;

Note: you'll still need to add a file name.

Robert Greiner
I can't access System.Windows.Forms.Application.StartupPath from a class library application, can i?
smkngspcmn
Yes, right-click references and import System.Windows.Forms
Robert Greiner
A: 

You can find out the path of your executable by doing this:

string path = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
BrokenGlass
when i try that on my locally hosted solution i get a path somewhere inside \Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\.. which is not really what i'm after.
smkngspcmn
ah my bad, this is not applicable to ASP.NET web services. Go with the Server.MapPath approach. You will still need write permissions to the target folder though.
BrokenGlass
+1  A: 

In my web product, in the web.config I specify an appSettings block like this:

<configuration>
    <appSettings>
      <add key="MyLogPath" value="LogPath" />
    </appSettings>
</configuration>

which you can use from the code like

ConfigurationManager.AppSettings["MyLogPath"]

then you can have the installer configure it to wherever you want. you probably don't want the log files in your application directory.

Alex Lo
Yeah but i need the Class Library DLL to log, not the web product.
smkngspcmn
as long at the appSetting is in the config of the product (web or application) that uses your library, you can get the setting from your library
Alex Lo
you could also put an app.config in your class library project to achieve this
EJC
Still would i be able to use a path relative to the application? And i don't really get to use an installer, just copy/publish to the virtual directory given to me by the ISP.
smkngspcmn
sorry, i meant "installer" like the person installing the application. as EJC noted, you can provide an arbitrary app.config file that the library can use.
Alex Lo
+3  A: 

Use Server.MapPath to get a path relative to the web application.

using (FileStream fs = new FileStream(Server.MapPath("~/logs/logfile.txt"),
                                      FileMode.Append)) {
  //do logging here.
}

While some of the previous posters have suggested using reflection to get the executing assembly, I'm not sure whether or not that will net you the web application or the w3wp process. If it's the latter, you're still going to end up trying to write to the System32 folder.

villecoder
Server.MapPath should work in the Class Library too
EJC
your making perfect sense, I will post my code here for my logging class that uses Server.MapPath... I use it to log in my class libraries as well as on the website. If I can find the code, I recently switched to using ELMAH and Log4Net...
EJC
http://stackoverflow.com/questions/1199486/server-mappath-in-c-classlibrary
smkngspcmn
smarter than I sir :) instead of finding out the real way to use it I just faked a Page so I could use the Server.MapPath method :)
EJC
+2  A: 

Here is what I used to use, it's a little clunky but it gets the job done:

using System;
using System.Collections.Generic;
using System.Web.UI;

public static class Logger
{
private static readonly Page Pge = new Page();
        private static readonly string Path = Pge.Server.MapPath("~/yourLogPath/Log.txt");
        private const string LineBreaker = "\r\n\r======================================================================================= \r\n\r";

public static void LogError(string myMessage, Exception e)
{
    const LogSeverity severity = LogSeverity.Error;
    string messageToWrite = string.Format("{0} {1}: {2} \r\n\r {3}\r\n\r {4}{5}", DateTime.Now, severity, myMessage, e.Message, e.StackTrace, LineBreaker);
    System.IO.File.AppendAllText(Path, messageToWrite);
}
}

I had this class in it's own project, separate from the website itself, and I used it in all of my other non website projects...

Edit: Btw LogSeverity is just an enum I made up...

EJC
Yeah this works as long as you add a reference to System.Web assembly
smkngspcmn
like i said, a little clunky, but it gets the job done. :) maybe I said a lot clunky...
EJC