How to Cleanly Exit Topshelf - c#

Based off the sample at this question which deals with passing custom parameters to Topshelf, I now want to be able to cleanly exit out of the Topshelf HostFactory.
I have the following code, and it does work, but when it "returns", the console displays an ugly error stating Topshelf.HostFactory Error: 0 : An exception occurred creating the host... The service was not properly configured... ServiceBuilderFactory must not be null
What should I uses instead of return to simply tell Topshelf to exit and not do anything?
string foo = null;
HostFactory.Run(x =>
{
x.AddCommandLineDefinition("foo", f => { foo = f; });
x.ApplyCommandLine();
if (!string.IsNullOrEmpty(foo))
{
Console.WriteLine("A value for Foo was received... exiting.");
return;
}
x.Service<MyService>(s =>
{
s.ConstructUsing(() => new MyService());
s.WhenStarted(z => z.Start());
s.WhenStopped(z => z.Stop());
});
x.StartAutomatically();
});

In this case, you should not be calling .ApplyCommandLine() in your code, that's automatically handled by Topshelf. And it's important to recognize that you're configuring the host at this point, and should not be throwing an exception.
The best place for your command-line value check is in the ConstructUsing() method, where you can verify the command-line arguments are present. If your conditions are not satisfied, throw an exception and the service will fail to start.
If you do it anywhere else, the command-line options for install/uninstall/etc. will not work without that command-line parameter specified.

Related

Verify mocks in Assert.Multiple

Is it possible to verify a method call in an Assert.Multiple block alongside other calls to Assert?
My current solution does not call the assert on SomeProperty, when the method call to MyMethod does not verify.
And the only way to get close to what I want would be to move the call to myInterfaceMock.Verify to the end, but that does no longer work when there are multiple method calls to verify.
var mInterfaceMock = new Mock<IMyInterface>()
.Setup(x => x.MyMethod())
.Verifiable();
var systemUnderTest = new MyClass(myInterfaceMock.Object);
systemUnderTest.MethodToTest();
Assert.Multiple(() => {
myInterfaceMock.Verify();
Assert.That(systemUnderTest.SomeProperty, Is.True);
});
The verify will throw its own exception that the assertion block wont know how to handle. That is why when the verify fails nothing gets invoked after it.
The notes in documentation also states
The test will be terminated immediately if any exception is thrown that is not handled. An unexpected exception is often an indication that the test itself is in error, so it must be terminated. If the exception occurs after one or more assertion failures have been recorded, those failures will be reported along with the terminating exception itself.
Reference Multiple Asserts
Consider the following approach
//...
Assert.Multiple(() => {
Assert.That(() => myInterfaceMock.Verify(), Throws.Nothing);
Assert.That(systemUnderTest.SomeProperty, Is.True);
});
If the verify throws an exception then it will be handled by its own assertion.
If your MethodToTest() does not return anything they I'd recommend just verifying if the method run, as you're trying to do with the assert, but I'd recommend doing something like this:
mInterfaceMock.Verify(x => x.MethodToTest(), Times.Once);
just specifying the times it has had to run, without it inside of an assertion

StreamInsight: Cannot serialize value of type X only if X is passed in a Task.Run() block

