With this code I can ensure that only one instance of the application is running. But I can not cause the window to be restored from the system tray. I tried window.Show() but not resolve.
public class SingletonApplication : Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase
{
public App application { get; private set; }
Telas.wndLogin window;
[STAThread]
public static void Main(string[] args)
{
new SingletonApplication().Run(args);
}
public SingletonApplication()
{
this.IsSingleInstance = true;
}
protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs eventArgs)
{
application = new App();
window = new Telas.wndLogin();
application.Run(window);
return false;
}
protected override void OnStartupNextInstance(Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs eventArgs)
{
//todo:
}
}
Related
I currently have an installation "framework" that does specific things. What I need now to do is be able to call my form in parallel with my script. Something like this:
InstallationForm f = new InstallationForm();
Application.Run(f);
InstallSoftware(f);
private static void InstallSoftware(InstallationForm f) {
f.WriteToTextbox("Starting installation...");
Utils.Execute(#"C:\temp\setup.msi", #"-s C:\temp\instructions.xml");
...
f.WriteToTextbox("Installation finished");
The current way I can do this is by adding the Form.Shown handler in InstallSoftware, but that seems really messy. Is there anyway I can do this better?
Your code will not work, because Application.Run(f) returns not until the form was closed.
You may use a simplified Model/View/Controller pattern. Create an InstallationFormController class that has several events, e.g. for textual notifications to be written to your textbox. The InstallationForm registers on these events in it's OnLoad() method and then calls InstallationFormController.Initialize(). That method starts your installation (on a worker thread/task). That installation callback method fires several text events.
InstallationForm f = new InstallationForm(new InstallationFormController());
Application.Run(f);
internal class InstallationFormController
{
public event EventHandler<DataEventArgsT<string>> NotificationTextChanged;
public InstallationFormController()
{
}
public void Initialize()
{
Task.Factory.StartNew(DoInstallation);
}
private void DoInstallation()
{
...
OnNotificationTextChanged(new DataEventArgsT<string>("Installation finished"));
}
private void OnNotificationTextChanged(DataEventArgsT<string> e)
{
if(NotificationTextChanged != null)
NotificationTextChanged(this, e);
}
}
public class DataEventArgsT<T> : EventArgs
{
...
public T Data { get; set; }
}
internal class InstallationForm : Form
{
private readonly InstallationFormController _controller;
public InstallationForm()
{
InitializeComponent();
}
public InstallationForm(InstallationFormController controller) : this()
{
if(controller == null)
throw new ArgumentNullException("controller")
_controller = controller;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
_controller.NotificationTextChanged += Controller_NotificationTextChanged;
_controller.Initialize();
}
protected virtual void Controller_NotificationTextChanged(object sender, DataEventArgsT<string> e)
{
if(this.InvokeRequired)
{ // call this method on UI thread!!!
var callback = new EventHandler<DataEventArgsT<string>>(Controller_NotificationTextChanged);
this.Invoke(callback, new object[] {sender, e});
}
else
{
_myTextBox.Text = e.Data;
}
}
...
}
I've just started looking into Xamarin and just can not to wrap around my head how to make multiple Activities have a reference same instance of service.
I am starting KeyPressedReceiver from MainActivity and start listening for power button being pressed.
When three click are being made, I am calling service method InitCancelActivity, which starts playing mp3 file and opens CancelActivity.
In CancelActivity there is a text field and a button. And when user press this button, I want the value from text field to be passes to the GeneralService method KillAlert.
The question is how to reference instance of GeneralService (which is already created) from CancelActivity, so I could call KillAlert?
And this part
if (_service == null)
_service = new GeneralService();
looks absolutely wrong. Should I instantiate it in MainActivity and pass to a KeyPressedReceiver constructor?
[Activity(Label = "TTTT", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity
{
KeyPressedReceiver receiver;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
receiver = new KeyPressedReceiver();
RegisterReceiver(receiver, new IntentFilter(Intent.ActionScreenOn));
}
}
[BroadcastReceiver(Enabled = true)]
public class KeyPressedReceiver : BroadcastReceiver
{
private GeneralService _service;
private int _clicks = 0;
public override void OnReceive(Context context, Intent intent)
{
if (_service == null)
_service = new GeneralService();
_clicks++;
if (_clicks > 5)
{
_service.InitCancelActivity();
}
}
}
[Service(Name = "com.ff.GeneralService")]
public class GeneralService : Service {
private readonly Android.Media.MediaPlayer _player;
public GeneralService()
{
_player = new Android.Media.MediaPlayer();
}
public void RaiseAlert()
{
// start playing .mp3 file
}
public void KillAlert(string pass)
{
// stop playing .mp3 file
}
public void InitCancelActivity()
{
this.RaiseAlert();
var i = new Intent(this, typeof(CancelActivity));
i.SetFlags(ActivityFlags.NewTask);
this.StartActivity(i);
}
}
[Activity(Label = "CancelActivity")]
public class CancelActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.cancel);
this.FindViewById(Resource.Id.cancelButtonYes).Click += delegate
{
var password = this.FindViewById(Resource.Id.cancelPassword);
// call KillAlert method from GeneralServic
};
}
}
Create static GeneralService instance and use in Cancel Activity.
for example
[Service(Name = "com.ff.GeneralService")]
public class GeneralService : Service {
private readonly Android.Media.MediaPlayer _player;
public static generalService;
public GeneralService()
{
_player = new Android.Media.MediaPlayer();
generalService=this
}
public void RaiseAlert()
{
// start playing .mp3 file
}
public void KillAlert(string pass)
{
// stop playing .mp3 file
}
public void InitCancelActivity()
{
this.RaiseAlert();
var i = new Intent(this, typeof(CancelActivity));
i.SetFlags(ActivityFlags.NewTask);
this.StartActivity(i);
}
}
and use in CancelActivity like below example
[Activity(Label = "CancelActivity")]
public class CancelActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.cancel);
this.FindViewById(Resource.Id.cancelButtonYes).Click += delegate
{
var password = this.FindViewById(Resource.Id.cancelPassword);
// call KillAlert method from GeneralServic
GeneralService.generalService.KillAlert(password.TEXT);
};
}
}
I have a problem where the notifyicon is showing up fine, and displaying its bubble, but it does not raise its click event when clicked.
It should show its contextmenustrip, but if i add contextmenustrip.show(); into the code, it just shows the shadows of the menu but not the menu itself.
the function is part of a WPF application and is called via a named pipe from a WCF service application.
Code, in case you need it:
in the service app:
public partial class Service1 : ServiceBase
{
ChannelFactory<ILicenseWatchingServiceUIHost> pipeFactory;
ILicenseWatchingServiceUIHost LWSProxy;
public Service1()
{
InitializeComponent();
}
#region service states
protected override void OnStart(string[] args)
{
pipeFactory = new ChannelFactory<ILicenseWatchingServiceUIHost>(
new NetNamedPipeBinding(),
new EndpointAddress("net.pipe://localhost/LWSPipe"));
LWSProxy = pipeFactory.CreateChannel();
Run();
}
//...
private void Run()
{
//...
LWSProxy.Execute();
}
}
server creation in WPF app:
public partial class App : Application
{
ServiceHost host = new ServiceHost(typeof(LicenseWatchingServiceUserInterface), new Uri[] { new Uri("net.pipe://localhost") });
public App()
{
StartServer();
}
private void StartServer()
{
host.AddServiceEndpoint(typeof(ILicenseWatchingServiceUIHost), new NetNamedPipeBinding(), "LWSPipe");
host.Open();
BackgroundWorker worker = new BackgroundWorker();
System.Windows.Threading.Dispatcher dispatcher = this.Dispatcher;
}
}
and finally:
public class LicenseWatchingServiceUserInterface : ILicenseWatchingServiceUIHost
{
private System.ComponentModel.IContainer components = null;
private System.Windows.Forms.NotifyIcon notifyIcon;
private System.Windows.Forms.ContextMenuStrip contextMenuStrip;
void Execute(){
//...
contextmenustrip.show(); //does not work
}
//does not get raised
private void notifyIcon_Click(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
contextMenuStrip.Show(Cursor.Position.X, Cursor.Position.Y);
}
else if (e.Button == MouseButtons.Left)
{
Execute();
}
}
}
void Init()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LicenseWatchingServiceUserInterface));
this.notifyIcon = new System.Windows.Forms.NotifyIcon();
this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip();
//
// notifyIcon
//
this.notifyIcon.BalloonTipIcon = System.Windows.Forms.ToolTipIcon.Info;
this.notifyIcon.ContextMenuStrip = this.contextMenuStrip;
this.notifyIcon.Icon = iconLoading;
this.notifyIcon.Visible = true;
//clickhandler is in fact wired up
this.notifyIcon.MouseClick += new System.Windows.Forms.MouseEventHandler(this.notifyIcon_Click);
//
// contextMenuStrip
//
this.contextMenuStrip.ImageScalingSize = new System.Drawing.Size(20, 20);
this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.settingsToolStripMenuItem,
this.openLicenseManagerToolStripMenuItem,
this.closeToolStripMenuItem});
this.contextMenuStrip.Name = "contextMenuStrip";
this.contextMenuStrip.Size = new System.Drawing.Size(234, 128);
//
// contextmenustrip items...
//
}
//...
}
Figured it out:
The LWSProxy.Execute(); was creating an instance of the LicenseWatchingServiceUserInterface class in a background thread, wich was causing problems. The notifyicon has to be created in the main thread, otherwise the eventhandlers won't work. My solution is a helper class (just put it below the class App) :
public class LicenseWatchingServiceUICreator : ILicenseWatchingServiceUIHost
{
public void Execute(List<LicenseInfoContainerExpiring> elcs, List<LicenseInfoContainerUntrusted> ulcs)
{
System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
{
LicenseWatchingServiceUserInterface LWSUI = new LicenseWatchingServiceUserInterface(elcs, ulcs);
}));
}
}
with minor tweaking, this classes execute method will get called through the pipe, and it will create an instance of my class in the main thread. Now my UI works as usual.
I have searched and searched for Windows Service information and it is mostly non-existent or outdated. Further, there is no Windows Service template in VS 2013 (that I can find).
I am making a simple performance monitor that logs to a text file the CPU and RAM. I followed a couple outdated tutorials and came up with stuff on my own.
When I try running via F5 (a coworker's suggestion) the command prompt flashes open, closes and then the program ends. I don't think the OnStart method is ever invoked.
I can get the service installed fine from the VS command prompt but when trying to start the process I get an error that it does not start in a timely manner. I have even tried enabling interaction with the desktop in the Service Manager.
I have also tried both Debug and Release builds.
I have looked at other SO questions that suggested to do all initialization in the OnStart method, which I think I do (though I may be wrong -- I am obviously still learning).
The relevant code:
namespace SystemMonitorD
{
public class SystemMonitorD : ServiceBase
{
private Timer StateTimer { get; set; }
private TimerCallback TimerDelegate { get; set; }
private SystemMonitorL SysMon { get; set; }
public SystemMonitorD()
{
ServiceName = "SystemMonitorD";
CanStop = true;
CanPauseAndContinue = true;
AutoLog = true;
}
protected override void OnStart(string[] args)
{
SysMon = new SystemMonitorL();
TimerDelegate = SysMon.Log;
StateTimer = new Timer(TimerDelegate, null, SysMon.WaitTime, SysMon.WaitTime);
}
protected override void OnStop()
{
SysMon.StatusLog("Stop");
StateTimer.Dispose();
}
protected override void OnPause()
{
SysMon.StatusLog("Pause");
StateTimer.Change(Timeout.Infinite, Timeout.Infinite);
}
protected override void OnContinue()
{
SysMon.StatusLog("Continue");
StateTimer.Change(SysMon.WaitTime, SysMon.WaitTime);
}
public static void Main()
{
}
}
public class SystemMonitorL
{
private readonly String _fileLocation = #"C:\Users\ian.elletson\Desktop\logD.txt";
public int WaitTime { get; private set; }
private IOutput Logger { get; set; }
private List<SystemMonitor> SystemMonitors { get; set; }
public SystemMonitorL()
{
WaitTime = 1000;
Logger = new Logger(_fileLocation);
SystemMonitors = new List<SystemMonitor>
{
SystemMonitorFactory.MakeSystemMonitor("CPU"),
SystemMonitorFactory.MakeSystemMonitor("RAM")
};
Logger.WriteLine(string.Format("Polling every {0} second(s)", WaitTime / 1000));
}
public void Log(Object stateObject)
{
foreach (var monitor in SystemMonitors)
{
Logger.WriteLine(monitor.ToString());
}
}
public void StatusLog(String status)
{
String message;
switch (status)
{
case "Stop" :
message = "stopped";
break;
case "Pause" :
message = "paused";
break;
case "Continue":
message = "continued";
break;
default:
message = "ERROR";
break;
}
Logger.WriteLine(string.Format("Logging {0} at {1}", message, TimeZone.CurrentTimeZone.ToLocalTime(DateTime.Now)));
}
}
[RunInstaller(true)]
public class SystemMonitorDInstaller : Installer
{
ServiceProcessInstaller ProcessInstaller { get; set; }
ServiceInstaller ServiceInstaller { get; set; }
public SystemMonitorDInstaller()
{
ProcessInstaller = new ServiceProcessInstaller();
ServiceInstaller = new ServiceInstaller();
ProcessInstaller.Account = ServiceAccount.LocalSystem;
ServiceInstaller.StartType = ServiceStartMode.Manual;
ServiceInstaller.ServiceName = "SystemMonitorD";
Installers.Add(ServiceInstaller);
Installers.Add(ProcessInstaller);
}
}
}
One thing that makes life easier dealing with while debugging windows services is to use the Debug\Release flag for your service. To step through the logic as a non-service.
static void Main()
{
#if (!DEBUG)
//RELEASE FLAG
System.ServiceProcess.ServiceBase[] ServicesToRun;
ServicesToRun = new System.ServiceProcess.ServiceBase[] { new MyService() };
System.ServiceProcess.ServiceBase.Run(ServicesToRun);
#else
//DEBUG
MyService service = new MyService(); //<--Put breakpoint here before you run your service
service.OnStart(null);
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
#endif
}
I discovered my problem. I was missing
ServiceBase.Run(new SystemMonitorD()); in my Main() method. That solved the problem. I found this from this MSDN link.
In a background agent I create (or update) one of application live tiles and this works as expected.
Problem is that when I click this live tile screen flickers but my app is not "restarted" nor "shown".
What's wrong?
I attach small part of the code, but ask for more is you need.
MAIN PAGE
public partial class MainPage : PhoneApplicationPage
{
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
}
public MainPage()
{
InitializeComponent();
// Runs background agent: code is simplified
StartAgent();
}
}
BACKGROUND AGENT
public class TileAgent : ScheduledTaskAgent
{
protected override void OnInvoke(ScheduledTask task)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
Vars.UpdateTiles();
});
NotifyComplete();
}
}
STATIC CLASS
public class Vars
{
private static Uri uri = new Uri(
"/MainPage.xaml?tile",
UriKind.RelativeOrAbsolute);
private static RadExtendedTileData ExtendedData
{
get
{
return new RadExtendedTileData()
{
VisualElement = frontTile,
BackVisualElement = backTile,
};
}
}
public static void UpdateTiles()
{
// I perform some task here
// Then I create/update live tile
Telerik.Windows.Controls.LiveTileHelper.CreateOrUpdateTile(
ExtendedData, uri);
}
}
Try /MainPage.xaml?tile=true instead of /MainPage.xaml?tile...
And move NotifyComplete() into the dispatcher call. Otherwise it will be called before the operation has been completed...