Linux Mono + Postsharp + Log4Net = No automated Exception catching - c#

We are developing a C# project with Monodevelop under Linux.
We have added Log4Net(1.2.11.0), Postsharp (4.1.24.0) and also Postsharp for Log4Net to our project via NuGet.
The following code throws an IndexOutOfRangeException:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using PostSharp;
using PostSharp.Aspects;
[System.Diagnostics.DebuggerStepThrough]
[Loggable]
class Program
{
static void Main (string[] args)
{
String[] myArray= new String[] { "X" };
for (int i = 0; i <= 100; i++) {
Console.WriteLine (myArray[i]);
}
}
}
Unfortunately, Postsharp doesn't even catch the exception.
We even tried to replace "[Loggable]" with "[LoggableAttribute]", since the Class' name is like that.
Here it is:
using System;
using System.Collections.Generic;
using System.Linq;
using PostSharp;
using PostSharp.Aspects;
using System.Collections;
[Serializable]
public class LoggableAttribute : OnExceptionAspect
{
public override void OnException(MethodExecutionArgs event_args)
{
Logging.SetExecutionTime(DateTime.Now);
Logging.SetParameter("parameters", ParametersToString(event_args));
Logging.SetParameter("method_name", event_args.Method.Name);
Logging.SetParameter("class_name", event_args.Instance.GetType().ToString());
Logging.Error("Error Encountered in " + event_args.Method, event_args.Exception);
}
private static String ParametersToString(MethodExecutionArgs event_args)
{
String output = "";
if (event_args.Method.GetParameters() != null)
{
for (int i = 0; i < event_args.Method.GetParameters().Length; i++)
{
output += String.Format("[{0} = {1}]", event_args.Method.GetParameters()[i].Name, event_args.Method.GetParameters()[i]);
}
}
return output;
}
}
Even a break point within OnException doesn't help. It doesn't get in there.

PostSharp works fine with mono, I actually use it there for quite some time already. I cannot now test on your mono version (3.2.8 is quite old already), but on 4.0.4 this code runs without problem:
[Loggable]
internal class Program {
private static void Main(string[] args) {
String[] myArray = new String[] {"X"};
for (int i = 0; i <= 100; i++) {
Console.WriteLine(myArray[i]);
}
}
}
[Serializable]
public class LoggableAttribute : OnExceptionAspect {
public override void OnException(MethodExecutionArgs args) {
Console.WriteLine("Caught by postsharp: " + args.Exception);
args.FlowBehavior = FlowBehavior.Continue;
}
}
Outputs "Caught by postsharp: ..." and no exception is thrown. As for log4net, you say yourself that it's not related to your question in any way - your code does not enter block where log4net is used.
So, just update to modern mono version and you'll be fine.

Related

What to troubleshoot MEF C#

The following demo application on MEF technology does not work.
Can't build the simplest extensible application. I started with the simplest, a console application that will simply display text on the screen according to the specified parameters. And even here he did not go to me. Where to dig?
IDemoInterface.cs
public interface IDemoInretface
{
void Run(int sleep, int count);
}
MEFDataDemo
Program.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.IO;
namespace MEFDataDemo
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
p.Run();
}
public void Run()
{
DoImport();
int count = 1;
foreach (var item in Plugin)
{
item.Value.Run(count * 1000, count * 10);*** This is Error
count++;
}
}
[ImportMany(typeof(IDemoInretface))]
public IEnumerable<Lazy<IDemoInretface>> Plugin { get; set; }
public void DoImport()
{
var catalog = new AggregateCatalog();
var path = Path.Combine(Directory.GetCurrentDirectory(), "Plugins");
catalog.Catalogs.Add(new DirectoryCatalog(path));
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
}
}
Plugin1 Class1.cs
using System;
using System.ComponentModel.Composition;
using System.Threading;
namespace Plugin1
{
[Export(typeof(IDemoInretface))]
internal class Class1 : IDemoInretface
{
public void Run(int sleep, int count)
{
for (int i = 0; i < count; i++)
{
Console.WriteLine("This plugin1 print {0}/{1} in {2}ms", i, count, sleep);
Thread.Sleep(sleep);
}
}
}
}
What am I doing wrong?
The program compiles, but either does not read plugins, or reads but does not run the (RUN) method

