/// <summary> /// Helper function that runs all of those checks that operate on each user group; /// intended to make the checks slightly more efficient by running them all at once /// rather than looping through all of the elements multiple times /// </summary> /// <param name="msgs">Add any GP messages to this object</param> /// <param name="errorCount">Counter used to track the number of problems found</param> /// <param name="logFileWriter">Object used to write error descriptions to a text file</param> private void ExecuteGroupChecks(IGPMessages msgs, ref int errorCount, StreamWriter logFileWriter) { // Check for groups w/o privileges if (!m_flagGroupsWithoutPrivileges && !m_flagGroupsWithoutEmails && !m_flagGroupsWithoutUsers) { return; } IJTXConfiguration3 configMgr = this.WmxDatabase.ConfigurationManager as IJTXConfiguration3; IJTXConfigurationEdit2 configEdit = configMgr as IJTXConfigurationEdit2; // Put the items into a sorted list in order to make the output easier to // read/follow IJTXUserGroupSet allGroups = configMgr.UserGroups; SortedList <string, IJTXUserGroup2> allGroupsSorted = new SortedList <string, IJTXUserGroup2>(); for (int i = 0; i < allGroups.Count; i++) { allGroupsSorted[allGroups.get_Item(i).Name] = allGroups.get_Item(i) as IJTXUserGroup2; } // Iterate over each group, performing the specified checks foreach (IJTXUserGroup2 group in allGroupsSorted.Values) { if (m_flagGroupsWithoutPrivileges) { if (group.Privileges.Count < 1) { string message = "Group '" + group.Name + "' has no associated privileges"; RecordMessage(message, msgs, logFileWriter); errorCount++; } } if (m_flagGroupsWithoutEmails) { if (group.Email == null || group.Email.Equals(string.Empty)) { string message = "Group '" + group.Name + "' has no associated e-mail address"; RecordMessage(message, msgs, logFileWriter); errorCount++; } } if (m_flagGroupsWithoutUsers) { if (group.Users.Count <= 0) { string message = "Group '" + group.Name + "' has no users assigned to it"; RecordMessage(message, msgs, logFileWriter); errorCount++; } } } }
/// <summary> /// Helper function that runs all of those checks that operate on each user in /// the database; intended to make the checks slightly more efficient by running /// through them all at once rather than looping through all of the elements /// multiple times /// </summary> /// <param name="msgs">Add any GP messages to this object</param> /// <param name="errorCount">Counter used to track the number of problems found</param> /// <param name="logFileWriter">Object used to write error descriptions to a text file</param> private void ExecuteUserChecks(IGPMessages msgs, ref int errorCount, StreamWriter logFileWriter) { // Only continue executing this function if needed if (!m_flagUsersWithoutEmails && !m_flagUsersWithoutGroups) { return; } IJTXConfiguration3 configMgr = this.WmxDatabase.ConfigurationManager as IJTXConfiguration3; IJTXConfigurationEdit2 configEdit = configMgr as IJTXConfigurationEdit2; // Put the items into a sorted list in order to make the output easier to // read/follow IJTXUserSet allUsers = configMgr.Users; SortedList <string, IJTXUser3> allUsersSorted = new SortedList <string, IJTXUser3>(); for (int i = 0; i < allUsers.Count; i++) { allUsersSorted[allUsers.get_Item(i).UserName] = allUsers.get_Item(i) as IJTXUser3; } // Iterate through each item foreach (IJTXUser3 user in allUsersSorted.Values) { if (m_flagUsersWithoutEmails) { if (user.Email == null || user.Email.Equals(string.Empty)) { string message = "User '" + user.UserName + "' (" + user.FullName + ") does not have an e-mail address configured"; RecordMessage(message, msgs, logFileWriter); errorCount++; } } if (m_flagUsersWithoutGroups) { if (user.Groups.Count < 1) { string message = "User '" + user.UserName + "' (" + user.FullName + ") does not belong to any groups"; RecordMessage(message, msgs, logFileWriter); errorCount++; } } } }
/// <summary> /// Required by IGPFunction2 interface; this function is called when the GP tool is ready to be executed. /// </summary> /// <param name="paramValues"></param> /// <param name="trackCancel"></param> /// <param name="envMgr"></param> /// <param name="msgs"></param> public override void Execute(IArray paramValues, ITrackCancel trackCancel, IGPEnvironmentManager envMgr, IGPMessages msgs) { // Do some common error-checking base.Execute(paramValues, trackCancel, envMgr, msgs); try { // Ensure that the current user has admin access to the current Workflow Manager DB if (!CurrentUserIsWmxAdministrator()) { throw new WmauException(WmauErrorCodes.C_USER_NOT_ADMIN_ERROR); } // Stash away the executing user's information, if appropriate string username = ESRI.ArcGIS.JTXUI.ConfigurationCache.GetCurrentSystemUser(ESRI.ArcGIS.JTXUI.ConfigurationCache.UseUserDomain); IJTXConfiguration3 configMgr = this.WmxDatabase.ConfigurationManager as IJTXConfiguration3; IJTXUser3 executingUser = configMgr.GetUser(username) as IJTXUser3; // Import the AD information string domain = System.Environment.UserDomainName; string domainUsername = string.Empty; string domainPassword = string.Empty; int numUsers = 0; int numGroups = 0; ActiveDirectoryHelper.SyncronizeJTXDatabaseWithActiveDirectory(this.WmxDatabase, domain, domainUsername, domainPassword, m_userGroup, m_groupGroup, out numGroups, out numUsers); // If the tool was set to preserve the current user's account and the user // was removed from the DB, then re-add their account if (configMgr.GetUser(username) == null) { if (m_preserveCurrentUser) { IJTXConfigurationEdit2 configEdit = this.WmxDatabase.ConfigurationManager as IJTXConfigurationEdit2; IJTXUserConfig newUser = configEdit.CreateUser() as IJTXUserConfig; newUser.FirstName_2 = executingUser.FirstName; newUser.FullName_2 = executingUser.FullName; newUser.LastName_2 = executingUser.LastName; newUser.UserName_2 = executingUser.UserName; (newUser as IJTXUser3).IsAdministrator = executingUser.IsAdministrator; newUser.Store(); msgs.AddMessage("User '" + username + "' not found in Active Directory group '" + m_userGroup + "'; re-added placeholder to Workflow Manager database"); } else { msgs.AddWarning("User '" + username + "' removed from Workflow Manager database"); } } // Update the output parameters WmauParameterMap paramMap = new WmauParameterMap(paramValues); IGPParameterEdit3 outParam = paramMap.GetParamEdit(C_PARAM_OUT_NUM_USERS); IGPLong value = new GPLongClass(); value.Value = numUsers; outParam.Value = value as IGPValue; outParam = paramMap.GetParamEdit(C_PARAM_OUT_NUM_GROUPS); value = new GPLongClass(); value.Value = numGroups; outParam.Value = value as IGPValue; msgs.AddMessage(Properties.Resources.MSG_DONE); } catch (WmauException wmEx) { try { msgs.AddError(wmEx.ErrorCodeAsInt, wmEx.Message); } catch { // Catch anything else that possibly happens } } catch (Exception ex) { try { WmauError error = new WmauError(WmauErrorCodes.C_UNSPECIFIED_ERROR); msgs.AddError(error.ErrorCodeAsInt, error.Message + "; " + ex.Message); } catch { // Catch anything else that possibly happens } } finally { // Release any COM objects here! } }
/// <summary> /// Required by IGPFunction2 interface; this function is called when the GP tool is ready to be executed. /// </summary> /// <param name="paramValues"></param> /// <param name="trackCancel"></param> /// <param name="envMgr"></param> /// <param name="msgs"></param> public override void Execute(IArray paramValues, ITrackCancel trackCancel, IGPEnvironmentManager envMgr, IGPMessages msgs) { // Do some common error-checking base.Execute(paramValues, trackCancel, envMgr, msgs); // Set the default properties for the specified job type try { IJTXConfiguration3 configMgr = this.WmxDatabase.ConfigurationManager as IJTXConfiguration3; IJTXConfigurationEdit2 configEdit = this.WmxDatabase.ConfigurationManager as IJTXConfigurationEdit2; IJTXJobTypeEdit3 jobType = configEdit.GetJobType(m_jobTypeName) as IJTXJobTypeEdit3; // Set the default data workspace for the selected job type if (m_dataWorkspaceName.Equals(C_OPT_NONE)) { jobType.DefaultDataWorkspace = null; msgs.AddMessage("Clearing default data workspace for job type '" + m_jobTypeName + "'"); } else { // Translate the workspace name to a DB name object IJTXDataWorkspaceName dwName = Common.WmauHelperFunctions.LookupWorkspaceNameObj(this.WmxDatabase, m_dataWorkspaceName); msgs.AddMessage("Default data workspace for job type '" + m_jobTypeName + "' is now '" + dwName.Name + "'"); jobType.DefaultDataWorkspace = dwName; } // Set the default parent version for the selected job type if (m_parentVersion.Equals(C_OPT_NONE)) { msgs.AddMessage("Clearing default parent version for job type '" + m_jobTypeName + "'"); jobType.DefaultParentVersionName_2 = string.Empty; } else { msgs.AddMessage("Default parent version for job type '" + m_jobTypeName + "' is now '" + m_parentVersion + "'"); jobType.DefaultParentVersionName_2 = m_parentVersion; } // Save the changes to the job type jobType.Store(); // Set the output parameter WmauParameterMap paramMap = new WmauParameterMap(paramValues); IGPParameterEdit3 outParamEdit = paramMap.GetParamEdit(C_PARAM_OUT_DATA_WORKSPACE); IGPString outValue = new GPStringClass(); outValue.Value = m_jobTypeName; outParamEdit.Value = outValue as IGPValue; msgs.AddMessage(Properties.Resources.MSG_DONE); } catch (WmauException wmEx) { try { msgs.AddError(wmEx.ErrorCodeAsInt, wmEx.Message); } catch { // Catch anything else that possibly happens } } catch (Exception ex) { WmauError error = new WmauError(WmauErrorCodes.C_UNSPECIFIED_ERROR); msgs.AddError(error.ErrorCodeAsInt, error.Message + "; " + ex.Message); } }
/// <summary> /// Required by IGPFunction2 interface; this function is called when the GP tool is ready to be executed. /// </summary> /// <param name="paramValues"></param> /// <param name="trackCancel"></param> /// <param name="envMgr"></param> /// <param name="msgs"></param> public override void Execute(IArray paramValues, ITrackCancel trackCancel, IGPEnvironmentManager envMgr, IGPMessages msgs) { // Do some common error-checking base.Execute(paramValues, trackCancel, envMgr, msgs); try { // Ensure that the current user has admin access to the current Workflow Manager DB if (!CurrentUserIsWmxAdministrator()) { throw new WmauException(WmauErrorCodes.C_USER_NOT_ADMIN_ERROR); } // Indicate if changes are not actually being made string actionStr = " Deleting"; if (m_previewChanges) { msgs.AddMessage("PREVIEWING CHANGES ONLY; no changes will be made"); actionStr = " Found"; } IJTXConfiguration3 configMgr = WmxDatabase.ConfigurationManager as IJTXConfiguration3; IJTXConfigurationEdit2 configEdit = WmxDatabase.ConfigurationManager as IJTXConfigurationEdit2; // Find all of the orphans in the database msgs.AddMessage("Searching for orphaned items..."); int orphanCount = UpdateAllOrphans(); msgs.AddMessage("Found " + orphanCount.ToString() + " total orphaned items"); // If requested, delete any workflows first if (m_cleanWorkflows) { List <int> unusedWorkflowIds = m_unusedWorkflows.Keys.ToList(); unusedWorkflowIds.Sort(); foreach (int id in unusedWorkflowIds) { msgs.AddMessage(actionStr + " workflow " + id.ToString() + " (" + m_unusedWorkflows[id] + ")"); if (!this.m_previewChanges) { configMgr.DeleteWorkflow(id); } } } // If requested, delete any step types if (m_cleanStepTypes) { List <int> unusedStepTypeIds = m_unusedStepTypes.Keys.ToList(); unusedStepTypeIds.Sort(); foreach (int stepTypeId in unusedStepTypeIds) { msgs.AddMessage(actionStr + " step type " + stepTypeId.ToString() + " (" + m_unusedStepTypes[stepTypeId] + ")"); if (!this.m_previewChanges) { configEdit.DeleteStepType(stepTypeId); } } } // If requested, delete any status types if (m_cleanStatusTypes) { List <int> unusedStatusTypeIds = m_unusedStatusTypes.Keys.ToList(); unusedStatusTypeIds.Sort(); foreach (int statusTypeId in unusedStatusTypeIds) { msgs.AddMessage(actionStr + " status type " + statusTypeId.ToString() + " (" + m_unusedStatusTypes[statusTypeId] + ")"); if (!this.m_previewChanges) { configEdit.DeleteStatus(statusTypeId); } } } // If requested, delete any priority types if (m_cleanPriorities) { List <int> unusedPriorityTypeIds = m_unusedPriorities.Keys.ToList(); unusedPriorityTypeIds.Sort(); foreach (int priority in unusedPriorityTypeIds) { msgs.AddMessage(actionStr + " priority " + priority.ToString() + " (" + m_unusedPriorities[priority] + ")"); if (!m_previewChanges) { configEdit.DeletePriority(priority); } } } // If requested, delete any unused Task Assistant workbooks if (m_cleanTaWorkbooks) { List <string> unusedTaWorkbookNames = m_unusedTaWorkbooks.Keys.ToList(); unusedTaWorkbookNames.Sort(); foreach (string workbookName in unusedTaWorkbookNames) { msgs.AddMessage(actionStr + " workbook " + workbookName); if (!m_previewChanges) { configMgr.RemoveTaskAssistantWorkflowRecord(workbookName); } } } // If requested, delete any unused users if (m_cleanUsers) { List <string> unusedUserNames = m_unusedUsers.Keys.ToList(); unusedUserNames.Sort(); foreach (string user in unusedUserNames) { msgs.AddMessage(actionStr + " user " + user + " (" + m_unusedUsers[user] + ")"); if (!m_previewChanges) { configEdit.DeleteUser(user); } } } // If requested, delete any unused map documents if (m_cleanMapDocs) { List <string> unusedMapDocs = m_unusedMapDocs.Keys.ToList(); unusedMapDocs.Sort(); foreach (string mapName in unusedMapDocs) { msgs.AddMessage(actionStr + " map document " + mapName + " (" + m_unusedMapDocs[mapName].ToString() + ")"); if (!m_previewChanges) { configMgr.DeleteJTXMap(m_unusedMapDocs[mapName]); } } } // Set the output parameter WmauParameterMap paramMap = new WmauParameterMap(paramValues); IGPParameterEdit3 outParamEdit = paramMap.GetParamEdit(C_PARAM_NUM_ITEMS_DELETED); IGPLong outValue = new GPLongClass(); outValue.Value = orphanCount; outParamEdit.Value = outValue as IGPValue; msgs.AddMessage(Properties.Resources.MSG_DONE); } catch (WmauException wmEx) { try { msgs.AddError(wmEx.ErrorCodeAsInt, wmEx.Message); } catch { // Catch anything else that possibly happens } } catch (Exception ex) { try { WmauError error = new WmauError(WmauErrorCodes.C_UNSPECIFIED_ERROR); msgs.AddError(error.ErrorCodeAsInt, error.Message + "; " + ex.Message); } catch { // Catch anything else that possibly happens } } }
/// <summary> /// Find those map documents embedded in the database that are not being /// referenced in any way /// </summary> /// <returns>The total number of orphaned items found</returns> private int UpdateOrphanedMapDocuments() { SortedList <string, int> unusedItems = new SortedList <string, int>(); IJTXDatabase3 wmxDb = this.WmxDatabase; IJTXConfiguration3 configMgr = wmxDb.ConfigurationManager as IJTXConfiguration3; IJTXConfigurationEdit2 configEdit = wmxDb.ConfigurationManager as IJTXConfigurationEdit2; IJTXMapSet allMaps = configMgr.JTXMaps; Dictionary <string, int> allMapNames = new Dictionary <string, int>(); for (int i = 0; i < allMaps.Count; i++) { IJTXMap map = allMaps.get_Item(i); allMapNames[map.Name] = map.ID; } Dictionary <string, int> usedItems = new Dictionary <string, int>(); // Find the map types that are associated with job types IJTXJobTypeSet allJobTypes = configMgr.JobTypes; for (int i = 0; i < allJobTypes.Count; i++) { // TODO: Skip orphaned job types IJTXJobType3 jobType = allJobTypes.get_Item(i) as IJTXJobType3; if (jobType.AOIMap != null) { usedItems[jobType.AOIMap.Name] = jobType.AOIMap.ID; } if (jobType.JobMap != null) { usedItems[jobType.JobMap.Name] = jobType.JobMap.ID; } } // If necessary, find the map types launched by custom steps. Look for // the "/mxd:" argument as an identifier. IJTXStepTypeSet allStepTypes = wmxDb.ConfigurationManager.StepTypes; for (int i = 0; i < allStepTypes.Count; i++) { IJTXStepType2 stepType = allStepTypes.get_Item(i) as IJTXStepType2; // Skip orphaned step types if (m_unusedStepTypes.Keys.Contains(stepType.ID)) { continue; } for (int j = 0; j < stepType.Arguments.Length; j++) { string stepArg = stepType.Arguments[j].ToString(); if (stepArg.StartsWith(C_MAP_DOC_FLAG)) { string suffix = stepArg.Substring(C_MAP_DOC_FLAG.Length); suffix = suffix.Trim(new char[] { '"' }); if (allMapNames.Keys.Contains(suffix)) { usedItems[suffix] = allMapNames[suffix]; } } } } // Add in the map document that's used as the template map document // (if one exists) IJTXConfigurationProperties configProps = this.WmxDatabase.ConfigurationManager as IJTXConfigurationProperties; string mapIdStr = configProps.GetProperty(Constants.JTX_PROPERTY_MAPVIEW_MAP_GUID); if (mapIdStr != null && !mapIdStr.Equals(string.Empty)) { for (int i = 0; i < allMaps.Count; i++) { IJTXMap tempMap = allMaps.get_Item(i); IJTXIdentifier tempMapId = tempMap as IJTXIdentifier; if (tempMapId.GUID.Equals(mapIdStr)) { usedItems[tempMap.Name] = tempMap.ID; break; } } } // Loop over all the map documents in the DB, looking for anything // that we didn't identify as "in use" foreach (string name in allMapNames.Keys) { if (!usedItems.ContainsKey(name)) { m_unusedMapDocs[name] = allMapNames[name]; } } return(m_unusedMapDocs.Count); }
/// <summary> /// Required by IGPFunction2 interface; this function is called when the GP tool is ready to be executed. /// </summary> /// <param name="paramValues"></param> /// <param name="trackCancel"></param> /// <param name="envMgr"></param> /// <param name="msgs"></param> public override void Execute(IArray paramValues, ITrackCancel trackCancel, IGPEnvironmentManager envMgr, IGPMessages msgs) { // Do some common error-checking base.Execute(paramValues, trackCancel, envMgr, msgs); try { // Ensure that the current user has admin access to the current Workflow Manager DB if (!CurrentUserIsWmxAdministrator()) { throw new WmauException(WmauErrorCodes.C_USER_NOT_ADMIN_ERROR); } IJTXConfigurationEdit2 configEdit = this.WmxDatabase.ConfigurationManager as IJTXConfigurationEdit2; // Look up the appropriate privilege(s) and group(s) IJTXPrivilegeSet privileges = null; if (m_privilegeName.Equals(C_OPT_ALL_PRIVILEGES)) { privileges = configEdit.Privileges; } else { privileges = new JTXPrivilegeSetClass(); (privileges as IJTXPrivilegeSetEdit).Add(configEdit.GetPrivilege(m_privilegeName)); } IJTXUserGroupSet groups = null; if (m_groupName.Equals(C_OPT_ALL_GROUPS)) { groups = configEdit.UserGroups; } else { groups = new JTXUserGroupSetClass(); (groups as IJTXUserGroupSetEdit).Add(configEdit.GetUserGroup(m_groupName)); } // Add/remove the privilege(s) to the group(s) for (int i = 0; i < privileges.Count; i++) { IJTXPrivilege2 privilege = privileges.get_Item(i) as IJTXPrivilege2; for (int j = 0; j < groups.Count; j++) { IJTXUserGroupConfig2 targetGroup = groups.get_Item(j) as IJTXUserGroupConfig2; if (m_privilegeAction.Equals(C_OPT_GRANT)) { targetGroup.AssignPrivilegeToGroup2(privilege.UID); } else { targetGroup.RemovePrivilegeFromGroup2(privilege.UID); } targetGroup.Store(); } } // Update the output parameter WmauParameterMap paramMap = new WmauParameterMap(paramValues); IGPParameterEdit3 outParam = paramMap.GetParamEdit(C_PARAM_OUT_PRIVILEGE_NAME); IGPString strValue = new GPStringClass(); strValue.Value = m_privilegeName; outParam.Value = strValue as IGPValue; msgs.AddMessage(Properties.Resources.MSG_DONE); } catch (WmauException wmEx) { try { msgs.AddError(wmEx.ErrorCodeAsInt, wmEx.Message); } catch { // Catch anything else that possibly happens } } catch (Exception ex) { try { WmauError error = new WmauError(WmauErrorCodes.C_UNSPECIFIED_ERROR); msgs.AddError(error.ErrorCodeAsInt, error.Message + "; " + ex.Message); } catch { // Catch anything else that possibly happens } } finally { // Release any COM objects here! } }
/// <summary> /// Required by IGPFunction2 interface; this function is called when the GP tool is ready to be executed. /// </summary> /// <param name="paramValues"></param> /// <param name="trackCancel"></param> /// <param name="envMgr"></param> /// <param name="msgs"></param> public override void Execute(IArray paramValues, ITrackCancel trackCancel, IGPEnvironmentManager envMgr, IGPMessages msgs) { // Do some common error-checking base.Execute(paramValues, trackCancel, envMgr, msgs); try { // Ensure that the current user has admin access to the current Workflow Manager DB if (!CurrentUserIsWmxAdministrator()) { throw new WmauException(WmauErrorCodes.C_USER_NOT_ADMIN_ERROR); } IJTXConfigurationEdit2 configEdit = this.WmxDatabase.ConfigurationManager as IJTXConfigurationEdit2; // Look up the appropriate user(s) IJTXUserSet users = null; if (m_userName.Equals(C_OPT_ALL_USERS)) { users = configEdit.Users; } else { users = new JTXUserSetClass(); (users as IJTXUserSetEdit).Add(configEdit.GetUser(m_userName)); } // Grant/revoke admin access to the specified users for (int i = 0; i < users.Count; i++) { IJTXUser3 user = users.get_Item(i) as IJTXUser3; user.IsAdministrator = m_privilegeAction.Equals(C_OPT_GRANT) ? true : false; (user as IJTXUserConfig).Store(); } // If the tool was set to preserve the current user's access and the tool removed it, // re-grant their access string username = ESRI.ArcGIS.JTXUI.ConfigurationCache.GetCurrentSystemUser(ESRI.ArcGIS.JTXUI.ConfigurationCache.UseUserDomain); IJTXUser3 userObj = configEdit.GetUser(username) as IJTXUser3; if (!userObj.IsAdministrator) { if (m_preserveCurrentUser) { userObj.IsAdministrator = true; (userObj as IJTXUserConfig).Store(); msgs.AddMessage("Re-granting admin access for user '" + username + "'"); } else { msgs.AddWarning("User '" + username + "' is no longer an administrator on this Workflow Manager database"); } } // Update the output parameter WmauParameterMap paramMap = new WmauParameterMap(paramValues); IGPParameterEdit3 outParam = paramMap.GetParamEdit(C_PARAM_OUT_USER_NAME); IGPString strValue = new GPStringClass(); strValue.Value = m_userName; outParam.Value = strValue as IGPValue; msgs.AddMessage(Properties.Resources.MSG_DONE); } catch (WmauException wmEx) { try { msgs.AddError(wmEx.ErrorCodeAsInt, wmEx.Message); } catch { // Catch anything else that possibly happens } } catch (Exception ex) { try { WmauError error = new WmauError(WmauErrorCodes.C_UNSPECIFIED_ERROR); msgs.AddError(error.ErrorCodeAsInt, error.Message + "; " + ex.Message); } catch { // Catch anything else that possibly happens } } finally { // Release any COM objects here! } }
/// <summary> /// Required by IGPFunction2 interface; this function is called when the GP tool is ready to be executed. /// </summary> /// <param name="paramValues"></param> /// <param name="trackCancel"></param> /// <param name="envMgr"></param> /// <param name="msgs"></param> public override void Execute(IArray paramValues, ITrackCancel trackCancel, IGPEnvironmentManager envMgr, IGPMessages msgs) { // Do some common error-checking base.Execute(paramValues, trackCancel, envMgr, msgs); StreamWriter logFileWriter = null; try { int errorCount = 0; if (!string.IsNullOrEmpty(m_logFilePath)) { logFileWriter = new StreamWriter(m_logFilePath); } IJTXConfiguration3 configMgr = this.WmxDatabase.ConfigurationManager as IJTXConfiguration3; IJTXConfigurationEdit2 configEdit = configMgr as IJTXConfigurationEdit2; IJTXJobManager jobMgr = this.WmxDatabase.JobManager; // Workflow Manager intentionally caches the data workspaces in the system. To ensure // that we have the most current list of data workspaces, invalidate this cache // before attempting to retrieve the list from the system. this.WmxDatabase.InvalidateDataWorkspaceNames(); // Run checks against users ExecuteUserChecks(msgs, ref errorCount, logFileWriter); // Run checks against groups ExecuteGroupChecks(msgs, ref errorCount, logFileWriter); // Run checks against any existing jobs ExecuteJobChecks(msgs, ref errorCount, logFileWriter); // Check for any template job types with an invalid default assignment ExecuteJobTypeChecks(msgs, ref errorCount, logFileWriter); // Check the workflow steps for problems ExecuteWorkflowStepChecks(msgs, ref errorCount, logFileWriter); // Set the output parameter WmauParameterMap paramMap = new WmauParameterMap(paramValues); IGPParameterEdit3 outParamEdit = paramMap.GetParamEdit(C_PARAM_OUT_ISSUES_FOUND); IGPLong outValue = new GPLongClass(); outValue.Value = errorCount; outParamEdit.Value = outValue as IGPValue; msgs.AddMessage(Properties.Resources.MSG_DONE); } catch (WmauException wmEx) { try { msgs.AddError(wmEx.ErrorCodeAsInt, wmEx.Message); } catch { // Catch anything else that possibly happens } } catch (Exception ex) { try { WmauError error = new WmauError(WmauErrorCodes.C_UNSPECIFIED_ERROR); msgs.AddError(error.ErrorCodeAsInt, error.Message + "; " + ex.Message); } catch { // Catch anything else that possibly happens } } finally { // Release any COM objects here! if (logFileWriter != null) { logFileWriter.Close(); } } }
/// <summary> /// Helper function that runs all of those checks that operate on each step in /// every workflow; intended to make the checks slightly more efficient by running /// through them all at once rather than looping through all of the elements /// multiple times /// </summary> /// <param name="msgs">Add any GP messages to this object</param> /// <param name="errorCount">Counter used to track the number of problems found</param> /// <param name="logFileWriter">Object used to write error descriptions to a text file</param> private void ExecuteWorkflowStepChecks(IGPMessages msgs, ref int errorCount, StreamWriter logFileWriter) { // Only continue executing this function if needed if (!m_flagInvalidStepAssign && !m_flagUnassignedSteps && !m_flagZeroPctSteps && !m_flagDifferingStepNames) { return; } IJTXConfiguration3 configMgr = this.WmxDatabase.ConfigurationManager as IJTXConfiguration3; IJTXConfigurationEdit2 configEdit = configMgr as IJTXConfigurationEdit2; // Put the items into a sorted list in order to make the output easier to // read/follow IJTXWorkflowSet allWorkflows = configMgr.Workflows; SortedList <string, IJTXWorkflow> allWorkflowsSorted = new SortedList <string, IJTXWorkflow>(); for (int i = 0; i < allWorkflows.Count; i++) { allWorkflowsSorted[allWorkflows.get_Item(i).Name] = allWorkflows.get_Item(i); } // Iterate through each item foreach (IJTXWorkflow workflow in allWorkflowsSorted.Values) { IJTXWorkflowConfiguration workflowCfg = workflow as IJTXWorkflowConfiguration; int[] allStepIds = workflowCfg.GetAllSteps(); foreach (int j in allStepIds) { IJTXStep3 step = workflowCfg.GetStep(j) as IJTXStep3; string assignedTo = step.AssignedTo; // Check for any default step types with an invalid step assignment if (m_flagInvalidStepAssign) { if (step.AssignedType == jtxAssignmentType.jtxAssignmentTypeUser && configMgr.GetUser(assignedTo) == null) { string message = "Workflow '" + workflow.Name + "', step '" + step.StepName + "' assigned to unknown user '" + assignedTo + "'"; RecordMessage(message, msgs, logFileWriter); errorCount++; } else if (step.AssignedType == jtxAssignmentType.jtxAssignmentTypeGroup && configMgr.GetUserGroup(assignedTo) == null) { string message = "Workflow '" + workflow.Name + "', step '" + step.StepName + "' assigned to unknown group '" + assignedTo + "'"; RecordMessage(message, msgs, logFileWriter); errorCount++; } } // Check for any steps that have not been assigned to a group or user if (m_flagUnassignedSteps) { if (step.AssignedType == jtxAssignmentType.jtxAssignmentTypeUnassigned) { string message = "Workflow '" + workflow.Name + "', step '" + step.StepName + "' is unassigned"; RecordMessage(message, msgs, logFileWriter); errorCount++; } } // Check for any steps whose "post-complete" percentage is 0 if (m_flagZeroPctSteps) { if (step.DefaultPercComplete < double.Epsilon) { string message = "Workflow '" + workflow.Name + "', step '" + step.StepName + "' sets percent complete to 0"; RecordMessage(message, msgs, logFileWriter); errorCount++; } } // Check for any steps whose descriptions in a workflow does not match // the underlying step type name if (m_flagDifferingStepNames) { IJTXStepType2 stepType = configMgr.GetStepTypeByID(step.StepTypeID) as IJTXStepType2; if (!step.StepName.Equals(stepType.Name)) { string message = "Workflow '" + workflow.Name + "', step name '" + step.StepName + "' does not match step type name '" + stepType.Name + "'"; RecordMessage(message, msgs, logFileWriter); errorCount++; } } } // end for each step } // end for each workflow }
/// <summary> /// Helper function that runs all of those checks that operate on each job type; /// intended to make the checks slightly more efficient by running through them all /// at once rather than looping through all of the elements multiple times /// </summary> /// <param name="msgs">Add any GP messages to this object</param> /// <param name="errorCount">Counter used to track the number of problems found</param> /// <param name="logFileWriter">Object used to write error descriptions to a text file</param> private void ExecuteJobTypeChecks(IGPMessages msgs, ref int errorCount, StreamWriter logFileWriter) { if (!m_flagInvalidJobTypeAssign && !m_flagJobTypesWithoutWorkflows && !m_flagMissingAoiMxds && !m_flagMissingBaseMxds && !m_flagNonActiveJobTypes) { return; } IJTXConfiguration3 configMgr = this.WmxDatabase.ConfigurationManager as IJTXConfiguration3; IJTXConfigurationEdit2 configEdit = configMgr as IJTXConfigurationEdit2; // Put the items into a sorted list in order to make the output easier to // read/follow IJTXJobTypeSet allJobTypes = configMgr.JobTypes; SortedList <string, IJTXJobType3> allJobTypesSorted = new SortedList <string, IJTXJobType3>(); for (int i = 0; i < allJobTypes.Count; i++) { allJobTypesSorted[allJobTypes.get_Item(i).Name] = allJobTypes.get_Item(i) as IJTXJobType3; } // Iterate through each item foreach (IJTXJobType3 jobType in allJobTypesSorted.Values) { if (m_flagInvalidJobTypeAssign) { string assignedTo = jobType.DefaultAssignedTo; if (jobType.DefaultAssignedType == jtxAssignmentType.jtxAssignmentTypeUser && configMgr.GetUser(assignedTo) == null) { string message = "Job Type '" + jobType.Name + "' assigned to unknown user '" + assignedTo + "'"; RecordMessage(message, msgs, logFileWriter); errorCount++; } else if (jobType.DefaultAssignedType == jtxAssignmentType.jtxAssignmentTypeGroup && configMgr.GetUserGroup(assignedTo) == null) { string message = "Job Type '" + jobType.Name + "' assigned to unknown group '" + assignedTo + "'"; RecordMessage(message, msgs, logFileWriter); errorCount++; } } if (m_flagJobTypesWithoutWorkflows) { if (jobType.Workflow == null) { string message = "Job Type '" + jobType.Name + "' has no workflow defined"; RecordMessage(message, msgs, logFileWriter); errorCount++; } } if (m_flagMissingAoiMxds) { if (jobType.AOIMap == null) { string message = "Job Type '" + jobType.Name + "' has no AOI map defined"; RecordMessage(message, msgs, logFileWriter); errorCount++; } } if (m_flagMissingBaseMxds) { if (jobType.JobMap == null) { string message = "Job Type '" + jobType.Name + "' has no job map (a.k.a. basemap) defined"; RecordMessage(message, msgs, logFileWriter); errorCount++; } } if (m_flagNonActiveJobTypes) { if (jobType.State != jtxJobTypeState.jtxJobTypeStateActive) { string message = "Job Type '" + jobType.Name + "' is not active"; RecordMessage(message, msgs, logFileWriter); errorCount++; } } } }
/// <summary> /// Helper function that runs all of those checks that operate on each job; intended /// to make the checks slightly more efficient by running through them all at once /// rather than looping through all of the elements multiple times /// </summary> /// <param name="msgs">Add any GP messages to this object</param> /// <param name="errorCount">Counter used to track the number of problems found</param> /// <param name="logFileWriter">Object used to write error descriptions to a text file</param> private void ExecuteJobChecks(IGPMessages msgs, ref int errorCount, StreamWriter logFileWriter) { // Only continue executing this function if needed if (!m_flagInvalidJobAssign && !m_flagIsSelfParent && !m_flagJobsWithoutTypes) { return; } IJTXConfiguration3 configMgr = this.WmxDatabase.ConfigurationManager as IJTXConfiguration3; IJTXConfigurationEdit2 configEdit = configMgr as IJTXConfigurationEdit2; IJTXJobManager jobMgr = this.WmxDatabase.JobManager; // Use a database query as an alternate way of finding certain specific // problems with jobs. Declare some of these ComReleaser objects to help // ensure that cursors, etc., are immediately released after they go out // of scope. // Check for jobs without any job types set (should be a DB error) if (m_flagJobsWithoutTypes) { using (ComReleaser cr1 = new ComReleaser(), cr2 = new ComReleaser()) { IFeatureWorkspace featureWorkspace = this.WmxDatabase.JTXWorkspace as IFeatureWorkspace; // Get the name of the correct table from the jobs workspace, so // that the table doesn't have to be owned by the connecting user. string tableName = Common.WmauHelperFunctions.GetQualifiedTableName(Constants.JTX_TABLE_JTX_JOBS_TABLE, this.WmxDatabase.JTXWorkspace); ITable jobsTable = featureWorkspace.OpenTable(tableName); cr1.ManageLifetime(jobsTable); IQueryFilter query = new QueryFilterClass(); query.WhereClause = Constants.FIELD_JOBTYPEID + " IS NULL"; ICursor searchCursor = jobsTable.Search(query, true); cr2.ManageLifetime(searchCursor); // Store the ID and name of each job matching this query int idIndex = jobsTable.FindField(Constants.FIELD_JOBID); int nameIndex = jobsTable.FindField(Constants.FIELD_JOBNAME); IRow row = null; while ((row = searchCursor.NextRow()) != null) { string idStr = row.get_Value(idIndex).ToString(); string nameStr = row.get_Value(nameIndex).ToString(); string msg = "Job " + idStr + " (" + nameStr + ") has no associated job type"; RecordMessage(msg, msgs, logFileWriter); errorCount++; } } } // Check for jobs that are their own parent job if (m_flagIsSelfParent) { using (ComReleaser cr1 = new ComReleaser(), cr2 = new ComReleaser()) { IFeatureWorkspace featureWorkspace = this.WmxDatabase.JTXWorkspace as IFeatureWorkspace; // Get the name of the correct table from the jobs workspace, so // that the table doesn't have to be owned by the connecting user. string tableName = Common.WmauHelperFunctions.GetQualifiedTableName(Constants.JTX_TABLE_JTX_JOBS_TABLE, this.WmxDatabase.JTXWorkspace); ITable jobsTable = featureWorkspace.OpenTable(tableName); cr1.ManageLifetime(jobsTable); const string C_FIELD_PARENT_JOB = "PARENT_JOB"; IQueryFilter query = new QueryFilterClass(); query.WhereClause = Constants.FIELD_JOBID + " = " + C_FIELD_PARENT_JOB; ICursor searchCursor = jobsTable.Search(query, true); cr2.ManageLifetime(searchCursor); // Store the ID and name of each job matching this query int idIndex = jobsTable.FindField(Constants.FIELD_JOBID); int nameIndex = jobsTable.FindField(Constants.FIELD_JOBNAME); IRow row = null; while ((row = searchCursor.NextRow()) != null) { string idStr = row.get_Value(idIndex).ToString(); string nameStr = row.get_Value(nameIndex).ToString(); string msg = "Job " + idStr + " (" + nameStr + ") is its own parent"; RecordMessage(msg, msgs, logFileWriter); errorCount++; } } } // See if there are any checks selected for which we should iterate through // all of the jobs using the WMX interfaces if (m_flagInvalidJobAssign) { // Put the items into a sorted list in order to make the output easier to // read/follow IJTXJobSet allJobs = jobMgr.GetAllJobs(); SortedList <int, IJTXJob3> allJobsSorted = new SortedList <int, IJTXJob3>(); for (int i = 0; i < allJobs.Count; i++) { allJobsSorted[allJobs.get_Item(i).ID] = allJobs.get_Item(i) as IJTXJob3; } // Iterate over all of the jobs foreach (IJTXJob3 job in allJobsSorted.Values) { string assignedTo = job.AssignedTo; // Check for any existing jobs with an invalid job assignment. NOTE: only // want to flag jobs that are not closed if (m_flagInvalidJobAssign && job.Stage != jtxJobStage.jtxJobStageClosed) { if (job.AssignedType == jtxAssignmentType.jtxAssignmentTypeUser && configMgr.GetUser(assignedTo) == null) { string message = "Job '" + job.ID.ToString() + "' assigned to unknown user '" + assignedTo + "'"; RecordMessage(message, msgs, logFileWriter); errorCount++; } else if (job.AssignedType == jtxAssignmentType.jtxAssignmentTypeGroup && configMgr.GetUserGroup(assignedTo) == null) { string message = "Job '" + job.ID.ToString() + "' assigned to unknown group '" + assignedTo + "'"; RecordMessage(message, msgs, logFileWriter); errorCount++; } } } } }