Logging.Logger does not contain a definition for SetLogWriter - c#

Copied code from here: https://www.c-sharpcorner.com/article/logging-block-in-microsoft-enterprise-library-6-0/
public class LoggerBlock
{
protected LogWriter logWriter;
public LoggerBlock()
{
InitLogging();
}
private void InitLogging()
{
logWriter = new LogWriterFactory().Create();
Logger.SetLogWriter(logWriter, false);
}
public LogWriter LogWriter
{
get
{
return logWriter;
}
}
}
The compile error is:
Microsoft.Practies.EnterpriseLibrary.Logging.Logger does not contain a
definition for 'SetLogWriter"
Sorry, I don't even know which version of the library I have installed. I'm trying to add some logging statements to an existing program that seems to have the app.config set up for Enterprise Library Logging.
Intellisense provides the following similar method only:
Logger.SetContextItemLog (object key, object value)

I'm guessing you are using an older version that doesn't have the Logger.SetLogWriter() method. I just installed the latest version and the code you pasted works fine. Can you update the version you are using?
Edit: It looks like the Logger.SetLogWriter() method just sets the default Logger to use the LogWriter you just created. How about using the created LogWriter directly instead of the default Logger?
var logWriter = new LogWriterFactory().Create();
logWriter.Write("Message");
The following article might also give you some more information. Creating and Writing Log Entries

Related

Can't import classes from same namespace

I'm fairly new to .NET and I'm trying to get an old program to work that no longer has it's .csproj file. I've managed to receive an old .sln file from the creator and opened the solution in VS.
From what I can see this is a Developer Web Server project?
Here is the issue.
In the folder Smreka there are 2 files, log.cs and smreka.cs. The log.cs contains the implementation of a class Logger, which I am trying to import in to smreka.cs. They are both using the same namespace Bum.Iglavci.Smreka so as far as I know, I should be able to import the Logger class without any issues.
The problem is that the compiler just can't see it. If I try to directly import it with using static Bum.Iglavci.Smreka.Logger;, I get an error Feature 'using static' is not available in C# 5. Please use language version 6 or greater.
I would like to know why the namespace can't see each other. Is it because I'm missing the .csproj file? Does Developer Web Server even need a .csproj file? If so what's the best way to generate one?
EDIT:
Due to some confusion I'll try to add more details regarding how log.cs and smreka.cs look like. The files are actually a lot longer but I think this should give an idea.
log.cs:
namespace Bum.Iglavci.Smreka{
public class Logger{
public Logger(){
}
public void DoSomething(){}
}
}
smreka.cs:
namespace Bum.Iglavci.Smreka{
public class Baza{
private Logger log;
public Baza(){
log = new Logger();
}
}
}
The compiler has no idea what Logger is under property private Logger log; It states the error The type or namespace name 'Logger' could not be found (are you missing a using directive or an assembly reference?)
I think the namespace is correctly placed, that's why i have a feeling there's something wrong with the project or the solution itself that i need to fix.
Since both classes are in the same namespace they are already able to use each other. You can acces the class by simply doing the following. Let's take Log as the class to call the other class.
Log class:
namespace Bum.Iglavci
{
public class Log
{
public static void ExecuteDoSomething()
{
Smreka.DoSomething();
}
}
}
Smerka class:
namespace Bum.Iglavci
{
public class Smerka
{
public static void DoSomething()
{
//execute code here
}
}
}
It could be possible that the files have the Buil Action property set to
None this will not compile the files. Set it to C# Compiler, this should solve it.
If you don't know how to acces the properties of a file.
Right click the file
Navigate to Properties in the bottom of the list
Set the Build Action to C# compiler (see image)
I found no simple solution. I now created a new .net framework application project and added the files in to the new project. For some reason the namespace works correctly now and the files can see each other in the same namespace.
Yes the error comes from the fact that you don't have a .csproj file.
Such files contain the list of files to compile when building a project. Just having the solution file is not enough.
I suggest some readings on project and solution using Visual Studio :
https://learn.microsoft.com/en-us/visualstudio/ide/solutions-and-projects-in-visual-studio?view=vs-2022
https://learn.microsoft.com/en-us/visualstudio/get-started/tutorial-projects-solutions?view=vs-2022

ICommandHandler not executing for SaveCommandArgs (Visual Studio for Mac Extension)

