public void TestTasks() { foreach (VMWareVirtualMachine virtualMachine in _test.PoweredVirtualMachines) { // copy a batch file to the remote machine, execute it and collect results string localTempFilename = Path.GetTempFileName(); string remoteTempFilename = string.Format(@"C:\{0}", Path.GetFileName(localTempFilename)); string remoteBatFilename = string.Format(@"C:\{0}.bat", Path.GetFileNameWithoutExtension(localTempFilename)); File.WriteAllText(localTempFilename, string.Format(@"dir C:\ > {0}", remoteTempFilename)); virtualMachine.CopyFileFromHostToGuest(localTempFilename, remoteBatFilename); VMWareVirtualMachine.Process cmdProcess = virtualMachine.RunProgramInGuest( "cmd.exe", string.Format("/C \"{0}\"", remoteBatFilename)); Assert.IsNotNull(cmdProcess); Assert.AreEqual(0, cmdProcess.ExitCode); virtualMachine.CopyFileFromGuestToHost(remoteTempFilename, localTempFilename); string remoteDirectoryListing = File.ReadAllText(localTempFilename); ConsoleOutput.WriteLine(remoteDirectoryListing); Assert.IsTrue(remoteDirectoryListing.Contains(Path.GetFileName(remoteTempFilename))); Assert.IsTrue(remoteDirectoryListing.Contains(Path.GetFileName(remoteBatFilename))); // delete the temp files virtualMachine.DeleteFileFromGuest(remoteTempFilename); virtualMachine.DeleteFileFromGuest(remoteBatFilename); File.Delete(localTempFilename); // virtualMachine.PowerOff(); } }
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(); } }
/// <summary> /// Execute a file from a remote vm. /// </summary> private TaskResult Execute(CommandTaskConfig executeConfig) { TaskResult copyFileResult = new TaskResult(); copyFileResult.CmdLine = executeConfig.CmdLine; copyFileResult.Name = executeConfig.Name; try { ConsoleOutput.WriteLine("{0}{1} 'Remote:{2}'", executeConfig.WaitForCompletion ? "Executing" : "Detaching", executeConfig.ActivateWindow ? " and activating" : "", executeConfig.CmdLine); if (!_installInstance.SimulationOnly) { int options = 0; if (!executeConfig.WaitForCompletion) { options |= Constants.VIX_RUNPROGRAM_RETURN_IMMEDIATELY; } if (executeConfig.ActivateWindow) { options |= Constants.VIX_RUNPROGRAM_ACTIVATE_WINDOW; } VMWareVirtualMachine.Process process = _installInstance.VirtualMachine.RunProgramInGuest( executeConfig.Command, executeConfig.CommandLineArgs, options); string exitCodeAction = "success"; if (executeConfig.IgnoreExitCode) { exitCodeAction = "ignored"; } else if (process.ExitCode != executeConfig.ExitCode) { exitCodeAction = "error"; } ConsoleOutput.WriteLine("Finished 'Remote:{0}', exit code = {1} ({2})", executeConfig.CmdLine, process.ExitCode, exitCodeAction); if (!executeConfig.IgnoreExitCode && executeConfig.WaitForCompletion) { if (process.ExitCode != executeConfig.ExitCode) { throw new Exception(string.Format("Execute failed, return code: {0}", process.ExitCode)); } } } } catch (Exception ex) { copyFileResult.LastError = ex.Message; copyFileResult.Success = false; ConsoleOutput.WriteLine(ex); } return(copyFileResult); }
/* * Detaches commands as the SYSTEM user in the guest OS * Added the /WAIT argument to have hstart64 run until it's called process (PsExec) is done. So tracking hstart is the most * effective way of figuring out if the process is alive. */ private static VMWareVirtualMachine.Process detachSystemCommand(string command, string args, VMWareVirtualMachine sysVm) { VMWareVirtualMachine.Process tst, desiredProc = null, hstartWait = sysVm.DetachProgramInGuest(pstempGuest + @"\hstart64.exe", "/WAIT /UAC \"" + pstempGuest + "\\PsExec.exe /accepteula -i -s \"" + command + "\" " + args + "\""); while ((tst = sysVm.GuestProcesses.FindProcess(hstartWait.Name, StringComparison.CurrentCulture)) != null && desiredProc == null) { desiredProc = sysVm.GuestProcesses.FindProcess(Path.GetFileName(command), StringComparison.CurrentCulture); } return(desiredProc); }
protected void TestRunScriptInGuest() { foreach (VMWareVirtualMachine virtualMachine in _test.PoweredVirtualMachines) { StringBuilder script = new StringBuilder(); script.AppendLine("print \"Hello World\";"); VMWareVirtualMachine.Process cmdProcess = virtualMachine.RunScriptInGuest(@"c:\perl\bin\perl.exe", script.ToString()); Assert.IsNotNull(cmdProcess); Assert.AreEqual(0, cmdProcess.ExitCode); } }
/* * Run PolicySync as system user * To wait for the completion of PolicySync, we look for PsExec.exe process on guest, * when null is returned the process does not exist */ private static void policySync(VMWareVirtualMachine ivm) { VMWareVirtualMachine.Process psync = detachSystemCommand(@"C:\Program Files (x86)\LANDesk\LDClient\PolicySync.exe", "", ivm); if (psync != null) { while (ivm.GuestProcesses.FindProcess(psync.Name, StringComparison.CurrentCulture) != null) { System.Threading.Thread.Sleep(1000); } } Console.WriteLine("[\u221A] PolicySync complete."); }
/* * Runs regedit export of LANDesk software tracking, pulls file from guest -> host and returns number of lines in the file. * */ private static int getRegEntryNum(VMWareVirtualMachine ivm) { if (ivm.FileExistsInGuest(pstempGuest + @"\reg.txt")) { ivm.DeleteFileFromGuest(pstempGuest + @"\reg.txt"); } VMWareVirtualMachine.Process proc = ivm.RunProgramInGuest(@"C:\Windows\System32\Reg.exe", "export \"HKEY_LOCAL_MACHINE\\SOFTWARE\\LANdesk\\SOFTWARE\" \"" + pstempGuest + "\\reg.txt\""); if (File.Exists(workingDir + @"\reg.txt")) { File.Delete(workingDir + @"\reg.txt"); } ivm.CopyFileFromGuestToHost(pstempGuest + @"\reg.txt", workingDir + @"\reg.txt"); return(File.ReadAllLines(workingDir + @"\reg.txt").Length); }
private void Run(out string logfile, string args) { logfile = _config.LogFile; _process = _vm.RunProgramInGuest( _config.DestinationPath, args, 0); if (_config.ExitCodes.Count > 0) { _config.ExitCodes.Check(_process.ExitCode); } else if (_process.ExitCode != 0) { throw new Exception(string.Format("Execution failed, return code: {0}", _process.ExitCode)); } }
/// <summary> /// /// </summary> /// <returns></returns> public override bool Execute() { using (VMWareVirtualHost host = GetConnectedHost()) { using (VMWareVirtualMachine virtualMachine = OpenVirtualMachine(host)) { LoginGuest(virtualMachine); Log.LogMessage(string.Format("Running '{0}{1}'", _guestProgramName, string.IsNullOrEmpty(_commandLineArgs) ? string.Empty : " " + _commandLineArgs)); _process = virtualMachine.RunProgramInGuest(_guestProgramName, _commandLineArgs, 0, _runProgramTimeout); } } return(true); }
/// <summary> /// Execute dotNetInstaller. /// </summary> /// <param name="dniPath"></param> /// <param name="dniArgs"></param> /// <param name="action"></param> /// <param name="logfile"></param> private void DniExec(string dniPath, string dniArgs, DniAction action, out string logfile) { logfile = string.Format("{0}{1}.log", _config.DestinationPath, action); _process = _vm.RunProgramInGuest( _config.DestinationPath, string.Format("/q /log /LogFile \"{0}\" {1}", logfile, dniArgs), 0); if (_config.ExitCodes.Count > 0) { _config.ExitCodes.Check(_process.ExitCode); } else if (_process.ExitCode != 0) { throw new Exception(string.Format("Execution failed, return code: {0}", _process.ExitCode)); } }
public void TestListAndKillProcesses() { foreach (VMWareVirtualMachine virtualMachine in _test.PoweredVirtualMachines) { VMWareVirtualMachine.Process notepadProcess = virtualMachine.DetachProgramInGuest("notepad.exe"); ConsoleOutput.WriteLine("Notepad.exe: {0}", notepadProcess.Id); VMWareProcessCollection guestProcesses = virtualMachine.GuestProcesses; Assert.IsTrue(guestProcesses.ContainsKey(notepadProcess.Id)); foreach (KeyValuePair <long, VMWareVirtualMachine.Process> process in guestProcesses) { Assert.IsTrue(process.Value.Id >= 0); Assert.IsFalse(string.IsNullOrEmpty(process.Value.Name)); ConsoleOutput.WriteLine("{0}: {1} [{2}] ({3})", process.Value.Id, process.Value.Name, process.Value.Command, process.Value.Owner); } notepadProcess.KillProcessInGuest(); Thread.Sleep(3000); // doc says: depending on the behavior of the guest operating system, there may be a short delay after the job completes before the process truly disappears VMWareProcessCollection guestProcesses2 = virtualMachine.GuestProcesses; Assert.IsFalse(guestProcesses2.ContainsKey(notepadProcess.Id)); } }
/// <summary> /// Install an MSI /// </summary> /// <param name="action">msi action</param> /// <param name="msiPath">path to the msi</param> /// <param name="msiArgs">additional msi parameters</param> /// <param name="logfile">resulting log file</param> private void MsiExec(string msiPath, string msiArgs, MsiAction action, out string logfile) { string msiAction = MsiActionToString(action); logfile = string.Format("{0}{1}.log", msiPath, msiAction); _msiexecProcess = this.VirtualMachineHost.RunProgramInGuest( "msiexec.exe", string.Format("/qn /{0} \"{1}\" /l*v \"{2}\" {3}", msiAction, msiPath, logfile, msiArgs), 0); if (_msiexecProcess.ExitCode == 3010) { // reboot required } else if (_msiexecProcess.ExitCode != 0) { throw new Exception(string.Format("{0} failed, return code: {1}", action, _msiexecProcess.ExitCode)); } }
public Process(VMWareVirtualMachine.Process p) { this.p = p; }
/// <summary> /// /// </summary> /// <returns></returns> public override bool Execute() { using (VMWareVirtualHost host = GetConnectedHost()) { using (VMWareVirtualMachine virtualMachine = OpenVirtualMachine(host)) { LoginGuest(virtualMachine); Log.LogMessage(string.Format("Running '{0}{1}'", _guestProgramName, string.IsNullOrEmpty(_commandLineArgs) ? string.Empty : " " + _commandLineArgs)); _process = virtualMachine.RunProgramInGuest(_guestProgramName, _commandLineArgs, 0, _runProgramTimeout); } } return true; }
// 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