Question

I have deployed a ClickOnce Windows Forms application (App A)

Another application (App B) starts App A with a filename as parameter. I do this with this Code

var basePath = Environment.GetFolderPath(Environment.SpecialFolder.Programs);
var location = String.Format(@"{0}\{1}\{2}\{3}",
    basePath, "MyCompany", "MyProduct", "MyApp.appref-ms");

var fileName = @"c:\temp\somefile.ext";
var uri = new Uri(fileName).ToString();

Process.Start(location, uri);

App A grabs the file name from AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData[0] and show the content.

This works like a charm. However, now I want App B to wait for App A to exit. But a call to Process.WaitForExit() returns instantly.

Is there a way to open a ClickOnce App and wait for it to exit? I can, if necessary, change the way the app is opend but the requirement is that I need to run the app as a ClickOnce app (I know that somewhere in my user profile AppData\Local\Apps\2.0\ folder the exe exists and can be started directly but If I do that ApplicationDeployment.IsNetworkDeployed is false and ApplicationDeployment.CurrentDeployment is null. In that I loose the ClickOnce Update Capabilities).

Was it helpful?

Solution

my suggestion would be to use Mutex in App A, and let App B check and wait for it. This is the cleanest way from my point of view.

App A does this when starts:

    private static Mutex mutex;

    public static void Main()
    {
        // if you want your app to be limited to a single instance
        // across ALL SESSIONS (multiple users & terminal services), then use the following line instead:
        // string mutexName = string.Format("Global\\{0}", ProgramInfo.AssemblyGuid);
        var mutexName = string.Format("Local\\{0}", SOME_SHARED_GUID);
        mutex = new Mutex(true, mutexName, out singleInstance);

        if (singleInstance == false)
        {

           // that means your app has more than one instance running
           // you need to decide what to do here.
        }

        // rest of initialization code

        Application.Run();

        // release the mutex so App B can continue
        mutex.ReleaseMutex();
    }

and App B just waits for the mutex to be released:

Process.Start(location, uri);
Thread.Sleep(5000);  // give it 5 seconds or so to check for updates and start
var mutexName = string.Format("Local\\{0}", SOME_SHARED_GUID);
mutex = new Mutex(false, mutexName);
mutex.WaitOne();

OTHER TIPS

The problem is that starting the appref-ms process does not actually start the application it starts the deployment manifest, which then launches the application itself, so the process you are starting exits straight away.

You can add a check to see when you application has started if you know the name (which I assume you do) like this:

string myAppName = "YourAppName";
DateTime startTime = DateTime.Now;
int newProcessId = 0;
List<int> runningProcessIds = new List<int>();

//find all the running processes and record their Ids
foreach (void proc_loopVariable in Process.GetProcessesByName(myAppName)) {
    proc = proc_loopVariable;
    runningProcessIds.Add(proc.Id);
}

//start the new process
Process.Start(location);

//wait for the new application to be started
while (!(Process.GetProcessesByName(myAppName).Count != runningProcessIds.Count)) {
    //timeout if we have not seen the application start
    if ((DateTime.Now - startTime).TotalSeconds > 30)
        break; 
}

//loop through all the running processes again to find the id of the one that has just started
foreach (void proc_loopVariable in Process.GetProcessesByName(myAppName)) {
    proc = proc_loopVariable;
    if (!runningProcessIds.Contains(proc.Id)) {
        newProcessId = proc.Id;
        break; 
    }
}

//wait for the application to finish
Process.GetProcessById(newProcessId).WaitForExit();

Debug.WriteLine("Finished");
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top