I created a windows service with Top Shelf. This service tests the battery level and when battery successfully charged(80%) it opens any UI Windows Form or application to nodify me about that (In this example it opens .txt). When i test it in Visual Studio in works perfectly so my UI or any application apperas both in Task Manager and Desktop but when i install it as service, UI or any application appears only in Task Manger not in Desktop here is code:
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Timers;
using System.Windows.Forms;
namespace SimpleHeartBeatService
{
public class Heartbeat
{
private readonly System.Timers.Timer _timer; //referance yaratdiq
private static bool firstChecker = true;
private static bool secondChecker = true;
public Heartbeat()
{
_timer = new System.Timers.Timer(1000) //referanca objecr menimsetdik
{
AutoReset = true //Object initializer (kitabda Constr deeper de en axirda var)
};
_timer.Elapsed += TimerElapsed;
}
private void TimerElapsed(object sender, ElapsedEventArgs e)
{ //Bize lazim olan hisse burdan asagidadir
PowerStatus status = SystemInformation.PowerStatus;
if (status.PowerLineStatus.ToString() == "Online" && secondChecker)
{
firstChecker = true;
secondChecker = false;
}
if (firstChecker && status.PowerLineStatus.ToString() == "Online" &&
status.BatteryLifePercent * 100 > 80)
{
Process.Start(#"C:\Users\qarib\Desktop\Test\batteryLevel.txt");
firstChecker = false;
}
if (status.PowerLineStatus.ToString() == "Offline")
{
secondChecker = true;
}
// code here
Thread.Sleep(500);
}
public void Start() //Bunlar mutleq yazilmalidir
{
_timer.Start();
}
public void Stop() //Bunlar mutleq yazilmalidir
{
_timer.Stop();
}
}
}
http://securityinternals.blogspot.com/2014/02/windows-session-0-isolation.html
You can read the details in the article, but suffice it to say that Windows services cannot interact with the desktop of regular users anymore. My guess is that your form is actually opening in Session 0, which is not something you'll normally be able to view or interact with.
In order to get around this problem, here's what my project has done.
We have created a Windows service that exposes some mechanism for communicating with it. In our case, the Windows service originally exposed a WCF-based interface using both sockets and pipes. Because of the overhead, we eventually moved to a TCP socket over localhost, and today we are using shared memory. The mechanism doesn't really matter for the purpose of this discussion. Your service just has to provide some way for a user-run application to connect, communicate, and disconnect.
Once this is in place, you can build an application that provides a UI for communicating with the service. We've done this and allowed the application to be minimized to the system tray to give the appearance that it's a behind-the-scenes thing. The system tray icon then provides a popup menu that allows the user to send commands directly to the service or open the application for additional features.
HTH
Related
I create a windows form application and a windows service, I can start my service from my windows form but if I try too launch the windows form application it doesn't work.
To launch my application I use System.Process.Start, I see in Task Manager in tab processes my windows form application name but it doesn't show my form.
public partial class testService: ServiceBase
{
Timer tm = new Timer();
int n = 0;
public testService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
tm.Interval = 10000;
tm.Elapsed += Tm_Elapsed;
tm.Start();
}
private void Tm_Elapsed(object sender, ElapsedEventArgs e)
{
if (n == 2)
{
try
{
ProcessStartInfo info = new ProcessStartInfo(#"pathName\appName.exe");
info.WorkingDirectory = Path.GetDirectoryName(#"pathName");
Process.Start(info);
}
catch (Exception exception)
{
Log.writeEventLog(exception.Message);
}
var service = new ServiceController("testService");
service.Stop();
}
n++;
}
protected override void OnStop()
{
tm.Stop();
}
}
Someone have any idea why it doesn't work ?
UPDATE
I need to do that because I have to ask with a windows form every 10min if the user is active or not.
Windows services are not allowed to interact with the desktop since Windows Vista. This was for many reasons. The checkbox is a legacy thing.
How do you launch stuff from a service then? You don't. That isn't how a service is supposed to work.
On the other hand, you can run a background process as the user to accomplish the same thing.
You can do this by starting your "service" via the registry, startup folder, or task scheduler.
I'm writing a simple watchdog application that will start and stop another application I'm writing based on whether the third application is running or not.
in other words, if application A is running then start application B. When application A stops, stop application B.
the problems is that my watchdog keeps stopping application B and immediately restarts it.
here is what I have:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;
using System.Windows.Forms;
using WindowScrape.Types;
namespace ConnectAndWait
{
class CheckForApplication
{
public static System.Windows.Forms.Timer _timer = new System.Windows.Forms.Timer();
public static bool goodtogo;
public static void checking()
{
_timer.Interval = 3000;
_timer.Tick += _timer_Tick;
_timer.Start();
}
public static void _timer_Tick(object sender, EventArgs e)
{
Process[] myprocess = Process.GetProcessesByName("ApplicationA");
Process[] proc = Process.GetProcessesByName("notepad");
if (myprocess.Length == 0)
{
goodtogo = false;
}
else
{
var win = Process.GetProcessesByName("ApplicationA");
var mainform = NativeMethods.FindWindow("TMainForm_ihm", null);
var children = NativeMethods.FindWindowEx(mainform, IntPtr.Zero, "TRzPageControl", null);
var final = NativeMethods.FindWindowEx(children, IntPtr.Zero, "TRzTabSheet", "Operation" );
if (final.ToString() != "0")
{
goodtogo = true;
}
else
{
goodtogo = false;
}
}
if (goodtogo == true)
{
if (proc.Length == 0)
{
Process.Start("notepad.exe");
MessageBox.Show("notepad started");
}
}
else if (goodtogo == false)
{
if (proc.Length != 0)
{
proc[0].Kill();
MessageBox.Show("process killed"); // <-- This never gets fired
// as long as application A keeps running. At first I thought I was stopping it
// with this code so I put the messageBox in to test that theory.
}
}
}
}
}
I am starting and stopping notepad for now just for testing.
can anyone see what I am doing wrong?
First: what is causing notepad to stop and then restart again even though the other application is still running?
Second: if there is anything else I should be doing differently please point that out as well.
As always, thank you so much for any help you can provide.
EDIT:
I didn't mention it before because of my lack of knowledge I didn't think it would be relevant.
The entire scope of the project is that I am writing an integration between two existing applications. If the one application is not running then there is no need for my application to use resources. So my thought was that a watchdog would take up fewer resources than the application itself.
My integration application uses multiple threads and gets and sets a lot of information between the other two applications.
The end user will start and stop application A whenever needed.
Application B is my integration application.
Application C - the one previously not mentioned - runs as a service and interacts with a database.
The watchdog application in question is simply to start and stop my integration application whenever Application A stops or starts.
There is simply no need for such a 'watchdog'. Use Job objects and bind the processes in a job. Read Destroying all child processes (and grandchildren) when the parent exits. See Working example of CreateJobObject/SetInformationJobObject pinvoke in .net? for C# examples.
For process start, use WMI Win32_ProcessStartTrace, see .NET Process Monitor.
I have a winform application which needs to consume a web service. Web service checks in the database for any changes. If there are any changes in the database the winform application should be notified and will perform some tasks accordingly. How do I do that?
I thought of using timer in my winform application and after say every 5 min connect to a web service and check if new changes are been done in Database. Is there any other way for this?
Update:
I am posting the code here base on the answers:
class PerformTasks
{
public static bool checkIfInProgress { get; set; }
public static void InitializeWebService()
{
try
{
Timer = new System.Timers.Timer(2000);
Timer.Elapsed += OnTimedEvent;
Timer.Enabled = true;
}
}
private static void callService()
{
using (var service = new WebServiceSoapClient())
{
checkIfInProgress = true;
task1();
task2();
popMessage();
checkIfInProgress = false;
}
}
private static void OnTimedEvent(Object source, ElapsedEventArgs e)
{
if (checkIfInProgress == false)
{
callService();
}
}
private static void PpopMessage()
{
var form = new Form
{
StartPosition = FormStartPosition.Manual,
ShowInTaskbar = false,
Text = "Message",
Size = new Size(500, 200),
};
var screen = Screen.FromPoint(form.Location);
Label lblText = new Label();
lblText.Text ="Test Text";
lblText.Dock = DockStyle.Fill;
lblText.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
form.MaximizeBox = false;
form.Controls.Add(lblText);
form.Location = new Point(screen.WorkingArea.Right - form.Width, screen.WorkingArea.Bottom - form.Height);
form.Show();
}
Now everything works fine except 1 task i.e popMessage(code snippet on top). Here the form is opened but it appears to be loading always. Before using times it used to work fine. How can I handle it?
That's the only way especially if the web service is not WCF-based or if you can't afford to modify it.
If you're using a timer just make sure you use System.Timers.Timer and follow the instructions here so that the Elapsed handler is executed on the UI thread. Moreover, when the timer ticks you should probably spawn a worker thread (or Task, or await on an async method) that makes the service call. You don't want your UI to be blocked while the service call is in progress.
If you have control over the web service, then you may want to explore WCF Duplex Services, which allow you to callback clients from within services.
SignalR allows you to implement Web Services to do this very thing, in real time (no need for a timer or delay between updates). It allows you to set up a persistent connection between client and server, the server is then able to send messages to the client at any point using a stack of transports; WebSockets, Server Sent Events, Forever Frame and Long Polling) based on support available in that order.
You could use SignalR to establish the connection and when something happens on the Server (such as the change in the database you mentioned) broadcast to all clients that need to be notified. eg.
Clients.All.notifyDatabaseChanged(args);
I'm developing a C# Application for OPC Access via "OPC DA Automation Wrapper 2.02"
For testing on my WIN8 machine I'm using "Iconics Simulator OPC Server 3.12"
I have 4 boolean OPCItems with different names configured on the server.
Connecting, reading the OPCItems works fine.
But:
If I write to ONE of them, the monitor (OPC DataSpy 9.01) and other tools are showing that ALL OPCItems have changed. The Change Event appears for all OPCItems
To check this behaviour, I've written the same application with VisualBasic 6 - same result!
What is wrong, my code or the Simulator Server?
using System;
using System.Windows.Forms;
using OPCAutomation;
namespace opc {
public partial class Form1 : Form {
OPCGroups opcGroups;
OPCGroup opcGroup;
bool aliveToggle;
Timer aliveTimer;
public Form1() {
InitializeComponent();
OPCServer opcServer = new OPCServer();
opcServer.Connect("Iconics.SimulatorOPCDA.2");
opcGroup = opcServer.OPCGroups.Add("Gruppe1");
opcGroup.OPCItems.AddItem("BOOL_1", 1);
opcGroup.OPCItems.AddItem("BOOL_2", 2);
opcGroup.OPCItems.AddItem("BOOL_3", 3);
opcGroup.OPCItems.AddItem("BOOL_4", 4);
opcGroup.UpdateRate = 10;
opcGroup.IsActive = true;
opcGroup.IsSubscribed = true;
aliveTimer = new Timer();
aliveTimer.Tick += new EventHandler(sendAlive);
aliveTimer.Interval=1000;
aliveTimer.Start();
}
private void sendAlive(object sender, EventArgs e) {
aliveToggle=!aliveToggle;
opcGroup.OPCItems.Item(2).Write(aliveToggle);
}
}
}
Easy fix is whenever adding a tag that needs to be event notified independently it should have it's own group, because unfortunately change events are fired on a group basis instead of a tag basis.
I want to detect and close any program (for example: Notepad.exe) by using a windows service. Below code is good choose in a console application.
class Program
{
private static SessionSwitchEventHandler sseh;
static void Main(string[] args)
{
sseh = new SessionSwitchEventHandler(SystemEvents_SessionSwitch);
SystemEvents.SessionSwitch += sseh;
while (true) { }
}
static void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
{
Console.WriteLine(e.Reason.ToString());
}
}
But Above code is not working in a windows service windows 7. look this link :
http://social.msdn.microsoft.com/Forums/eu/netfxcompact/thread/04b16fac-043a-41c3-add9-482c912e95be
I have written below code in the windows service which does not run on win 7, it is working every time on windows 7 in console application.
protected override void OnStart(string[] args)
{
SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
Console.ReadLine();
SystemEvents.SessionSwitch -= SystemEvents_SessionSwitch;
}
static void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
{
WriteToLogFile( e.Reason.ToString());
if (e.Reason == SessionSwitchReason.SessionLock)
{
WriteToLogFile("SessionLock ");
}
if (e.Reason == SessionSwitchReason.SessionUnlock)
{
WriteToLogFile("SessionUnlock ");
}
if (e.Reason == SessionSwitchReason.SessionLogon)
{
WriteToLogFile("SessionLogon ");
}
}
I have been read this article (http://rhauert.wordpress.com/category/ucc/) but I can not use
protected override void OnStart(string[] args)
{
WriteToText("Windows Service is started");
SessionChangeHandler x = new SessionChangeHandler();
}
MSDN:
SystemEvents.SessionSwitch Event:
This event is only raised if the message pump is running. In a Windows service, unless a hidden form is used or the message pump has been started manually, this event will not be raised. For a code example that shows how to handle system events by using a hidden form in a Windows service, see the SystemEvents class.
The code sample is on this page, which also notes:
Services do not have message loops, unless they are allowed to interact with the desktop. If the message loop is not provided by a hidden form, as in this example, the service must be run under the local system account, and manual intervention is required to enable interaction with the desktop. That is, the administrator must manually check the Allow service to interact with desktop check box on the Log On tab of the service properties dialog box. In that case, a message loop is automatically provided. This option is available only when the service is run under the local system account. Interaction with the desktop cannot be enabled programmatically.