I have two projects in a Visual Studio solution where one is a console app and the other is a WPF app. Both have a composite root where a common bootstrapper is instantiated in each and registers some common types.
I'm trying to get the console app to subscribe to some events published by the WPF app. When a WPF window is moved, opened, or resized, the console app prints a string on the console.
The Bootstrapper class is in a separate class library with the following code:
public class Bootstrapper
{
public void Initialize()
{
var container = IocContainer.Instance.Container;
container.Register<IOrderRepository, SqlOrderRepository>(Lifestyle.Singleton);
container.Register<ILogger, FileLogger>(Lifestyle.Singleton);
container.Register<IEventPublisher, EventPublisher>(Lifestyle.Singleton);
container.Register<CancelOrderHandler>();
container.Register<IViewsIntegrationService, ViewsIntegrationService>(
Lifestyle.Singleton);
try
{
// Verify the container
container.Verify();
}
catch (Exception ex)
{
System.Console.WriteLine(ex.Message);
System.Console.ReadLine();
}
}
}
Both apps have this code in the composite root:
var bs = new Bootstrapper();
bs.Initialize();
The ViewsIntegrationService fires the events in the WPF app.
The Console app subscribes to the ViewsIntegrationService events.
When I run both applications, the console app does not receive the events and nothing prints on the console.
Is it because each of the apps use separate instances of the bootstrapper? Hence two sets of identical registrations? Or is this not working because of another reason?
Despite being 2 projects in the same Visual Studio solution, when compiled each one is an individual Windows executable program. These two programs will not automatically communicate with each other. If you need to transfer information from one program to the other, you will need to use some sort of communication channel such as TCP or MSMQ. See Send/Receive message To/From two running application.
Alternatively, you could make your "console application" into a class library (which when referenced from WPF will be part of the same application) and use a WPF window that looks like a console application window write out information.
Events and dependency injection only affect a single application, so neither are relevant in the case you are communicating across application boundaries.
Related
I'm playing with Microsoft's UWP AppServiceBridgeSample (here).
It is working well, but I would like to get rid of the console window of the BackgroundProcess application. The reason for this is that my BackgroundProcess starts another Win32 desktop application and works only as a mediator, so I don't want to disturb users with a console window. (Yes, it can be minimized, but I would rather not show it at all).
I have tried to hide it using the API mentioned here, but with no luck, the console window is still visible. Neither did switching the project's output type from Console Application to Windows Application.work.
Another thing I have tried was to create other BackgroundProcess project as a Windows application. It runs fine until I call AppServiceConnection.OpenAsync(), which causes the BackgroundProcess application to exitstrong text, thus the connection to UWA is not available.
static async void ThreadProc()
{
try
{
AppServiceConnection connection = new AppServiceConnection();
connection.AppServiceName = "CommunicationService";
connection.PackageFamilyName = Windows.ApplicationModel.Package.Current.Id.FamilyName;
connection.RequestReceived += Connection_RequestReceived;
AppServiceConnectionStatus status = await connection.OpenAsync();
//status check etc. ...
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
It seems that opening the AppService connection is only possible from a console app.
So here are my two questions:
Is it, by any chance, even possible to hide the background process' console window?
Can I use the background process as a Windows application, without AppServiceConnection failing during OpenAsync calls?
Re 1: Go into the project settings and change the output type from Console to Windows app. Also make sure the Main() function doesn't exit until you are done with the background process. Here is a better sample that shows this with a Windows Application:
https://stefanwick.com/2017/05/26/uwp-calling-office-interop-apis/
Re 2: AppServiceConnection works the same way from a windowed application as well. Make sure you add the right reference to the Windows.winmd to be able to build. If you have trouble with that, please post a specific question with details of the problem you are seeing
I'm writing complex application where are server and client application, if i want to add some new window in my application i need to run server, then run client, then login click few buttons before i reach window which i right now developing, it's annoying and takes much time. So now i'm looking for some solution where i can run test which can run only my wpf form using mock for services (so i don't need running server and don't need to login), can click or fire events and check controls appear and act the way i want.
In this case i can save a lot of time because i dont need to waste time when i try to reach my form by running whole application where i need to use login, search bypass some validation forms and etc.
If there is already simple solution then it will be great.
Take a look at the MVVM pattern.
MVVM for WPF
Are you using any kind of dependency injection? It would be easy if so, you could simply create fake version of your heavy service using mocking framework with combination of #if-else directives. Somewhere in your application startup code:
ILoginService service;
#if DEBUG
service = A.Fake<ILoginService>();
// you could even set up your fakes to return logged user to
// automate logging in process:
var userFake = A.Fake<IUser>();
A.CallTo(() => service.LogIn(A<string>.Ignored)).Returns(userFake);
#else
service = new RealLoginService();
#endif
var myWindow = new MyWindow();
var viewModel = new ViewModel(service);
myWindow.DataContext = viewModel;
// ...
All you need is ViewModel (assuming you use such) being able to take ILoginService dependency. Then you can mock/fake it up to your liking.
I have a WCF service that is hosted on a c# console application. Is there a way to restart this service, preferably by calling an endpoint in the service itself (ex. myService.Restart()).
Thanks
I have to do something similar when I perform an automatic update of a remote WCF service. In your Restart() method, close the host:
try
{
host.Description.Endpoints.Where(x => !x.Address.ToString().EndsWith("MEX")).ForEach(endpoint => _log.InfoFormat("Closing {0}", endpoint.Address));
host.Close(TimeSpan.FromSeconds(5));
}
catch (Exception)
{
host.Abort();
}
I wait for my update to apply, and then after a success or failure, I re-open the host using the same code I used to start it in the first place.
If you just wanted to restart immediately, you could just call host.Open(), or you could set up a timer to call it, etc.
try
{
host.Open();
host.Description.Endpoints.Where(x => !x.Address.ToString().EndsWith("MEX")).ForEach(endpoint => _log.InfoFormat("Host opened at: {0}", endpoint.Address));
}
catch (Exception ex)
{
_log.Error("Unable to open host.", ex);
}
To answer my question, I have solved the problem by doing the following:
Separating the code that loads the DLL files from the WCF service code into another class library project
Create an interface with the same method signatures as the ones that load DLL files in the new project (this interface is used by both projects now)
In the web service, load the other project in a new application domain. This way the DLL files are locked by the new application domain not the default.
If I want to update my nunit DLL files now, all I have to do is unload the application domain from the web service, update the files and finally create a new application domain.
AppDomain remoteDomain = AppDomain.CreateDomain("New Domain");
IClass1 class1 = (IClass1)remoteDomain.CreateInstanceFromAndUnwrap(
"Test1.dll", "Test1.Class1");
Note: IClass1 is the common interface between the projects.
you definitely are not going to be able to 'restart' a faulted service from calling that same service itself. In theory you could host 2 services in the same process. put the one you want to be 'restartable' in a public static variable and restart it within the other service. The problem would be restarting the restarter service if it faults... :) and you definitely want 'administrator-like' restrictions on your restarter service so unauthorized users can't do it.
It's a bit kludgy, but I suppose you could expose a callback on your service that the host could attach to and take appropriate action when it's triggered. That would give your host the ability to decide what a "restart" really means and how it needs to be executed. More importantly, it lets your decide whether it should do something extreme like spawn off a watcher process and then off itself or gracefully trash and reinstantiate your service (preferable).
Mmmmmm... kludge....
You cannot ask a service to restart itself. Consider a windows service (a service hosted in windows provided container) which has a RESTART functionality. Here RESTART functionality is provided not by the service but by the container. The container controls how to stop the service and start it.
Similarly in your case, you should try to look out for options if your container can provide the functionality you need. Since you want to control it remotely, the container should also be available remotely, which cannot be possible if the container is a console application. Instead it has to be another web service or web application.
I wrote, installed, and successfully started a Windows Service in c# that does nothing :) Initially I just want echo stuff to the console, db queries the service makes etc. I used the OnStart in my service, but from a cmd prompt when I do a net start "My Service" where do these messages show up?
I'm open to better ways. I'm new to this and feeling my way through it step by step by echoing back to the console my progress. Should I echo to the event log instead? How do I do that?(I know, I know, google it)
protected override void OnStart(string[] args)
{
base.OnStart(args);
Console.WriteLine("Sham-Wow!");
}
You cannot write the console from a Windows Service.
I recommend you using any logging utility, such as log4net.
The second alternative is writing to the Event Log (System.Diagnostics.EventLog)
Try System.Diagnostics.Trace.WriteLine and you will see your messages in Output window of Visual Studio or with dbgview utility.
If you want to run your application as a console application (so you can see your console output) or as a service you can achieve this with the following:
Ensure that your application is compiled as a Console application.
Alter the application's Main method so that you can branch for service or console execution.
Run your application as follows to get a console "myservice.exe /console".
It's been years since I have done this so might need a little tweaking, but something like follows:
static void Main(string[]] args)
{
if (args.Length == 0)
{
//Service entry
System.ServiceProcess.ServiceBase[] services;
services = new System.ServiceProcess.ServiceBase[] { new WinService1() };
System.ServiceProcess.ServiceBase.Run(services);
}
else
{
//Console entry
OnStart(args);
}
}
protected override void OnStart(string[] args)
{
base.OnStart(args);
Console.WriteLine("Sham-Wow!");
}
This is fine for some early experimentation, but I would recommend Log4Net once you have got your head around things.
The most common/accepted way of communicating the status of your service is to write to the Windows Event Log.
For easier debugging, I would recommend that you put all of your business code into a separate class from the service component. You can then use that class from either your service, or from a console application. While you are creating the service, you will use the console application to host your component, so that you can easily step-into the code.
Very old question, but very relevant. This is how I implemented a logging mechanism that I could inspect while the Windows service is running.
Create a log file. My favorite is Log4net as mentioned before.
Open PowerShell and run this command Get-Content "path/to/file.log" -Wait
You will be able to monitor the file as it changes. This is like the tail command in linux.
I have a project that is deployed to production as a windows service. However for local development purposes it would be useful to run it as a console application. At the moment I have a class Called ReportingHost that provides my core functionality, And a class called ReportingServiceHost that inherits from ServiceBase and allows me to run the application as a service. There is also a program class with a main method that calls ServiceBase.Run on my ReportingServiceHost.
I think I need to write a ReportingConsoleHost class that allows me to run the functionality in a console. Then I need to modify my Main to react to a command line switch and choose one or the other. These are the two bits I am having trouble with.
I have had a look at this and attempted to use that code but my app exits immediately, it doesn't show a console window and it doesn't wait for Enter before closing.
Part of the problem is that I dont have a deep understanding of how these things work. a definitive pattern for splitting my functionality, my two different ways of running that functionality, and a main method that chooses one of these ways based on a command line argument is what I am hoping to achieve.
I suspect your test project was configured as a windows exe, not a console exe. With a windows exe Console.ReadLine will return immediately.
To have a console exe that works both as a service and at the command line, start it as a service project (in Visual Studio) - and add a check on Environment.UserInteractive - i.e.
static void Main() {
if(Environment.UserInteractive) {
// code that starts the listener and waits on ReadLine
} else {
// run the service code that the VS template injected
}
}
You can of course also use a command line switch. I have example on microsoft.public.dotnet.languages.csharp that acts as:
an installer / uninstaller
a service
a console-mode app
depending on the switches
I have done this before by implementing a normal Windows Service (by deriving from ServiceBase), but putting a check in the main method to check for a command line argument.
If the args contain /console, start the console version, otherwise start the service.
Something like this:
internal class MyService : ServiceBase
{
internal static void Main(string[] args)
{
if (args.Length == 0)
{
// run as a service....
ServiceBase[] servicesToRun = new ServiceBase[] {new MyService()};
Run(servicesToRun);
}
else
{
// run as a console application....
}
}
}
My advise? Put all your logic for your service in a separate assembly. (A class library or DLL.) Then create one project as service which references your class library and puts the code to use as services. Create a second console project which also references your class library but which will make it available as a console application.
You would end up with three different projects in your solution but it does allow you to keep things separate. Actually, this would make it possible to extend your service in several other shapes too. You could, for example, create a 4th project as a web service and thus call your service from a web browser on a client system. Because the software logic is separated from the usage logic, you gain lots of control over it.
Be aware that a service will possibly run with more limitations than a console application. In general, services don't have network access by default, don't have a monitor assigned to them to display error messages and in general run with a limited user account or system account. Your service might work as a console yet fail as a service because of this.
There are already two good answers above - but I thought I'd post a link to Brian Noyes' Debuggable Self-Host Windows Service Project blog post - it talks about WCF but should apply to any 'Windows Service'.
The best thing is the sample code - if you can't figure out where the above examples 'fit', grab the complete project and see how it works. Thanks Brian!