// reads message off the queue; calls ProcessMessage internal void PeekMessage(string mqPath) { try { // grab a handle to the queue MessageQueue mq = new MessageQueue(mqPath); ((XmlMessageFormatter)mq.Formatter).TargetTypeNames = new string[] { "System.String" }; // receive the next message with a timeout of 30 seconds System.Messaging.Message msg = mq.Peek(new TimeSpan(0, 0, 0, Constants.QUEUE_TIMEOUT, 0)); // save message ID; will remove from queue later if all is successful string msgId = msg.Id; // log SharedSupport.LogMessage(SharedSupport.GetLocalizedString("ServerAction_PeekMessage") + msg.Label + " " + msg.Body); // set boolean to remove from queue bool removeFromQueue = ProcessMessage(msg.Body.ToString(), msg.Label.ToString()); // if ProcessMessage true, remove the message from the queue if (removeFromQueue == true) { mq.ReceiveById(msgId, new TimeSpan(0, 0, 0, Constants.QUEUE_TIMEOUT, 0)); // log SharedSupport.LogMessage(SharedSupport.GetLocalizedString("ServerAction_RemoveMessage") + msg.Label + " " + msg.Body); } } catch (System.Exception ex) { SharedSupport.HandleError(ex); } }
// validates, processes directions inside XML Message; returns true if ok to remove msg from queue internal bool ProcessMessage(string message, string label) { // always return true because always want to remove message from queue in this implementation try { // raise error if no label or message label = label.Trim(); message = message.Trim(); if (label.Equals(String.Empty)) { SharedSupport.HandleError(new System.Exception(SharedSupport.GetLocalizedString("ServerAction_MissingLabel"))); } if (message.Equals(String.Empty)) { SharedSupport.HandleError(new System.Exception(SharedSupport.GetLocalizedString("ServerAction_MissingBody"))); } // xml object declarations XmlDocument doc = new XmlDocument(); doc.LoadXml(message); //load the string as xml XPathNavigator nav = ((IXPathNavigable)doc).CreateNavigator(); // misc vars bool bCheckRequested = false; // track if check requested bool bBuildSuccessful = false; // track if build successful int buildUserAssnId = 0; // build userAssignmentId int checkUserAssnId = 0; // check userAssignmentId string buildResults = string.Empty; // results of the build string checkResults = string.Empty; // results of the check string workingDirectory = string.Empty; // working directory //------------------------------------------------------------------------------------------------------------- // evaluate label, parse xml message; extract instructions //------------------------------------------------------------------------------------------------------------- switch (label) { //////////////////////////////////////////////////////////////// // This is a submit action //////////////////////////////////////////////////////////////// case Constants.AM_SUBMIT_ACTION: // select the serverActions XPathNodeIterator serverActionsIterator = nav.Select("serverActions/serverAction"); // retrieve all serverAction actions from xml while (serverActionsIterator.MoveNext()) { // perform the appropriate action evaluating the serverAction attribute string actionCommand = serverActionsIterator.Current.GetAttribute("name", doc.NamespaceURI).ToString().Trim(); switch (actionCommand) { ////////////////////////////////////////////////////////////// // AutoBuild ///////////////////////////////////////////////////////////// case Constants.AM_BUILD: // grab the userAssignmentId from the xml buildUserAssnId = Convert.ToInt32(serverActionsIterator.Current.Value.ToString()); ///////////////////////////////////////////////// // extensibility: add custom parameters here ///////////////////////////////////////////////// break; ///////////////////////////////////////////////////////////// // AutoCheck ///////////////////////////////////////////////////////////// case Constants.AM_CHECK: // set check flag bCheckRequested = true; // grab the userAssignmentId from the xml checkUserAssnId = Convert.ToInt32(serverActionsIterator.Current.Value.ToString()); ///////////////////////////////////////////////// // extensibility: add custom parameters here ///////////////////////////////////////////////// break; ///////////////////////////////////////////////// // extensibility: add future submit actions here ///////////////////////////////////////////////// // 1. load all actions from ServerActions table // 2. loop actions; do any match xml serverAction element? // 3. if so, retrieve parameters from ServerActions // 4. make 'late bound' call to proper class, method ///////////////////////////////////////////////// default: break; } } break; ///////////////////////////////////////////////// // extensibility: add future actions here ///////////////////////////////////////////////// default: throw new System.NotImplementedException(SharedSupport.GetLocalizedString("ServerAction_ActionNotImplemented")); } //------------------------------------------------------------------------------------------------------------- // execute instructions from xml message in proper order //------------------------------------------------------------------------------------------------------------- // perform prep work, execute build, record results; returns true if successful // we always do the build: necessary for check and expected by custom actions // set the working directory workingDirectory = getUserWorkingDirectory(); //////////////////////////////////////////// // Perform AutoBuild //////////////////////////////////////////// // check to make sure we have a valid userAssignmentId if (buildUserAssnId == 0) { if (checkUserAssnId == 0) { // raise error SharedSupport.HandleError(new System.Exception(SharedSupport.GetLocalizedString("ServerAction_MissingUserAssignmentElement"))); } else { // set the buildUserAssnId = check buildUserAssnId = checkUserAssnId; } } // raise error if no buildUserAssnId if (buildUserAssnId <= 0) { SharedSupport.HandleError(new System.Exception(SharedSupport.GetLocalizedString("ServerAction_MissingUserAssignmentElement"))); } // raise error if build disabled on the server if (!Convert.ToBoolean(SharedSupport.GetSetting(Constants.AUTOBUILD_SETTING))) { SharedSupport.HandleError(new System.Exception(SharedSupport.GetLocalizedString("ServerAction_BuildDisabled"))); } // delete any previous user assignment detail records for this userassignment and detail type deleteUserAssignmentDetails(buildUserAssnId, Constants.AUTO_COMPILE_DETAILTYPE); bBuildSuccessful = AutoBuild.Run(buildUserAssnId, workingDirectory); // was check requested? if (bCheckRequested) { //////////////////////////////////////////// // Perform AutoCheck //////////////////////////////////////////// // raise error if no checkUserAssnId if (checkUserAssnId <= 0) { SharedSupport.HandleError(new System.Exception(SharedSupport.GetLocalizedString("ServerAction_MissingUserAssignmentElement"))); } // check that checkUserAssnId = buildUserAssnId; if (checkUserAssnId != buildUserAssnId) { // raise error SharedSupport.HandleError(new System.Exception(SharedSupport.GetLocalizedString("ServerAction_DifferentUserAssignmentIDs"))); } else { // did the build execute ok if it was requested? if (bBuildSuccessful) { // raise error if check disabled on the server if (!Convert.ToBoolean(SharedSupport.GetSetting(Constants.AUTOCHECK_SETTING))) { SharedSupport.HandleError(new System.Exception(SharedSupport.GetLocalizedString("ServerAction_CheckDisabled"))); } AutoCheck.Run(buildUserAssnId, workingDirectory); } } } //////////////////////////////////////////// // extensibility: CUSTOM ACTIONS //////////////////////////////////////////// } catch (System.Exception ex) { SharedSupport.LogMessage(ex.Message + " " + SharedSupport.GetLocalizedString("ServerAction_GeneralProcessError") + " " + label + " " + SharedSupport.GetLocalizedString("ServerAction_GeneralProcessErrorBody") + " " + message + " ", SharedSupport.GetLocalizedString("ServerAction_MethodName"), System.Diagnostics.EventLogEntryType.Warning); } // returning true here ensures message is removed from the queue return(true); }
internal bool Run(int maxTime) { IntPtr hJob = IntPtr.Zero; IntPtr hUser = IntPtr.Zero; IntPtr hEnvironment = IntPtr.Zero; STARTUPINFO si = new STARTUPINFO(); PROCESS_INFORMATION pi = new PROCESS_INFORMATION(); PROFILEINFOW profInfo = new PROFILEINFOW(); profInfo.lpUserName = null; pi.hProcess = IntPtr.Zero; pi.hThread = IntPtr.Zero; try { hJob = CreateJobObject(IntPtr.Zero, null); if (hJob == IntPtr.Zero) { SharedSupport.LogMessage("Unable to create the Job object."); return(false); } string commandLine = "\"" + StartInfo.FileName + "\" " + StartInfo.Arguments; if (StartInfo.RedirectStandardInput && System.IO.File.Exists(InputFile)) { commandLine += " < \"" + InputFile + "\""; } if (StartInfo.RedirectStandardOutput) { commandLine += " > \"" + OutputFile + "\""; } si.cb = (uint)Marshal.SizeOf(si); LSAUtil lsaUtil = new LSAUtil(Constants.AMUserLSAPasswordKey); string strPassword = lsaUtil.RetrieveEncryptedString(); string strDomain = System.Environment.MachineName; if (!LogonUserW(Constants.AMUserName, strDomain, strPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out hUser)) { return(false); } profInfo.dwSize = (uint)Marshal.SizeOf(profInfo); profInfo.lpUserName = Constants.AMUserName; if (!LoadUserProfileW(hUser, ref profInfo)) { return(false); } if (!CreateEnvironmentBlock(out hEnvironment, hUser, false)) { return(false); } // Create process suspended commandLine = System.Environment.SystemDirectory + "\\cmd.exe /c \"" + commandLine + "\""; if (!CreateProcessAsUserW(hUser, null, commandLine, IntPtr.Zero, IntPtr.Zero, false, CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT, hEnvironment, StartInfo.WorkingDirectory, ref si, out pi)) { return(false); } if (!AssignProcessToJobObject(hJob, pi.hProcess)) { return(false); } if (ResumeThread(pi.hThread) < 0) { return(false); } IntPtr[] h = { pi.hProcess, hJob }; const int WAIT_OBJECT_0 = 0; uint dw = WaitForMultipleObjects(2, h, false, (uint)maxTime); switch (dw) { case WAIT_OBJECT_0: // Process exited normally HasExited = true; GetExitCodeProcess(pi.hProcess, out ExitCode); break; case WAIT_OBJECT_0 + 1: // If the job object is signaled, it means that it has // terminated because it reached a resource limit. case WAIT_TIMEOUT: // We ran out of time for the process being run by the user. // It will be killed in the 'finally' block when the Job // object is terminated. default: HasExited = false; break; } } finally { if (hEnvironment != IntPtr.Zero) { DestroyEnvironmentBlock(hEnvironment); } if (hUser != IntPtr.Zero && profInfo.lpUserName != String.Empty) { UnloadUserProfile(hUser, profInfo.hProfile); } if (hUser != IntPtr.Zero) { CloseHandle(hUser); hUser = IntPtr.Zero; } if (hJob != IntPtr.Zero) { TerminateJobObject(hJob, 1); CloseHandle(hJob); } if (pi.hThread != IntPtr.Zero) { CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } } return(true); }
public void RunService() { //Spawn new process - invoking the compiledFile UserProcess oProcess = new UserProcess(); try { // set actual output file location actualOutputFileLocation = workingDirectory + actualOutputFile; //Set process start parameters ProcessStartInfo psi = new ProcessStartInfo(); psi.Arguments = commandLineParams; psi.FileName = compiledFileName; psi.WorkingDirectory = workingDirectory; psi.RedirectStandardOutput = true; psi.RedirectStandardError = false; psi.UseShellExecute = false; if (File.Exists(inputFileLocation)) { oProcess.InputFile = workingDirectory + Guid.NewGuid() + ".txt"; File.Copy(inputFileLocation, oProcess.InputFile, true); psi.RedirectStandardInput = true; try { SecurityACL dacl = new SecurityACL(Constants.AMUserName); dacl.ApplyACLToFile(oProcess.InputFile); } catch (Exception) { // Continue on. If we fail to apply the ACL, we may still be able // to autocheck (i.e. if user has set custom permissions. } } oProcess.StartInfo = psi; oProcess.OutputFile = actualOutputFileLocation; //Log start SharedSupport.LogMessage(SharedSupport.GetLocalizedString("StudentAssignment_CheckStart")); if (!oProcess.Run(processTime)) { throw new System.Exception(SharedSupport.GetLocalizedString("ServerAction_FailedCreateTestProcess")); } //wait to see if process comes back in time. Otherwise if it runs too long - kill it if (!oProcess.HasExited) { SharedSupport.LogMessage(SharedSupport.GetLocalizedString("StudentAssignment_CheckKilled")); throw new System.Exception(SharedSupport.GetLocalizedString("StudentAssignemtn_CheckExceededProcessTime")); } else { SharedSupport.LogMessage(SharedSupport.GetLocalizedString("StudentAssignment_CheckEnd")); } } catch (Exception ex) { checkSuccessful = false; errorString = ex.Message; SharedSupport.HandleError(ex); } }