Resharper test runner not outputting Console.WriteLine()? - c#

Why is it that Console.Writeline() will work when executing from a console app main() method; but when I execute the same using resharpers test runner I do not see the Console.Writeline() in the test runner output window?
The best way to explain this is with an example.
I am using: Resharper Ultimate 2017.1.3, Visual Studio 2017 Community, and .Net 4.6.1 framework. Language is C#. I also installed (via nuget) nunit framework 2.6.4.
First create a class library and copy paste the following in to a .cs file.
using System;
using System.Collections;
using System.Threading;
using NUnit.Framework;
namespace ObserverPatternExample
{
[TestFixture]
internal class ObserverTestFixture
{
[Test]
public void DemonstrateObserverPattern()
{
var subject = new Subject();
var a = new Observer(subject, "a");
var b = new Observer(subject, "b"); // etc. as many observers as you want.
subject.Go();
}
}
// "subject" is observer pattern lingo. The "subject" will do the broadcasting to the observers.
public class Subject
{
public delegate void CallbackHandler(string s);
public event CallbackHandler NotifyEvent;
private const int waitTimeInMilliseconds = 200;
private readonly Simulator simulator = new Simulator();
public string FakeSimulatorState { get; set; }
public void Go()
{
new Thread(Run).Start(); // a good thing to notice: events cross thread boundaries!!!
}
private void Run()
{
foreach (string s in simulator)
{
Console.WriteLine("Subject: " + s);
FakeSimulatorState = s;
NotifyEvent?.Invoke(s);
Thread.Sleep(
waitTimeInMilliseconds); // we do this to "pretend" that the simulator is actually doing someting.
}
}
}
public class Observer : IObserverPattern // the "observer" will subscribe to the event being broadcast by the "subject"
{
private readonly string _name;
public Observer(Subject subject, string name)
{
_name = name;
subject.NotifyEvent += Update;
}
public void Update(string state)
{
Console.WriteLine("Observer {0}: {1}", _name, state);
}
}
internal interface IObserverPattern
{
void Update(string state);
}
public class Simulator : IEnumerable
{
private readonly string[] _stateSequence = { "BEGIN", "CRAWL", "WALK", "JUMP", "END" };
public IEnumerator GetEnumerator()
{
foreach (var s in _stateSequence)
yield return s;
}
}
}
And now execute the test. I expect to see the Console.WriteLine() calls display strings in the Resharper test runner output window. But I don't. For example here is a screenshot:
Now let's perform the exact same sequence, but this time we'll call the client code from a new console project main() method. To set this up copy paste the following code and reference the class library you created in the steps above.
using ObserverPatternExample;
namespace ConsoleApp1
{
internal class Program
{
private static void Main(string[] args)
{
var subject = new Subject();
var a = new Observer(subject, "a");
var b = new Observer(subject, "b"); // etc. as many observers as you want.
subject.Go();
}
}
}
Next execute the console app. You should see the following displayed:
Can anyone please explain how I can configure either my code or the test runner to display the output in the test runner output window?
* UPDATE *
I made partial success. InBetween's suggestion to use a TraceListener made me realize I should be using a ConsoleTraceListener. To faciliate this I modified the unit test to appear like this:
using System.Threading;
using NUnit.Framework;
namespace ObserverPatternExample.DontUse
{
[TestFixture]
internal class ObserverTestFixture
{
[SetUp]
public void Setup()
{
Trace.Listeners.Add(new ConsoleTraceListener());
}
[TearDown]
public void TearDown()
{
Trace.Flush();
}
[Test]
public void DemonstrateObserverPattern()
{
var subject = new Subject();
var a = new Observer(subject, "a");
var b = new Observer(subject, "b"); // etc. as many observers as you want.
subject.Go();
}
}
And the results are surprising: I do get SOME output; but only the initial BEGIN state. Which appears like this:
Short story: I'm still looking for a solution.
*** SOLUTION ****
[Test]
public void DemonstrateObserverPattern()
{
var subject = new Subject();
var a = new Observer(subject, "a");
var b = new Observer(subject, "b"); // etc. as many observers as you want.
subject.Go();
Thread.Sleep(1000); // <--- add this to force test runner to wait for other thread to complete.
}

It looks like Resharper is finishing before your thread completes. Your call to
Thread(Run).Start();
is non-blocking. This means the test thread will complete before the Go thread does, hence you get no results.
See https://msdn.microsoft.com/en-us/library/6x4c42hc(v=vs.110).aspx where is states "Note that the call to Start does not block the calling thread."

Related

Convert C# Console>Service? How to retain dictionary when Class calls itself?

I'm attempting to transform a simple console application so that it may be used as a service using a nested Service class (relevant code below). The intent is to create a service to perform the actions within the Run method more-or-less at a set interval (eventually, ~hourly).
In short, the Service's OnStart calls my own Start method once, which creates a timer. Inside the timer, I'm creating an instance of the Program class, and performing the Run method till it finishes. I believe this is a valid implementation of what I want that doesn't leave resources outstanding.
Part of what the Run method does is build a dictionary of actions it was unable to perform on the file system, and I would like to retain the dictionary in subsequent calls to Run in order to attempt these actions again, if possible. What would be the best implementation to accomplish this? I'm a bit green and not terribly confident I'm doing things correctly, but I'm attempting to get up to speed as quickly as possible, so any assistance is appreciated.
partial class Program{
static object timerLck = new object();
public class Service : ServiceBase{
public Service(){
ServiceName = Program.ServiceName;
}
protected override void OnStart(string[] args){
Program.Start(args);
}
protected override void OnStop(){
Program.Stop();
}
}
static void Main(string[] args){
if (!Environment.UserInteractive)
using (var service = new Service())
ServiceBase.Run(service);
else{
Start(args);
Stop();
}
}
private static void Start(string[] args){
Timer t = new Timer(CallTimer, null, 0, 50000);
Console.ReadKey();
}
private static void Stop(){
//???
}
static void CallTimer(object state){
bool Lock = false;
try{
Lock = Monitor.TryEnter(timerLck);
if (Lock){
Program Prg = new Program()
var task = Task.Run((Func<Task<int>>)Prg.Run);
task.Wait();
}
}
finally{
if (Lock) Monitor.Exit(timerLck);
}
}
//Perform the repeated actions here
private async Task<int> Run()
{
Dictionary<string, Metadata> d = new Dictionary<string, Metadata>();
//...
return 0;
}
}
You can just have Run accept a Dictionary as a parameter and return the populated Dictionary.
private async Task<Dictionary<string, Metadata>> Run(Dictionary<string,
Metadata> previousErrors)
{
Dictionary<string, Metadata> d = new Dictionary<string, Metadata>();
//...
return d;
}
Then set a property PreviousErrors on your Program class to the returned Dictionary.
static void CallTimer(object state){
bool Lock = false;
try{
Lock = Monitor.TryEnter(timerLck);
if (Lock){
Program Prg = new Program()
var task = Task.Run(()=>Run(PreviousErrors));
PreviousErrors = task.Result;
}
}
finally{
if (Lock) Monitor.Exit(timerLck);
}
}
Note, that I'm only addressing your question not the quality of the rest of the code. It could do with improvements that are outside of the scope of your question.

Access statusbar on form from cplex callback function c#

I'm working with an C# .Net application that uses Cplex DLL's for an optimization operation, and during that operation I want to write status progress to a statusbar on the that initiated the operation.
This is the general layout of the specific form;
namespace ActResMain
{
public class FormOptimize : System.Windows.Forms.Form
{
private callCplex()
{
//...
cplex.Use(new Cplex_ContinuousCallback());
cplex.Solve()
}
public void Update_OptimizeStatusbarPanel(String strText)
{
statusBarPanel_1.Text = strText;
statusBar1.Refresh();
}
internal class Cplex_ContinuousCallback : Cplex.ContinuousCallback
{
FormOptimize formOpt = new FormOptimize();
public override void Main()
{
//From here I want to edit the statusbar at FormOptimize. I can write progress to console without any problems, but cannot reach function "Update_OptimizeStatusbarPanel".
//If I include "FormOptimize formOpt = new FormOptimize" here, i get Visual studio exception on illegal window reference.
}
}
}
}
I have also tried invoking the Update_OptimizeStatusbarPanel function like this:
internal class Cplex_ContinuousCallback : Cplex.ContinuousCallback
{
FormOptimize formOpt = new FormOptimize();
public override void Main()
{
FormCollection fc = Application.OpenForms;
var mpc = fc[1];
Type type = mpc.GetType();
MethodInfo dynMethod = type.GetMethod("Update_OptimizeStatusbarPanel");
dynMethod.Invoke(mpc, new object[] { String.Format("Running Optimization: {0} iterations ", Niterations)});
}
}
But then I get an exception from visual studio stating that an object created by one thread cannot be modified from another thread.
Maybe this is something stupid that I have missed, but help is greatly appriciated
EDIT: I edited the code as per Mohammad Dehghans suggestion,
public class FormOptimize : System.Windows.Forms.Form
{
private callCplex()
{
cplex.Use(new Cplex_ContinuousCallback(this));
cplex.Solve()
}
internal class Cplex_ContinuousCallback : Cplex.ContinuousCallback
{
FormOptimize _formOptimize;
public Cplex_ContinuousCallback(FormOptimize formOptimize)
{
this._formOptimize = formOptimize;
}
public override void Main()
{
if (Niterations % 10 == 0)
{
_formOptimize.Update_OptimizeStatusbarPanel(0, String.Format("Running Optimization: {0} iterations ", Niterations), 0);
}
}
}
public void Update_OptimizeStatusbarPanel(short panelIndex, String strText, short severity)
{
if (statusBar1.InvokeRequired)
statusBar1.Invoke(new Action<short, string, short>(Update_OptimizeStatusbarPanel), panelIndex, strText, severity);
else
{
if (panelIndex == 0)
{
//...
statusBarPanel_0.Text = strText;
}
else if (panelIndex == 1)
{
//...
statusBarPanel_1.Text = strText;
}
statusBar1.Refresh();
}
}
}
But by doing that I apparently broke something, as the application just ..stops after statusBar1.Invoke() is called the first time. If I pause the debugger it says that cplex.Solve() is executing, but then nothing more happens.
First of all, you need to pass the instance of your form to the implemented callback class, so when the Main method is called, you have access to the exact instance that is being shown on the screen.
Secondly, you need to use Invoke method to update the UI controls from anther thread (I've not worked with CPLEX so far, but I guess the callback is invoked from another thread. That's usual).
Read this for more information.
The complete code could be:
public class FormOptimize : System.Windows.Forms.Form
{
private callCplex()
{
//Misc code
cplex.Use(new Cplex_ContinuousCallback(this)); // <-- passing `this`
cplex.Solve()
//Misc code
}
public void Update_OptimizeStatusbarPanel(String strText)
{
if (statusBarPanel_1.InvokeRequired)
statusBarPanel_1.Invoke(Action<string>(Update_OptimizeStatusbarPanel), strText);
else
{
statusBarPanel_1.Text = strText;
statusBar1.Refresh();
}
}
internal class Cplex_ContinuousCallback : Cplex.ContinuousCallback
{
FormOptimize _formOptimize;
public Cplex_ContinuousCallback(FormOptimize formOptimize)
{
this._formOptimize = formOptimize;
}
public override void Main()
{
//...
_formOptimize.Update_OptimizeStatusbarPanel(String.Format("Running Optimization: {0} iterations ", Niterations));
}
}
}

How do I Execute Code after a Test failed

I am Creating Unit Tests for a Library. This Library Connects to a Datasource and then I am doing some testing Stuff afterwards the Datasource will be disconnected.
If one of the Tests fails, the Method is Terminated and I dont get to execute the Disconnection Function.
Here's a Sample to understande the above description:
[TestMethod]
public void Test()
{
var datasourceObject = new DatasourceObject("location-string");
datasourceObject.Connect();
// Do some Stuff with Asserts
datasourceObject.Disconnect(); // must be executed
}
Is There any Bestpractice to achieve that?
If you use resource in other tests, then move it to class fields and use [TestInitialize] and [TestCleanup] to get and free that resource:
private Foo datasourceObject;
[TestInitialize]
public void TestInitialize()
{
this.datasourceObject = new DatasourceObject("location-string");
this.datasourceObject.Connect();
}
[TestMethod]
public void Test()
{
// Do some Stuff with Asserts
}
[TestCleanup]
public void TestCleanup()
{
this.datasourceObject.Disconnect();
}
If you use resource in this test only, then use either try..finally
[TestMethod]
public void Test()
{
try
{
var datasourceObject = new DatasourceObject("location-string");
datasourceObject.Connect();
// Do some Stuff with Asserts
}
finally
{
datasourceObject.Disconnect(); // must be executed
}
}
Or using statement if resource is disposable:
[TestMethod]
public void Test()
{
using(var datasourceObject = new DatasourceObject("location-string"))
{
datasourceObject.Connect();
// Do some Stuff with Asserts
}
}

How to Run c# Multiple Selenium Unit Test with one driver instance?

i have a problem running Multiple C# Selenium Unit Test tests with one driver instance.
Please find my class as below.
Folder : Com.Main.Web.Selenium
SeleniumTestInitialize.cs is the main class which contains the driver.
[DeploymentItem(#"Resources\IEDriverServer.exe")]
public class SeleniumTestInitialize
{
public TestContext TestContext
{
get { return testContextInstance; }
set { testContextInstance = value; }
}
private TestContext testContextInstance;
public bool SeleniumExecutionTerminateFlag=false;
public SeleniumTestInitialize seleniumTestInitalize;
public FindWebDriverElement findWebDriverElement;
public JavaScriptCalls javaScriptCalls;
public OperateOnWebDriverElement operateOnWebDriverElement;
**public RemoteWebDriver driver;**
// how to use this driver object across multiple unit test classes
public string baseURL;
public void SeleniumSetup()
{
try
{
Console.WriteLine("Starting Driver...........");
seleniumTestInitalize = new SeleniumTestInitialize();
var options = new InternetExplorerOptions
{
IntroduceInstabilityByIgnoringProtectedModeSettings = true,
//ForceCreateProcessApi=true
EnableNativeEvents = false,
RequireWindowFocus = false,
IgnoreZoomLevel = true
};
driver = new InternetExplorerDriver(TestContext.DeploymentDirectory, options);
javaScriptCalls = new JavaScriptCalls(driver);
findWebDriverElement = new FindWebDriverElement(javaScriptCalls);
operateOnWebDriverElement = new OperateOnWebDriverElement(findWebDriverElement);
GoToSite(ConfigParameters.WEB_APPLICATION_URL);
driver.Manage().Window.Maximize();
}
catch (Exception e)
{
log.Debug("Error Starting Web Driver...........");
Console.WriteLine(e.StackTrace);
}
}
public bool SeleniumInitalizeCheck()
{
if (seleniumTestInitalize != null)
return true;
else
return false;
}
public void SeleniumQuit()
{
Console.WriteLine("Quitting Driver...........");
try
{
if (driver != null)
{
driver.Quit();
}
log.Info("Closing Web Driver...........");
ProcessMgn.killProcessByNames("IEDriverServer");//Make sure the process is killed
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
}
}
public void GoToSite(string urlToOpen)
{
driver.Navigate().GoToUrl(urlToOpen);
}
}
Folder com.main.tests
Test01.cs
[TestClass]
public class Test01 : SeleniumTestInitialize
{
[TestInitialize]
public void Setup()
{
SeleniumExecutionTerminateFlag = false;
if (!SeleniumInitalizeCheck())
{
SeleniumSetup();
}
}
[TestCleanup]
public void TearDown()
{
if (SeleniumExecutionTerminateFlag)
{
SeleniumQuit();
}
}
[TestMethod]
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.TestCase", "http://tfsserver:8080/tfs/PoL;project", "1320", DataAccessMethod.Sequential)]
public void UCP002_M1()
{
var userName = this.TestContext.DataRow["UserName"].ToString();
var passWord = this.TestContext.DataRow["PassWord"].ToString();
//use the local host adress for your project here->
baseURL = this.TestContext.DataRow["URL"].ToString();
driver.Navigate().GoToUrl(baseURL);
//driver.FindElement(By.XPath("//html/body/div[2]/div/a/p/desc")).Click();
//driver.FindElement(By.Id("registerLink")).Click();
driver.FindElement(By.Id("ctl00_LoginTextBox")).Clear();
driver.FindElement(By.Id("ctl00_LoginTextBox")).SendKeys(userName);
driver.FindElement(By.Id("ctl00_PasswordTextbox")).Clear();
driver.FindElement(By.Id("ctl00_PasswordTextbox")).SendKeys(passWord);
driver.FindElement(By.Id("ctl00_LogInButton")).Click();
}
}
Test02.cs
[TestClass]
public class Test02 : SeleniumTestInitialize
{
[TestInitialize]
public void Setup()
{
SeleniumExecutionTerminateFlag = false;
if (!SeleniumInitalizeCheck())
{
SeleniumSetup();
}
}
[TestCleanup]
public void TearDown()
{
if (SeleniumExecutionTerminateFlag)
{
SeleniumQuit();
}
}
[TestMethod]
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.TestCase", "http://tfsserver:8080/tfs/PoL;project", "1320", DataAccessMethod.Sequential)]
public void Test02()
{
//some test script
}
}
I have created an ordered test and prioritized the tests in the order of execution . But it is invoking two instances of the driver that means two times the browser.
My question is to How to share a single driver object across all selenium unit tests ?? create at the start and close the driver at the end.
Thanks.
HI If you are using using NUnit.Framework;
The code Execution plan is like below.
For First Test Case
[TestFixtureSetup] ---->For each test case this will work so here we can
initialize the driver instance.
[TestMethod] ----->test method will goes here
[TearDown] -----> clean up code
**For Second Test Case**
[TestFixtureSetup]
[TestMethod]
[TearDown]
If you have to run both test case in one browser instance
Dont close the driver inside TearDown.
AND INITIALIZE THE DRIVER UNDER TextFixtureSetup
[TestFixture()]
public class TestClass
{
[TestFixtureSetUp]
public void Init()
{
Driver.initialize(new InternetExplorerDriver());
}
[TearDown]
public void Close()
{
//dont do any driver.close()
}
[TestMethod]
public void TestCase001()
{
//your code goes here
}
[TestMethod]
public void TestCase002()
{
//your code goes here
}
You can take a look on this thread, where I answered how I did it: How to run multiple test methods in same browser instance without closing it (C#, SeleniumWebDriverz NUnit)?
Basically, I used:
using Microsoft.VisualStudio.TestTools.UnitTesting;
Instead of:
using NUnit.Framework;
So now I have next hierarchy:
[TestFixture]
[TestFixtureSetup] // this is where I initialize my WebDriver " new FirefoxDriver(); "
[Test] //first test
[Test] //second test
[Test] //third test
[TestFixtureTearDown] // this is where I close my driver
With this changes, my browser will open only once for TestFixture (or TestClass if you use "using Microsoft.VisualStudio.TestTools.UnitTesting;") and all [Test]-s from that fixture will run in that same browser instance. After all tests are done, browser will close.
Hope this will help someone else in future. Ask me if you need additional help.
I used NUnit Framework:
using NUnit.Framework;
I then set up my WebDriver initialisation, test and teardown like this:
[TestFixture()]
class NUnitSeleniumTests
{
[OneTimeSetUp]
public void Init()
{
driverIE = new InternetExplorerDriver(ConfigurationManager.AppSettings["IEDriver"]);
driverIE.Manage().Window.Maximize();
// other setup logic
}
[Test]
public void TestMethod1()
{
// Test logic
}
[Test]
public void TestMethod2()
{
// Test logic
}
...
...
...
[Test]
public void TestMethodN()
{
// Test logic
}
[OneTimeTearDown]
public void Close()
{
driverIE.Close();
}
}
When I Run All tests, the WebDriver driverIE is initialised. All tests then execute in that WebDriver instance before the WebDriver instance is closed at the end of the test run.
The tests execute in alphabetical order by default; each test can also execute in isolation.

How restart the Console app?

I need to restart the app Console when the user press "R".
I have this
Console.WriteLine(message, "Rebuild Log Files"
+ " Press Enter to finish, or R to restar the program...");
string restar = Console.ReadLine();
if(restar.ToUpper() == "R")
{
//here the code to restart the console...
}
thanks
// Starts a new instance of the program itself
System.Diagnostics.Process.Start(Application.ExecutablePath);
// Closes the current process
Environment.Exit(0);
static void Main(string[] args)
{
var info = Console.ReadKey();
if (info.Key == ConsoleKey.R)
{
var fileName = Assembly.GetExecutingAssembly().Location;
System.Diagnostics.Process.Start(fileName);
}
}
I don't think you really need restart whole app. Just run required method(s) after pressing R. No need to restart.
Another simple way
//Start process, friendly name is something like MyApp.exe (from current bin directory)
System.Diagnostics.Process.Start(System.AppDomain.CurrentDomain.FriendlyName);
//Close the current process
Environment.Exit(0);
I realize that this is 7 years old, but I just came across this. I think actually calling the executable and closing the current program is a bit of a cluge. As stated before, this is being over thought. I think that the cleanest and most modular way is to take everything that is in the Main method and make a different method, let's say Run() that contains everything that was in the Main method and then call the new Run() method from the Main method or wherever in the code it is desired to re-start the program.
So if the Main method looked like this:
static void Main(string[] args)
{
/*
Main Method Variable declarations;
Main Method Method calls;
Whatever else in the Main Method;
*/
int SomeNumber = 0;
string SomeString = default(string);
SomeMethodCall();
//etc.
}
Then just create a Run() method and put everything from Main into it, like so:
public static void Run()
{
//Everything that was in the Main method previously
/*
Main Method Variable declarations;
Main Method Method calls;
Whatever else in the Main Method;
*/
int SomeNumber = 0;
string SomeString = default(string);
SomeMethodCall();
//etc.
}
Now that the Run() method is created and it has all the stuff that was in the Main method before, just make your main method like so:
static void Main(string[] args)
{
Run();
}
Now, wherever in the code you want to "re-start" the program, just call the Run() method like so:
if(/*whatever condition is met*/)
{
//do something first
//then "re-start" the program by calling Run();
Run();
}
So this is a look at the whole program simplified:
EDIT: When I posted this originally I didn't take into consideration any arguments that might have been passed to the program. To account for this four things need to be changed in my original answer.
declare a global List<string> like this:
public static List<string> MainMethodArgs = new List<string>();.
In the Main method set the value of the MainMethodArgs list equal to the
values passed into the Main method via args like this:
MainMethodArgs = args.ToList();
When creating the Run() method change the signature so that it expects a
string[] called args to be passed to it like this:
public static void Run(string[] args)
{
....
}
Wherever in the program the Run() method is called, pass MainMethodArgs
to Run() like this:
Run(MainMethodArgs.ToArray());
I changed the example below to reflect these changes.
using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ExampleConsole
{
class Program
{
public static List<string> MainMethodArgs = new List<string>();
static void Main(string[] args)
{
MainMethodArgs = args.ToList();
Run(MainMethodArgs.ToArray());
}
public static void Run(string[] args)
{
Console.WriteLine("Run() is starting");
Console.ReadLine();
//stuff that used to be in the public method
int MainMethodSomeNumber = 0;
string MainMethodSomeString = default(string);
SomeMethod();
//etc.
}
public static void SomeMethod()
{
Console.WriteLine("Rebuild Log Files"
+ " Press Enter to finish, or R to restar the program...");
string restar = Console.ReadLine();
if (restar.ToUpper() == "R")
{
//here the code to restart the console...
Run(MainMethodArgs.ToArray());
}
}
}
}
In effect the program is "re-started" without having to re-run the executable and close the existing instance of the program. This seems a lot more "programmer like" to me.
Enjoy.
try like this:
// start new process
System.Diagnostics.Process.Start(
Environment.GetCommandLineArgs()[0],
Environment.GetCommandLineArgs()[1]);
// close current process
Environment.Exit(0);
Ended up with something like this.
#if DEBUG
Process.Start("dotnet", Environment.GetCommandLineArgs().Prepend("run").Take(2));
#else
Process.Start(Environment.CommandLine);
#endif
Quit.ConsoleShutdown(null, null);
I'm sure this specific line: Process.Start("dotnet", Environment.GetCommandLineArgs().Prepend("run").Take(2)); can be improved on though, since it looks a bit confusing at first glance.
Launch a second exe that ends the console program, starts a new instance, and ends itself?
be explicit, how is it in code?
This namespace should have everything you need, if that is a solution you want to pursue.
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.aspx
//here the code to restart the console...
System.Diagnostics.Process.Start(Environment.GetCommandLineArgs()[0], Environment.GetCommandLineArgs().Length > 1 ? string.Join(" ", Environment.GetCommandLineArgs().Skip(1)) : null);
Everybody is over-thinking this. Try something like this:
class Program : IDisposable
{
class RestartException : Exception
{
public RestartException() : base()
{
}
public RestartException( string message ) : base(message)
{
}
public RestartException( string message , Exception innerException) : base( message , innerException )
{
}
protected RestartException( SerializationInfo info , StreamingContext context ) : base( info , context )
{
}
}
static int Main( string[] argv )
{
int rc ;
bool restartExceptionThrown ;
do
{
restartExceptionThrown = false ;
try
{
using ( Program appInstance = new Program( argv ) )
{
rc = appInstance.Execute() ;
}
}
catch ( RestartException )
{
restartExceptionThrown = true ;
}
} while ( restartExceptionThrown ) ;
return rc ;
}
public Program( string[] argv )
{
// initialization logic here
}
public int Execute()
{
// core of your program here
DoSomething() ;
if ( restartNeeded )
{
throw new RestartException() ;
}
DoSomethingMore() ;
return applicationStatus ;
}
public void Dispose()
{
// dispose of any resources used by this instance
}
}

Categories

Resources