Test Executed successfully but report doesn't extent report doesn't generate in specflow

Currently I am working designing my project in Specflow. I want to implement some reporting to my project. Currently I have created one separate .cs file and kept all my report setting. But when i execute my code test run successfully but report doesn't generate. i am using the given code please check and suggest me
SeleniumDriver.cs
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Firefox;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ReportDemoPOC
{
class SeleniumDriver
{
public static IWebDriver WebDriver { get; set; }
public static string BaseAddress
{
get { return Constants.Url; }
}
public static void Intitialize()
{
WebDriver = new ChromeDriver();
WebDriver.Manage().Window.Maximize();
TurnOnWait();
}
public static void Navigate()
{
WebDriver.Navigate().GoToUrl(BaseAddress);
}
public static void Close()
{
WebDriver.Close();
}
public static void Quit()
{
WebDriver.Quit();
}
private static void TurnOnWait()
{
WebDriver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
WebDriver.Manage().Timeouts().PageLoad = TimeSpan.FromMinutes(2);
}
public void Shutdown()
{
WebDriver.Quit();
}
}
}
Start.cs
using AventStack.ExtentReports;
using AventStack.ExtentReports.Reporter;
using AventStack.ExtentReports.Reporter.Configuration;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TechTalk.SpecFlow;
namespace ReportDemoPOC
{
public class Start
{
public static ExtentReports extent;
public static ExtentHtmlReporter htmlReporter;
public static ExtentTest test;
static Start()
{
if (extent == null)
{
BasicSetUp();
}
}
[BeforeScenario]
public void Setup()
{
SeleniumDriver.Intitialize();
SeleniumDriver.Navigate();
test = extent.CreateTest(ScenarioContext.Current.ScenarioInfo.Title);
}
[AfterScenario]
public void TearDown()
{
if (ScenarioContext.Current.TestError != null)
{
var error = ScenarioContext.Current.TestError;
var errormessage = "<pre>" + error.Message + "</pre>";
//Add capture screen shot line here
extent.AddTestRunnerLogs(errormessage);
test.Log(Status.Error, errormessage);
test.Fail(errormessage);
}
SeleniumDriver.Close();
}
[OneTimeSetUp]
public static void BasicSetUp()
{
string pth = System.Reflection.Assembly.GetCallingAssembly().CodeBase;
// string pth = System.IO.Directory.GetCurrentDirectory();
string actualPath = pth.Substring(0, pth.LastIndexOf("bin"));
string projectPath = new Uri(actualPath).LocalPath;
Console.WriteLine(" -----------Project Path--------------------------------------");
Console.WriteLine(projectPath);
// string reportPath = projectPath + "Reports\\" + FeatureContext.Current.FeatureInfo.Title + ".html";
string reportPath = projectPath + "Reports\\TestRunReport.html";
// Console.WriteLine("Report Path is " + reportPath);
htmlReporter = new ExtentHtmlReporter(reportPath);
htmlReporter.Configuration().Theme = Theme.Dark;
htmlReporter.Configuration().DocumentTitle = "SpecFlow Test Resport Document";
htmlReporter.Configuration().ReportName = "Feature Run Results";
extent = new ExtentReports();
extent.AttachReporter(htmlReporter);
//extent.LoadConfig(projectPath + "Extent-Config.xml");
}
[AfterFeature()]
public static void EndReport()
{
extent.Flush();
}
}
}
LoginSteps.cs
using NUnit.Framework;
using ReportDemoPOC.Page;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TechTalk.SpecFlow;
namespace ReportDemoPOC.Steps
{
[Binding]
[TestFixture]
class LoginSteps : Start
{
LoginPage loginPage;
[Given(#"I am at Facebook login page")]
public void GivenIAmAtFacebookLoginPage()
{
//Navigate();
loginPage = new LoginPage();
}
[When(#"I enter ashusoni(.*)#gmail\.com in the Email or Phone textbox")]
public void WhenIEnterAshusoniGmail_ComInTheEmailOrPhoneTextbox(String p0)
{
loginPage.enterValueInUser("abcd" + p0 + "#gmail.com");
}
[When(#"I Enter (.*) in the password")]
public void WhenIEnterInThePassword(String p0)
{
loginPage.enterValueInPassword(p0);
}
[When(#"Click on the Login button")]
public void WhenClickOnTheLoginButton()
{
loginPage.clickOnLoginButton();
}
[Then(#"Application should display an error message")]
public void ThenApplicationShouldDisplayAnErrorMessage()
{
Console.WriteLine("Verification");
// loginPage.Shutdown();
}
}
}
It may sound like off topic, but still...
I'm not sure it makes sense to use ExtentReports for you automation frameworkwritten in C#.
Starting from v.4 ExtentReports they don't support it anymore.
The reply from them was that they were going to support only Java.
This is a feature of NUnit 3. You should install the Visual Studio Test Adapter ( https://github.com/nunit/docs/wiki/Visual-Studio-Test-Adapter ) via NuGet package named "NUnit3TestAdapter" to get the OneTimeSetup to work.
Then you can check your implementation of the report :-)
Maybe your report is created in the temporary folder (after some time I found it, using windows search). I have the same when running my tests, using Visual Studio. Try to run your test, using Nunit console application. Download it separately, then run tests using console command
nunit "path to compiled .dll with tests"
In this case, I think you should found reports near .dll file. This happens in my case (using Allure reports).

im getting error of program does not contain a static 'main' method suitable for an entry point

I'm getting an error, "Program does not contain a static 'main' method suitable for an entry point."
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
namespace ConsoleApplication1
{
class Program<T>
{
List<T> a1 = new List<T>();
public void AddData(T data1)
{
a1.Add(data1);
}
public void Insert(T arrayValue, int arrayPosition)
{
// var key = arrayPosition.ToInt();
var key1 = arrayValue.ToString();
for (int i = 0; i < a1.Count; i++)
{
if (i == arrayPosition)
{
a1.Add(arrayValue);
break;
}
}
}
public void Delete(int arrayPosition)
{
for (int i = 0; i < a1.Count; i++)
{
if (i == arrayPosition)
{
a1.Remove(a1[i]);
break;
}
}
}
public void DisplayData()
{
foreach (T x in a1)
{
Console.WriteLine(x);
}
}
static void Main(string[] args)
{
Program<int> obj = new Program<int>();
obj.AddData(123);
obj.AddData(56);
obj.AddData(34);
obj.AddData(87);
obj.DisplayData();
obj.Insert(125, 3);
obj.DisplayData();
obj.Delete(2);
obj.DisplayData();
}
}
}
Per Microsoft documentation (https://learn.microsoft.com/en-us/dotnet/csharp/misc/cs0402) you cannot put your main function in a generic class. It's strange that this was reported as a warning, and the error was less helpful, but that is your problem.
using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
public static class Program
{
[STAThread]
public static void Main(string[] args)
{
List<Int32> obj = new List<Int32>();
obj.Add(123);
obj.Add(56);
obj.Add(34);
obj.Add(87);
foreach (Int32 value in obj)
Console.WriteLine(value.ToString());
obj.Insert(3, 125);
foreach (Int32 value in obj)
Console.WriteLine(value.ToString());
obj.RemoveAt(2);
foreach (Int32 value in obj)
Console.WriteLine(value.ToString());
}
}
}
Defining a custom class to handle this tasks looked to me like an overkill. This code should reproduct what you were attempting to do without errors. Anyway, I suggest you to take a look at some basic C# tutorial.

C# console reference use on windows form application project

I am Learning C#, but when i was trying to do a reference on a windows form application using a console code, the error The type or namespace name 'TidPunkt' could not be found (are you missing a using directive or an assembly reference?)
Posting reference code below, then the Desinger.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class TidPunkt
{
int tim, min, sek;
bool VisaSek = true;
public void Sätt(int t, int m, int s)
{
if (t >= 0 && t < 24 && m >= 0 && m < 60 && s >= 0 && s < 60)
{
tim = t; min = m; sek = s;
}
else
Console.WriteLine("Felaktig tidpunkt");
}
}
public void SättVisaSek(bool visa)
{
VisaSek = visa;
}
public int AvLäsTim()
{
return tim;
}
public int AvläsMin()
{
return min;
}
public int AvläsSek()
{
return sek;
}
public void Ticka()
{
if (++sek == 60)
{
sek = 0; ++min;
}
if (min == 60)
{
min = 0; ++tim;
}
if (tim == 24)
{
tim = 0;
}
}
public override string ToString()
{
string tid = tim + ":" + min;
if (VisaSek)
tid = tid + ":" + sek;
return tid;
}
}
}
Thats the reference code. posting the "Klockvisare.cs" code.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Klockvisare : Form
{
TidPunkt tp = new TidPunkt();
public Klockvisare()
{
InitializeComponent();
DateTime dt = DateTime.Now;
tp.Sätt(dt.Hour, dt.Minute, dt.Second);
a.Text = tp.ToString();
}
private void timer1_Tick(object sender, EventArgs e)
{
tp.Ticka();
a.Text = tp.ToString();
}
}
}
Change class TidPunkt to public class TidPunkt.
Be sure your assembly is referenced in the second project.
Add public before class TidPunkt
Add this to your second file
using ConsoleApplication1;
Anyway, you should create a Class Library project and put there your first file logic (without the Console.WriteLine). Then you create another project, let's say a WinForm like you did, and you add the previous assembly as reference. After you import the appropriate namespaces you can use the types of the class library.
You have to add your ConsoleApplication1 reference to your winforms application. If it's in another solution, then you have to add the ConsoleApplication1 dll to the references (right click on the references, then browse the dll). If it's in the same solution, then you have to right click on the references again, choose Solution option, then choose the ConsoleApplication1. After these, you can just use the "CTRL" + "." combination on the TidPunkt class and Visual Studio will find the correct namespace for you.

How to create a Sleep method for my application

I want to create a method which makes my application wait X number of seconds, then continues on down a line of scripts. For example, this is the code that I have so far, after reading many similar help topics:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
methods.WriteTextToScreen(label1, "Hello!");
methods.sleepFor(1);
methods.WriteTextToScreen(label1, "Welcome!");
methods.sleepFor(1);
methods.WriteTextToScreen(label1, "Allo!");
}
public class methods
{
public static int timeSlept;
public static void WriteTextToScreen(Label LabelName, string text)
{
LabelName.Text = text;
}
public static void sleepFor(int seconds)
{
timeSlept = 0;
System.Timers.Timer newTimer = new System.Timers.Timer();
newTimer.Interval = 1000;
newTimer.AutoReset = true;
newTimer.Elapsed += new System.Timers.ElapsedEventHandler(newTimer_Elapsed);
newTimer.Start();
while (timeSlept < seconds)
{
Application.DoEvents();
}
Application.DoEvents();
}
public static void newTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
timeSlept = IncreaseTimerValues(ref timeSlept);
Application.DoEvents();
}
public static int IncreaseTimerValues(ref int x)
{
int returnThis = x + 1;
return returnThis;
}
}
}
}
What I want to do is have my program do the methods.WriteTextToScreen(label1, "Hello!")
then wait for 1 second, then continue on in the same fashion. The problem is that the Form I'm displaying the text on doesn't show up at all until it has written "Allo!" onto the screen, so the first time it appears it already says that. Am I doing something wrong, or is there just no way to do this?
The form doesn't show until it has been constructed i.e. all the code in Form1 is run. See here for info on form constructors: http://msdn.microsoft.com/en-us/library/system.windows.forms.form.form.aspx
To fix your problem you could move the writeTextToScreen and sleep code into the forms on load method. See http://msdn.microsoft.com/en-us/library/system.windows.forms.form.onload.aspx

Categories