0

I need to call addDownload() method that is inside the main application class MainWindow.xaml.cs from App.xaml.cs

Some info about the Application:

  • In my App.xaml.cs i have code to run only one instance of the application. (Not my Code. I found it)

    using System;
    using System.Diagnostics;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Threading;
    using System.Windows;
    using DownloadManager;
    namespace DownloadManager
    {
        public partial class App : Application
    {
        private static readonly Semaphore singleInstanceWatcher;
        private static readonly bool createdNew;
    
        static App()
        {
            // Ensure other instances of this application are not running.
            singleInstanceWatcher = new Semaphore(
                0, // Initial count.
                1, // Maximum count.
                Assembly.GetExecutingAssembly().GetName().Name,
                out createdNew);
    
    
    
            if (createdNew)
            {
                // This thread created the kernel object so no other instance
                // of this application must be running.
            }
            else
            {
            // This thread opened an existing kernel object with the same
            // string name; another instance of this app must be running now.
    
            // Gets a new System.Diagnostics.Process component and the
            // associates it with currently active process.
                Process current = Process.GetCurrentProcess();
    
                foreach (Process process in
                     Process.GetProcessesByName(current.ProcessName))
                {
                    if (process.Id != current.Id)
                    {
                        NativeMethods.SetForegroundWindow(
                            process.MainWindowHandle);
                        NativeMethods.ShowWindow(process.MainWindowHandle,
                            WindowShowStyle.Restore);
                        break;
                    }
                }
    
                // Terminate this process and gives the underlying operating 
                // system the specified exit code.
                Environment.Exit(-2);
            }
        }
    
        private static class NativeMethods
        {
            [DllImport("user32.dll")]
            internal static extern bool SetForegroundWindow(IntPtr hWnd);
            [DllImport("user32.dll")]
            internal static extern bool ShowWindow(IntPtr hWnd,
                WindowShowStyle nCmdShow);
        }
    
        /// <summary>
        /// Enumeration of the different ways of showing a window.</summary>
        internal enum WindowShowStyle : uint
        {
            Hide = 0,
            ShowNormal = 1,
            ShowMinimized = 2,
            ShowMaximized = 3,
            Maximize = 3,
            ShowNormalNoActivate = 4,
            Show = 5,
            Minimize = 6,
            ShowMinNoActivate = 7,
            ShowNoActivate = 8,
            Restore = 9,
            ShowDefault = 10,
            ForceMinimized = 11
        }
    }
    }
    
  • I need to pass Command Line Parameters to addDownload() method every time, whether the application is already running or not.

What i've tried so far:

  • First, i deleted the Startup entry point in App.xaml, so i can manage it inside code-behind

  • Then, if the Application is not running, create a new instance of MainWindow, and show it:

    MainWindow MW = new MainWindow();
    MW.Show();
    
  • Get Command Line Parameters, and pass it to the addDownload() method:

    string[] args = Environment.GetCommandLineArgs();
    if(args.Length > 1)
    {
        MW.addDownload(args[1]);
    }
    

Ok, this part work perfectly.

But as i say, i need to pass Command Line Parameters also if the application is already running. Getting the command line parameters it's the same as before, but passing it to the addDownload() method of the current MainWindow instance, is not, and i have troubles to find a working way;

I tried:

try
{
    var main = App.Current.MainWindow as MainWindow;
    string[] args = Environment.GetCommandLineArgs();
    if (args.Length > 1)
    {
        main.addDownload(args[1]);
    }
}
catch(Exception ex)
{
    MessageBox.Show(String.Format("{0}\n{1}", ex.GetType().ToString(), ex.Message));
}

But i get a NullReferenceException.. i think on the main declaration.. I don't know how to debug this particular situation inside Visual Studio.

Any help? What i'm doing wrong?

Fr0z3n
  • 1,569
  • 1
  • 18
  • 39
  • How do you pass command arguments to an application that is already running, if you call app.exe with args when app.exe is already running it just starts a new app.exe, it does not run the code in the existing app.exe – sa_ddam213 Aug 28 '13 at 01:10
  • I think it does instead, i tried to add args[1] on the Exception MessageBox, and by checking with different parameters, they all get displayed inside the MessageBox along the Exception. If it was opening a new app.exe then there was no exception, because it works the first time i open the app. – Fr0z3n Aug 28 '13 at 01:15
  • When you start app.exe you start a NEW app.exe you don't enter the existing app.exe, you can't directly access the first process from the second process – sa_ddam213 Aug 28 '13 at 01:17
  • Ok, i understood, it check if there is a process running, and since there is, the code is running, but on a different process where MainWindow it's not initialized. Thank you.. – Fr0z3n Aug 28 '13 at 01:20

1 Answers1

0

You get a NullReferenceException because you are wanting to access an instance of an object (MainWindow) that exists in a different process, and you can't do that. What you need to do is some sort of InterProcess communication, there are many ways to do this, one of which is to use .NET remoting (probably not the best way).

Here are a few links that turned up with a quick search:

http://www.codeproject.com/Articles/17606/NET-Interprocess-Communication

What is the best choice for .NET inter-process communication?

http://msdn.microsoft.com/en-us/library/kwdt6w2k(v=vs.100).aspx

Community
  • 1
  • 1
CodingGorilla
  • 19,612
  • 4
  • 45
  • 65
  • Thanks, Is this the only solution? many app have "Open with" option, and if the app is already running, it's just open that file inside the running process... They use inter-process? – Fr0z3n Aug 28 '13 at 01:25
  • The "Open with" is actually a function of windows (assuming you're talking about Right Click -> Open with...). But yes, you *cannot* access the code executing in another process. So you have to communicate with that other process through the methods provided by the operating system, and there are a lot of those, the 3 I linked are just a few. – CodingGorilla Aug 28 '13 at 01:43
  • Yes i know it's a Windows function, but since "Open With" create a new process using parameters, the opened app need to handle that, and i asked how they do. But i understand now, i'm trying a library i found called XDMessaging. Seems exactly what i need. – Fr0z3n Aug 28 '13 at 01:54