How can you make two different NLog targets with same date inside? - asp.net-core

I have the following two targets defined in NLog.config inside my ASP.NET Core project:
<targets>
<target name="MyApp" xsi:type="File"
fileName="${specialfolder:folder=ApplicationData}/MyApp/${date:format=yyyyMMdd_HHmmss:cached=true}_MyApp.log"
layout="${longdate}|${level:uppercase=true}|${logger}|${message}"
deleteOldFileOnStartup="false"/>
<target name="MyAppAll" xsi:type="File"
fileName="${specialfolder:folder=ApplicationData}/MyApp/${date:format=yyyyMMdd_HHmmss:cached=true}_MyApp.log"
layout="${longdate}|${level:uppercase=true}|${logger}|${message}"
deleteOldFileOnStartup="false"/>
</targets>
MyApp target logs all my logs from the app while MyAppAll includes some framework logs as well.
I am trying to get the NLog to create two log files that have the same timestamp but what I have observed is that MyAppAll will be created immediately on app start since this is the time framework logs start while MyApp will only be created once I send request to API and the result is that I have two files with different dates.
Any ideas on how to solve this?

You can use ${processinfo:StartTime}:
<targets>
<target name="MyApp" xsi:type="File"
fileName="${specialfolder:folder=ApplicationData}/MyApp/${processinfo:StartTime:format=yyyyMMdd_HHmmss:cached=true}_MyApp.log"
layout="${longdate}|${level:uppercase=true}|${logger}|${message}" />
<target name="MyAppAll" xsi:type="File"
fileName="${specialfolder:folder=ApplicationData}/MyApp/${processinfo:StartTime:format=yyyyMMdd_HHmmss:cached=true}_MyApp.log"
layout="${longdate}|${level:uppercase=true}|${logger}|${message}" />
</targets>
See also: https://github.com/NLog/NLog/wiki/ProcessInfo-Layout-Renderer
Notice having 2 file-targets sharing the same filename is not recommended. Forexample with NLog 5 where KeepFileOpen=true by default, then one will stop working.

Related

Apply a web.config transform within a Teamcity Build Step

I am trying to run a MSBuild task on team city that also transforms a web.casper.config file.
I have tried various switches but can;t get this right. Which most likely means there is a different way to achieve my desired result (like publish).
I have tried:-
/t:TransformWebConfig
/p:TransformWebConfig=true
Basically I want to
- BUILD website.csproj into a custom dir
- THEN apply a web.config transform on web.casper.config
Can anyone help?
One thing that seems to work (not sure if its the best way) is to add a before/after build event on the csproj file for the website e.g.
<Target Name="BeforeBuild">
<Copy SourceFiles="Web.config" DestinationFiles="Web.temp.config"
OverwriteReadOnlyFiles="True" />
<TransformXml Source="Web.temp.config" Transform="Web.$(Configuration).config"
Destination="Web.config" />
</Target>
<Target Name="AfterBuild">
<Copy SourceFiles="Web.temp.config" DestinationFiles="Web.config"
OverwriteReadOnlyFiles="True" />
<Delete Files="Web.temp.config" />
</Target>
This basically copies web.config to web.temp.config then uses the casper config to transform.
Source from SO

How do I specify where MSBUILD publishes a web service too?

I've seen lots of info on the web about this, but nothing clear & specific which seems to address the problem of simply publishing a web service or web site to a specific folder that I specify at build time.
I'm using Nant and Nant Contrib:
<target name="build" description="builds the service">
<msbuild project="${buildoutput}\${service.source}\wsMyService.sln" >
<property name="Configuration" value="Release" />
<property name="PublishDir" value="${buildoutput}\${service.target}\" />
<property name="Targets" value="Publish" />
</msbuild>
</target>
Can anyone show me how this is supposed to be done. I can change the output folder in the property pages of the project, but I want this to be configurable from Nant so I can specify the path at build time.
When you call msbuild from the command line, you can pass in strings to assign to msbuild properties. I don't know anything about NAnt, so I assume it has to resort to a calling msbuild.exe. So you can override msbuild properties like this:
MsBuild /property:buildoutput=C:\arbitrary\folder\bin\
These properties specified from the command line override anything you specify in your build files.
This is what im currently using to build webservices using msbuild:
<Target Name="BuildWebService">
<ConvertToAbsolutePath Paths="$(Root)">
<Output TaskParameter="AbsolutePaths" PropertyName="Root" />
</ConvertToAbsolutePath>
<ItemGroup>
<WebServices Include="$(Root)\services\Solutions\**\*.host.csproj"/>
</ItemGroup>
<MSBuild Projects="%(WebServices.FullPath)"
Targets="Build"
Properties="WebProjectOutputDir=$(Root)\services\build\WebService\%(RecursiveDir);OutDir=$(Root)\services\build\WebService\%(RecursiveDir)\bin\" />
</Target>
Hope you can translate to nant easy enough.

