////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public Task <DebugLaunchSettings> StartWithoutDebugging(int launchOptions, LaunchConfiguration launchConfig, ICollection <LaunchProps> launchProps, IDictionary <string, string> projectProperties)
        {
            LoggingUtils.PrintFunction();

            if (launchConfig == null)
            {
                throw new ArgumentNullException(nameof(launchConfig));
            }

            if (launchProps == null)
            {
                throw new ArgumentNullException(nameof(launchProps));
            }

            if (projectProperties == null)
            {
                throw new ArgumentNullException(nameof(projectProperties));
            }

            //
            // Refresh ADB service and evaluate a list of connected devices or emulators.
            //

            AndroidAdb.Refresh();

            AndroidDevice debuggingDevice = GetPrioritisedConnectedDevice() ?? throw new InvalidOperationException("No device/emulator found or connected. Check status using \"adb devices\".");

            //
            // Construct VS launch settings to debug or attach to the specified target application.
            //

            launchOptions |= (int)DebugLaunchOptions.Silent;

            DebugLaunchSettings nonDebuglaunchSettings = new DebugLaunchSettings((DebugLaunchOptions)launchOptions);

            nonDebuglaunchSettings.LaunchDebugEngineGuid = new Guid("8310DAF9-1043-4C8E-85A0-FF68896E1922");

            nonDebuglaunchSettings.PortSupplierGuid = new Guid("3AEE417F-E5F9-4B89-BC31-20534C99B7F5");

            nonDebuglaunchSettings.PortName = debuggingDevice.ID;

            nonDebuglaunchSettings.Options = launchConfig.ToString();

            nonDebuglaunchSettings.Executable = launchConfig ["TargetApk"];

            nonDebuglaunchSettings.LaunchOperation = DebugLaunchOperation.Custom;

            return(Task.FromResult(nonDebuglaunchSettings));
        }
