Example #1
0
        public void TestRecordingBeginEnd()
        {
            if (!_test.Config.RunWorkstationTests)
            {
                Assert.Ignore("Skipping, Workstation tests disabled.");
            }

            foreach (VMWareVirtualMachine virtualMachine in _test.PoweredVirtualMachines)
            {
                Assert.IsFalse(virtualMachine.IsRecording);
                string snapshotName = Guid.NewGuid().ToString();
                ConsoleOutput.WriteLine("Begin recording ...");
                VMWareSnapshot snapshot = virtualMachine.BeginRecording(snapshotName, Guid.NewGuid().ToString());
                Assert.IsNotNull(snapshot);
                Assert.IsTrue(virtualMachine.IsRecording);
                Assert.IsFalse(virtualMachine.IsReplaying);
                virtualMachine.WaitForToolsInGuest();
                ConsoleOutput.WriteLine("Snapshot: {0}", snapshot.DisplayName);
                VMWareVirtualMachine.Process cmdProcess = virtualMachine.RunProgramInGuest("cmd.exe", "/C dir");
                Assert.IsNotNull(cmdProcess);
                ConsoleOutput.WriteLine("Process: {0}", cmdProcess.Id);
                ConsoleOutput.WriteLine("End recording ...");
                virtualMachine.EndRecording();
                Assert.IsFalse(virtualMachine.IsRecording);
                Assert.IsFalse(virtualMachine.IsReplaying);
                ConsoleOutput.WriteLine("Begin replay ...");
                snapshot.BeginReplay(Constants.VIX_VMPOWEROP_LAUNCH_GUI, VMWareInterop.Timeouts.ReplayTimeout);
                Assert.IsTrue(virtualMachine.IsReplaying);
                Thread.Sleep(10000);
                snapshot.EndReplay();
                Assert.IsFalse(virtualMachine.IsReplaying);
                ConsoleOutput.WriteLine("Removing snapshot ...");
                snapshot.RemoveSnapshot();
            }
        }
        public void PrepareSnapshot()
        {
            ConsoleOutput.WriteLine("Preparing '{0}:{1}'", _vmConfig.Name, _snapshotConfig.Name);

            if (!_snapshotConfig.IsCurrentSnapshot)
            {
                ConsoleOutput.WriteLine("Restoring snapshot '{0}:{1}'", _vmConfig.Name, _snapshotConfig.Name);

                if (!_simulationOnly)
                {
                    VMWareSnapshot snapshot = _vm.Snapshots.FindSnapshot(_snapshotConfig.Name);
                    if (snapshot == null)
                    {
                        snapshot = _vm.Snapshots.GetNamedSnapshot(_snapshotConfig.Name);
                    }
                    if (snapshot == null)
                    {
                        throw new Exception(string.Format("Missing snapshot: {0}",
                                                          _snapshotConfig.Name));
                    }
                    snapshot.RevertToSnapshot(Constants.VIX_VMPOWEROP_SUPPRESS_SNAPSHOT_POWERON);
                }
            }

            PowerOn();
        }
Example #3
0
 public void TestCreateSnapshotSameName()
 {
     foreach (VMWareVirtualMachine virtualMachine in _test.VirtualMachines)
     {
         // this is the root snapshot
         Assert.IsTrue(virtualMachine.Snapshots.Count >= 0);
         string name = Guid.NewGuid().ToString();
         // take a snapshot at the current state
         ConsoleOutput.WriteLine("Creating snapshot 1: {0}", name);
         using (VMWareSnapshot snapshot = virtualMachine.Snapshots.CreateSnapshot(name, Guid.NewGuid().ToString()))
         {
             // needs to be disposed
         }
         ConsoleOutput.WriteLine("Creating snapshot 2: {0}", name);
         using (VMWareSnapshot snapshot = virtualMachine.Snapshots.CreateSnapshot(name, Guid.NewGuid().ToString()))
         {
             // needs to be disposed
         }
         int count = 0;
         IEnumerable <VMWareSnapshot> snapshots = virtualMachine.Snapshots.FindSnapshotsByName(name);
         foreach (VMWareSnapshot snapshot in snapshots)
         {
             ConsoleOutput.WriteLine("Removing snapshot: {0}", snapshot.Path);
             snapshot.RemoveSnapshot();
             count++;
         }
         Assert.AreEqual(2, count);
     }
 }
Example #4
0
 public void TestEnumerateSnapshots()
 {
     foreach (VMWareVirtualMachine virtualMachine in _test.VirtualMachines)
     {
         List <string> snapshotPaths = GetSnapshotPaths(virtualMachine.Snapshots, 0);
         foreach (string snapshotPath in snapshotPaths)
         {
             VMWareSnapshot snapshot = virtualMachine.Snapshots.FindSnapshot(snapshotPath);
             Assert.IsNotNull(snapshot);
             ConsoleOutput.WriteLine("{0}: {1}, power state={2}",
                                     snapshot.DisplayName, snapshotPath, snapshot.PowerState);
         }
     }
 }
Example #5
0
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        public override bool Execute()
        {
            using (VMWareVirtualHost host = GetConnectedHost())
            {
                using (VMWareVirtualMachine virtualMachine = OpenVirtualMachine(host))
                {
                    Log.LogMessage(string.Format("Creating snapshot {0}", _snapshotName));
                    using (VMWareSnapshot snapshot = virtualMachine.Snapshots.CreateSnapshot(
                               _snapshotName, _snapshotDescription, 0, _createSnapshotTimeout))
                    {
                        // snapshot created
                    }
                }
            }

            return(true);
        }
Example #6
0
 public void TestRevertToLiveSnapshot()
 {
     using (VMWareVirtualHost virtualHost = new VMWareVirtualHost())
     {
         virtualHost.ConnectToVMWareWorkstation();
         Console.WriteLine(virtualHost.ConnectionType);
         using (VMWareVirtualMachine virtualMachine = virtualHost.Open(
                    @"C:\Users\dblock\Documents\Virtual Machines\Windows 98 SE\Windows 98.vmx"))
         {
             Console.WriteLine(virtualMachine.PathName);
             VMWareSnapshot snapshot = virtualMachine.Snapshots.GetNamedSnapshot("Live");
             // snapshot.RevertToSnapshot();
             // snapshot.RevertToSnapshot(Interop.VixCOM.Constants.VIX_VMPOWEROP_LAUNCH_GUI,
             //    VMWareInterop.Timeouts.RevertToSnapshotTimeout);
             snapshot.RevertToSnapshot(Interop.VixCOM.Constants.VIX_VMPOWEROP_SUPPRESS_SNAPSHOT_POWERON,
                                       VMWareInterop.Timeouts.RevertToSnapshotTimeout);
             // virtualMachine.PowerOn();
         }
     }
 }
Example #7
0
 public void TestCreateRemoveSnapshot()
 {
     foreach (VMWareVirtualMachine virtualMachine in _test.VirtualMachines)
     {
         // this is the root snapshot
         Assert.IsTrue(virtualMachine.Snapshots.Count >= 0);
         string name = Guid.NewGuid().ToString();
         ConsoleOutput.WriteLine("Snapshot name: {0}", name);
         // take a snapshot at the current state
         using (VMWareSnapshot snapshot = virtualMachine.Snapshots.CreateSnapshot(name, Guid.NewGuid().ToString()))
         {
             ConsoleOutput.WriteLine("Created snapshot: {0}", name);
         }
         // check whether the snapshot was created
         Assert.IsNotNull(virtualMachine.Snapshots.GetNamedSnapshot(name));
         // delete the snapshot via VM interface
         virtualMachine.Snapshots.RemoveSnapshot(name);
         // check whether the snapshot was deleted
         Assert.IsNull(virtualMachine.Snapshots.FindSnapshotByName(name));
     }
 }