msbuild fileupdate setup project

I'm looking to use the fileUpdate task from msbuildtasks.tigris.org to modify image src's as part of our web setup project so that they will point to a static img sub domain (or later a CDN)
I can run a task within a given project with:
<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />
<Target Name="AfterBuild">
<FileUpdate
Files="basic.css"
Regex="/images/([^\)]*)"
ReplacementText="http://img.domain.com/images/$1" />
</Target>
However, I dont want to overwrite the original css source file, but want to run this as part of our deployment project that produces an msi.
This is done using a web setup project (.vdproj) which also uses a custom actions project which is just a standard .csproj
My questions are:
How can I run this task in the setup project so that I replace content in the files that go into the .msi?
Is there a way to use wildcards for the files - ideally I want to say do this for ALL .css files?
In order to achieve this you need to use an item group to create the list for you
<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />
<Target Name="AfterBuild">
<ItemGroup>
<CssFiles Include='$(SolutionRoot)\**\*.css' />
</ItemGroup>
<FileUpdate
Files="#(CssFiles)"
Regex="/images/([^\)]*)"
ReplacementText="http://img.domain.com/images/$1" />
</Target>

MSBuild passing parameters to CallTarget

I'm trying to make a reusable target in my MSBuild file so I can call it multiple times with different parameters.
I've got a skeleton like this:
<Target Name="Deploy">
<!-- Deploy to a different location depending on parameters -->
</Target>
<Target Name="DoDeployments">
<CallTarget Targets="Deploy">
<!-- Somehow indicate I want to deploy to dev -->
</CallTarget>
<CallTarget Targets="Deploy">
<!-- Somehow indicate I want to deploy to testing -->
</CallTarget>
</Target>
But I can't work out how to allow parameters to be passed into the CallTarget, and then in turn the Target itself.
MSBuild targets aren't designed to receive parameters. Instead, they use the properties you define for them.
<PropertyGroup>
<Environment>myValue</Environment>
</PropertyGroup>
<Target Name="Deploy">
<!-- Use the Environment property -->
</Target>
However, a common scenario is to invoke a Target several times with different parameters (i.e. Deploy several websites). In that case, I use the MSBuild MSBuild task and send the parameters as Properties:
<Target Name="DoDeployments">
<MSBuild Projects ="$(MSBuildProjectFullPath)"
Properties="VDir=MyWebsite;Path=C:\MyWebsite;Environment=$(Environment)"
Targets="Deploy" />
<MSBuild Projects ="$(MSBuildProjectFullPath)"
Properties="VDir=MyWebsite2;Path=C:\MyWebsite2;Environment=$(Environment)"
Targets="Deploy" />
</Target>
$(MSBuildProjectFullPath) is the fullpath of the current MSBuild script in case you don't want to send "Deploy" to another file.
You can 'foreach' over an ItemGroup with a target, only you have to do it in declaritive manner. You can even have additional metadata in items, like in the code example:
<ItemGroup>
<What Include="Dev">
<How>With bugs</How>
</What>
<What Include="Test">
<How>With tests</How>
</What>
<What Include="Chicken">
<How>Deep fried</How>
</What>
</ItemGroup>
<Target Name="Deploy">
<Message Text="#(What), %(How)" />
</Target>
Using an item group as a scalar value #(What) inside a target does the trick, and %(How) references a metadata element in a foreach item.
It's a natural way of doing things in msbuild, for example you can find this pattern everywhere in project files generated with Visual Studio.
There might be a better way to do this in MSBuild, but in Ant, I would use global properties to carry information from one task to the next. It was a lousy solution, but I didn't see a better way at the time. You should be able to do this in MSBuild, but bear in mind that you will need to use the CreateProperty task to dynamically assign a property.
On the other hand, it's pretty easy to implement tasks in C# (or VB or whatever). Maybe that's a better solution for you.
<CreateProperty
Value="file1">
<Output
TaskParameter="Value"
PropertyName="filename" />
</CreateProperty>
<CallTarget Targets="Deploy"/>
<Message Text="$(filename)"/>
<CreateProperty
Value="file2">
<Output
TaskParameter="Value"
PropertyName="filename" />
</CreateProperty>
<Message Text="$(filename)"/>
<CallTarget Targets="Deploy"/>

NAnt <msbuild> custom output directory

