Query FxCop For Supported Rules (Using commandline) - fxcop

I would like to run a command to see all rules that FxCop will support (based on the DLLs in its Rules directory).
Is this possible?

The rule list can be viewed in the Rules tab of the FxCop UI (e.g.: http://www.binarycoder.net/fxcop/html/screenshot.png).
If you want a text version and don't have a screen clipping tool that will allow you to extract this from the UI, the rules list is pretty trivial to extract with a bit of reflection. You can either invoke internal types and methods in the FxCop object model to do this, or you can look for concrete classes that implement the Microsoft.FxCop.Sdk.IRule interface in the rule assemblies. e.g.:
internal static class Program
{
private static void Main(string[] args)
{
Program.EnumerateFxCopRules(#"C:\Program Files (x86)\Microsoft Fxcop 10.0\Rules");
Console.ReadLine();
}
private static void EnumerateFxCopRules(string ruleDirectoryPath)
{
foreach (var ruleAssembly in Program.GetAssemblies(ruleDirectoryPath))
{
Program.WriteRuleList(ruleAssembly);
}
}
private static IEnumerable<Assembly> GetAssemblies(string directoryPath)
{
var result = new List<Assembly>();
foreach (var filePath in Directory.GetFiles(directoryPath, "*.dll"))
{
try
{
result.Add(Assembly.LoadFrom(filePath));
}
catch (FileLoadException)
{
Console.WriteLine("FileLoadException attempting to load {0}.", filePath);
}
catch (BadImageFormatException)
{
Console.WriteLine("BadImageFormatException attempting to load {0}.", filePath);
}
}
return result;
}
private static void WriteRuleList(Assembly ruleAssembly)
{
Console.WriteLine(ruleAssembly.Location);
foreach (var ruleType in ruleAssembly.GetTypes().Where(t => (!t.IsAbstract) && typeof(IRule).IsAssignableFrom(t)))
{
Console.WriteLine("\t{0}", ruleType.FullName);
}
}
}

Related

Asp Net Core SQL Custom Configuration Provider with Dapper and Error Handling

I am setting up my MVC web application to pull configuration data from my SQL Azure database on startup. I have used these two articles (Microsoft, Medium) to guide me but neither include error handling and I want to avoid any Entity Framework references as i'm using Dapper. So far I've got it working with below code but I'm not sure how to handle errors in this scenario. For instance if I remove the try/catch from the Load method in SQLConfigurationProvider then the app crashes on startup but if I include the try/catch then the error is handled and the app starts normally but no config data is available so will eventually break when trying to access a config value. What is the best way to handle these errors gracefully (ie app still loads but displays an error page/message instead)? Also is there any benefit to having the SQLConfigurationSource or would it make more sense just to create the new SqlConnection instance inside SQLConfigurationProvider instead?
Program.cs
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.CaptureStartupErrors(true)
.UseSetting(WebHostDefaults.DetailedErrorsKey, "true")
.UseApplicationInsights()
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddSQLConfiguration(); // Custom configuration here
})
.UseStartup<Startup>();
}
ConfigurationExtensions.cs
public static class ConfigurationExtensions
{
public static IConfigurationBuilder AddSQLConfiguration(this IConfigurationBuilder builder)
{
var connectionString = builder.Build().GetConnectionString("DefaultConnection");
return builder.Add(new SQLConfigurationSource(connectionString));
}
}
SQLConfigurationSource.cs
public class SQLConfigurationSource : IConfigurationSource
{
private readonly SqlConnection _connection;
public SQLConfigurationSource(string connectionString)
{
_connection = new SqlConnection(connectionString);
}
public IConfigurationProvider Build(IConfigurationBuilder builder)
{
return new SQLConfigurationProvider(_connection);
}
}
SQLConfigurationProvider.cs
public class SQLConfigurationProvider : ConfigurationProvider
{
private readonly SqlConnection _connection;
public SQLConfigurationProvider(SqlConnection connection)
{
_connection = connection;
}
public override void Load()
{
try
{
var model = _connection.Query<SQLConfigurationModel>("sp does not exist for example", commandType: CommandType.StoredProcedure);
Data = model.ToDictionary(x => x.Property, x => x.Value);
}
catch (Exception ex)
{
// WHAT TO DO HERE?
}
}
}
public class SQLConfigurationModel
{
public string Property { get; set; }
public string Value { get; set; }
}
---- UPDATE: CLOSE BUT NOT QUITE THERE ----
I added the exception as a configuration value which I then check for in the Configure method of Startup.cs as per below. This helps ensure the app doesn't crash on startup but when I throw the exception it is not getting routed to the Error view even though the exception handler has already been configured with app.UseExceptionHandler("/Home/Error")
// Inside SQLConfigurationProvider
public override void Load()
{
try
{
var model = _connection.Query<SQLConfigurationModel>("sp does not exist for example", commandType: CommandType.StoredProcedure);
Data = model.ToDictionary(x => x.Property, x => x.Value);
}
catch (Exception ex)
{
Data.Add("ConfigurationLoadException", ex.Message);
}
}
// Inside Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseExceptionHandler("/Home/Error");
// Check for custom config exception
string configurationLoadException = Configuration["ConfigurationLoadException"];
if (configurationLoadException.Length > 0)
{
throw new Exception("Configuration Failed: " + configurationLoadException);
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
If your application can't work without the configurations stored in SQL, you should move this code to fetch data to have better error management. That way you will be able to show a proper error message to user and log it better. Other option is use try/catch block in program.cs, and the assumption is that the not having the SQL driven configuration, will not break the startup project but further in the application usage. If that's the case, you will already have error management placed in startup and it can show you a functional error page for this.
This link will give you some views about startup/program.cs error handling
You should configure a custom error handling page Please read following. it's easy to do
Custom Error Page .net Core

Instantiate using Windsor's factory

Below's code is working fine, and successfully create an instance for class DummyComponnent.
But the problem arises when i had changed the factory method name CreatDummyComponnent()
to GetDummyComponnent() or anything else except Creat as the beginning of method name, say AnyThingComponent throws an exception. is there any specify naming rule for factory methods ?
using System;
using Castle.Facilities.TypedFactory;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
namespace AsFactoryImplementation
{
public interface IDummyComponnentFactory
{
IDummyComponnent CreatDummyComponnent();
// void Relese(IDummyComponnent factory);
}
public interface IDummyComponnent
{
void Show();
}
public class DummyComponnent:IDummyComponnent
{
public DummyComponnent()
{
Console.WriteLine("we are working here");
}
public void Show()
{
Console.WriteLine("just testing this for better performance");
}
}
class Program
{
static void Main(string[] args)
{
var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<IDummyComponnent>().ImplementedBy<DummyComponnent>().Named("FirstConnection"),
Component.For<IDummyComponnentFactory>().AsFactory());
var val = container.Resolve<IDummyComponnentFactory>();
var iDummy = val.CreatDummyComponnent();
iDummy.Show();
Console.WriteLine("OK its done ");
Console.ReadLine();
}
}
}
You should be able to use anything for starting the method names on the Factory, except for starting with Get.
If you start with Get it will try to resolve the component by name instead of by interface.
So what would work in your example is:
var iDummy = val.GetFirstConnection();
Good luck,
Marwijn.