Example #8
0
        public void TestFindByName()
        {
            foreach (VMWareVirtualMachine virtualMachine in _test.VirtualMachines)
            {
                // this is the root snapshot
                string name = Guid.NewGuid().ToString();
                // take two snapshots at the current state
                ConsoleOutput.WriteLine("Creating snapshot 1: {0}", name);
                using (VMWareSnapshot snapshot = virtualMachine.Snapshots.CreateSnapshot(
                           name, Guid.NewGuid().ToString()))
                {
                    Console.WriteLine("Created snapshot: {0}", snapshot.DisplayName);
                }

                ConsoleOutput.WriteLine("Creating snapshot 2: {0}", name);
                using (VMWareSnapshot snapshot = virtualMachine.Snapshots.CreateSnapshot(
                           name, Guid.NewGuid().ToString()))
                {
                    Console.WriteLine("Created snapshot: {0}", snapshot.DisplayName);
                }

                ConsoleOutput.WriteLine("Locating snapshot ...");
                Assert.IsNotNull(virtualMachine.Snapshots.FindSnapshotByName(name));
                ConsoleOutput.WriteLine("Locating snapshots ...");
                IEnumerable <VMWareSnapshot> snapshots = virtualMachine.Snapshots.FindSnapshotsByName(name);
                int count = 0;
                foreach (VMWareSnapshot snapshot in snapshots)
                {
                    count++;
                    Assert.IsNotNull(virtualMachine.Snapshots.FindSnapshotByName(name));
                    ConsoleOutput.WriteLine("Removing {0}: {1}", snapshot.Path, snapshot.Description);
                    snapshot.RemoveSnapshot();
                    snapshot.Close();
                }
                Assert.AreEqual(2, count);
                Assert.IsNull(virtualMachine.Snapshots.FindSnapshotByName(name));
            }
        }
Example #9
0
 public void GettingStartedWorkstation()
 {
     #region Example: Getting Started (Workstation)
     // declare a virtual host
     using (VMWareVirtualHost virtualHost = new VMWareVirtualHost())
     {
         // connect to a local VMWare Workstation virtual host
         virtualHost.ConnectToVMWareWorkstation();
         // open an existing virtual machine
         using (VMWareVirtualMachine virtualMachine = virtualHost.Open(@"C:\Virtual Machines\xp\xp.vmx"))
         {
             // power on this virtual machine
             virtualMachine.PowerOn();
             // wait for VMWare Tools
             virtualMachine.WaitForToolsInGuest();
             // login to the virtual machine
             virtualMachine.LoginInGuest("Administrator", "password");
             // run notepad
             virtualMachine.RunProgramInGuest("notepad.exe", string.Empty);
             // create a new snapshot
             string name = "New Snapshot";
             // take a snapshot at the current state
             VMWareSnapshot createdSnapshot = virtualMachine.Snapshots.CreateSnapshot(name, "test snapshot");
             createdSnapshot.Dispose();
             // power off
             virtualMachine.PowerOff();
             // find the newly created snapshot
             using (VMWareSnapshot foundSnapshot = virtualMachine.Snapshots.GetNamedSnapshot(name))
             {
                 // revert to the new snapshot
                 foundSnapshot.RevertToSnapshot();
                 // delete snapshot
                 foundSnapshot.RemoveSnapshot();
             }
         }
     }
     #endregion
 }
Example #10
0
 public void GettingStartedVI()
 {
     #region Example: Getting Started (VI)
     // declare a virtual host
     using (VMWareVirtualHost virtualHost = new VMWareVirtualHost())
     {
         // connect to a remove (VMWare ESX) virtual machine
         virtualHost.ConnectToVMWareVIServer("esx.mycompany.com", "vmuser", "password");
         // open an existing virtual machine
         using (VMWareVirtualMachine virtualMachine = virtualHost.Open("[storage] testvm/testvm.vmx"))
         {
             // power on this virtual machine
             virtualMachine.PowerOn();
             // wait for VMWare Tools
             virtualMachine.WaitForToolsInGuest();
             // login to the virtual machine
             virtualMachine.LoginInGuest("Administrator", "password");
             // run notepad
             virtualMachine.RunProgramInGuest("notepad.exe", string.Empty);
             // create a new snapshot
             string name = "New Snapshot";
             // take a snapshot at the current state
             virtualMachine.Snapshots.CreateSnapshot(name, "test snapshot");
             // power off
             virtualMachine.PowerOff();
             // find the newly created snapshot
             using (VMWareSnapshot snapshot = virtualMachine.Snapshots.GetNamedSnapshot(name))
             {
                 // revert to the new snapshot
                 snapshot.RevertToSnapshot();
                 // delete snapshot
                 snapshot.RemoveSnapshot();
             }
         }
     }
     #endregion
 }
Example #11
0
 public void TestCreateRevertRemoveSnapshot()
 {
     foreach (VMWareVirtualMachine virtualMachine in _test.VirtualMachines)
     {
         // this is the root snapshot
         Assert.IsTrue(virtualMachine.Snapshots.Count >= 0);
         string name = Guid.NewGuid().ToString();
         ConsoleOutput.WriteLine("Creating snapshot: {0}", name);
         // take a snapshot at the current state
         using (VMWareSnapshot snapshot = virtualMachine.Snapshots.CreateSnapshot(name, Guid.NewGuid().ToString()))
         {
         }
         // revert to the newly created snapshot
         ConsoleOutput.WriteLine("Locating snapshot: {0}", name);
         using (VMWareSnapshot snapshot = virtualMachine.Snapshots.GetNamedSnapshot(name))
         {
             Assert.IsNotNull(snapshot);
             ConsoleOutput.WriteLine("Reverting snapshot: {0}", name);
             snapshot.RevertToSnapshot();
             ConsoleOutput.WriteLine("Removing snapshot: {0}", name);
             snapshot.RemoveSnapshot();
         }
     }
 }
Example #12
0
        /// <summary>
        /// Execute a file from a remote vm.
        /// </summary>
        private TaskResult Execute(SnapshotTaskConfig snapshotConfig)
        {
            TaskResult snapshotTaskResult = new TaskResult();

            snapshotTaskResult.CmdLine = string.Format("Snapshot: {0} '{1}'", snapshotConfig.Command, snapshotConfig.Name);
            snapshotTaskResult.Name    = snapshotConfig.Name;
            try
            {
                ConsoleOutput.WriteLine(snapshotTaskResult.CmdLine);

                if (!_installInstance.SimulationOnly)
                {
                    switch (snapshotConfig.Command)
                    {
                    case SnapshotCommand.create:
                        _installInstance.VirtualMachine.Snapshots.CreateSnapshot(
                            snapshotConfig.Name, snapshotConfig.Description,
                            snapshotConfig.IncludeMemory ? Constants.VIX_SNAPSHOT_INCLUDE_MEMORY : 0,
                            VMWareInterop.Timeouts.CreateSnapshotTimeout);
                        break;

                    case SnapshotCommand.remove:
                        _installInstance.VirtualMachine.Snapshots.RemoveSnapshot(
                            snapshotConfig.Name);
                        break;

                    case SnapshotCommand.removeifexists:

                        VMWareSnapshot snapshot = _installInstance.VirtualMachine.Snapshots.FindSnapshotByName(
                            snapshotConfig.Name);

                        if (snapshot != null)
                        {
                            ConsoleOutput.WriteLine("Removing {0}", snapshotTaskResult.CmdLine);
                            snapshot.RemoveSnapshot();
                        }
                        else
                        {
                            ConsoleOutput.WriteLine("No {0}", snapshotTaskResult.CmdLine);
                        }

                        break;

                    case SnapshotCommand.revert:
                        _installInstance.VirtualMachine.Snapshots.FindSnapshotByName(
                            snapshotConfig.Name).RevertToSnapshot(Constants.VIX_VMPOWEROP_SUPPRESS_SNAPSHOT_POWERON);
                        break;

                    default:
                        throw new Exception(string.Format("Unsupported command '{0}'",
                                                          snapshotConfig.Command));
                    }

                    ConsoleOutput.WriteLine(string.Format("Finished {0}", snapshotTaskResult.CmdLine));
                }
            }
            catch (Exception ex)
            {
                snapshotTaskResult.LastError = ex.Message;
                snapshotTaskResult.Success   = false;
                ConsoleOutput.WriteLine(ex);
            }

            return(snapshotTaskResult);
        }