I have an IQStreamable object created by using DefineObservable of a Microsoft.ComplexEventProcessing.Application.
The code looks normally, but what I dont understand is when I use a passed-in argument from Task.Run() into DefineObservable, I got an exception.
However when I used the property directly without pass it into the method inside Task.Run(), it worked.
Exception
An unhandled exception of type 'System.InvalidOperationException' occurred in Microsoft.ComplexEventProcessing.Diagnostics.dll
Additional information: Cannot serialize value of type 'System.IObservable'1[ValueObjects.Price]'.
The Method
private void Monitor(IObservable<Price> priceObservable)
{
const string applicationName = "RealtimeMonitoring";
Microsoft.ComplexEventProcessing.Application application = PriceObserver.Server.CreateApplication(applicationName);
IQStreamable<Price> sStreamable = application
//.DefineObservable<Price>(() => PriceRealtimeProvider.Instance.PriceObservable)
.DefineObservable<Price>(() => PriceObservable)
.ToPointStreamable( => PointEvent<Price>.CreateInsert(DateTime.Now, price), AdvanceTimeSettings.IncreasingStartTime);
var standingQuery = from p in streamable select price ;
var sink = application.DefineObserver(() => new PriceObserver());
using (standingQuery.Bind(sink).Run())
{
// some code...
}
}
The call:
Task.Run(()=>Monitor(PriceRealtimeProvider.Instance.PriceObservable)
Question:
Does StreamInsight serialze the observer object? And Why?
What is different between
this
.DefineObservable<Price>(() => PriceObservable)
and
this
DefineObservable<Price>(() => PriceRealtimeProvider.Instance.PriceObservable)
Why using the arugument causes the problem?
Yes, but I still don't know the original design and reason for this.
For this call: .DefineObservable<Price>(() => PriceObservable). It means the argument is in application memory. And the argument need to be serialized to be passed to the remote server. So after this, the argument is actually in the StreamInsight server memory. And the argument cannot be serialized due to it is type of interface.
For this call: DefineObservable<Price>(() => PriceRealtimeProvider.Instance.PriceObservable), my guess, this is considered as a delegate call, so the Instance.PriceObservable is not instantiated yet, until StreamInsight server calls the code. And when this happens, everything is in StreamInsight server memory. So no need for serialization.
In sum, serialization doesn't happen for the second call.
I'm open for correction.

How to catch exception and stop Topshelf service?

I have a topshelf windows service where I want to do some checking (i.e. if an xml file exists) and if the check fails I need the windows service to stop.
So I tried doing the check in the Start() method and then raise an exception:
public void Start()
{
if (!File.Exists(_xmlFile) throw new FileNotFoundException();
// Do some work here if xml file exists.
}
However, the windows service stays around as a process after the exception which I then have to kill manually in the task manager.
Is there a way to not run the service if certain conditions (i.e. file not found) hold?
You could use the HostControl object and modify your method like this:
public bool Start(HostControl hostControl)
{
if (!File.Exists(_xmlFile)
{
hostControl.Stop();
return true;
}
// Do some work here if xml file exists.
...
}
And you will need to pass the HostControl in to the Start method like this:
HostFactory.Run(conf =>
{
conf.Service<YourService>(svcConf =>
{
svcConf.WhenStarted((service, hostControl) =>
{
return service.Start(hostControl);
}
}
}
Each of the WhenXxx methods can also take an argument of the HostControl interface, which can be used to request the service be stopped, request additional start/stop time, etc.
In such case, change signature of start() to be bool start(HostControl hc). Retain reference to this HostControl in the service as follow:
public bool Start(HostControl hc)
{
hostControl = hc;
Restart();
return true;
}
Now when you want to stop the service use following call:
hostControl.Stop();
I was curious about this from the point of view of a best practice or recommendation in Topshelf's documentation, but couldn't find anything. I did, however, find two separate comments from phatboyg...
Best comment... how to stop service on exception, via this issue (I cut out some of the detail):
If your service's Start method throws an exception, the service will fail to start.
Once the service is running, if an unhandled exception is thrown, the service will stop, and report it as a crash to the service control manager.
If you need to Stop your service programatically, use the HostControl method Stop.
So I think the easiest answer is to throw an exception.
You were doing that, and you mention "the windows service stays around as a process after the exception". That seems like an unrelated bug somewhere in your code, or perhaps you somehow had multple instances running? I've been testing these scenarios this morning and have not seen my service running after throwing an Exception in the start method.
Also, relevant to checking before HostFactory.Run, mentioned in the accepted answer, via https://groups.google.com/forum/embed/#!topic/topshelf-discuss/nX97k3yOhJU:
"Your application should do nothing more than configure NLog/Log4Net before calling the HostFactory.Run() method."
I just ran into this issue and all the above answers seem to be over complicating things. All you need to do is use the WhenStarted overload that accepts a Func<T,HostControl,bool> and return false if your internal service bootstrap failed. I don't think hostControl.Stop() needs to be called explicitly.
//Here is bit from inside the .Service<T>() call
s.WhenStarted((YourService svc, HostControl hc) => svc.Start());
//And the svc.Start method would look something like this:
class YourService
{
public bool Start() {
//return true if all is well
//or false if you want service startup to be halted
}
}
I've "borrowed" the sample code for the functional setup of topshelf to demonstrate a point:
HostFactory.Run(x => //1
{
x.Service<TownCrier>(s => //2
{
s.ConstructUsing(name=> new TownCrier()); //3
s.WhenStarted(tc => tc.Start()); //4
s.WhenStopped(tc => tc.Stop()); //5
});
x.RunAsLocalSystem(); //6
x.SetDescription("Sample Topshelf Host"); //7
x.SetDisplayName("Stuff"); //8
x.SetServiceName("stuff"); //9
});
You're going to have to place your file system check BEFORE the above code runs. Let's think about this a second. The point of having a service is to make sure it RUNS and KEEPS RUNNING. You're attempting to subvert a basic principle of having service applications in the first place. Instead of trying to stop the service because of the missing file, figure out some way to alert your support staff and NOT do whatever depends on that missing file.
When you catch the exception you can use ServiceBase.Stop() Method to stop the service by itself.
try
{
// Your Code
}
catch (Exception ex)
{
// The code for stopping service
}
Also you can have multi catch blocks in some cases:
try
{
// Your Code
}
catch (IndexOutOfRengeException ex)
{
// The code for stopping service
}
catch (FileNotFoundException exc)
{
// The code for stopping service
}
Read more about ServiceBase.Stop()

I sometimes can't get the method name from my method in Silverlight

I have this method that logs errors from the Silverlight client:
[MethodImpl(MethodImplOptions.NoInlining)]
public static bool ErrorHandler(Exception error, bool showError = true)
{
string callingMethod = new StackFrame(1).GetMethod().Name;
//write log - call webservice
//show error that some error happened if showError is true
}
my problem is this, that when I run the app and call a method that throws an exception it logs like this:
<ThrowExceptionMethod>b__72: test
but when someone that has a normal (non-developer runtime) runs this app and throws an exception it logs like this:
b__72: test
I'm only guessing that this is due SDK Silverlight runtime. It's hard to tell, because most of my colleagues have Silverlight SDK installed... Could someone confirm if this is the reason for this anomaly.
SOLVED!
It was not due SDK runtime, it was just because I call anonymous methods.
I added this line of code to it:
var listStackFrame = new List<StackFrame>();
for (int i = 1; i < 20; i++)
{
listStackFrame.Add(new StackFrame(i));
}
string callingMethod = string.Empty; //new StackFrame(1).GetMethod().Name;
foreach (var item in listStackFrame
.Where(m => m != null && m.GetMethod() != null && !string.IsNullOrEmpty(m.GetMethod().Name) && m.GetMethod().Name.Contains("__")))
{
callingMethod += item.GetMethod().Name + "->";
}
I am not worried about how much this eats up resources, because after all an exception has occured and the user will stop whatever he is doing and contact support.
That's usually because what you are executing is actually a yield iterator or anonymous delegates delegate (there may be other cases I'm missing). What happens is that the compiler actually create new methods and even classes for most of the syntactic sugar.
I think you can iterate all the previous methods call looking for the first that doesn't have the [CompilerGenerated] attribute.
This makes sense for the difference between a dev and normal machine:
StackFrame information will be most informative with Debug build configurations. By default, Debug builds include debug symbols, while Release builds do not. The debug symbols contain most of the file, method name, line number, and column information used in constructing StackFrame objects.
That is from the StackFrame's documentation.

Uniformly handling error codes in an unmanaged API

I'm writing a wrapper around a fairly large unmanaged API. Almost every imported method returns a common error code when it fails. For now, I'm doing this:
ErrorCode result = Api.Method();
if (result != ErrorCode.SUCCESS) {
throw Helper.ErrorToException(result);
}
This works fine. The problem is, I have so many unmanaged method calls that this gets extremely frustrating and repetitive. So, I tried switching to this:
public static void ApiCall(Func<ErrorCode> apiMethod) {
ErrorCode result = apiMethod();
if (result != ErrorCode.SUCCESS) {
throw Helper.ErrorToException(result);
}
}
Which allows me to cut down all of those calls to one line:
Helper.ApiCall(() => Api.Method());
There are two immediate problems with this, however. First, if my unmanaged method makes use of out parameters, I have to initialize the local variables first because the method call is actually in a delegate. I would like to be able to simply declare a out destination without initializing it.
Second, if an exception is thrown, I really have no idea where it came from. The debugger jumps into the ApiCall method and the stack trace only shows the method that contains the call to ApiCall rather than the delegate itself. Since I could have many API calls in a single method, this makes debugging difficult.
I then thought about using PostSharp to wrap all of the unmanaged calls with the error code check, but I'm not sure how that would be done with extern methods. If it ends up simply creating a wrapper method for each of them, then I would have the same exception problem as with the ApiCall method, right? Plus, how would the debugger know how to show me the site of the thrown exception in my code if it only exists in the compiled assembly?
Next, I tried implementing a custom marshaler that would intercept the return value of the API calls and check the error code there. Unfortunately, you can't apply a custom marshaler to return values. But I think that would have been a really clean solution it if had worked.
[return:
MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(ApiMethod))]
public static extern ErrorCode Method();
Now I'm completely out of ideas. What are some other ways that I could handle this?
Follow ErrorHandler class from the Visual Studio 2010 SDK. It existed in earlier versions, but the new one has CallWithCOMConvention(Action), which may prove valuable depending on how your API interacts with other managed code.
Of the available methods, I recommend implementing the following:
Succeeded(int)
(Failed() is just !Succeeded(), so you can skip it)
ThrowOnFailure(int)
(Throws a proper exception for your return code)
CallWith_MyErrorCode_Convention(Action) and CallWith_MyErrorCode_Convention(Func<int>)
(like CallWithCOMConvention, but for your error codes)
IsCriticalException(Exception)
(used by CallWith_MyErrorCode_Convention)
What happens if you don't check ErrorCode.SUCCESS? Will your code quickly fail and throw an exception? Can you tell which unmanaged API failed if your managed code throws? If so, consider not checking for errors and just letting the runtime throw when your unmanaged API fails.
If this is not the case, I suggest biting the bullet and following your first idea. I know you called it "frustrating and repetitive", but after coming from a project with a "clever" macro solution to a similar problem, checking return values in method calls and wrapping exceptions is the doorway to insanity: exception messages and stack traces become misleading, you can't trace the code, performance suffers, your code become optimized for errors and goes off the rails upon success.
If a particular return value is an error, thow a unique exception then. If it might not be an error, let it go and throw if becomes an error. You said you wanted to reduce the check to one line?
if (Api.Method() != ErrorCode.SUCCESS) throw new MyWrapperException("Api.Method broke because ...");
Your proposal also throws the same exception if any method returns the same "common error code". This is another debugging nightmare; for APIs which return the same error codes from multiple calls, do this:
switch (int returnValue = Api.Method1())
{
case ErrorCode.SUCCESS: break;
case ErrorCode.TIMEOUT: throw new MyWrapperException("Api.Method1 timed out in situation 1.");
case ErrorCode.MOONPHASE: throw new MyWrapperException("Api.Method1 broke because of the moon's phase.");
default: throw new MyWrapperException(string.Format("Api.Method1 returned {0}.", returnValue));
}
switch (int returnValue = Api.Method2())
{
case ErrorCode.SUCCESS: break;
case ErrorCode.TIMEOUT: throw new MyWrapperException("Api.Method2 timed out in situation 2, which is different from situation 1.");
case ErrorCode.MONDAY: throw new MyWrapperException("Api.Method2 broke because of Mondays.");
default: throw new MyWrapperException(string.Format("Api.Method2 returned {0}.", returnValue));
}
Verbose? Yup. Frustrating? No, what's frustrating is trying to debug an app that throws the same exception from every line whatever the error.
I think, the easy way is to add aditional layer.
class Api
{
....
private static ErrorCode Method();//changing Method to private
public static void NewMethod()//NewMetod is void, because error is converted to exceptions
{
ErrorCode result = Method();
if (result != ErrorCode.SUCCESS) {
throw Helper.ErrorToException(result);
}
}
....
}
Create a private property to hold the ErrorCode value, and throw the exception from the setter.
class Api
{
private static ErrorCode _result;
private static ErrorCode Result
{
get { return _result; }
set
{
_result = value;
if (_result != ErrorCode.SUCCESS)
{
throw Helper.ErrorToException(_result);
}
}
}
public static void NewMethod()
{
Result = Api.Method();
Result = Api.Method2();
}
}
Write a T4 template to do the generation for you.
Your existing code is actually really, really close. If you use an expression tree to hold the lambda, instead of a Func delegate, then your Helper.ApiCall can pull out the identity of the function that was called and add that to the exception it throws. For more information on expression trees and some very good examples, Google Marc Gravell.

Categories