Can't get Ninject.Extensions.Interception working

I've been trying for ages to figure this our. when i try to bind my class with an interceptor i'm getting the following exception on the line
Kernel.Bind<MyClass>().ToSelf().Intercept().With<ILoggerAspect>();
Error loading Ninject component IAdviceFactory. No such component has been registered in the kernel's component container
I've tried with and without LoadExtensions, With about with using a Module to set up my bindings and my last attempt looks like this
internal class AppConfiguration
{
internal AppConfiguration( )
{
var settings = new NinjectSettings() { LoadExtensions = false };
Kernel = new StandardKernel(settings);
Load();
}
internal StandardKernel Kernel { get; set; }
public static AppConfiguration Instance
{
get { return _instance ?? (_instance = new AppConfiguration()); }
}
private static AppConfiguration _instance;
private void Load()
{
Kernel.Bind<ILoggerAspect>().To<Log4NetAspect>().InSingletonScope();
Kernel.Bind<MyClass>().ToSelf().Intercept().With<ILoggerAspect>();
}
internal static StandardKernel Resolver()
{
return Instance.Kernel;
}
}
My Logger Attribute looks like this
public class LogAttribute : InterceptAttribute
{
public override IInterceptor CreateInterceptor(IProxyRequest request)
{
return request.Context.Kernel.Get<ILoggerAspect>();
}
}
And my interceptor like this
public class Log4NetAspect : SimpleInterceptor, ILoggerAspect
{
protected override void BeforeInvoke(IInvocation invocation)
{
Debug.WriteLine("Running " + invocation.ReturnValue);
base.BeforeInvoke(invocation);
}
public new void Intercept(IInvocation invocation)
{
try
{
base.Intercept(invocation);
}
catch (Exception e)
{
Debug.WriteLine("Exception: " + e.Message);
}
}
protected override void AfterInvoke(IInvocation invocation)
{
Debug.WriteLine("After Method");
base.AfterInvoke(invocation);
}
}
Most likely you didn't deploy Ninject.Extensions.Interception.DynamicProxy or Ninject.Extensions.Interception.Linfu alongside your application [and Ninject.Extensions.Interception]. You have to pick exactly one of them.
With the code as you have it right now (LoadExtensions=false) it will fail to pick up the specific interception library - you should remove that and the normal extensions loading should wire the extension into the Kernel on creation for the interception bits to pick it up.
In addition to Remo Gloor's answer which pointed me toward adding the nuget package for Ninject.Extensions.Interception.DynamicProxy, I kept getting the same exception as the OP, until I manually loaded a DynamicProxyModule - the FuncModule is manually loaded as well, to work around a similar error involving the factory extension:
_kernel = new StandardKernel(
new NinjectSettings{LoadExtensions = true},
new FuncModule(),
new DynamicProxyModule()); // <~ this is what fixed it