Example #13
0
        // Main method. Start point of the program
        static void Main(string[] args)
        {
            /*
             * Print a banner to the screen
             */
            Console.WriteLine(Properties.Resources.banner);



            /*
             * Do nothing if no arguments given.
             *
             * if the argument is -f, output to a file instead of console.
             */
            if (args.Length == 0 || args == null)
            {
                Environment.Exit(0);
            }
            else if (args[0] == "-f")
            {
                consoleOut = false;
            }



            /*
             * Get the current directory and store in a variable to avoid multiple calls
             */
            workingDir = Directory.GetCurrentDirectory();



            /*
             * Check to ensure that the pstemp directory is present in the same directory as
             * the TestSuite.exe file, with all important files included
             */
            pstempHost = workingDir + @"\pstemp";
            if (!Directory.Exists(pstempHost))
            {
                Console.WriteLine("[!] Error: the pstemp directory does not exist.");
                Environment.Exit(0);
            }
            else if (!File.Exists(pstempHost + @"\hstart64.exe") ||
                     !File.Exists(pstempHost + @"\PsExec.exe"))
            {
                Console.WriteLine("[!] Error: one or more files missing from pstemp directory.");
                Environment.Exit(0);
            }



            /*
             * Read lines from teh variables.ini file and set variables accordingly
             */
            string[] vars = File.ReadAllLines(workingDir + @"\Resources\variables.ini");
            foreach (string var in vars)
            {
                if (var.Contains("DOMAIN="))
                {
                    domainName = var.Replace("DOMAIN=", "");
                }
                else if (var.Contains("USERNAME="******"USERNAME="******"");
                }
                else if (var.Contains("PASSWORD="******"PASSWORD="******"");
                }
                else if (var.Contains("VMX="))
                {
                    vmxPath = var.Replace("VMX=", "");
                }
                else if (var.Contains("CPUID="))
                {
                    compId = var.Replace("CPUID=", "");
                }
                else if (var.Contains("TESTSPERSNAP="))
                {
                    testPerSnap = int.Parse(var.Replace("TESTSPERSNAP=", ""));
                }
                else if (var.Contains("TASKCNXNSTRING="))
                {
                    taskString = var.Replace("TASKCNXNSTRING=", "");
                }
                else if (var.Contains("IMAGENAME="))
                {
                    imageName = var.Replace("IMAGENAME=", "");
                }
                else if (var.Contains("PICTIME="))
                {
                    picTime = int.Parse(var.Replace("PICTIME=", ""));
                }
                else if (var.Contains("USESERVER="))
                {
                    useServer = bool.Parse(var.Replace("USESERVER=", ""));
                }
                else if (var.Contains("HOSTNAME="))
                {
                    hostName = var.Replace("HOSTNAME=", "");
                }
                else if (var.Contains("HOSTUSER="******"HOSTUSER="******"");
                }
                else if (var.Contains("HOSTPASS="******"HOSTPASS="******"");
                }
                else if (var.Contains("SFWRCNXNSTRING="))
                {
                    sfwrString = var.Replace("SFWRCNXNSTRING=", "");
                }
                else if (var.Contains("SCREENSHOTSDIR="))
                {
                    screenShotsDir = var.Replace("SCREENSHOTSDIR=", "");
                }
            }



            /*
             * If some variable is not initialized, exit.
             */
            if (domainName == null ||
                usrnm == null ||
                psswd == null ||
                vmxPath == null ||
                compId == null ||
                taskString == null ||
                useServer == null ||
                sfwrString == null)
            {
                Console.WriteLine("[!] An essential variable has not been initiated. See variables.ini");
                Environment.Exit(0);
            }



            /*
             * If no image name was given, use the name of the VMX file
             */
            if (imageName == null)
            {
                imageName = Path.GetFileNameWithoutExtension(vmxPath);
            }
            screenShotsDir = screenShotsDir + imageName;



            /*
             * If the output is specified to file, redirect all Console.WriteLine to a file instead of the console.
             */
            if (!consoleOut)
            {
                FileStream   fStream = new FileStream(screenShotsDir + @"\log\" + string.Format("{0:yyyy-MM-dd_hh-mm-ss-tt}", DateTime.Now) + ".txt", FileMode.OpenOrCreate, FileAccess.Write);
                StreamWriter fileOut = new StreamWriter(fStream);
                Console.SetOut(fileOut);
            }


            /*
             * If useServer is true and any of the essential server variables are empty, quit
             */
            if ((bool)useServer && (hostName == null ||
                                    hostPass == null ||
                                    hostUser == null))
            {
                Console.WriteLine("[!] Variables.ini is not configured for server use.");
                Environment.Exit(0);
            }



            /*
             * Create a new directory with the date and time stamp to store the test results
             */
            resultDir = workingDir + @"\Results\";
            System.IO.Directory.CreateDirectory(resultDir);


            resultDir = resultDir + imageName + @"\";
            System.IO.Directory.CreateDirectory(resultDir);



            /*
             * Create the autoLogon.reg file, used to allow auto-logon in the guest OS after snapshot revert
             *
             * Sets to auto login
             * Turns off screensaver (broken?)
             * Turns off lock screen (broken?)
             */
            try
            {
                if (File.Exists(pstempHost + @"\autoLogon.reg"))
                {
                    File.Delete(pstempHost + @"\autoLogon.reg");
                }
                string[] lines = { "Windows Registry Editor Version 5.00",
                                   @"[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon]",
                                   "\"DefaultUserName\"=\"" + usrnm + "\"",
                                   "\"DefaultDomainName\"=\"" + domainName + "\"",
                                   "\"DefaultPassword\"=\"" + psswd + "\"",
                                   "\"AutoAdminLogon\"=\"1\"",
                                   "",
                                   @"[HKEY_CURRENT_USER\Control Panel\Desktop]",
                                   "\"ScreenSaveActive\"=\"0\"",
                                   "",
                                   @"[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Personalization]",
                                   "\"NoLockScreen\"=dword:00000001" };
                File.WriteAllLines(pstempHost + @"\autoLogon.reg", lines);
            }
            catch (Exception e)
            {
                Console.WriteLine("[!] Could not create auto-login registry file. You may need to do this manually.");
                Console.WriteLine("[?] Exception message: " + e.Message);
            }



            /*
             * Query the SQL database and use the reader to create a collection of
             * the information
             */
            try
            {
                conn = new SqlConnection(taskString);
                conn.Open();
                cmd    = new SqlCommand(Properties.Resources.taskQuery + compId, conn); // use the command resource, add the computer ID number
                reader = cmd.ExecuteReader();
                tests  = new Dictionary <int, TestPackage>();
                while (reader.Read())
                {
                    tests.Add(reader.GetInt32(1), new TestPackage(reader.GetString(0), reader.GetInt32(1).ToString()));
                }
                reader.Close();
                conn.Close();
                Console.WriteLine("[i] " + tests.Count + " packages assigned to this machine.");
            }
            catch (SqlException sqle)
            {
                Console.WriteLine("Exception thrown: " + sqle.Message);
                Environment.Exit(0);
            }



            /*
             * Create VirtualHost and VirtualMachine objects with using directive
             */
            using (VMWareVirtualHost vhost = new VMWareVirtualHost())
            {
                /*
                 * Connect to either vSphere or Workstation, based on useServer variable
                 */
                if ((bool)useServer)
                {
                    vhost.ConnectToVMWareVIServer(hostName, hostUser, hostPass);
                    Console.WriteLine("[\u221A] Connected to vSphere.");
                }
                else
                {
                    vhost.ConnectToVMWareWorkstation();
                    Console.WriteLine("[\u221A] Connected to VMWareWorkstation.");
                }


                /*
                 * Open a virtual machine using the vmxPath
                 */
                using (VMWareVirtualMachine vm = vhost.Open(vmxPath))
                {
                    Console.WriteLine("[\u221A] Virtual machine opened.");



                    /*
                     * Power on the virtual machine and log in interactively.
                     * Requires user to log in interactively on the VM
                     */
                    try
                    {
                        vm.PowerOn();
                        Console.WriteLine("[\u221A] Powered on.");

                        vm.WaitForToolsInGuest();
                        Console.WriteLine("[\u221A] Tools found in guest.");


                        /*
                         * Login using the interactive login procedure
                         */
                        interactiveLogin(vm);



                        /*
                         * Copy necessary files for SYSTEM execution from host to guest.
                         *
                         */
                        if (vm.DirectoryExistsInGuest(pstempGuest))
                        {
                            vm.DeleteDirectoryFromGuest(pstempGuest);
                        }
                        vm.CopyFileFromHostToGuest(pstempHost, pstempGuest);
                        Console.WriteLine("[\u221A] Files copied to temp directory " + pstempGuest + ".");



                        /*
                         * Run the AutoLogon script for proper VM rollbacks
                         * We try try to delete the PSEXESVC process, if it exists. If it doesn't it throws an exception,
                         * which we ignore.
                         */
                        VMWareVirtualMachine.Process reg = detachSystemCommand(@"C:\Windows\regedit.exe", "/s \"" + pstempGuest + "\\autoLogon.reg\"", vm);
                        if (reg != null)
                        {
                            while (vm.GuestProcesses.FindProcess(reg.Name, StringComparison.CurrentCulture) != null)
                            {
                                ;
                            }
                        }
                        Console.WriteLine("[\u221A] Registry configured for auto logon.");



                        /*
                         * Create snapshot for deployment rollbacks
                         * If a snapshot
                         */
                        try
                        {
                            deployPoint = vm.Snapshots.GetNamedSnapshot(snapName);
                            deployPoint.RemoveSnapshot();
                        }
                        catch (VMWareException) { }

                        deployPoint = vm.Snapshots.CreateSnapshot(snapName, "Start point for deployment tests");
                        Console.WriteLine("[\u221A] Snapshot 'deployPoint' captured.");


                        /*
                         * Sync policies with server.
                         */
                        policySync(vm);



                        /*
                         * Create a list of all files in the policy directory
                         * Remove all non-xml files from the list
                         * Look for the task ID in the file name, and map the file name to the correct package
                         */

                        policyDirectoryFiles = vm.ListDirectoryInGuest(@"C:\ProgramData\LANDesk\Policies", false);
                        policyDirectoryFiles.RemoveAll(x => !(x.Contains(".xml")));

                        foreach (string dir in policyDirectoryFiles)
                        {
                            Match m   = idPattern.Match(dir);
                            int   key = (m.Success) ? Int32.Parse(m.Value.Substring(3, 4)) : -1;
                            if (tests.ContainsKey(key))
                            {
                                tests[key].Cmd = dir;
                            }
                        }
                        Console.WriteLine((policyDirectoryFiles.Count == tests.Count) ? "[\u221A] All packages can be deployed." : "[!] There are " + policyDirectoryFiles.Count + " policy files and " + tests.Count + " tasks assigned.");



                        /*
                         * Rrun through each entry in the dictionary of test cases,
                         *
                         */
                        using (myConn = new MySqlConnection(sfwrString))
                        {
                            myConn.Open();
                            foreach (KeyValuePair <int, TestPackage> entry in tests)
                            {
                                TestPackage test = entry.Value;

ReTest:
                                try
                                {
                                    /*
                                     * Query SLM, if any result is given test is a pass else fail
                                     */
                                    myCmd          = new MySqlCommand("SELECT * FROM software WHERE task_id=" + test.TaskID, myConn);
                                    myReader       = myCmd.ExecuteReader();
                                    test.NewResult = new TestResult("SLM Entry Exists", (myReader.HasRows) ? "1" : "0", "");
                                    myReader.Close();



                                    /*
                                     * If there is no xml file for the package, continue
                                     * For the package that cannot be deployed, add a test result saying so
                                     * If it can be deployed, add a positive test result
                                     */
                                    if (!test.isDeployable)
                                    {
                                        Console.WriteLine("[!] Continuing, cannot deploy " + test.Name);
                                        test.NewResult = new TestResult("LANDesk Task Available", "0", "Policy file not found.");
                                        continue;
                                    }
                                    else
                                    {
                                        Console.WriteLine("[*] Deploying " + test.Name);
                                        test.NewResult = new TestResult("LANDesk Task Available", "1", "");
                                    }



                                    /*
                                     * Directory for pictures resolved from resultDir and taskID
                                     */
                                    picDir = resultDir + test.TaskID + @"\";
                                    System.IO.Directory.CreateDirectory(picDir);



                                    /*
                                     * Get the number of registry entries in the LANDesk reg folder before deployment
                                     */
                                    int beforeDeploy = getRegEntryNum(vm);



                                    /*
                                     * Capture the process to determine when the deployment is complete
                                     * Start timing the deployment from when the PsExec process is detected
                                     */
                                    VMWareVirtualMachine.Process deployProcess = detachSystemCommand(@"C:\Program Files (x86)\LANDesk\LDClient\SDCLIENT.EXE", test.Cmd, vm);
                                    stopwatch.Restart();



                                    /*
                                     * While the program deploys
                                     * if 10000ms has passed since last pic taken, take a pic and increment
                                     * if the test is taking too long, add a failed test, revert snapshot, convert
                                     * png files to single gif and go to the next test
                                     */
                                    int pictureCount = 0;
                                    while (vm.GuestProcesses.FindProcess(deployProcess.Name, StringComparison.CurrentCulture) != null)
                                    {
                                        if (stopwatch.ElapsedMilliseconds > pictureCount * picTime)
                                        {
                                            vm.CaptureScreenImage().Save(picDir + pictureCount++.ToString() + @".png");
                                        }
                                        if (stopwatch.ElapsedMilliseconds > test.MaxTime)
                                        {
                                            test.NewResult = new TestResult("LANDesk Task Completed", "0", "");
                                            test.Pngs      = Directory.GetFiles(picDir);
                                            test.PicsDir   = picDir;
                                            revertAndLogin(vm);
                                            goto NextTest;
                                        }
                                    }
                                    stopwatch.Stop();
                                    test.Time      = stopwatch.ElapsedMilliseconds;
                                    test.NewResult = new TestResult("LANDesk Task Completed", "1", test.Time.ToString());
                                    detachSystemCommand(@"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe", "-command \"& {&\'Stop-Process\' -processname htmldialog}\"", vm);
                                    Console.WriteLine("[\u221A] Task complete. Task took " + (test.Time / 1000) + " seconds.");



                                    /*
                                     * The task has successfully completed running, we now add to the TestPackage object the
                                     * names of all .png files and the location of these files, for later gif creation.
                                     */
                                    test.Pngs    = Directory.GetFiles(picDir);
                                    test.PicsDir = picDir;



                                    /*
                                     * Test if a new registry key was added. If there are more registry entries now than before the deployment,
                                     * pass. Otherwise fail.
                                     */
                                    test.NewResult = new TestResult("Registry Key Added", (beforeDeploy < getRegEntryNum(vm)) ? "1" : "0", "");



                                    /*
                                     * Check to see if any of the exe's returned by query to database exist on the guest
                                     *
                                     */
                                    bool anyExeOnGuest = false;
                                    myCmd    = new MySqlCommand(Properties.Resources.exeQuery + test.TaskID, myConn);
                                    myReader = myCmd.ExecuteReader();
                                    if (!myReader.HasRows)
                                    {
                                        anyExeOnGuest = true;
                                    }
                                    else
                                    {
                                        while (myReader.Read())
                                        {
                                            string exeName = myReader.GetString(2);
                                            string fileId  = myReader.GetString(0);
                                            if (vm.FileExistsInGuest(exeName))
                                            {
                                                /*
                                                 * If the file exists on the guest; run the exe, wait 60 seconds and take a pic.
                                                 */
                                                anyExeOnGuest = true;
                                                VMWareVirtualMachine.Process testExe = vm.DetachProgramInGuest(myReader.GetString(2));
                                                stopwatch.Restart();
                                                while (stopwatch.ElapsedMilliseconds < 60000 && vm.GuestProcesses.FindProcess(testExe.Name, StringComparison.CurrentCulture) != null)
                                                {
                                                    ;
                                                }
                                                if (vm.GuestProcesses.FindProcess(testExe.Name, StringComparison.CurrentCulture) != null)
                                                {
                                                    vm.CaptureScreenImage().Save(picDir + "exescreen_" + fileId + ".png");
                                                    try
                                                    {
                                                        testExe.KillProcessInGuest();
                                                    }
                                                    catch { }
                                                }
                                                detachSystemCommand(@"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe", "-command \"& {&\'Stop-Process\' -processname @(javaw, java)}\"", vm);
                                                test.NewResult = new TestResult("Ran EXE - " + Path.GetFileName(exeName), "1", fileId);
                                            }
                                        }// end myReader.Read() while
                                    }



                                    /*
                                     * If there are no exe's on the guest, result is a fail.
                                     * If there are, result is a pass with optional message
                                     */
                                    test.NewResult = (!anyExeOnGuest) ? new TestResult("Files Installed", "0", "") : new TestResult("Files Installed", "1", (!myReader.HasRows) ? "No executables returned" : "");
                                    myReader.Close();



                                    /*
                                     *
                                     * If the number of tests completed is greater than the revert
                                     * threshold, revert and continue testing.
                                     * Otherwise, kill the htmldialog.exe process for the next test.
                                     */
                                    if (++count == testPerSnap)
                                    {
                                        revertAndLogin(vm);
                                    }
                                }
                                catch (Exception e)
                                {
                                    /*
                                     * If this code is reached, test has not completed.
                                     * If this is not the first test deployed since a test passed, revert and try the test again.
                                     * Otherwise, revert and move to the next test.
                                     * Add a test result containing some info from Exception e
                                     */
                                    if (count != 0)
                                    {
                                        Console.WriteLine("[!] Test suite error.");
                                        Console.WriteLine("[!] Restarting test of " + test.Name);
                                        revertAndLogin(vm);
                                        goto ReTest;
                                    }
                                    test.NewResult = new TestResult("Test Suite Error", "0", e.Message);
                                    Console.WriteLine("[!] Exception caught, rolling back then moving to next test: ");
                                    Console.WriteLine("Type: " + e.GetType().ToString());
                                    Console.WriteLine("Message: " + e.Message);
                                    Console.WriteLine("Stack trace:\n" + e.StackTrace);
                                    revertAndLogin(vm);
                                }

                                NextTest :;
                            }// end foreach


                            try
                            {
                                /*
                                 * We now have a dictionary of all the tests with taskID as the keys.
                                 * Send the results to the SQL server
                                 */
                                Console.WriteLine("[\u221A] Sending test results to database.");
                                myDeleteCmd = new MySqlCommand("DELETE FROM unit_test WHERE image=?image AND task_id=?task");
                                myDeleteCmd.Parameters.AddWithValue("?image", imageName);
                                myDeleteCmd.Parameters.AddWithValue("?task", "");
                                myDeleteCmd.Connection  = myConn;
                                myDeleteCmd.CommandType = System.Data.CommandType.Text;

                                myCmd             = new MySqlCommand(@"INSERT INTO unit_test (task_id, image, test_name, result, message) VALUES (?task_id, ?image, ?test_name, ?result, ?message)");
                                myCmd.CommandType = System.Data.CommandType.Text;
                                myCmd.Connection  = myConn;
                                myCmd.Parameters.AddWithValue("?image", imageName);
                                myCmd.Parameters.AddWithValue("?task_id", "");
                                myCmd.Parameters.AddWithValue("?test_name", "");
                                myCmd.Parameters.AddWithValue("?result", "");
                                myCmd.Parameters.AddWithValue("?message", "");

                                foreach (KeyValuePair <int, TestPackage> entry in tests)
                                {
                                    myDeleteCmd.Parameters["?task"].Value = entry.Value.TaskID;
                                    myDeleteCmd.ExecuteNonQuery();

                                    myCmd.Parameters["?task_id"].Value = entry.Value.TaskID;
                                    foreach (TestResult result in entry.Value.AllResults)
                                    {
                                        myCmd.Parameters["?test_name"].Value = result.Name;
                                        myCmd.Parameters["?result"].Value    = result.Result;
                                        myCmd.Parameters["?message"].Value   = result.Message;
                                        myCmd.ExecuteNonQuery();
                                    }
                                }

                                Console.WriteLine("[\u221A] Results committed to database.");
                            }


                            /*
                             * If the database commit failed, print all results to a file in the working directory.
                             */
                            catch (Exception)
                            {
                                string       fileName = screenShotsDir + @"\log\" + string.Format("{0:yyyy-MM-dd_hh-mm-ss-tt}", DateTime.Now) + ".txt";
                                FileStream   fStream  = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write);
                                StreamWriter fileOut  = new StreamWriter(fStream);
                                foreach (KeyValuePair <int, TestPackage> pair in tests)
                                {
                                    foreach (TestResult result in pair.Value.AllResults)
                                    {
                                        fileOut.WriteLine(pair.Key.ToString() + "," + imageName + "," + result.Name + "," + result.Result + "," + result.Message);
                                    }
                                }
                                Console.WriteLine("[\u221A] Results written to file.\n" + fileName);
                            }
                        }// end of myConn using statement



                        /*
                         * Gif creation
                         */
                        Console.WriteLine("[\u221A] Creating gifs.");
                        foreach (KeyValuePair <int, TestPackage> pair in tests)
                        {
                            pair.Value.createGif();
                        }



                        /*
                         * Copy the screenshots and gifs to the share
                         */
                        CopyFolder(resultDir, screenShotsDir);

                        Console.WriteLine("[\u221A] Testing complete. Exiting.");
                    }// end try



                    /*
                     * If for whatever reason an exception is thrown, print the error message to the screen.
                     * Distinguish between VMWare exception and other exceptions.
                     */
                    catch (VMWareException vmwe)
                    {
                        Console.WriteLine("[!] VMware exception: " + vmwe.Message);
                        Console.WriteLine(vmwe.ToString());
                        Console.WriteLine(vmwe.Source);
                        Environment.Exit(0);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("[!] Exception: " + e.Message + "\n");
                        Console.WriteLine("[!] Type:" + e.GetType());
                        Console.WriteLine(e.Source);
                        Console.WriteLine(e.StackTrace);
                        Environment.Exit(0);
                    }
                } // End vm using
            }     // End vhost using
        }         // end main
        // Main method. Start point of the program
        static void Main(string[] args)
        {
            /*
             * Print a banner to the screen
             */
            Console.WriteLine(Properties.Resources.banner);



            /*
             * Do nothing if no arguments given.
             * 
             * if the argument is -f, output to a file instead of console.
             */
            if (args.Length == 0 || args == null) Environment.Exit(0);
            else if (args[0] == "-f") consoleOut = false;



            /*
             * Get the current directory and store in a variable to avoid multiple calls
             */
            workingDir = Directory.GetCurrentDirectory();



            /*
             * Check to ensure that the pstemp directory is present in the same directory as
             * the TestSuite.exe file, with all important files included
             */
            pstempHost = workingDir + @"\pstemp";
            if (!Directory.Exists(pstempHost))
            {
                Console.WriteLine("[!] Error: the pstemp directory does not exist.");
                Environment.Exit(0);
            }
            else if (!File.Exists(pstempHost + @"\hstart64.exe") ||
                    !File.Exists(pstempHost + @"\PsExec.exe"))
            {
                Console.WriteLine("[!] Error: one or more files missing from pstemp directory.");
                Environment.Exit(0);
            }




            /*
             * Read lines from teh variables.ini file and set variables accordingly
             */
            string[] vars = File.ReadAllLines(workingDir + @"\Resources\variables.ini");
            foreach (string var in vars)
            {
                if (var.Contains("DOMAIN=")) domainName = var.Replace("DOMAIN=", "");
                else if (var.Contains("USERNAME="******"USERNAME="******"");
                else if (var.Contains("PASSWORD="******"PASSWORD="******"");
                else if (var.Contains("VMX=")) vmxPath = var.Replace("VMX=", "");
                else if (var.Contains("CPUID=")) compId = var.Replace("CPUID=", "");
                else if (var.Contains("TESTSPERSNAP=")) testPerSnap = int.Parse(var.Replace("TESTSPERSNAP=", ""));
                else if (var.Contains("TASKCNXNSTRING=")) taskString = var.Replace("TASKCNXNSTRING=", "");
                else if (var.Contains("IMAGENAME=")) imageName = var.Replace("IMAGENAME=", "");
                else if (var.Contains("PICTIME=")) picTime = int.Parse(var.Replace("PICTIME=", ""));
                else if (var.Contains("USESERVER=")) useServer = bool.Parse(var.Replace("USESERVER=", ""));
                else if (var.Contains("HOSTNAME=")) hostName = var.Replace("HOSTNAME=", "");
                else if (var.Contains("HOSTUSER="******"HOSTUSER="******"");
                else if (var.Contains("HOSTPASS="******"HOSTPASS="******"");
                else if (var.Contains("SFWRCNXNSTRING=")) sfwrString = var.Replace("SFWRCNXNSTRING=", "");
                else if (var.Contains("SCREENSHOTSDIR=")) screenShotsDir = var.Replace("SCREENSHOTSDIR=", "");
            }





            /*
             * If some variable is not initialized, exit.
             */
            if (domainName == null ||
                usrnm == null ||
                psswd == null ||
                vmxPath == null ||
                compId == null ||
                taskString == null ||
                useServer == null ||
                sfwrString == null)
            {
                Console.WriteLine("[!] An essential variable has not been initiated. See variables.ini");
                Environment.Exit(0);
            }




            /*
             * If no image name was given, use the name of the VMX file
             */
            if (imageName == null) imageName = Path.GetFileNameWithoutExtension(vmxPath);
            screenShotsDir = screenShotsDir + imageName;



            /*
             * If the output is specified to file, redirect all Console.WriteLine to a file instead of the console.
             */
            if (!consoleOut)
            {
                FileStream fStream = new FileStream(screenShotsDir + @"\log\" + string.Format("{0:yyyy-MM-dd_hh-mm-ss-tt}", DateTime.Now) + ".txt", FileMode.OpenOrCreate, FileAccess.Write);
                StreamWriter fileOut = new StreamWriter(fStream);
                Console.SetOut(fileOut);
            }


            /*
             * If useServer is true and any of the essential server variables are empty, quit
             */
            if ((bool)useServer && (hostName == null ||
                            hostPass == null ||
                             hostUser == null))
            {
                Console.WriteLine("[!] Variables.ini is not configured for server use.");
                Environment.Exit(0);
            }




            /*
             * Create a new directory with the date and time stamp to store the test results
             */
            resultDir = workingDir + @"\Results\";
            System.IO.Directory.CreateDirectory(resultDir);


            resultDir = resultDir + imageName + @"\";
            System.IO.Directory.CreateDirectory(resultDir);






            /*
             * Create the autoLogon.reg file, used to allow auto-logon in the guest OS after snapshot revert

             * Sets to auto login
             * Turns off screensaver (broken?)
             * Turns off lock screen (broken?)
             */
            try
            {
                if (File.Exists(pstempHost + @"\autoLogon.reg")) File.Delete(pstempHost + @"\autoLogon.reg");
                string[] lines = { "Windows Registry Editor Version 5.00",
                                 @"[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon]",
                                 "\"DefaultUserName\"=\"" + usrnm + "\"",
                                 "\"DefaultDomainName\"=\"" + domainName + "\"",
                                 "\"DefaultPassword\"=\"" + psswd + "\"",
                                 "\"AutoAdminLogon\"=\"1\"",
                                 "",
                                 @"[HKEY_CURRENT_USER\Control Panel\Desktop]",
                                 "\"ScreenSaveActive\"=\"0\"",
                                 "",
                                 @"[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Personalization]",
                                 "\"NoLockScreen\"=dword:00000001"};
                File.WriteAllLines(pstempHost + @"\autoLogon.reg", lines);
            }
            catch (Exception e)
            {
                Console.WriteLine("[!] Could not create auto-login registry file. You may need to do this manually.");
                Console.WriteLine("[?] Exception message: " + e.Message);
            }




            /*
             * Query the SQL database and use the reader to create a collection of 
             * the information
             */
            try
            {
                conn = new SqlConnection(taskString);
                conn.Open();
                cmd = new SqlCommand(Properties.Resources.taskQuery + compId, conn); // use the command resource, add the computer ID number
                reader = cmd.ExecuteReader();
                tests = new Dictionary<int, TestPackage>();
                while (reader.Read()) tests.Add(reader.GetInt32(1), new TestPackage(reader.GetString(0), reader.GetInt32(1).ToString()));
                reader.Close();
                conn.Close();
                Console.WriteLine("[i] " + tests.Count + " packages assigned to this machine.");

            }
            catch (SqlException sqle)
            {
                Console.WriteLine("Exception thrown: " + sqle.Message);
                Environment.Exit(0);
            }




            /*
             * Create VirtualHost and VirtualMachine objects with using directive
             */
            using (VMWareVirtualHost vhost = new VMWareVirtualHost())
            {


                /*
                 * Connect to either vSphere or Workstation, based on useServer variable
                 */
                if ((bool)useServer)
                {
                    vhost.ConnectToVMWareVIServer(hostName, hostUser, hostPass);
                    Console.WriteLine("[\u221A] Connected to vSphere.");
                }
                else
                {
                    vhost.ConnectToVMWareWorkstation();
                    Console.WriteLine("[\u221A] Connected to VMWareWorkstation.");
                }


                /*
                 * Open a virtual machine using the vmxPath
                 */
                using (VMWareVirtualMachine vm = vhost.Open(vmxPath))
                {
                    Console.WriteLine("[\u221A] Virtual machine opened.");




                    /*
                     * Power on the virtual machine and log in interactively.
                     * Requires user to log in interactively on the VM
                     */
                    try
                    {
                        vm.PowerOn();
                        Console.WriteLine("[\u221A] Powered on.");

                        vm.WaitForToolsInGuest();
                        Console.WriteLine("[\u221A] Tools found in guest.");


                        /*
                         * Login using the interactive login procedure
                         */
                        interactiveLogin(vm);



                        /*
                         * Copy necessary files for SYSTEM execution from host to guest.
                         * 
                         */
                        if (vm.DirectoryExistsInGuest(pstempGuest)) vm.DeleteDirectoryFromGuest(pstempGuest);
                        vm.CopyFileFromHostToGuest(pstempHost, pstempGuest);
                        Console.WriteLine("[\u221A] Files copied to temp directory " + pstempGuest + ".");





                     
                        /*
                         * Run the AutoLogon script for proper VM rollbacks
                         * We try try to delete the PSEXESVC process, if it exists. If it doesn't it throws an exception,
                         * which we ignore.
                         */
                        VMWareVirtualMachine.Process reg = detachSystemCommand(@"C:\Windows\regedit.exe", "/s \"" + pstempGuest + "\\autoLogon.reg\"", vm);
                        if (reg != null) while (vm.GuestProcesses.FindProcess(reg.Name, StringComparison.CurrentCulture) != null) ;
                        Console.WriteLine("[\u221A] Registry configured for auto logon.");




                        /*
                         * Create snapshot for deployment rollbacks
                         * If a snapshot 
                         */
                        try
                        {
                            deployPoint = vm.Snapshots.GetNamedSnapshot(snapName);
                            deployPoint.RemoveSnapshot();
                        }
                        catch (VMWareException) { }

                        deployPoint = vm.Snapshots.CreateSnapshot(snapName, "Start point for deployment tests");
                        Console.WriteLine("[\u221A] Snapshot 'deployPoint' captured.");


                        /*
                         * Sync policies with server.
                         */
                        policySync(vm);




                        /*
                         * Create a list of all files in the policy directory
                         * Remove all non-xml files from the list
                         * Look for the task ID in the file name, and map the file name to the correct package
                         */

                        policyDirectoryFiles = vm.ListDirectoryInGuest(@"C:\ProgramData\LANDesk\Policies", false);
                        policyDirectoryFiles.RemoveAll(x => !(x.Contains(".xml")));

                        foreach (string dir in policyDirectoryFiles)
                        {
                            Match m = idPattern.Match(dir);
                            int key = (m.Success) ? Int32.Parse(m.Value.Substring(3, 4)) : -1;
                            if (tests.ContainsKey(key)) tests[key].Cmd = dir;
                        }
                        Console.WriteLine((policyDirectoryFiles.Count == tests.Count) ? "[\u221A] All packages can be deployed." : "[!] There are " + policyDirectoryFiles.Count + " policy files and " + tests.Count + " tasks assigned.");





                        /*
                         * Rrun through each entry in the dictionary of test cases,
                         * 
                         */
                        using (myConn = new MySqlConnection(sfwrString))
                        {
                            myConn.Open();
                            foreach (KeyValuePair<int, TestPackage> entry in tests)
                            {
                                TestPackage test = entry.Value;

                            ReTest:
                                try
                                {


                                    /*
                                     * Query SLM, if any result is given test is a pass else fail
                                     */
                                    myCmd = new MySqlCommand("SELECT * FROM software WHERE task_id=" + test.TaskID, myConn);
                                    myReader = myCmd.ExecuteReader();
                                    test.NewResult = new TestResult("SLM Entry Exists", (myReader.HasRows) ? "1" : "0", "");
                                    myReader.Close();



                                    /*
                                     * If there is no xml file for the package, continue
                                     * For the package that cannot be deployed, add a test result saying so
                                     * If it can be deployed, add a positive test result
                                     */
                                    if (!test.isDeployable)
                                    {

                                        Console.WriteLine("[!] Continuing, cannot deploy " + test.Name);
                                        test.NewResult = new TestResult("LANDesk Task Available", "0", "Policy file not found.");
                                        continue;
                                    }
                                    else
                                    {
                                        Console.WriteLine("[*] Deploying " + test.Name);
                                        test.NewResult = new TestResult("LANDesk Task Available", "1", "");
                                    }



                                    /*
                                     * Directory for pictures resolved from resultDir and taskID
                                     */
                                    picDir = resultDir + test.TaskID + @"\";
                                    System.IO.Directory.CreateDirectory(picDir);




                                    /*
                                     * Get the number of registry entries in the LANDesk reg folder before deployment
                                     */
                                    int beforeDeploy = getRegEntryNum(vm);



                                    /*
                                     * Capture the process to determine when the deployment is complete
                                     * Start timing the deployment from when the PsExec process is detected
                                     */
                                    VMWareVirtualMachine.Process deployProcess = detachSystemCommand(@"C:\Program Files (x86)\LANDesk\LDClient\SDCLIENT.EXE", test.Cmd, vm);
                                    stopwatch.Restart();




                                    /*
                                     * While the program deploys
                                     * if 10000ms has passed since last pic taken, take a pic and increment
                                     * if the test is taking too long, add a failed test, revert snapshot, convert
                                     * png files to single gif and go to the next test
                                     */
                                    int pictureCount = 0;
                                    while (vm.GuestProcesses.FindProcess(deployProcess.Name, StringComparison.CurrentCulture) != null)
                                    {
                                        if (stopwatch.ElapsedMilliseconds > pictureCount * picTime) vm.CaptureScreenImage().Save(picDir + pictureCount++.ToString() + @".png");
                                        if (stopwatch.ElapsedMilliseconds > test.MaxTime)
                                        {
                                            test.NewResult = new TestResult("LANDesk Task Completed", "0", "");
                                            test.Pngs = Directory.GetFiles(picDir);
                                            test.PicsDir = picDir;
                                            revertAndLogin(vm);
                                            goto NextTest;
                                        }
                                    }
                                    stopwatch.Stop();
                                    test.Time = stopwatch.ElapsedMilliseconds;
                                    test.NewResult = new TestResult("LANDesk Task Completed", "1", test.Time.ToString());
                                    detachSystemCommand(@"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe", "-command \"& {&\'Stop-Process\' -processname htmldialog}\"", vm);
                                    Console.WriteLine("[\u221A] Task complete. Task took " + (test.Time / 1000) + " seconds.");





                                    /*
                                     * The task has successfully completed running, we now add to the TestPackage object the
                                     * names of all .png files and the location of these files, for later gif creation.
                                     */
                                    test.Pngs = Directory.GetFiles(picDir);
                                    test.PicsDir = picDir;





                                    /*
                                     * Test if a new registry key was added. If there are more registry entries now than before the deployment,
                                     * pass. Otherwise fail.
                                     */
                                    test.NewResult = new TestResult("Registry Key Added", (beforeDeploy < getRegEntryNum(vm)) ? "1" : "0", "");





                                    /*
                                     * Check to see if any of the exe's returned by query to database exist on the guest
                                     * 
                                     */
                                    bool anyExeOnGuest = false;
                                    myCmd = new MySqlCommand(Properties.Resources.exeQuery + test.TaskID, myConn);
                                    myReader = myCmd.ExecuteReader();
                                    if (!myReader.HasRows) anyExeOnGuest = true;
                                    else
                                    {
                                        while (myReader.Read())
                                        {
                                            string exeName = myReader.GetString(2);
                                            string fileId = myReader.GetString(0);
                                            if (vm.FileExistsInGuest(exeName))
                                            {
                                                /*
                                                 * If the file exists on the guest; run the exe, wait 60 seconds and take a pic.
                                                 */
                                                anyExeOnGuest = true;
                                                VMWareVirtualMachine.Process testExe = vm.DetachProgramInGuest(myReader.GetString(2));
                                                stopwatch.Restart();
                                                while (stopwatch.ElapsedMilliseconds < 60000 && vm.GuestProcesses.FindProcess(testExe.Name, StringComparison.CurrentCulture) != null) ;
                                                if (vm.GuestProcesses.FindProcess(testExe.Name, StringComparison.CurrentCulture) != null)
                                                {
                                                    vm.CaptureScreenImage().Save(picDir + "exescreen_" + fileId + ".png");
                                                    try
                                                    {
                                                        testExe.KillProcessInGuest();
                                                    }
                                                    catch { }
                                                }
                                                detachSystemCommand(@"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe", "-command \"& {&\'Stop-Process\' -processname @(javaw, java)}\"", vm);
                                                test.NewResult = new TestResult("Ran EXE - " + Path.GetFileName(exeName), "1", fileId);
                                            }
                                        }// end myReader.Read() while
                                    }





                                    /*
                                     * If there are no exe's on the guest, result is a fail.
                                     * If there are, result is a pass with optional message
                                     */
                                    test.NewResult = (!anyExeOnGuest) ? new TestResult("Files Installed", "0", "") : new TestResult("Files Installed", "1", (!myReader.HasRows) ? "No executables returned" : "");
                                    myReader.Close();





                                    /*
                                     * 
                                     * If the number of tests completed is greater than the revert
                                     * threshold, revert and continue testing.
                                     * Otherwise, kill the htmldialog.exe process for the next test.
                                     */
                                    if (++count == testPerSnap) revertAndLogin(vm);
                                }
                                catch (Exception e)
                                {
                                    /*
                                     * If this code is reached, test has not completed.
                                     * If this is not the first test deployed since a test passed, revert and try the test again.
                                     * Otherwise, revert and move to the next test.
                                     * Add a test result containing some info from Exception e
                                     */
                                    if (count != 0)
                                    {
                                        Console.WriteLine("[!] Test suite error.");
                                        Console.WriteLine("[!] Restarting test of " + test.Name);
                                        revertAndLogin(vm);
                                        goto ReTest;
                                    }
                                    test.NewResult = new TestResult("Test Suite Error", "0", e.Message);
                                    Console.WriteLine("[!] Exception caught, rolling back then moving to next test: ");
                                    Console.WriteLine("Type: " + e.GetType().ToString());
                                    Console.WriteLine("Message: " + e.Message);
                                    Console.WriteLine("Stack trace:\n" + e.StackTrace);
                                    revertAndLogin(vm);
                                }

                            NextTest:;
                            }// end foreach


                            try
                            {
                                /*
                             * We now have a dictionary of all the tests with taskID as the keys.
                             * Send the results to the SQL server
                             */
                                Console.WriteLine("[\u221A] Sending test results to database.");
                                myDeleteCmd = new MySqlCommand("DELETE FROM unit_test WHERE image=?image AND task_id=?task");
                                myDeleteCmd.Parameters.AddWithValue("?image", imageName);
                                myDeleteCmd.Parameters.AddWithValue("?task", "");
                                myDeleteCmd.Connection = myConn;
                                myDeleteCmd.CommandType = System.Data.CommandType.Text;

                                myCmd = new MySqlCommand(@"INSERT INTO unit_test (task_id, image, test_name, result, message) VALUES (?task_id, ?image, ?test_name, ?result, ?message)");
                                myCmd.CommandType = System.Data.CommandType.Text;
                                myCmd.Connection = myConn;
                                myCmd.Parameters.AddWithValue("?image", imageName);
                                myCmd.Parameters.AddWithValue("?task_id", "");
                                myCmd.Parameters.AddWithValue("?test_name", "");
                                myCmd.Parameters.AddWithValue("?result", "");
                                myCmd.Parameters.AddWithValue("?message", "");

                                foreach (KeyValuePair<int, TestPackage> entry in tests)
                                {

                                    myDeleteCmd.Parameters["?task"].Value = entry.Value.TaskID;
                                    myDeleteCmd.ExecuteNonQuery();

                                    myCmd.Parameters["?task_id"].Value = entry.Value.TaskID;
                                    foreach (TestResult result in entry.Value.AllResults)
                                    {
                                        myCmd.Parameters["?test_name"].Value = result.Name;
                                        myCmd.Parameters["?result"].Value = result.Result;
                                        myCmd.Parameters["?message"].Value = result.Message;
                                        myCmd.ExecuteNonQuery();
                                    }
                                }

                                Console.WriteLine("[\u221A] Results committed to database.");
                            }


                            /*
                             * If the database commit failed, print all results to a file in the working directory.
                             */
                            catch (Exception)
                            {
                                string fileName = screenShotsDir + @"\log\" + string.Format("{0:yyyy-MM-dd_hh-mm-ss-tt}", DateTime.Now) + ".txt";
                                FileStream fStream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write);
                                StreamWriter fileOut = new StreamWriter(fStream);
                                foreach(KeyValuePair<int, TestPackage> pair in tests)
                                {
                                    foreach(TestResult result in pair.Value.AllResults)
                                    {
                                        fileOut.WriteLine(pair.Key.ToString() + "," + imageName + "," + result.Name + "," + result.Result + "," + result.Message);
                                    }
                                }
                                Console.WriteLine("[\u221A] Results written to file.\n" + fileName);
                            }

                        }// end of myConn using statement




                        /*
                         * Gif creation
                         */
                        Console.WriteLine("[\u221A] Creating gifs.");
                        foreach (KeyValuePair<int, TestPackage> pair in tests) pair.Value.createGif();



                        /*
                         * Copy the screenshots and gifs to the share
                         */
                        CopyFolder(resultDir, screenShotsDir);

                        Console.WriteLine("[\u221A] Testing complete. Exiting.");
                    }// end try



                    /*
                     * If for whatever reason an exception is thrown, print the error message to the screen.
                     * Distinguish between VMWare exception and other exceptions.
                     */
                    catch (VMWareException vmwe)
                    {
                        Console.WriteLine("[!] VMware exception: " + vmwe.Message);
                        Console.WriteLine(vmwe.ToString());
                        Console.WriteLine(vmwe.Source);
                        Environment.Exit(0);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("[!] Exception: " + e.Message + "\n");
                        Console.WriteLine("[!] Type:" + e.GetType());
                        Console.WriteLine(e.Source);
                        Console.WriteLine(e.StackTrace);
                        Environment.Exit(0);
                    }
                }// End vm using
            }// End vhost using
        }// end main
 /// <summary>
 /// Delete/remove a snapshot.
 /// </summary>
 /// <param name="item">Snapshot to delete.</param>
 /// <returns>True if the snapshot was deleted.</returns>
 public void RemoveSnapshot(VMWareSnapshot item)
 {
     RemoveSnapshot(item, VMWareInterop.Timeouts.RemoveSnapshotTimeout);
 }
 /// <summary>
 /// Delete/remove a snapshot.
 /// </summary>
 /// <param name="item">Snapshot to delete.</param>
 /// <param name="timeoutInSeconds">Timeout in seconds.</param>
 /// <returns>True if the snapshot was deleted.</returns>
 public void RemoveSnapshot(VMWareSnapshot item, int timeoutInSeconds)
 {
     item.RemoveSnapshot(timeoutInSeconds);
     RemoveAll();
 }