public IAppInstance Run(IAppInstall App)
        {
            IOSAppInstall IOSApp = App as IOSAppInstall;

            if (IOSApp == null)
            {
                throw new DeviceException("AppInstance is of incorrect type!");
            }

            string CommandLine = IOSApp.CommandLine.Replace("\"", "\\\"");

            Log.Info("Launching {0} on {1}", App.Name, ToString());
            Log.Verbose("\t{0}", CommandLine);

            // ios-deploy notes: -L launches detached, -I non-interactive  (exits when app exits), -r uninstalls before install (removes app Documents folder)
            // -t <seconds> number of seconds to wait for device to be connected

            // setup symbols if available
            string DSymBundle = "";
            string DSymDir    = Path.Combine(GauntletAppCache, "Symbols");

            if (Directory.Exists(DSymDir))
            {
                DSymBundle = Directory.GetDirectories(DSymDir).Where(D => Path.GetExtension(D).ToLower() == ".dsym").FirstOrDefault();
                DSymBundle = string.IsNullOrEmpty(DSymBundle) ? "" : DSymBundle = " -S \"" + DSymBundle + "\"";
            }

            string CL = "--noinstall -I" + DSymBundle + " -b \"" + LocalAppBundle + "\" --args '" + CommandLine.Trim() + "'";

            IProcessResult Result = ExecuteIOSDeployCommand(CL, 0);

            Thread.Sleep(5000);

            // Give ios-deploy a chance to throw out any errors...
            if (Result.HasExited)
            {
                Log.Warning("ios-deploy exited early: " + Result.Output);
                throw new DeviceException("Failed to launch on {0}. {1}", Name, Result.Output);
            }

            return(new IOSAppInstance(IOSApp, Result, IOSApp.CommandLine));
        }
        public IAppInstall InstallApplication(UnrealAppConfig AppConfig)
        {
            IOSBuild Build = AppConfig.Build as IOSBuild;

            // Ensure Build exists
            if (Build == null)
            {
                throw new AutomationException("Invalid build for IOS!");
            }

            bool CacheResigned      = false;
            bool UseLocalExecutable = Globals.Params.ParseParam("dev");

            lock (IPALock)
            {
                Log.Info("Installing using IPA {0}", Build.SourceIPAPath);

                // device artifact path
                DeviceArtifactPath = string.Format("/Documents/{0}/Saved", AppConfig.ProjectName);

                CacheResigned = File.Exists(CacheResignedFilename);

                if (CacheResigned && !UseLocalExecutable)
                {
                    if (File.Exists(IPAHashFilename))
                    {
                        Log.Verbose("App was resigned, invalidating app cache");
                        File.Delete(IPAHashFilename);
                    }
                }

                PrepareIPA(Build);

                // local executable support
                if (UseLocalExecutable)
                {
                    ResignApplication(AppConfig);
                }
            }

            if (CacheResigned || UseLocalExecutable || !CheckDeployedIPA(Build))
            {
                // uninstall will clean all device artifacts
                ExecuteIOSDeployCommand(String.Format("--uninstall -b \"{0}\"", LocalAppBundle), 10 * 60);
            }
            else
            {
                // remove device artifacts
                CleanDeviceArtifacts(Build);
            }

            // parallel iOS tests use same app install folder, so lock it as setup is quick
            lock (Globals.MainLock)
            {
                // local app install with additional files, this directory will be mirrored to device in a single operation
                string AppInstallPath;

                AppInstallPath = Path.Combine(Globals.TempDir, "iOSAppInstall");

                if (Directory.Exists(AppInstallPath))
                {
                    Directory.Delete(AppInstallPath, true);
                }

                Directory.CreateDirectory(AppInstallPath);

                if (LocalDirectoryMappings.Count == 0)
                {
                    PopulateDirectoryMappings(AppInstallPath);
                }

                //@todo: Combine Build and AppConfig files, this should be done in higher level code, not per device implementation

                if (AppConfig.FilesToCopy != null)
                {
                    foreach (UnrealFileToCopy FileToCopy in AppConfig.FilesToCopy)
                    {
                        string PathToCopyTo = Path.Combine(LocalDirectoryMappings[FileToCopy.TargetBaseDirectory], FileToCopy.TargetRelativeLocation);

                        if (File.Exists(FileToCopy.SourceFileLocation))
                        {
                            FileInfo SrcInfo = new FileInfo(FileToCopy.SourceFileLocation);
                            SrcInfo.IsReadOnly = false;
                            string DirectoryToCopyTo = Path.GetDirectoryName(PathToCopyTo);
                            if (!Directory.Exists(DirectoryToCopyTo))
                            {
                                Directory.CreateDirectory(DirectoryToCopyTo);
                            }
                            if (File.Exists(PathToCopyTo))
                            {
                                FileInfo ExistingFile = new FileInfo(PathToCopyTo);
                                ExistingFile.IsReadOnly = false;
                            }

                            SrcInfo.CopyTo(PathToCopyTo, true);
                            Log.Verbose("Copying app install: {0} to {1}", FileToCopy, DirectoryToCopyTo);
                        }
                        else
                        {
                            Log.Warning("File to copy {0} not found", FileToCopy);
                        }
                    }
                }

                // copy mapped files in a single pass
                string CopyCommand = String.Format("--bundle_id {0} --upload={1} --to {2}", Build.PackageName, AppInstallPath, DeviceArtifactPath);
                ExecuteIOSDeployCommand(CopyCommand, 120);

                // store the IPA hash to avoid redundant deployments
                CopyCommand = String.Format("--bundle_id {0} --upload={1} --to {2}", Build.PackageName, IPAHashFilename, "/Documents/IPAHash.txt");
                ExecuteIOSDeployCommand(CopyCommand, 120);
            }

            IOSAppInstall IOSApp = new IOSAppInstall(AppConfig.Name, this, Build.PackageName, AppConfig.CommandLine);

            return(IOSApp);
        }
 public IOSAppInstance(IOSAppInstall InInstall, IProcessResult InProcess, string InCommandLine)
 {
     Install            = InInstall;
     this.CommandLine   = InCommandLine;
     this.ProcessResult = InProcess;
 }