I have simple C# console application:
static int main(string[] args){
return SomeBoolMethod() ? 1:0;
}
How in WiX 2.0 should I define property and set this value to it? I don't care about future upgrade/uninstall
UPD
I want latter use this property in condition: so the group B will not execute if MYPROPERTY == 0 but all further components in feature F_A will
I.E.
<Feature Id="F_A" Level="1">
<Condition Level="0">NOT INSTALLED</Condition> <!-- Another custom property -->
<ComponentGroupRef Id="B" />
<ComponentRef Id="C_AnotherComponent" />
</Feature>
<ComponentGroup Id="B">
<Condition Level="0">NOT MYPROPERTY</Condition> <!-- property that set in console-->
<ComponentRef Id="C_ComponentName" />
</ComponentGroup>
TIA
Executables that are run as Custom Actions do not have access to the Installation session, so they cannot modify a property. Ideally you would rewrite the code that's currently in an exe to reside in a dll, so it could be called as a dll custom action.
If you cannot rewrite things (perhaps you received the exe from elsewhere), you would need to write a dll custom action that launches the exe, examines its exit code, and sets properties accordingly.
In neither case do you need to predefine the property; you can just set it in the dll custom action. In both cases, if the dll is written in C# you will have to use a technology like DTF to invoke it, as Windows Installer cannot directly invoke managed code.
Related
I've watched the following video explaining about Serilog. I would like to use structured logging in my application as well (at least parts of it), but I prefer to use NLog (1) because it's already part of our stack and we're used to it and prefer to have the same logger on across our projects, and (2) I have read the comparison here and seems like NLog is more performant.
So I read that NLog also support structured logging and I have implemented it in a test application without a problem. It works very well.
What I saw in the video and liked about Serilog, is when writing to console it highlights the parameters passed to the logging function like this:
I would like to have the same on the console application I'm currently building. I have tried both Console target and ColoredConsole but non has that effect. Is it possible in NLog?
This is my targets configurations:
<target name="file"
xsi:type="File"
archiveEvery="Day"
archiveFileName="Logs\log.{#}.txt"
fileName="Logs\log.txt"
archiveNumbering="DateAndSequence"
archiveDateFormat="yyyy-MM-dd"
archiveAboveSize="104857600"
maxArchiveFiles="30"
layout="${longdate} | ${uppercase:${level}} | ${logger} | ${threadid} | ${message} ${exception}"
/>
<target xsi:type="ColoredConsole"
name="ColorConsole"
layout="${uppercase:${level}}: ${message} ${exception:innerFormat=Message,StackTrace}"
header="Memoriez API"
useDefaultRowHighlightingRules="false"
>
<highlight-word foregroundColor="Green" ignoreCase="true" text="info" wholeWords="true" />
<highlight-word foregroundColor="Red" ignoreCase="true" text="warn" wholeWords="true" />
<highlight-word backgroundColor="Red" foregroundColor="White" ignoreCase="true" text="error" wholeWords="true" />
<highlight-row backgroundColor="DarkRed" foregroundColor="Yellow" condition="level == LogLevel.Fatal" />
</target>
I do not think you can colorized the parameters in ColoredConsoleTarget. It might be possible to use WordHighlighting, but you would quickly run into issues where matching a number would highlight all numbers and not just the parameter.
My guess is that you would need to write a custom ColoredConsoleTarget in order to highlight parameters. I just looked at the src\NLog\Targets\ColoredConsoleTarget.cs file and it only offers RowHighlightingRules and WordHighlightingRules. It looks like when the color codes are applied the LogEventInfo has been rendered into a plain string.
I think you would need to write a custom RenderLogEvent function that would render the color escape sequences for parameters. It would be a bit tricky because the GenerateColorEscapeSequences for WordHighlighting would escape any color sequences generated before it is called).
Here are my thoughts:
Create a new class ColoredParamConsoleTarget with code copied from ColoredConsoleTarget. It doesn't look like there are virtual methods to just override the existing class.
Create a ColoredRenderLogEvent method and parse for parameters and add color sequences before and after parameters.
Replace calls to RenderLogEvent with ColoredRenderLogEvent
I want to enable developers to log objects as JSON with NLog. To do this I need to implement some logic before sending to nLog OR before sending to target.
I can build my own Target(TargetWithLayout) but I can´t find a way to check the log level from the config for this specific target/logger? Another drawback is that I need to make a new TargetWithLayout class for each target that we will use (EventLog, File, WebService and so on).
Another solution would be to do it in my LogHandler that uses NLog. The only way to know if I should translate the object is probably to read all the loggers from the config file, if any of them is set to log objects then I serialize. I am however not sure if I can check this information from the LogHandler (without doing it manually)?
You can use the NLog-Logger object to query active logging-rules:
if (myLogger.IsTraceEnabled)
myLogger.Trace("Hello World");
You can use the NLog json layout to write json in you log files, no need to check and do the serialization yourself:
<target name="jsonFile" xsi:type="File" fileName="${logFileNamePrefix}.json">
<layout xsi:type="JsonLayout">
<attribute name="time" layout="${longdate}" />
<attribute name="level" layout="${level:upperCase=true}"/>
<attribute name="message" layout="${message}" />
</layout>
</target>
The log messages formatting is handled by NLog instead of doing it yourself.
release notes nlog
To add some theory ;)
Another drawback is that I need to make a new TargetWithLayout class for each target that we will use (EventLog, File, WebService and so on).
That's the reasons there are Layouts in NLog. Those are the layouts that could be used in the target, but those are independent of the target.
(don't get confused with Layout Renderers, those ${..} things.)
There are multiple layouts (plain text, CSV, JSON) (see list) , and you could easily add your own layout, analogous to adding a custom Target / Layout renderer, see the wiki
I have an application and I want to use my own file extension that opens my application when double clicked.
I'm using Wix to build my installer and understand that I can make use of file association in my .wxs file. A snippet from the file currently looks like this:
<DirectoryRef Id ="INSTALLFOLDER">
<Component Id ="RBUpdate.exe" Guid="*">
<File Id="RBUpdate.exe" KeyPath="yes" Source="$(var.RBUpdate.TargetDir)RBUpdate.exe" />
<ProgId Id ="MyProgID" Description="RBUpdate data files" Advertise="yes">
<Extension Id ="rbu" ContentType="application/rbu">
<Verb Id ="open" Command="open" TargetFile="RBUpdate.exe" Argument=""%1""/>
</Extension>
</ProgId>
</Component>
</DirectoryRef>
<Feature Id ="ProductFeature" Title="RBUpdateSetup" Level="1">
<ComponentRef Id ="RBUpdate.exe"/>
</Feature>
This builds fine but, if I'm honest, I'm new to this and not quite quite sure what it does.
How do I create an instance of my created file type? The files I'm creating are not going to be as a result of running the application and they will be manually made externally to the application, which it will then load. I simply want to be able to make an xml file, name it with the .rbu extension, and have it open with my application.
I was very simply not renaming my xml files .rbu! This is a working example of how to use file association with wix anyway, to not completely waste time :L
Trying to update my resharper extension to work for 9.0, before I was just moving the dll into the plugins directory but now I need to figure out how to get nuget to work... I've been able to package the files, dll gets included in the nupkg but I think I have some namespace\id something something issues(not very familiar with .net) and it doesn't seem as if my actions.xml is even being read by resharper when I import the nuget package. The menu item isn't being added. Anwyays if anyone can give me any sort of advice on how to debug a nuget package or what might be going wrong would really really appreciate as I've been stuck on this for a few days now.
Actions.xml
<?xml version="1.0" encoding="utf-8" ?>
<actions>
<action id="yuval" text="L10N"></action>
<insert group-id="ReSharper" position="last">
<action-ref id="yuval" text="About Localization Helper"/>
</insert>
</actions>
AboutAction.cs
namespace JetBrains.Resharper.L10N
{
[Action(Id)]
public class AboutAction : IExecutableAction
{
public const string Id = "yuval";
public bool Update(IDataContext context, ActionPresentation presentation, DelegateUpdate nextUpdate)
{
return true;
}
public void Execute(IDataContext context, DelegateExecute nextExecute)
{
MessageBox.ShowMessageBox(
"Localization Helper\nYuval\n\nHelps Localize",
"About Localization Helper",
MbButton.MB_OK,
MbIcon.MB_ICONASTERISK);
}
}
}
nuget spec
<?xml version="1.0"?>
<package >
<metadata>
<id>JetBrains.Resharper.L10N</id>
<version>1.0.0.7</version>
<title>L10N</title>
<authors>Yuval</authors>
<owners>UW</owners>
<licenseUrl>https://myurl.com</licenseUrl>
<projectUrl>https://myurl.com</projectUrl>
<iconUrl>https://myurl.com/logo.png</iconUrl>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
<description>Tool to help localize</description>
<releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
<copyright>Copyright 2015</copyright>
<tags></tags>
<dependencies>
<dependency id="Wave" version="[1.0]" />
</dependencies>
</metadata>
<files>
<file src="..\bin\Debug\JetBrains.Resharper.L10N.dll"
target="dotFiles\"/>
</files>
</package>
The way actions are registered has changed in ReSharper 9. It's no longer done with actions.xml, but with interfaces on your action class. For example, to add an action to the ReSharper → Tools menu, you would do:
[Action(ActionId, Id = 1)]
public class AboutAction : IExecutableAction, IInsertLast<ToolsMenu>
{
public const string ActionId = "yuval";
// …
}
You also need to specify a unique value for Id. As of 9.1, this needs to be unique within your own extension (9.0 required it to be unique across the whole installation, including ReSharper itself and any other extensions).
Whenever you change the attributes or interfaces of an action, the extension needs to be reinstalled via nupkg (the actions are statically registered with Visual Studio, in the same way as a standard VS extension), but if just the implementation has changed, you can copy the dlls to the install folder, either manually, or via a small change to the .csproj.
You also need to make sure you've defined a ZoneMarker class. This declares that your action belongs to a zone, which is used to enable/disable functionality based on installed features and the current host (e.g. so Visual Studio specific extensions only work in VS and don't get loaded into dotPeek, etc.). You can find out more about Zones in the devguide, with this page providing useful info for defining a zone marker.
This thread should help, too.
Also, it's probably a good idea to name you dll and nupkg something other than JetBrains.ReSharper.(Whatever) to prevent any potential clashes with official dlls, and to prevent confusion as to where the dll comes from. The first part of the name is supposed to be your company's name (or personal name).
My application can be started both as a Windows Service and in console environment. For each case, I need some log4net appenders to be active (or not, respectively) as well as some which are active in both cases. (Service: RollingFileAppender, DebugAppender (if enabled), EventLogAppender | Console: ColoredConsoleAppender, DebugAppender (if enabled))
The only way to achieve something similar is using the PropertyFilter together with ThreadContext.Properties like so:
<filter type="log4net.Filter.PropertyFilter">
<key value="ApplicationMode" />
<stringToMatch value="Service" />
</filter>
if(!Environment.UserInteractive)
ThreadContext.Properties["ApplicationMode"] = "Service";
However, since the property is declared on the thread context, it only works on the current thread. If the thread changes, the configuration is being reset and I have to declare it again.
Does log4net support a way to declare a PropertyFilter in configuration to setup the desired environment automatically? Like this:
<filter type="log4net.Filter.PropertyFilter">
<key value="{Environment.UserInteractive}" />
<stringToMatch value="false" />
</filter>
Or... is there a better approach? Since I didn't found a solution yet.. is this an uncommon practice?
See the last part of my answer to this question:
Capture username with log4net
To summarize, you can implement an object that contains the logic that you have above and put that object in GlobalContext.Properties. When log4net retrieves the value (your object) from the Properties, it will call ToString to get the actual value. Put your logic inside ToString.
Maybe something like this:
public class ApplicationModeProvider
{
public override string ToString()
{
return Environment.UserInteractive ? "Console" : "Service";
}
}
Put it in your dictionary at startup:
GlobalContext.Properties["ApplicationMode"] = new ApplicationModeProvider();
In effect, this is sort of like adding
if(!Environment.UserInteractive)
ThreadContext.Properties["ApplicationMode"] = "Service";
before ever logging statement.
I'm not sure, but I think that then you can configure your filter as you describe in your post.