I associated .pdf files with my C#.NET WPF app in Windows.
If I open the pdf file by clicking on it, array "param" is:
string[] param = Environment.GetCommandLineArgs();
Which contains two paths:
1) Path to my app (param[0])
2) Path to opened (param[1])
I have set in the C# code (app.xaml.cs) that only one instance of my app may be opened in Windows. If I try to open a second instance, the main window of the first instance is activated.
But now, if I open the next pdf file by click on it “param” contains the path to the first file logically, therefore I can not open the next file :0(.
How should I solve this problem? I don’t want to move to the next instance of the app!
Here is my app.xaml.code
public partial class App : Application
{
App()
{
InitializeComponent();
}
[STAThread]
static void Main()
{
SingleInstanceManager manager = new SingleInstanceManager();
manager.Run(new[] { "test" });
}
}
public class SingleInstanceManager : WindowsFormsApplicationBase
{
SingleInstanceApplication app;
public SingleInstanceManager()
{
this.IsSingleInstance = true;
}
protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs e)
{
// First time app is launched
app = new SingleInstanceApplication();
app.Run();
return false;
}
protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
{
// Subsequent launches
base.OnStartupNextInstance(eventArgs);
app.Activate();
}
}
public class SingleInstanceApplication : Application
{
protected override void OnStartup(System.Windows.StartupEventArgs e)
{
base.OnStartup(e);
// Create and show the application's main window
MainWindow window = new MainWindow();
window.Show();
}
public void Activate()
{
// Reactivate application's main window
this.MainWindow.WindowState = WindowState.Normal;
this.MainWindow.Activate();
((MainWindow)this.MainWindow).SpracujStartovacieParametre();
}
}
Here is my solution:
public partial class App : Application
{
App()
{
InitializeComponent();
}
[STAThread]
static void Main()
{
SingleInstanceManager manager = new SingleInstanceManager();
//manager.Run(new[] { "test" });
manager.Run(Environment.GetCommandLineArgs());
}
}
public class SingleInstanceManager : WindowsFormsApplicationBase
{
SingleInstanceApplication app;
public SingleInstanceManager()
{
this.IsSingleInstance = true;
}
protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs e)
{
// First time app is launched
app = new SingleInstanceApplication();
app.Run();
return false;
}
protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
{
// Subsequent launches
base.OnStartupNextInstance(eventArgs);
//MessageBox.Show("Event arguments:"+ eventArgs.ToString());
app.Activate(eventArgs.CommandLine.ToArray<string>());
}
}
public class SingleInstanceApplication : Application
{
protected override void OnStartup(System.Windows.StartupEventArgs e)
{
base.OnStartup(e);
// Create and show the application's main window
MainWindow window = new MainWindow();
window.Show();
}
public void Activate(string[] eventArgs)
{
((MainWindow)this.MainWindow).SpracujCommandLineArgs(eventArgs);
this.MainWindow.WindowState = WindowState.Maximized;
this.MainWindow.Activate();
}
}
Related
I have to add functionality on the App.xaml.cs to get this to work. I added functionality on OnStart but now it logs me out of the app over and over again intermittently. What do I need to do to get it to stop doing this based on my code below. Or is there a problem at all with my code. Here is my latest code:
namespace MyApp
{
public partial class App : Application
{
DateTime _sessionStart;
public App()
{
InitializeComponent();
DatabaseManager = new DatabaseManager(new DatabaseService());
HttpManager = new HttpManager(new HTTPService());
MainPage = new NavigationPage(new LoginPage());
}
protected override void OnStart()
{
// Handle when your app starts
_sessionStart = DateTime.Now;
Device.StartTimer(TimeSpan.FromSeconds(60), () =>
{
// Check if 24 hours has elapsed
if (DateTime.Now > _sessionStart.AddHours(24))
{
//logout
MainPage = new NavigationPage(new LoginPage());
}
return true; // True = Repeat again, False = Stop the timer
});
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
Try tracking the idle time (time without touches in the app) by registering a custom application on Main. See example below
Set TimeoutInSeconds value to your desired interval (ex 24 hours)
public class Application
{
// This is the main entry point of the application.
static void Main (string[] args)
{
UIApplication.Main (args, "MYCUSTOMAPP", "AppDelegate");
}
}
[Register ("MYCUSTOMAPP")]
public class MYCUSTOMAPP : UIApplication
{
const int TimeoutInSeconds = 1800; // 30 minutes
NSTimer idleTimer;
public override void SendEvent (UIEvent uievent)
{
base.SendEvent (uievent);
if (idleTimer == null)
ResetTimer ();
var allTouches = uievent.AllTouches;
if (allTouches != null && allTouches.Count > 0 && ((UITouch)allTouches.First ()).Phase == UITouchPhase.Began)
ResetTimer ();
}
void ResetTimer ()
{
if (idleTimer != null)
idleTimer.Invalidate ();
idleTimer = NSTimer.CreateScheduledTimer (new TimeSpan (0, 0, TimeoutInSeconds), (t) => TimerExceeded());
}
void TimerExceeded ()
{
NSNotificationCenter.DefaultCenter.PostNotificationName ("TimeoutNotification", null);
}
}
Add an observer to you view controller to log them out
public override void ViewDidLoad()
{
base.ViewDidLoad();
NSNotificationCenter.DefaultCenter.AddObserver(new NSString("TimeoutNotification"), handleInactivityNotification);
}
public void handleInactivityNotification(NSNotification notification)
{
//Return to login page (Root view controller)
this.NavigationController.PopToRootViewController(true);
}
The problem is that i have some kind of splash screen which shows loading animation.
I have special manager that show and hide it.
class Manager
{
private Form CurForm;
Thread curt;
private Manager()
{
curt= new Thread(start);
curt.ApartmentState = ApartmentState.STA;
curt.IsBackground = true;
curt.Start();
}
void start()
{
CurForm = new Animation();
Application.Run(CurForm);
}
public static readonly Manager Active = new Manager();
public static void Show()
{
if (Active.CurForm != null)
{
Active.CurForm.Invoke(new Action(() => { Active.CurForm.Show(); }));
}
}
public static void Hide()
{
if (Active.CurForm != null)
{
Active.CurForm.Invoke(new Action(() => { Active.CurForm.Hide(); }));
}
}
}
I open some modal form (ShowDialog). This modal form doesn't show in taskbar.
I easily can minimise it and after clicking on main form on task bar it show that modal form on top.
But when I show this loading animation while it's loading all necessary data.
some kind like that (of course it is just a sample to test it work, and in real app it tooks much time to load all data and form with lots of controls)
public modal()
{
Manager.Show();
InitializeComponent();
Thread.Sleep(5000);
Manager.Hide();
}
And when i'm trying to minimise and restore it like i said above it doesn't restore my modal form and just show my main not available form. And more than that it works in some cases but in some not.
Does anybody know why it is happens or how to fix it?
it is strange but when i modify like this, everything seems to work normal.
I just kill separate ui thread.
public class MyApplicationContext:ApplicationContext
{
public Form CurForm;
ManualResetEvent ready = new ManualResetEvent(false);
public MyApplicationContext()
{
CurForm=new Animation();
CurForm.Show();
}
}
class Manager
{
private MyApplicationContext CurContext;
Thread curt;
void start()
{
try
{
CurContext = new MyApplicationContext();
Application.Run(CurContext);
}
catch
{
CurContext.CurForm.Close();
}
}
private void Init()
{
curt = new Thread(start);
curt.SetApartmentState(ApartmentState.STA);
curt.IsBackground = true;
curt.Start();
}
public static Manager Active
{
get
{
if (active == null)
{
active = new Manager();
}
return active;
}
}
private static Manager active;
public static void Show()
{
Active.Init();
}
public static void Hide()
{
Active.curt.Abort();
}
I have an application in C# which creates a form and stack it in front of another app's window.
I do this by using SetParent. However, the (new) parent window freezes.
How can I solve that? Is this a matter of threading?
This is working:
private void Test(object sender, EventArgs e)
{
FormCover cov = new FormCover();
IntPtr hwnd = Win32Utils.FindWindowByCaptionStart(IntPtr.Zero, TrackerName, null);
Win32Utils.SetParent(cov.Handle, hwnd);
cov.SetDesktopLocation(0, 0);
cov.Show();
}
But this (with a timer elapsed event) is not:
public partial class Form1 : Form
{
FormCover cover;
void tmrCheck_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
ShowCover();
}
private void ShowCover()
{
cover = new FormCover();
IntPtr hwnd = Win32Utils.FindWindowByCaptionStart(IntPtr.Zero, TrackerName, null);
cover.CoverInitialize(hwnd);
cover.Activate();
}
}
//------
public partial class FormCover : Form
{
public delegate void IntPtrDlg(IntPtr param);
public FormCover()
{
InitializeComponent();
}
internal void CoverInitialize(IntPtr hwdnParent)
{
if (this.InvokeRequired)
{
this.Invoke(new IntPtrDlg(CoverInitialize), new object[] { hwdnParent });
}
else
{
Win32Utils.SetParent(this.Handle, hwdnParent);
this.SetDesktopLocation(0, 0);
}
}
internal void CoverActivate(IntPtr handleFormulario)
{
if (!Visible)
this.Show();
}
internal void CoverFinalize()
{
Hide();
Win32ParentUtils.SetParent(Handle, new IntPtr());
}
}
What is the difference between these two samples? The first one is working fine, the second one is freezing the aprent window.
As I just stated, you'll need to create a message pump for your form.
Try
Thread thread = new Thread( () =>
{
var formCover = new FormCover();
Application.Run(formCover);
});
thread.ApartmentState = ApartmentState.STA;
thread.Start();
Then you should be able to set the parent of your form.
See here for further reference.
I have managed to find the following code from StackOverflow:
using Microsoft.VisualBasic.ApplicationServices;
using System.Windows.Forms;
namespace ExciteEngine2.MainApplication {
public class SingleInstanceController: WindowsFormsApplicationBase {
public delegate Form CreateMainForm();
public delegate void StartNextInstanceDelegate(Form mainWindow);
private readonly CreateMainForm formCreation;
private readonly StartNextInstanceDelegate onStartNextInstance;
public SingleInstanceController() {
}
public SingleInstanceController(AuthenticationMode authenticationMode)
: base(authenticationMode) {
}
public SingleInstanceController(CreateMainForm formCreation, StartNextInstanceDelegate onStartNextInstance) {
// Set whether the application is single instance
this.formCreation = formCreation;
this.onStartNextInstance = onStartNextInstance;
IsSingleInstance = true;
StartupNextInstance += this_StartupNextInstance;
}
private void this_StartupNextInstance(object sender, StartupNextInstanceEventArgs e) {
if (onStartNextInstance != null) {
onStartNextInstance(MainForm);
// This code will be executed when the user tries to start the running program again,
// for example, by clicking on the exe file.
// This code can determine how to re-activate the existing main window of the running application.
}
}
protected override void OnCreateMainForm() {
// Instantiate your main application form
MainForm = formCreation();
}
//public void Run() {
// string[] commandLine = new string[0];
// base.Run(commandLine);
//}
protected override void OnRun() {
base.OnRun();
}
}
}
And I have this in my Program.cs:
private static Form CreateForm() {
return new AppMDIRibbon();
}
private static void OnStartNextInstance(Form mainWindow)
{
// When the user tries to restart the application again, the main window is activated again.
mainWindow.WindowState = FormWindowState.Maximized;
}
[STAThread]
static void Main(string[] args) {
SingleInstanceController ApplicationSingleInstanceController = new SingleInstanceController(CreateForm, OnStartNextInstance);
ApplicationSingleInstanceController.Run(args);
#region Application Logic
#endregion
}
Now, I have a lot of application logic that I need BEFORE the Run():
#region Application Logic
//Uninstall
foreach (string arg in args) {
if (arg.Split('=')[0] == "/u") {
ApplicationLogger.Info("Uninstallation command received.");
Process.Start(new ProcessStartInfo(Environment.GetFolderPath(Environment.SpecialFolder.System) + "\\msiexec.exe", "/x " + arg.Split('=')[1]));
return;
}
}
SetupXPO();
SetupLogging();
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-GB");
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.ThreadException += Application_ThreadException;
try {
ApplicationLogger.Info("Setting Telerik Theme: " + ConfigurationManager.AppSettings["ThemeToUse"]);
ThemeResolutionService.ApplicationThemeName = ConfigurationManager.AppSettings["ThemeToUse"];
}
catch (Exception ex) {
ApplicationLogger.Error("Exception while setting Telerik Theme.", ex);
ThemeResolutionService.ApplicationThemeName = "ControlDefault";
}
DevExpress.UserSkins.OfficeSkins.Register();
DevExpress.UserSkins.BonusSkins.Register();
DevExpress.Skins.SkinManager.EnableFormSkins();
DevExpress.Skins.SkinManager.EnableMdiFormSkins();
if (args.Contains("/dx")) {
Application.Run(new AppMDIRibbonDX());
ApplicationLogger.Info("Application (DX) started.");
}
else {
Application.Run(new AppMDIRibbon());
ApplicationLogger.Info("Application started.");
}
#endregion
How can I setup this logic? I'm using a commandline argument to actually start an alternate form. I'm using a commandline argument to cause an uninstallation and also calling some method to setup DB and logging. Similarly, I'm setting up culture and themes too. All this before the actual application run. Can anyone suggest?
If you simplify the Visual Basic-derived class you linked, you can just replace your current call to Application.Run(). This does depend on how you want to handle subsequent instances.
With the version below, just change you calls of: Application.Run(myForm) to SingleInstanceApplication.Run(myForm);
public sealed class SingleInstanceApplication : WindowsFormsApplicationBase
{
private static SingleInstanceApplication _application;
private SingleInstanceApplication()
{
base.IsSingleInstance = true;
}
public static void Run(Form form)
{
_application = new SingleInstanceApplication {MainForm = form};
_application.StartupNextInstance += NextInstanceHandler;
_application.Run(Environment.GetCommandLineArgs());
}
static void NextInstanceHandler(object sender, StartupNextInstanceEventArgs e)
{
// Do whatever you want to do when the user launches subsequent instances
// like when the user tries to restart the application again, the main window is activated again.
_application.MainWindow.WindowState = FormWindowState.Maximized;
}
}
Then your Main() method contains your "Application Logic"
[STAThread]
static void Main(string[] args) {
#region Application Logic
//Uninstall
foreach (string arg in args) {
if (arg.Split('=')[0] == "/u") {
ApplicationLogger.Info("Uninstallation command received.");
Process.Start(new ProcessStartInfo(Environment.GetFolderPath(Environment.SpecialFolder.System) + "\\msiexec.exe", "/x " + arg.Split('=')[1]));
return;
}
}
SetupXPO();
SetupLogging();
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-GB");
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.ThreadException += Application_ThreadException;
try {
ApplicationLogger.Info("Setting Telerik Theme: " + ConfigurationManager.AppSettings["ThemeToUse"]);
ThemeResolutionService.ApplicationThemeName = ConfigurationManager.AppSettings["ThemeToUse"];
}
catch (Exception ex) {
ApplicationLogger.Error("Exception while setting Telerik Theme.", ex);
ThemeResolutionService.ApplicationThemeName = "ControlDefault";
}
DevExpress.UserSkins.OfficeSkins.Register();
DevExpress.UserSkins.BonusSkins.Register();
DevExpress.Skins.SkinManager.EnableFormSkins();
DevExpress.Skins.SkinManager.EnableMdiFormSkins();
if (args.Contains("/dx")) {
SingleInstanceApplication.Run(new AppMDIRibbonDX());
ApplicationLogger.Info("Application (DX) started.");
}
else {
SingleInstanceApplication.Run(new AppMDIRibbon());
ApplicationLogger.Info("Application started.");
}
#endregion
}
I got the following code to run the application at windows startup:
private void SetStartup(string AppName, bool enable)
{
string runKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
Microsoft.Win32.RegistryKey startupKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(runKey);
if (enable)
{
if (startupKey.GetValue(AppName) == null)
{
startupKey.Close();
startupKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(runKey, true);
startupKey.SetValue(AppName, Application.ExecutablePath.ToString());
startupKey.Close();
}
}
else
{
startupKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(runKey, true);
startupKey.DeleteValue(AppName, false);
startupKey.Close();
}
}
It works. but I want the program to start minimized (at windows startup only).
I didnt find a working code / good explanation how to do it.
Can you help me please?
thanks.
Have you tried
this.WindowState = FormWindowState.Minimized;
If you want to start minimized at windows startup only you can add extra argument to command line, like myapp.exe --start-minimized, then you can parse this parameter and detect whether you need to start minimized or not.
Since this is only adding a registry key to SOFTWARE\Microsoft\Windows\CurrentVersion\Run which causes the OS to start the app at startup there isn't a lot you can do unless the application you want to startup accepts a command line parameter to start minimized (You could then add the parameter to the executable path of the key).
If this is a necessary function and you can't modify the program to accept a parameter to minimize the only thing I can think of doing would be to write a program that would minimize these apps after the OS has started them.
Don't normally revive old threads but one Easy way including minimize to system tray, for WPF like this:
public class EntryPoint
{
[STAThread]
public static void Main(string[] args)
{
SingleInstanceManager manager = new SingleInstanceManager();
manager.Run(args);
}
}
public class SingleInstanceManager : WindowsFormsApplicationBase
{
SingleInstanceApplication app;
public SingleInstanceManager()
{
this.IsSingleInstance = true;
}
protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs e)
{
app = new SingleInstanceApplication();
app.Run();
return false;
}
protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
{
base.OnStartupNextInstance(eventArgs);
app.Activate();
}
}
public class SingleInstanceApplication : Application
{
protected override void OnStartup(System.Windows.StartupEventArgs e)
{
base.OnStartup(e);
bool startMinimized = false;
for (int i = 0; i != e.Args.Length; ++i)
{
if (e.Args[i] == "/StartMinimized")
{
startMinimized = true;
}
}
MainWindow mainWindow = new MainWindow();
if (startMinimized)
{
mainWindow.WindowState = WindowState.Minimized;
}
mainWindow.Show();
}
public void Activate()
{
this.MainWindow.Activate();
this.MainWindow.WindowState = WindowState.Normal;
}
}
}
Your Window class:
public partial class MainWindow : Window
{
private Window _window;
public MainWindow()
{
InitializeComponent();
SetStartup("AppName", true);
}
private void SetStartup(string AppName, bool enable)
{
string runKey = #"SOFTWARE\Microsoft\Windows\CurrentVersion\Run";
Microsoft.Win32.RegistryKey startupKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(runKey);
if (enable)
{
if (startupKey.GetValue(AppName) == null)
{
startupKey.Close();
startupKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(runKey, true);
startupKey.SetValue(AppName, Assembly.GetExecutingAssembly().Location + " /StartMinimized");
startupKey.Close();
}
}
else
{
startupKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(runKey, true);
startupKey.DeleteValue(AppName, false);
startupKey.Close();
}
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
if (this.WindowState == System.Windows.WindowState.Minimized)
{
var minimized = (_window.WindowState == WindowState.Minimized);
_window.ShowInTaskbar = !minimized;
}
else
ShowInTaskbar = true;
}
Worked first time so had to post. I'm using WPF notifyicon, hence why i needed it to go to system tray on windows startup.
Had a really hard time finding a good answer to this, finally found it in a really old book. On my Forms application, just opened the program.cs and changed
Application.Run(new Form1());
to
Form1 f = new Form1();
f.WindowState = FormWindowState.Minimized;
f.ShowInTaskbar = false;
Application.Run(f);
and it opens without a flicker directly to the tray. This app was more just a service, so set it to just have a notify icon and exit button when right clicked. Hope this helps!!
I have strugled with the same issue, and found a working solution:
In your program.cs, handle the parameter, and then pass that parameter to Form1:
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
if (args.Length != 0){
Application.Run(new Form1(args[0]));
}
else
{
Application.Run(new Form1("normalState"));
}
}
In your Form1.cs, you can call a function with the passed parameter and minimize the app:
public Form1(string parameter)
{
InitializeComponent();
MinimizeApp(parameter);
}
For example, with this function i used, if you start the application with the -minimized parameter, then it will start minimized, a notifyicon pops up in the taskbar and a bubble saying the app is started and running in the background.
public void MinimizeApp(string parameter)
{
if (parameter == "-minimized")
{
this.WindowState = FormWindowState.Minimized;
notifyIcon1.Visible = true;
notifyIcon1.BalloonTipText = "Program is started and running in the background...";
notifyIcon1.ShowBalloonTip(500);
Hide();
}
}