I'm new to NAnt and have been able to create a <target> which
1) Deletes any code from the current folder
2) Exports fresh code from SVN
3) Builds the code in the default directory which is the PrecompiledWeb folder (its a web app)
Here it is:
<target name="export" description="export code from svn">
<delete dir="${Delete.Dir}"></delete>
<exec program="svn" commandline="export ${MySVN.Repos} ${MySVN.Dest}" />
<msbuild project="${Solution.Filename}">
<property name="Configuration" value="Release"/>
</msbuild>
</target>
I want to specify a custom output directory (other than "PrecompiledWeb"). Is this possible and could you please show me the necessary tag/property?
Thank you!
EDIT
Thanks to Scott and Si, I'm getting closer to a solution, but I still don't have anything that works. There comments led me to this article on MSBuild's Output Path Property. Using their code:
<?xml version="1.0"?>
<project name="test" default="build" basedir="." xmlns="http://nant.sf.net/schemas/nant-0.84.win32.net-1.0.xsd">
<target name="build">
<exec program="${framework::get-framework-directory('net-3.5')}/msbuild.exe">
<arg value="${Full.Path}\Code\MySolution.sln" />
<arg value="/p:OutputPath=${Full.Path}\Output\" />
</exec>
</target>
</project>
This will sucessfully run; however, in my solution which contains a web site and a class library, it publishes the class library dll to the specified output path, but it still publishes the actual web site to the default PrecompiledWeb folder.
Does anyone have any suggestions for how to change the PrecompiledWeb folder path from NAnt?
Thanks again to everyone who's helped!
Edit 2 Final Solution
Here is what I finally was able to get working (updated for .net 4):
<exec program="${framework::get-framework-directory('net-4.0')}/msbuild.exe">
<arg value="${Full.Path}\Code\MySolution.sln" />
<arg value="/t:Rebuild" />
<arg value="/t:ResolveReferences" />
<arg value="/t:_CopyWebApplication" />
<arg value="/p:OutDir=${Build.Output}bin\" />
<arg value="/p:WebProjectOutputDir=${Build.Output}" />
<arg value="/p:Configuration=Release" />
</exec>
One can specify and override some of properties for msbuild. In order to specify the output directory, override the OutputDir property.
<target name="export" description="export code from svn">
<delete dir="${Delete.Dir}" />
<exec program="svn" commandline="export ${MySVN.Repos} ${MySVN.Dest}" />
<msbuild project="${Solution.Filename}">
<property name="Configuration" value="Release"/>
<property name="OutputDir" value="${Output.Dir}"/>
</msbuild>
</target>
Just had a quick peek at a project, does OutputPath instead of OutputDir help?
Another option might be a web deployment project, which I like because it calls aspnet_compiler as well as the C# compiler, so it picks up issues which you may otherwise miss until deployment.
A build script for one of our projects uses this command to publish a web application:
msbuild.exe /t:_CopyWebApplication /p:Configuration=Release /p:OutDir=.\..\published\ /p:WebProjectOutputDir=.\..\published
(The current directory is set to the web app's project directory at this point, which is why no .csproj file is specified. The entire solution has already been rebuilt earlier in the script.)
By the sound of it, WebProjectOutputDir might be the property you need.
/t:_CopyWebApplication may also be important. I've not used NAnt so I don't know if you can pass this parameter with the msbuild task. You may need to use an exec task, like in this example: http://www.netomatix.com/development/wapwithnant.aspx. This example appears to rebuild and copy all in one go.
When using the task, the correct property name is OutDir, not OutputDir:
<msbuild project="${Solution.Filename}">
<property name="Configuration" value="Release"/>
<property name="OutDir" value="${Output.Dir}"/>
</msbuild>
A source of confusion is that you're blending two distinct build systems. Your NAnt target is delegating all the work of figuring out how to publish your web application to the solution file, hence by extension to the csproj files it references.
csproj files are MsBuild files, so you should probably look there for how to direct your project output. This post by dave^2 might be helpful on that issue.
You can publish your web application wherever you want using NAnt, provided it's doing the publishing. You can do the same with MsBuild. The cause of your quandary is that NAnt is not doing the publishing in this case, and you're letting the csproj file determine the location of your web directory. So either bypass the csproj file and have NAnt (or MsBuild) publish the code; or modify the csproj file to publish the web application where you want; or make a second location for your web application and publish it there as well using your build tool.
AFAIK, those options are exhaustive.
Hmm, don't know how to do it with MSBuild in Nant, but using NAnt, I've done it previously like this:
<solution solutionfile="${build.dir}\solution.sln">
<webmap>
<map url="http://localhost/somdir/project.csproj"
path="c:\inetpub\wwwroot\somelocaldir" />
<webmap>
</solution>
But then, you're using the NAnt 'solution' task offcourse instead of using MSBuild directly.
edit:
I'm also having a look at some msbuild options;
If you set OutDir & OutputPath to the same value, what happens ?
Try something like this:
<property name="nant.settings.currentframework" value="net-3.5"/>
<msbuild project="${Solution.Filename}">
<property name="Configuration" value="Release"/>
<property name="OutDir" value="${Full.Path}\Output\\"/>
<property name="WebProjectOutputDir" value="${Full.Path}\Output\Web\\"/>
</msbuild>