a web service is running with IIS.
When calling the initialize service, some libraries are dynamically loaded in order to start a wpf application.
The code compiles, runs... but the window never shows up. No exception is thrown whatsoever.
Below is the code that is executed to create the WPF application:
public void Start()
{
ThreadStart ts = Run;
Thread t = new Thread(ts);
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
[STAThread]
public void Run()
{
try
{
App app = new App();
MainWindow w = new MainWindow();
w.Show();
app.Run(w);
} catch (Exception e)
{
LogManager.GetLogger("general").Debug(e.StackTrace);
}
}
If I run that in a console application, it works perfectly:
static void Main(string[] args)
{
MyApplication app = new MyApplication();
app.Start();
Console.ReadKey();
}
But if I run it from the web service, code is correctly executed (as I can debug it, and no exceptions) but the window never shows up:
public void initialize() {
IMyApplication application = assembly.CreateInstance(namespaceValue + ".MyApplication") as IMyApplication;
application.Start();
}
I can see in the process manager that the WPF process is running... Any idea why the window does not show up ?
Regards,
Francois
Is there something special to do to grant all access/rigths to the web service ?
Check your application pool and tell me what user it uses - or if you use impersonation.
My first guess would be that this runs as a service user (with no rights to mess with a desktop and especially not with your desktop). In general I think this is a strange thing to do..
Why don't you use a Silverlight out of browser application? Why no ClickOnce?
Related
I am trying to create a Windows service with C# which spawns multiple processes inside it.
For this I am using AppDomain functionality and creating multiple of them at startup in the OnStart method of my service:
public partial class MyService : ServiceBase
{
public ServiceBase()
{
InitializeComponents();
}
protected override void OnStart(string[] args)
{
var setup = new AppDomainSetup();
setup.ApplicationBase = Path.GetDirectoryName(GetMyExePath());
var ad = AppDomain.CreateDomain("Domain NEW", null, setup);
var t = new Thread(() => {
ad.ExecuteAssembly(GetMyExePath());
AppDomain.Unload(ad);
});
t.Start();
}
}
(I know I should put a check to prevent recursively starting new domains from each new one, but for now it doesn't even start the first one)
When I try the same in a Console Application, it works fine.
But when I build it as a Windows Service and run it from the service manager, it seems to terminate after startup.
Opening the Event Viewer, I see this about my service:
"Service can not be started. An instance of the service is already running."
Running it without the app domain creation code works just fine. It fails to start even a single domain as it seems to view them as trying to start the same process twice instead making a new domain within the process.
Is there a way to get this to run on services or does it only work for regular applications?
#if DEBUG
MainService service1 = new MainService();
service1.onDebug();
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
ConfigurationSync.logDebugMessage(logMessageType.message, "Starting main service thread");
#else
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new MainService()
};
ServiceBase.Run(ServicesToRun);
ConfigurationSync.logDebugMessage(logMessageType.message, "Starting main service thread");
#endif
I have created my first windows service and I am wondering what the correct way is to start the service in the Program.cs file.
The code supplied above is what was suggested to me by an online tut, #if debug running while testing in Visual Studio and the else block running when built in release mode and installed on the server.
The problem is, it doesn't seem to run on the server after install if I don't use the code in the #if debug code block.
If i run the code as supplied above it says the service has started but nothing seems to happen, while if I only run what's in the debug block the service runs but I get an error on the server "Service failed to start in a timely manner"
Any help would be appreciated
Update:
In my mainservice I have a function that kicks off all the features of the service, this function is startSoftwareUpdates();
These are the functions I have in MainService:
public MainService()
{
startSoftwareUpdates();
public void onDebug()
{
OnStart(null);
}
protected override void OnStart(string[] args)
{
startSoftwareUpdates();
}
Update 3:
So I have reshuffled MainService as follows:
public MainService()
{
InitializeComponent();
}
public void onDebug()
{
OnStart(null);
}
protected override void OnStart(string[] args)
{
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
startSoftwareUpdates();
}).Start();
}
What kind of problems might I run into with this approach? I'd like the Thread to run infinitely too...
Nothing looks wrong with your code. If you could post some more of the code that is inside of your MainService() constructor, that'd be helpful considering that could be where the issue is.
However, when I build these services, instead of the #if DEBUG route, I generally do something like this
if (Environment.UserInteractive)
{
//**** this is for debugging in console mode
}
else
{
//*** this is for running as a Windows service
var ServicesToRun = new ServiceBase[]
{
new ServiceHome()
};
ServiceBase.Run(ServicesToRun);
}
To be clear, I don't expect this to resolve your issue as the code you posted above seems to do the same thing, just in a different manner. I'm posting this to give you a different way to accomplish what you did above.
If I had to guess, I'd say the issue is in your MainService constructor.
Edit
I don't believe the issue is with any of the code that you've written. The error you're getting is caused by a number of potential issues, so it's tough to tell you exactly what it is. Here is a link that has some solutions for you to try. Also, you should try to find the error in the Event Log, assuming you're on a windows machine. That will have a bit more detail to the issue most of the time.
I'm currently trying to use a WPF component that makes use of Application.Current from a WPF application, however due to several reasons I never call Application.Run (nor is that an option). The result is a NullReferenceException.
I'm basically trying to display multiple instances of the same WPF window from what would be a console application.
Any advice (and code samples in C#/F#) would be welcome!
Thanks in advance
Just to offer an alternative solution.
It is possible to keep an application running without any windows open. To me this feels less 'hackish'. :) http://msdn.microsoft.com/en-us/library/system.windows.application.shutdownmode.aspx
public class AppCode : Application
{
// Entry point method
[STAThread]
public static void Main()
{
AppCode app = new AppCode();
app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
app.Run();
...
app.Shutdown();
}
}
EDIT:
Ok this got a bit cumbersome. Application.Run will block, so it needs to run in its own thread.
When it does run in its own thread, any interaction between your main thread and your ui thread had best be done by Application.Current.Dispatcher.Invoke. Here is some working code, that assumes you have a class that inherits from Application. I'm using a modified App.xaml/App.xaml.cs that a WPF project template creates for you, to get nice handling of ResourceDictionaries for free.
public class Program
{
// Entry point method
[STAThread]
public static void Main()
{
var thread = new System.Threading.Thread(CreateApp);
thread.SetApartmentState(System.Threading.ApartmentState.STA);
thread.Start();
// This is kinda shoddy, but the thread needs some time
// before we can invoke anything on the dispatcher
System.Threading.Thread.Sleep(100);
// In order to get input from the user, display a
// dialog and return the result on the dispatcher
var result = (int)Application.Current.Dispatcher.Invoke(new Func<int>(() =>
{
var win = new MainWindow();
win.ShowDialog();
return 10;
}), null);
// Show something to the user without waiting for a result
Application.Current.Dispatcher.Invoke(new Action(() =>
{
var win = new MainWindow();
win.ShowDialog();
}), null);
System.Console.WriteLine("result" + result);
System.Console.ReadLine();
// This doesn't really seem necessary
Application.Current.Dispatcher.InvokeShutdown();
}
private static void CreateApp()
{
App app = new App();
app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
app.Run();
}
}
The following is the intended behavior of Application class:
The first open window is the MainWindow.
The only window in the list becomes the MainWindow (if others are to
be removed).
Application Class is designed to exit if no windows are present in
windows list.
Check this link.
So basically you cannot run an Application, without any window open. Keep a window open but hidden.
If I have misunderstood your problem, then perhaps the following similar cases might help:
Managing Application Resources when WPF is Hosted.
When running unit tests in Visual Studio 2008
I get the error "Cannot start service from the command line or a debugger. A Windows Service must first be installed (using installutil.exe) and then started with the ServerExplorer, Windows Services Administrative tool or the NET START command.
So, is there not a way to run or test the Windows Service without installing it? Should I build my project in a Console Application, then transfer the code to a Windows Server project after it has been tested?
Thanks.
I tend to add a static Main method to my service class so that it can be invoked as a console application for debugging, but installed and ran as a service as well.
Something similar to the following:
public partial class ControllerService : ServiceBase
{
static void Main(string[] args)
{
ControllerService service = new ControllerService();
cmdLine = CommandLineParser.Parse(args);
if (Environment.UserInteractive)
{
switch (cmdLine.StartMode)
{
case StartMode.Install:
//Service Install Code Here
break;
case StartMode.Uninstall:
//Service Uninstall Code Here
break;
case StartMode.Console:
default:
service.OnStart(args);
consoleCloseEvent.WaitOne();
break;
}
}
else
{
ServiceBase.Run(service);
}
}
protected override void OnStart(string[] args)
{
//Do Start Stuff Here
}
protected override void OnStop()
{
if (Environment.UserInteractive)
{
consoleCloseEvent.Set();
}
}
}
You could try to keep the code that performs the actual work in a separate assembly, and call that code from the service or a console application for testing.
there are two approaches you can use.
Create separate windows form application and call that code from the windows form project.
in the calling method, please use:
#if Debug
Debugger.Launch()
#endif
I hope it helps.
Scenario
I've created a windows service, but whenever I start it, it stops immediately. The service was concieved from a console application that used to subscribe to an event and watch processes on a server. If anything happened to process (i.e. It was killed), then the event would trigger the process to be restarted. The reason I'm telling you this is because the original code used to look like this:
Original Console App Code:
static void Main(string[] args)
{
StartProcess sp = new StartProcess();
//Note the readline that means the application sits here waiting for an event!
Console.ReadLine();
}
Now that this code has been turned into a Windows Service, it is essentially EXACTLY THE SAME. However, the service does not sit there waiting, even with the readline, it just ends.....
New Windows Service Code:
protected override void OnStart(string[] args)
{
ProcessMonitor pm = new ProcessMonitor();
Console.ReadLine();
}
Thoughts
Since the functionality is entirely encapsulated within this single class (It quite literally starts, sets up some events and waits) - How can I get the service to actually sit there and just wait? It seems to be ignoring the readline. However this works perfectly as a console application, it is just far more convenient to have it as a service.
Typically you would want something like this. As Joe mentioned in the comments you want Start to initialize and release control to another thread to make sure that you return within 30 seconds.
private readonly ProcessMonitor processMonitor = new ProcessMonitor();
protected override void OnStart(string[] args)
{
processMonitor.Start();
}
protected override void OnStop()
{
processMonitor.Stop();
}
In a Service there is no concept of a readline - there's no keyboard. I wouldn't be surprised if this is throwing an exception at that call. Have you checked your Application Log?
Well... A service doesn't have a console input/output. So the ReadLine won't stop it from executing.
What does ProcessMonitor do?
Typically, for services your code lives in a thread that monitors whether the service has been stopped or paused.
OnStart() must complete and end successfully for the service to be considered "Started"
Move your Console.ReadLine(); into your ProcessMonitor() constructor, and create your ProcessMonitor inside the constructor for the service. Your OnStart method can be empty. Despite what people are saying the Console methods will NOT crash your service, however it is probably not best practice. I guess the proper way to keep a service running (after your timers are started) is to use a while loop with a Thread.Sleep(60000) inside it.
When I am writing a service I put all the functionality in a Class Library project, then I create a Console Application project to test the service functionality, and then a Windows Service project. Both the Console Application and Windows Service project call one method in the Class Library to start the service functionality. If you use this technique you can call Console.WriteLine in the Class Library which can be viewed when running the Console Application. PS Topshelf is overrated, writing a windows service is not that difficult.
public partial class ProcessMonitor_Service : ServiceBase
{
public ProcessMonitor_Service()
{
InitializeComponent();
ProcessMonitor pm = new ProcessMonitor();
}
protected override void OnStart(string[] args)
{
}
protected override void OnStop()
{
}
}
public class ProcessMonitor
{
public ProcessMonitor()
{
// start timers
Console.ReadLine();
}
}