Exemplo n.º 2
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public object StartWithoutDebugging(int launchOptionsFlags, LaunchConfiguration launchConfig, LaunchProps [] launchProps, IDictionary <string, string> projectProperties)
        {
            LoggingUtils.PrintFunction();

            try
            {
                //
                // Refresh ADB service and evaluate a list of connected devices or emulators.
                //

                AndroidAdb.Refresh();

                AndroidDevice debuggingDevice = GetPriortisedConnectedDevice();

                if (debuggingDevice == null)
                {
                    throw new InvalidOperationException("No device/emulator found or connected. Check status via 'adb devices'.");
                }

                //
                // Construct VS launch settings to debug or attach to the specified target application.
                //

                launchOptionsFlags |= (int)DebugLaunchOptions.Silent;

                DebugLaunchSettings nonDebuglaunchSettings = new DebugLaunchSettings((DebugLaunchOptions)launchOptionsFlags);

                nonDebuglaunchSettings.LaunchDebugEngineGuid = new Guid("8310DAF9-1043-4C8E-85A0-FF68896E1922");

                nonDebuglaunchSettings.PortSupplierGuid = new Guid("3AEE417F-E5F9-4B89-BC31-20534C99B7F5");

                nonDebuglaunchSettings.PortName = debuggingDevice.ID;

                nonDebuglaunchSettings.Options = launchConfig.ToString();

                nonDebuglaunchSettings.Executable = launchConfig ["TargetApk"];

                nonDebuglaunchSettings.LaunchOperation = DebugLaunchOperation.Custom;

                return(nonDebuglaunchSettings);
            }
            catch (Exception e)
            {
                LoggingUtils.HandleException(e);

                throw;
            }
        }
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public async Task <DebugLaunchSettings> StartWithDebugging(int launchOptions, LaunchConfiguration launchConfig, ICollection <LaunchProps> launchProps, IDictionary <string, string> projectProperties)
        {
            LoggingUtils.PrintFunction();

            if (launchConfig == null)
            {
                throw new ArgumentNullException(nameof(launchConfig));
            }

            if (launchProps == null)
            {
                throw new ArgumentNullException(nameof(launchProps));
            }

            if (projectProperties == null)
            {
                throw new ArgumentNullException(nameof(projectProperties));
            }

            //
            // Refresh ADB service and evaluate a list of connected devices or emulators.
            //

            AndroidAdb.Refresh();

            AndroidDevice debuggingDevice = GetPrioritisedConnectedDevice() ?? throw new InvalidOperationException("No device/emulator found or connected. Check status using \"adb devices\".");

            //
            // Enforce required device/emulator properties.
            //

            foreach (var prop in launchProps)
            {
                debuggingDevice.Shell("setprop", string.Format(CultureInfo.InvariantCulture, "{0} {1}", prop.Item1, prop.Item2));
            }

            //
            // Construct VS launch settings to debug or attach to the specified target application.
            //

            bool shouldAttach = false;

#if false
            AndroidProcess [] debuggingDeviceProcesses = debuggingDevice.GetProcesses();

            foreach (AndroidProcess process in debuggingDeviceProcesses)
            {
                if (process.Name.Equals(applicationPackageName))
                {
                    shouldAttach = true;

                    break;
                }
            }
#endif

            launchOptions |= (int)DebugLaunchOptions.Silent;

            DebugLaunchSettings debugLaunchSettings = new DebugLaunchSettings((DebugLaunchOptions)launchOptions);

            debugLaunchSettings.LaunchDebugEngineGuid = new Guid("8310DAF9-1043-4C8E-85A0-FF68896E1922");

            debugLaunchSettings.PortSupplierGuid = new Guid("3AEE417F-E5F9-4B89-BC31-20534C99B7F5");

            debugLaunchSettings.PortName = debuggingDevice.ID;

            debugLaunchSettings.Options = launchConfig.ToString();

            if (shouldAttach)
            {
                debugLaunchSettings.Executable = launchConfig ["PackageName"];

                debugLaunchSettings.LaunchOperation = DebugLaunchOperation.AlreadyRunning;
            }
            else
            {
                //
                // Determine whether the application is currently installed, and if it is;
                // check last modified date to ensure we don't re-installed unchanged binaries.
                //

                bool upToDateCheck = launchConfig ["UpToDateCheck"].Equals("true");

                bool appIsInstalled = false;

                bool appIsOutOfDate = true;

                if (upToDateCheck)
                {
                    FileInfo targetApkFileInfo = new FileInfo(launchConfig ["TargetApk"]);

                    try
                    {
                        var adbPmPathOutput = debuggingDevice.Shell("pm", "path " + launchConfig ["PackageName"]).Replace("\r", "").Split(new char [] { '\n' }, StringSplitOptions.RemoveEmptyEntries);

                        foreach (string line in adbPmPathOutput)
                        {
                            if (line.StartsWith("package:", StringComparison.OrdinalIgnoreCase))
                            {
                                appIsInstalled = true;

                                LoggingUtils.RequireOk(await m_debugConnectionService.LaunchDialogUpdate(string.Format(CultureInfo.InvariantCulture, "'{0}' already installed on target '{1}'.", launchConfig ["PackageName"], debuggingDevice.ID), false));

                                string path = line.Substring("package:".Length);

                                //
                                // Get the target device/emulator's UTC current time.
                                //
                                //   This is done by specifying the '-u' argument to 'date'. Despite this though,
                                //   the returned string will always claim to be in GMT:
                                //
                                //   i.e: "Fri Jan  9 14:35:23 GMT 2015"
                                //

                                DateTime debuggingDeviceUtcTime;

                                try
                                {
                                    var deviceDateOutput = debuggingDevice.Shell("date", "-u").Replace("\r", "").Split(new char [] { '\n' }, StringSplitOptions.RemoveEmptyEntries);

                                    string debuggingDeviceUtcTimestamp = deviceDateOutput [0];

                                    var debuggingDeviceUtcTimestampComponents = debuggingDeviceUtcTimestamp.Split(new char [] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                                    debuggingDeviceUtcTimestampComponents [4] = "-00:00";

                                    if (!DateTime.TryParseExact(string.Join(" ", debuggingDeviceUtcTimestampComponents), "ddd MMM  d HH:mm:ss zzz yyyy", CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out debuggingDeviceUtcTime))
                                    {
                                        break;
                                    }

                                    debuggingDeviceUtcTime = debuggingDeviceUtcTime.ToUniversalTime();
                                }
                                catch (Exception e)
                                {
                                    throw new InvalidOperationException("Failed to evaluate device local time.", e);
                                }

                                //
                                // Convert current device/emulator time to UTC, and probe the working machine's time too.
                                //

                                DateTime thisMachineUtcTime = DateTime.UtcNow;

                                TimeSpan thisMachineUtcVersusDeviceUtc = debuggingDeviceUtcTime - thisMachineUtcTime;

                                await m_debugConnectionService.LaunchDialogUpdate(string.Format(CultureInfo.InvariantCulture, "Current UTC time on '{0}': {1}", debuggingDevice.ID, debuggingDeviceUtcTime.ToString()), false);

                                await m_debugConnectionService.LaunchDialogUpdate(string.Format(CultureInfo.InvariantCulture, "Current UTC time on '{0}': {1}", System.Environment.MachineName, thisMachineUtcTime.ToString()), false);

                                await m_debugConnectionService.LaunchDialogUpdate(string.Format(CultureInfo.InvariantCulture, "Difference in UTC time between '{0}' and '{1}': {2}", System.Environment.MachineName, debuggingDevice.ID, thisMachineUtcVersusDeviceUtc.ToString()), false);

                                //
                                // Check the last modified date; ls output currently uses this format:
                                //
                                // -rw-r--r-- system   system   11533274 2015-01-09 13:47 com.example.native_activity-2.apk
                                //

                                DateTime lastModifiedTimestampDeviceLocalTime;

                                try
                                {
                                    var extendedLsOutput = debuggingDevice.Shell("ls -l", path).Replace("\r", "").Split(new char [] { '\n' }, StringSplitOptions.RemoveEmptyEntries);

                                    var extendedLsOutputComponents = extendedLsOutput [0].Split(new char [] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                                    string date = extendedLsOutputComponents [4];

                                    string time = extendedLsOutputComponents [5];

                                    if (!DateTime.TryParseExact(date + " " + time, "yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out lastModifiedTimestampDeviceLocalTime))
                                    {
                                        break;
                                    }
                                }
                                catch (Exception e)
                                {
                                    throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Failed to evaluate device local modified time of: {0}", path), e);
                                }

                                //
                                // Calculate how long ago the APK was changed, according to the device's local time.
                                //

                                TimeSpan timeSinceLastModification = debuggingDeviceUtcTime - lastModifiedTimestampDeviceLocalTime;

                                DateTime debuggingDeviceUtcTimeAtLastModification = debuggingDeviceUtcTime - timeSinceLastModification;

                                DateTime thisMachineUtcTimeAtLastModification = thisMachineUtcTime - timeSinceLastModification;

                                await m_debugConnectionService.LaunchDialogUpdate(string.Format(CultureInfo.InvariantCulture, "'{0}' was last modified on '{1}' at: {2}.", launchConfig ["PackageName"], debuggingDevice.ID, debuggingDeviceUtcTimeAtLastModification.ToString()), false);

                                await m_debugConnectionService.LaunchDialogUpdate(string.Format(CultureInfo.InvariantCulture, "{0} (on {1}) was around {2} (on {3}).", debuggingDeviceUtcTimeAtLastModification.ToString(), debuggingDevice.ID, thisMachineUtcTimeAtLastModification.ToString(), System.Environment.MachineName), false);

                                await m_debugConnectionService.LaunchDialogUpdate(string.Format(CultureInfo.InvariantCulture, "'{0}' was last modified on '{1}' at: {2}.", Path.GetFileName(targetApkFileInfo.FullName), System.Environment.MachineName, targetApkFileInfo.LastWriteTime.ToString()), false);

                                if ((targetApkFileInfo.LastWriteTime + thisMachineUtcVersusDeviceUtc) > thisMachineUtcTimeAtLastModification)
                                {
                                    await m_debugConnectionService.LaunchDialogUpdate(string.Format(CultureInfo.InvariantCulture, "'{0}' was determined to be out-of-date. Reinstalling...", launchConfig ["PackageName"]), false);
                                }
                                else
                                {
                                    appIsOutOfDate = false;
                                }

                                break;
                            }
                        }
                    }
                    catch (Exception)
                    {
                        appIsInstalled = false;
                    }
                }
                else
                {
                    await m_debugConnectionService.LaunchDialogUpdate("Skipping up-to-date check.", false);
                }

                if (!appIsInstalled || appIsOutOfDate)
                {
                    await m_debugConnectionService.LaunchDialogUpdate(string.Format(CultureInfo.InvariantCulture, "Installing '{0}' to '{1}'...", launchConfig ["PackageName"], debuggingDevice.ID), false);

                    InstallApplicationAsync(debuggingDevice, launchConfig);

                    await m_debugConnectionService.LaunchDialogUpdate(string.Format(CultureInfo.InvariantCulture, "'{0}' installed successfully.", launchConfig ["PackageName"]), false);
                }
                else
                {
                    await m_debugConnectionService.LaunchDialogUpdate(string.Format(CultureInfo.InvariantCulture, "'{0}' on '{1}' is up-to-date. Skipping installation...", launchConfig ["PackageName"], debuggingDevice.ID), false);
                }

                debugLaunchSettings.Executable = launchConfig ["TargetApk"];

                debugLaunchSettings.LaunchOperation = DebugLaunchOperation.Custom;
            }

            return(debugLaunchSettings);
        }
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        public object StartWithoutDebugging(int launchOptions, LaunchConfiguration launchConfig, LaunchProps [] launchProps, IDictionary<string, string> projectProperties)
        {
            LoggingUtils.PrintFunction ();

              if (launchConfig == null)
              {
            throw new ArgumentNullException ("launchConfig");
              }

              if (launchProps == null)
              {
            throw new ArgumentNullException ("launchProps");
              }

              if (projectProperties == null)
              {
            throw new ArgumentNullException ("projectProperties");
              }

              try
              {
            //
            // Refresh ADB service and evaluate a list of connected devices or emulators.
            //

            AndroidAdb.Refresh ();

            AndroidDevice debuggingDevice = GetPrioritisedConnectedDevice ();

            if (debuggingDevice == null)
            {
              throw new InvalidOperationException ("No device/emulator found or connected. Check status using \"adb devices\".");
            }

            //
            // Construct VS launch settings to debug or attach to the specified target application.
            //

            launchOptions |= (int) DebugLaunchOptions.Silent;

            DebugLaunchSettings nonDebuglaunchSettings = new DebugLaunchSettings ((DebugLaunchOptions) launchOptions);

            nonDebuglaunchSettings.LaunchDebugEngineGuid = new Guid ("8310DAF9-1043-4C8E-85A0-FF68896E1922");

            nonDebuglaunchSettings.PortSupplierGuid = new Guid ("3AEE417F-E5F9-4B89-BC31-20534C99B7F5");

            nonDebuglaunchSettings.PortName = debuggingDevice.ID;

            nonDebuglaunchSettings.Options = launchConfig.ToString ();

            nonDebuglaunchSettings.Executable = launchConfig ["TargetApk"];

            nonDebuglaunchSettings.LaunchOperation = DebugLaunchOperation.Custom;

            return nonDebuglaunchSettings;
              }
              catch (Exception e)
              {
            LoggingUtils.HandleException (e);

            throw;
              }
        }
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        public object StartWithDebugging(int launchOptions, LaunchConfiguration launchConfig, LaunchProps [] launchProps, IDictionary<string, string> projectProperties)
        {
            LoggingUtils.PrintFunction ();

              if (launchConfig == null)
              {
            throw new ArgumentNullException ("launchConfig");
              }

              if (launchProps == null)
              {
            throw new ArgumentNullException ("launchProps");
              }

              if (projectProperties == null)
              {
            throw new ArgumentNullException ("projectProperties");
              }

              try
              {
            //
            // Refresh ADB service and evaluate a list of connected devices or emulators.
            //

            AndroidAdb.Refresh ();

            AndroidDevice debuggingDevice = GetPrioritisedConnectedDevice ();

            if (debuggingDevice == null)
            {
              throw new InvalidOperationException ("No device/emulator found or connected. Check status using \"adb devices\".");
            }

            //
            // Enforce required device/emulator properties.
            //

            foreach (LaunchProps prop in launchProps)
            {
              debuggingDevice.Shell ("setprop", string.Format (CultureInfo.InvariantCulture, "{0} {1}", prop.Item1, prop.Item2));
            }

            //
            // Construct VS launch settings to debug or attach to the specified target application.
            //

            bool shouldAttach = false;

            #if false
            AndroidProcess [] debuggingDeviceProcesses = debuggingDevice.GetProcesses ();

            foreach (AndroidProcess process in debuggingDeviceProcesses)
            {
              if (process.Name.Equals (applicationPackageName))
              {
            shouldAttach = true;

            break;
              }
            }
            #endif

            launchOptions |= (int) DebugLaunchOptions.Silent;

            DebugLaunchSettings debugLaunchSettings = new DebugLaunchSettings ((DebugLaunchOptions) launchOptions);

            debugLaunchSettings.LaunchDebugEngineGuid = new Guid ("8310DAF9-1043-4C8E-85A0-FF68896E1922");

            debugLaunchSettings.PortSupplierGuid = new Guid ("3AEE417F-E5F9-4B89-BC31-20534C99B7F5");

            debugLaunchSettings.PortName = debuggingDevice.ID;

            debugLaunchSettings.Options = launchConfig.ToString ();

            if (shouldAttach)
            {
              debugLaunchSettings.Executable = launchConfig ["PackageName"];

              debugLaunchSettings.LaunchOperation = DebugLaunchOperation.AlreadyRunning;
            }
            else
            {
              //
              // Determine whether the application is currently installed, and if it is;
              // check last modified date to ensure we don't re-installed unchanged binaries.
              //

              bool upToDateCheck = launchConfig ["UpToDateCheck"].Equals ("true");

              bool appIsInstalled = false;

              bool appIsOutOfDate = true;

              if (upToDateCheck)
              {
            FileInfo targetApkFileInfo = new FileInfo (launchConfig ["TargetApk"]);

            try
            {
              string [] adbPmPathOutput = debuggingDevice.Shell ("pm", "path " + launchConfig ["PackageName"]).Replace ("\r", "").Split (new char [] { '\n' }, StringSplitOptions.RemoveEmptyEntries);

              foreach (string line in adbPmPathOutput)
              {
                if (line.StartsWith ("package:", StringComparison.OrdinalIgnoreCase))
                {
                  appIsInstalled = true;

                  LoggingUtils.RequireOk (m_debugConnectionService.LaunchDialogUpdate (string.Format (CultureInfo.InvariantCulture, "'{0}' already installed on target '{1}'.", launchConfig ["PackageName"], debuggingDevice.ID), false));

                  string path = line.Substring ("package:".Length);

                  //
                  // Get the target device/emulator's UTC current time.
                  //
                  //   This is done by specifying the '-u' argument to 'date'. Despite this though,
                  //   the returned string will always claim to be in GMT:
                  //
                  //   i.e: "Fri Jan  9 14:35:23 GMT 2015"
                  //

                  DateTime debuggingDeviceUtcTime;

                  try
                  {
                    string [] deviceDateOutput = debuggingDevice.Shell ("date", "-u").Replace ("\r", "").Split (new char [] { '\n' }, StringSplitOptions.RemoveEmptyEntries);

                    string debuggingDeviceUtcTimestamp = deviceDateOutput [0];

                    string [] debuggingDeviceUtcTimestampComponents = debuggingDeviceUtcTimestamp.Split (new char [] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                    debuggingDeviceUtcTimestampComponents [4] = "-00:00";

                    if (!DateTime.TryParseExact (string.Join (" ", debuggingDeviceUtcTimestampComponents), "ddd MMM  d HH:mm:ss zzz yyyy", CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out debuggingDeviceUtcTime))
                    {
                      break;
                    }

                    debuggingDeviceUtcTime = debuggingDeviceUtcTime.ToUniversalTime ();
                  }
                  catch (Exception e)
                  {
                    throw new InvalidOperationException ("Failed to evaluate device local time.", e);
                  }

                  //
                  // Convert current device/emulator time to UTC, and probe the working machine's time too.
                  //

                  DateTime thisMachineUtcTime = DateTime.UtcNow;

                  TimeSpan thisMachineUtcVersusDeviceUtc = debuggingDeviceUtcTime - thisMachineUtcTime;

                  LoggingUtils.RequireOk (m_debugConnectionService.LaunchDialogUpdate (string.Format (CultureInfo.InvariantCulture, "Current UTC time on '{0}': {1}", debuggingDevice.ID, debuggingDeviceUtcTime.ToString ()), false));

                  LoggingUtils.RequireOk (m_debugConnectionService.LaunchDialogUpdate (string.Format (CultureInfo.InvariantCulture, "Current UTC time on '{0}': {1}", System.Environment.MachineName, thisMachineUtcTime.ToString ()), false));

                  LoggingUtils.RequireOk (m_debugConnectionService.LaunchDialogUpdate (string.Format (CultureInfo.InvariantCulture, "Difference in UTC time between '{0}' and '{1}': {2}", System.Environment.MachineName, debuggingDevice.ID, thisMachineUtcVersusDeviceUtc.ToString ()), false));

                  //
                  // Check the last modified date; ls output currently uses this format:
                  //
                  // -rw-r--r-- system   system   11533274 2015-01-09 13:47 com.example.native_activity-2.apk
                  //

                  DateTime lastModifiedTimestampDeviceLocalTime;

                  try
                  {
                    string [] extendedLsOutput = debuggingDevice.Shell ("ls -l", path).Replace ("\r", "").Split (new char [] { '\n' }, StringSplitOptions.RemoveEmptyEntries);

                    string [] extendedLsOutputComponents = extendedLsOutput [0].Split (new char [] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                    string date = extendedLsOutputComponents [4];

                    string time = extendedLsOutputComponents [5];

                    if (!DateTime.TryParseExact (date + " " + time, "yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out lastModifiedTimestampDeviceLocalTime))
                    {
                      break;
                    }
                  }
                  catch (Exception e)
                  {
                    throw new InvalidOperationException (string.Format (CultureInfo.InvariantCulture, "Failed to evaluate device local modified time of: {0}", path), e);
                  }

                  //
                  // Calculate how long ago the APK was changed, according to the device's local time.
                  //

                  TimeSpan timeSinceLastModification = debuggingDeviceUtcTime - lastModifiedTimestampDeviceLocalTime;

                  DateTime debuggingDeviceUtcTimeAtLastModification = debuggingDeviceUtcTime - timeSinceLastModification;

                  DateTime thisMachineUtcTimeAtLastModification = thisMachineUtcTime - timeSinceLastModification;

                  LoggingUtils.RequireOk (m_debugConnectionService.LaunchDialogUpdate (string.Format (CultureInfo.InvariantCulture, "'{0}' was last modified on '{1}' at: {2}.", launchConfig ["PackageName"], debuggingDevice.ID, debuggingDeviceUtcTimeAtLastModification.ToString ()), false));

                  LoggingUtils.RequireOk (m_debugConnectionService.LaunchDialogUpdate (string.Format (CultureInfo.InvariantCulture, "{0} (on {1}) was around {2} (on {3}).", debuggingDeviceUtcTimeAtLastModification.ToString (), debuggingDevice.ID, thisMachineUtcTimeAtLastModification.ToString (), System.Environment.MachineName), false));

                  LoggingUtils.RequireOk (m_debugConnectionService.LaunchDialogUpdate (string.Format (CultureInfo.InvariantCulture, "'{0}' was last modified on '{1}' at: {2}.", Path.GetFileName (targetApkFileInfo.FullName), System.Environment.MachineName, targetApkFileInfo.LastWriteTime.ToString ()), false));

                  if ((targetApkFileInfo.LastWriteTime + thisMachineUtcVersusDeviceUtc) > thisMachineUtcTimeAtLastModification)
                  {
                    LoggingUtils.RequireOk (m_debugConnectionService.LaunchDialogUpdate (string.Format (CultureInfo.InvariantCulture, "'{0}' was determined to be out-of-date. Reinstalling...", launchConfig ["PackageName"]), false));
                  }
                  else
                  {
                    appIsOutOfDate = false;
                  }

                  break;
                }
              }
            }
            catch (Exception)
            {
              appIsInstalled = false;
            }
              }
              else
              {
            LoggingUtils.RequireOk (m_debugConnectionService.LaunchDialogUpdate ("Skipping up-to-date check.", false));
              }

              if (!appIsInstalled || appIsOutOfDate)
              {
            LoggingUtils.RequireOk (m_debugConnectionService.LaunchDialogUpdate (string.Format (CultureInfo.InvariantCulture, "Installing '{0}' to '{1}'...", launchConfig ["PackageName"], debuggingDevice.ID), false));

            InstallApplicationAsync (debuggingDevice, launchConfig);

            LoggingUtils.RequireOk (m_debugConnectionService.LaunchDialogUpdate (string.Format (CultureInfo.InvariantCulture, "'{0}' installed successfully.", launchConfig ["PackageName"]), false));
              }
              else
              {
            LoggingUtils.RequireOk (m_debugConnectionService.LaunchDialogUpdate (string.Format (CultureInfo.InvariantCulture, "'{0}' on '{1}' is up-to-date. Skipping installation...", launchConfig ["PackageName"], debuggingDevice.ID), false));
              }

              debugLaunchSettings.Executable = launchConfig ["TargetApk"];

              debugLaunchSettings.LaunchOperation = DebugLaunchOperation.Custom;
            }

            return debugLaunchSettings;
              }
              catch (Exception e)
              {
            LoggingUtils.HandleException (e);

            throw;
              }
        }