Problem with call from MSBuild

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Problem with call from MSBuild

Vincent026
Hello,

I have a difficulty with logging when my assembly (let's say MyLib.dll) is called by a MSBuild script. In MyLib.dll if have included a NLog.config file which holds fileName="${basedir}/myfile.log". This works fine when the assembly is called by an executable (MyApp.exe). After logging myfile.log is found in /MyApp/bin/Debug. But when MyLib.dll is called by a MSBuild script the assembly executes it's primary task, as it did before, but there is no log file created. I can't find myfile.log anywhere on the machine. And there are no exceptions thrown either. I can see this because the log lines are also shown in the Command Prompt Console (with Console.Writeline). I guess that the problem arises because of the different execution context in which MyLib.dll is used. Is there an easy way to solve this in NLog.config? Otherwise I will try to pass the output directory as an argument from the MSBuild script to the assembly.

Thanks in advance,
Vincent
Reply | Threaded
Open this post in threaded view
|

Re: Problem with call from MSBuild

Jason LaFlair
Administrator
I think your problem is the use of ${basedir} in your config for the .dll - check the path of MSBuild for your config files for this use.

${basedir} = The current application domain's base directory.  - in the case of the MSBuild calling a dll - my assumption would be to check the MSBuild directory.

Please let us know what you find.
Reply | Threaded
Open this post in threaded view
|

Re: Problem with call from MSBuild

Vincent026
What I see is that LogManager.Configuration = null when the dll is called from the MSBuild script. When called from the exe this is not the case. I don't change the files, I just execute  the MSBuild script in the same directory where the files (exe, dll and config) reside.
Reply | Threaded
Open this post in threaded view
|

Re: Problem with call from MSBuild

Vincent026
I found a solution by (re)loading the configuration file in my assembly (MyApp.dll) if LogManager.Configuration == null:
{
...
string CurrentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase);
string myConfigFile = Path.Combine(CurrentDirectory, "NLog.config");
LogManager.Configuration = new XmlLoggingConfiguration(myConfigFile);
...
}

You can also take a look at the directory of the executing process, in my case MyApp.exe or MSBuild.exe, depending on how MyApp.dll is called:
{
...
string entry = Path.GetDirectoryName(Assembly.GetEntryAssembly().CodeBase);
...
}

This shows that in the case of MSBuild.exe entry gets this value: C:\Windows\Microsoft.NET\Framework64\v4.0.30319
This is what I expect to be the cause of the problem: NLog probably looks for NLog.config in, or nearby, the directory of the executing process.
In the case of MSBuild.exe this is too far out of reach. So I have to reload it from within my assembly. After that, logging works as expected.

Reply | Threaded
Open this post in threaded view
|

Re: Problem with call from MSBuild

Vincent026
This post was updated on .
A modification of my previous answer is that it is perhaps easier to use the following line of code to get the desired path:

string CurrentDirectory = Environment.CurrentDirectory;

instead of:

string CurrentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase);

The second option yields a string in URI format, starting with "file:\\...". This may cause problems if you use this path later on to set the FileName property in the target. The target cannot cope with this URI format. If you use the first option, the path starts with "C:\...".  directly. I am not 100% sure but I think that both options always point to the same directory.

If you prefer using the second option then this is a good way to convert the URI string to a regular path-string:
{
...
   string CurrentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase);
   Uri uri;
   if (Uri.TryCreate(CurrentDirectory , UriKind.Absolute, out uri))
   {
          CurrentDirectory = uri.LocalPath;
   }
...
}