AppDomain.Unload does not remove lock on dll

am using the following code to create new AppDomain and load my assemblies into it, where my assemblies load successfully, but after i call the AppDomain.Unload method, there is still lock on the loaded dlls, where i went for creating new AppDomain solution because i found over the net that this is the recommended technique to load/unload assemblies and also to make the assemblies replaceable, any idea?
here is my code:
public sealed class AssemblyLoader : MarshalByRefObject
{
private static AppDomain LocalDomain = AppDomain.CreateDomain("LocalDomain");
public static Assembly LoadAssembly(string path)
{
try
{
Assembly assembly = Assembly.Load(AssemblyName.GetAssemblyName(path));
if (assembly != null)
return assembly;
}
catch { }
return Assembly.LoadFrom(path);
}
public static void Unload()
{
if (LocalDomain != null)
{
AppDomain.Unload(LocalDomain);
LocalDomain = null;
}
}
}
I'm not sure but from the theory shouldn't it be more like this.
You're not loading the assembly through the newly created AppDomain.
public static Assembly LoadAssembly(string path)
{
try
{
Assembly assembly = LocalDomain.Load(AssemblyName.GetAssemblyName(path));
if (assembly != null)
return assembly;
}
catch { }
// ..
}

CodeCampServer don't input any logging from NHibernate?

Are you ever succeed input NHibernate logging using CodeCampServer architecture?
I read this and I did everything that I can. Maybe there is know problem in this architecture.
I using Infrastructure.NHibernate.DataAccess.Bases.Logger.EnsureInitialized();
to initialize log4net. here the code:
public class DependencyRegistrar
{
private static bool _dependenciesRegistered;
private static void RegisterDependencies()
{
ObjectFactory.Initialize(x => x.Scan(y =>
{
y.AssemblyContainingType<DependencyRegistry>();
y.AssemblyContainingType<NaakRegistry>();
y.LookForRegistries();
y.AddAllTypesOf<IRequiresConfigurationOnStartup>();
}));
new InitiailizeDefaultFactories().Configure();
}
private static readonly object sync = new object();
internal void ConfigureOnStartup()
{
Infrastructure.NHibernate.DataAccess.Bases.Logger.EnsureInitialized();
RegisterDependencies();
var dependenciesToInitialized = ObjectFactory.GetAllInstances<IRequiresConfigurationOnStartup>();
foreach (var dependency in dependenciesToInitialized)
{
dependency.Configure();
}
}
public static T Resolve<T>()
{
return ObjectFactory.GetInstance<T>();
}
public static object Resolve(Type modelType)
{
return ObjectFactory.GetInstance(modelType);
}
public static bool Registered(Type type)
{
EnsureDependenciesRegistered();
return ObjectFactory.GetInstance(type) != null;
}
public static void EnsureDependenciesRegistered()
{
if (!_dependenciesRegistered)
{
lock (sync)
{
if (!_dependenciesRegistered)
{
RegisterDependencies();
_dependenciesRegistered = true;
}
}
}
}
}
And I see the logging files, I can't delete them when the app run, so I know they are generated. in addition, when I log for test, the log are input. For example, this code do input log.
Bases.Logger.Debug(this, "Debug test!")
So, do CodeCampServer have a architecture problem with log4net?
The post looks correct to me.
Are you sure you added the necessary assembly level attribute?
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
If this won't work maybe you should try:
log4net.Config.XmlConfigurator.Configure();
for example in your Application_Start of Global.asax.
If this won't work please post your example code.
Accidentally found solution by replacing the reference forlog4net.dll to the on that come with NHibernate bins, instead the own log4net.
Wired, but I have logs... :)