I'm trying to create simple extension for Visual Studio for Mac which will handle the moment when user saves the document (sample project is on GitHub, right here).
Here's how looks my implementation of ICommandHandler<SaveCommandArgs>:
[Export(typeof(ICommandHandler))]
[Name(nameof(SaveCommandHandler))]
[ContentType(StandardContentTypeNames.Code)]
[TextViewRole(PredefinedTextViewRoles.PrimaryDocument)]
public class SaveCommandHandler : ICommandHandler<SaveCommandArgs>
{
public string DisplayName => nameof(SaveCommandHandler);
private readonly IEditorCommandHandlerServiceFactory _editorCommandHandlerServiceFactory;
[ImportingConstructor]
public SaveCommandHandler(IEditorCommandHandlerServiceFactory editorCommandHandlerServiceFactory)
{
_editorCommandHandlerServiceFactory = editorCommandHandlerServiceFactory;
}
public bool ExecuteCommand(SaveCommandArgs args, CommandExecutionContext executionContext)
{
try
{
var service = _editorCommandHandlerServiceFactory.GetService(args.TextView);
Debug.WriteLine($"I am executing something on save with {service.GetType()}");
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
return true;
}
public CommandState GetCommandState(SaveCommandArgs args)
{
return CommandState.Available;
}
}
Good point: system call the constructor of this handler, when you start editing the first file
Bad point: ExecuteCommand method never called, as well as GetCommandState method
Any ideas why it doesn't work?
I was trying to do all the things according to the documentation on official wiki in github project for visual studio api
Unfortunately, there're only samples for quick info and autocomplete features. No samples for ICommandHandler-s, haven't found any similar projects for Visual Studio for Mac as well
I agree the examples since Microsoft Visual Studio SDK documentation is horrible with no good examples of ICommandHandler.
I tried your exact code in visual studio 2022 on Windows 10 and the ExecuteCommand function is called.
So your code is fine.
I think the core problem here is that the ICommandHandler interface structure is somewhat newer and Microsoft did a poor job of properly checking for custom command handlers and adding calls.
I am trying to do a similar thing where I add an ICommandHandler to intercept the GoToDefinition command using an ICommandHandler, using this very similar code I can't get the ExecuteCommand function to fire ever.
I have been able to intercept commands using Microsofts older, yuckier DTE or DTE2 interface.
//provider constructor code
var dte2 = (DTE2)Package.GetGlobalService(typeof(DTE));
dte2.Events.CommandEvents.BeforeExecute += CommandEvents_BeforeExecute;
private static void CommandEvents_BeforeExecute(string guid, int id, object customIn, object customOut, ref bool cancelDefault)
{ //All events fired here use, the guid you want is likely
// Microsoft.VisualStudio.VSConstants.CMDSETID.StandardCommandSet97_string
// With an ID defined in
// Microsoft.VisualStudio.VSConstants.VSStd97CmdID
Debug.WriteLine("CommandEvents_BeforeExecute1 " + String.Format(
"dte2 GUID: {0}\nID: {1}\nIn: {2}\nOut: {3}",
guid, id, customIn, customOut));
}

Roslyn AdditionalFiles

I want to develop a Roslyn Code Analyzer which has access to some static configuration in the form of text files. Since an analyzer cannot access the local file system I guess the only way to read such external configuration is via Context Option and AdditionalFiles.
I am aware of this example dealing with this problem:
https://github.com/dotnet/roslyn/blob/master/docs/analyzers/Using%20Additional%20Files.md
What the example does not say is: Is the analyzer reading the AdditionalFiles shipped with the analyzer assembly or the target being analyzed? The latter does not solve my problem because the configuration is analyzer and not target specific.
Update:
I cannot use the standard "Add New Text File" resource mechanism either. The according context menu entry is disabled:
This seems to be related to the TargetFrameworkProfile which is set to Profile7 when creating a new "Analyzer with Code Fix (NuGet + VSIX)" project.
You should be able to use this overload of the ResourceManager class and just pass in a type defined in your assembly.
class MyResourceManager
{
private readonly ResourceManager _manager;
public MyResourceManager()
{
_manager = new ResourceManager(typeof(MyResourceManager))
}
public string GetStringResouce(string name)
{
return _manager.GetString(name);
}
}

Alternatives to reading config files from class libraries at design time?

I have a WinForm project that contains several UserControls. This WinForm project has a reference to an assembly (lets call it lib.dll) that is created from another project (Class Library) that exists in a different solution.
Now, several of the UserControls make calls into lib.dll that return values from the app.config file. At runtime lib.dll works fine and returns the necessary data but at design time, I am getting an exception from lib.dll because the app.config sections are NULL (the exceptions are by design).
Now I could go through each control and wrap any code that calls into lib with
if(!DesignMode) { //code }
But that is a lot of controls to go and apply that to. Is there something I can do globally that would be more elegant then testing the DesignMode property?
Edit
In response to the two comments left below: the solutions provided don't appear to work. The assembly that is causing me a problem lives in the same directory as the app.config. The general directory structure looks like this
References Folder
Configurations (Folder)
appsettings.config
app.config
lib.dll
app.config pulls in several other config files (appsettings, cnx strings, etc) which reside in the Configurations directory. In the case of my exception the value I am trying to get resides in one of these ancillary config files that is referenced by app.config.
This is an interesting question. A solution could be to create in lib.dll a static class like this one :
public static class Config
{
private static readonly _param1;
static Config()
{
_param1 = ConfigurationManager.AppSettings["Param1"] ?? "Your default value";
}
public static string Param1
{
get { return _param1; }
}
}
Then, in your code, insted of writing ConfigurationManager.AppSettings["Param1"], you will use Config.Param1. So you won't need to test the property DesignMode.
There are so many ways to do this, IMHO.
One thought that immedidately comes to mind would be to use an inheritance-based approach for the user controls in question? That way, in the base class, you can put that if (DesignMode) check in, and do the correct branching from there.
// if i were to visualizeyour lib.dll data initializer call like this:
class BaseUserControl
{
// i'm guessing that you initialize the data somehow...
void InitializeData()
{
if (!DesignMode)
{
InitializeDataLocal();
}
}
protected virtual InitializeDataLocal()
{
// whatever base behavior you want should go here.
}
}
// in the derived classes, just put the code you currently have for
// fetching the data from lib.dll here...
class UserControl : BaseUserControl
{
protected override InitializeDataLocal()
{
// fetch from lib.dll...
// optionally invoke some base behavior as well,
// if you need to...
base.InitializeDataLocal();
}
}

How to make designer generated .Net application settings portable

I've been looking at modifying the source of the Doppler podcast aggregator with the goal of being able to run the program directly from my mp3 player.
Doppler stores application settings using a Visual Studio designer generated Settings class, which by default serializes user settings to the user's home directory. I'd like to change this so that all settings would be stored in the same directory as the exe.
It seems that this would be possible by creating a custom provider class which inherits the SettingsProvider class. Has anyone created such a provider and would like to share code?
Update: I was able to get a custom settings provider nearly working by using this MSDN sample, i.e. with simple inheritance. I was initially confused as Windows Forms designer stopped working until I did this trick suggested at Codeproject:
internal sealed partial class Settings
{
private MySettingsProvider settingsprovider = new MySettingsProvider();
public Settings()
{
foreach (SettingsProperty property in this.Properties)
{
property.Provider = settingsprovider;
}
...
The program still starts with window size 0;0 though.
Anyone with any insight to this?
Why the need to assing the provider in runtime---instead of using attributes as suggested by MSDN?
Why the changes in how the default settings are passed to the application with the default settings provider vs. the custom one?
Why not use the CodeProject PortableSettingsProvider solution as is (with a few minor changes) ?
I have done so in my project (StreamRecorder.NET) with success.
Some comments on the project's page were useful:
http://www.codeproject.com/Messages/2934144/Fixed-csharp-version.aspx
http://www.codeproject.com/Messages/3285411/Re-Win-Form-Designer-breaking-with-custom-Settings.aspx
And the code I ended up with:
static void Main(string[] args)
{
if (args.Contains("-p") || args.Contains("--portable"))
{
MakePortable(Properties.Settings.Default);
MakePortable(Properties.LastUsedSettings.Default);
MakePortable(Properties.DefaultSettings.Default);
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm(args));
}
private static void MakePortable(ApplicationSettingsBase settings)
{
var portableSettingsProvider =
new PortableSettingsProvider(settings.GetType().Name + ".settings");
settings.Providers.Add(portableSettingsProvider);
foreach (System.Configuration.SettingsProperty prop in settings.Properties)
prop.Provider = portableSettingsProvider;
settings.Reload();
}
Lastly I made these changes to the CP project:
string _fileName;
public PortableSettingsProvider(string fileName)
{
_fileName = fileName;
}
public virtual string GetAppSettingsFilename()
{
//Used to determine the filename to store the settings
//return ApplicationName + ".settings";
return _fileName;
}
I know this question is quite old already. I just want to share my own version of a portable settings provider which I published as nuget package here.
The usage is pretty simple:
// make the default settings class portable
PortableSettingsProvider.ApplyProvider(Properties.Settings.Default);
I also explained the basic strategy of this implementation at https://www.codeproject.com/Articles/1238550/Making-Application-Settings-Portable.
Just to 'close' the question: The somewhat unsatisfactory solution I ended up with was
Create a custom settings provider, which inherits from SettingsProvider and stores the settings in a XML file
Set the Provider property of each of the setting (by selecting the entire grid in the designer) to the custom settings provider using the designer
Drawbacks: The forms designer breaks and gives an exception which basically says that the custom provider class cannot be found. The built exe however works OK. Setting the provider in the code as described in the question makes the designer work, but then for some reason, which I haven't looked closely at, the settings won't serialize.
It seems that making settings portable was all that was needed to make Doppler portable. Whether I'll start using Doppler as my main podcast aggregator or stick with my homebrew command line aggregator, I'll see.

Categories