Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes308downloads
JobManager.cs1056 linesDownload Raw Back to client
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections;5using System.Collections.Generic;6using System.Globalization;7using System.Management.Automation.Remoting;8using System.Management.Automation.Runspaces;9using System.Management.Automation.Tracing;10using System.Reflection;11using System.Security;12using System.Threading;13 14using Dbg = System.Management.Automation.Diagnostics;15 16// Stops compiler from warning about unknown warnings17#pragma warning disable 1634, 169118 19namespace System.Management.Automation20{21    /// <summary>22    /// Manager for JobSourceAdapters for invocation and management of specific Job types.23    /// </summary>24    public sealed class JobManager25    {26        private readonly PowerShellTraceSource _tracer = PowerShellTraceSourceFactory.GetTraceSource();27 28        /// <summary>29        /// Collection of registered JobSourceAdapters.30        /// </summary>31        private readonly Dictionary<string, JobSourceAdapter> _sourceAdapters =32            new Dictionary<string, JobSourceAdapter>();33 34        private readonly object _syncObject = new object();35 36        /// <summary>37        /// Collection of job IDs that are valid for reuse.38        /// </summary>39        private static readonly Dictionary<Guid, KeyValuePair<int, string>> s_jobIdsForReuse = new Dictionary<Guid, KeyValuePair<int, string>>();40 41        private static readonly object s_syncObject = new object();42 43        /// <summary>44        /// Creates a JobManager instance.45        /// </summary>46        internal JobManager()47        {48        }49 50        /// <summary>51        /// Returns true if the type is already registered.52        /// </summary>53        /// <param name="typeName">Type to check.</param>54        /// <returns>Whether the type is registered already.</returns>55        public bool IsRegistered(string typeName)56        {57            if (string.IsNullOrEmpty(typeName))58            {59                return false;60            }61 62            lock (_syncObject)63            {64                return _sourceAdapters.ContainsKey(typeName);65            }66        }67 68        /// <summary>69        /// Adds a new JobSourceAdapter to the JobManager instance.70        /// After addition, creating a NewJob with a JobDefinition71        /// indicating the JobSourceAdapter derivative type will function.72        /// </summary>73        /// <param name="jobSourceAdapterType">The derivative JobSourceAdapter type to74        /// register.</param>75        /// <exception cref="InvalidOperationException">Throws when there is no public76        /// default constructor on the type.</exception>77        internal void RegisterJobSourceAdapter(Type jobSourceAdapterType)78        {79            Dbg.Assert(typeof(JobSourceAdapter).IsAssignableFrom(jobSourceAdapterType), "BaseType of any type being registered with the JobManager should be JobSourceAdapter.");80            Dbg.Assert(jobSourceAdapterType != typeof(JobSourceAdapter), "JobSourceAdapter abstract type itself should never be registered.");81            Dbg.Assert(jobSourceAdapterType != null, "JobSourceAdapterType should never be called with null value.");82            object instance = null;83 84            ConstructorInfo constructor = jobSourceAdapterType.GetConstructor(Type.EmptyTypes);85            if (!constructor.IsPublic)86            {87                string message = string.Format(CultureInfo.CurrentCulture,88                                                RemotingErrorIdStrings.JobManagerRegistrationConstructorError,89                                                jobSourceAdapterType.FullName);90                throw new InvalidOperationException(message);91            }92 93            try94            {95                instance = constructor.Invoke(null);96            }97            catch (MemberAccessException exception)98            {99                _tracer.TraceException(exception);100                throw;101            }102            catch (TargetInvocationException exception)103            {104                _tracer.TraceException(exception);105                throw;106            }107            catch (TargetParameterCountException exception)108            {109                _tracer.TraceException(exception);110                throw;111            }112            catch (NotSupportedException exception)113            {114                _tracer.TraceException(exception);115                throw;116            }117            catch (SecurityException exception)118            {119                _tracer.TraceException(exception);120                throw;121            }122 123            if (instance != null)124            {125                lock (_syncObject)126                {127                    _sourceAdapters.Add(jobSourceAdapterType.Name, (JobSourceAdapter)instance);128                }129            }130        }131 132        /// <summary>133        /// Returns a token that allows a job to be constructed with a specific id and instanceId.134        /// The original job must have been saved using "SaveJobIdForReconstruction" in the JobSourceAdapter.135        /// </summary>136        /// <param name="instanceId">The instance id desired.</param>137        /// <param name="typeName">The requesting type name for JobSourceAdapter implementation.</param>138        /// <returns>Token for job creation.</returns>139        internal static JobIdentifier GetJobIdentifier(Guid instanceId, string typeName)140        {141            lock (s_syncObject)142            {143                KeyValuePair<int, string> keyValuePair;144                if (s_jobIdsForReuse.TryGetValue(instanceId, out keyValuePair) && keyValuePair.Value.Equals(typeName))145                    return new JobIdentifier(keyValuePair.Key, instanceId);146                return null;147            }148        }149 150        /// <summary>151        /// Saves the Id information for a job so that it can be constructed at a later time by a JobSourceAdapter152        /// with the same type.153        /// </summary>154        /// <param name="instanceId">The instance id to save.</param>155        /// <param name="id">The session specific id to save.</param>156        /// <param name="typeName">The type name for the JobSourceAdapter implementation doing the save.</param>157        internal static void SaveJobId(Guid instanceId, int id, string typeName)158        {159            lock (s_syncObject)160            {161                if (s_jobIdsForReuse.ContainsKey(instanceId))162                {163                    return;164                }165 166                s_jobIdsForReuse.Add(instanceId, new KeyValuePair<int, string>(id, typeName));167            }168        }169 170        #region NewJob171 172        /// <summary>173        /// Creates a new job of the appropriate type given by JobDefinition passed in.174        /// </summary>175        /// <param name="definition">JobDefinition defining the command.</param>176        /// <returns>Job2 object of the appropriate type specified by the definition.</returns>177        /// <exception cref="InvalidOperationException">If JobSourceAdapter type specified178        /// in definition is not registered.</exception>179        /// <exception cref="Exception">JobSourceAdapter implementation exception thrown on error.180        /// </exception>181        public Job2 NewJob(JobDefinition definition)182        {183            ArgumentNullException.ThrowIfNull(definition);184 185            JobSourceAdapter sourceAdapter = GetJobSourceAdapter(definition);186            Job2 newJob;187 188#pragma warning disable 56500189            try190            {191                newJob = sourceAdapter.NewJob(definition);192            }193            catch (Exception exception)194            {195                // Since we are calling into 3rd party code196                // catching Exception is allowed. In all197                // other cases the appropriate exception198                // needs to be caught.199 200                // sourceAdapter.NewJob returned unknown error.201                _tracer.TraceException(exception);202                throw;203            }204#pragma warning restore 56500205 206            return newJob;207        }208 209        /// <summary>210        /// Creates a new job of the appropriate type given by JobDefinition passed in.211        /// </summary>212        /// <param name="specification">JobInvocationInfo defining the command.</param>213        /// <returns>Job2 object of the appropriate type specified by the definition.</returns>214        /// <exception cref="InvalidOperationException">If JobSourceAdapter type specified215        /// in definition is not registered.</exception>216        /// <exception cref="Exception">JobSourceAdapter implementation exception thrown on error.217        /// </exception>218        public Job2 NewJob(JobInvocationInfo specification)219        {220            ArgumentNullException.ThrowIfNull(specification);221 222            if (specification.Definition == null)223            {224                throw new ArgumentException(RemotingErrorIdStrings.NewJobSpecificationError, nameof(specification));225            }226 227            JobSourceAdapter sourceAdapter = GetJobSourceAdapter(specification.Definition);228            Job2 newJob = null;229 230#pragma warning disable 56500231            try232            {233                newJob = sourceAdapter.NewJob(specification);234            }235            catch (Exception exception)236            {237                // Since we are calling into 3rd party code238                // catching Exception is allowed. In all239                // other cases the appropriate exception240                // needs to be caught.241 242                // sourceAdapter.NewJob returned unknown error.243                _tracer.TraceException(exception);244                throw;245            }246#pragma warning restore 56500247 248            return newJob;249        }250 251        #endregion NewJob252 253        #region Persist Job254 255        /// <summary>256        /// Saves the job to a persisted store.257        /// </summary>258        /// <param name="job">Job2 type job to persist.</param>259        /// <param name="definition">Job definition containing source adapter information.</param>260        public void PersistJob(Job2 job, JobDefinition definition)261        {262            if (job == null)263            {264                throw new PSArgumentNullException(nameof(job));265            }266 267            if (definition == null)268            {269                throw new PSArgumentNullException(nameof(definition));270            }271 272            JobSourceAdapter sourceAdapter = GetJobSourceAdapter(definition);273 274            try275            {276                sourceAdapter.PersistJob(job);277            }278            catch (Exception exception)279            {280                // Since we are calling into 3rd party code281                // catching Exception is allowed. In all282                // other cases the appropriate exception283                // needs to be caught.284 285                // sourceAdapter.NewJob returned unknown error.286                _tracer.TraceException(exception);287                throw;288            }289        }290 291        #endregion292 293        /// <summary>294        /// Helper method, finds source adapter if registered, otherwise throws295        /// an InvalidOperationException.296        /// </summary>297        /// <param name="adapterTypeName">The name of the JobSourceAdapter derivative desired.</param>298        /// <returns>The JobSourceAdapter instance.</returns>299        /// <exception cref="InvalidOperationException">If JobSourceAdapter type specified300        /// is not found.</exception>301        private JobSourceAdapter AssertAndReturnJobSourceAdapter(string adapterTypeName)302        {303            JobSourceAdapter adapter;304            lock (_syncObject)305            {306                if (!_sourceAdapters.TryGetValue(adapterTypeName, out adapter))307                {308                    throw new InvalidOperationException(RemotingErrorIdStrings.JobSourceAdapterNotFound);309                }310            }311 312            return adapter;313        }314 315        /// <summary>316        /// Helper method to find and return the job source adapter if currently loaded or317        /// otherwise load the associated module and the requested source adapter.318        /// </summary>319        /// <param name="definition">JobDefinition supplies the JobSourceAdapter information.</param>320        /// <returns>JobSourceAdapter.</returns>321        private JobSourceAdapter GetJobSourceAdapter(JobDefinition definition)322        {323            string adapterTypeName;324            if (!string.IsNullOrEmpty(definition.JobSourceAdapterTypeName))325            {326                adapterTypeName = definition.JobSourceAdapterTypeName;327            }328            else if (definition.JobSourceAdapterType != null)329            {330                adapterTypeName = definition.JobSourceAdapterType.Name;331            }332            else333            {334                throw new InvalidOperationException(RemotingErrorIdStrings.JobSourceAdapterNotFound);335            }336 337            JobSourceAdapter adapter;338            bool adapterFound = false;339            lock (_syncObject)340            {341                adapterFound = _sourceAdapters.TryGetValue(adapterTypeName, out adapter);342            }343 344            if (!adapterFound)345            {346                if (!string.IsNullOrEmpty(definition.ModuleName))347                {348                    // Attempt to load the module.349                    Exception ex = null;350                    try351                    {352                        InitialSessionState iss = InitialSessionState.CreateDefault2();353                        iss.Commands.Clear();354                        iss.Formats.Clear();355                        iss.Commands.Add(new SessionStateCmdletEntry("Import-Module", typeof(Microsoft.PowerShell.Commands.ImportModuleCommand), null));356                        using (PowerShell powerShell = PowerShell.Create(iss))357                        {358                            powerShell.AddCommand("Import-Module");359                            powerShell.AddParameter("Name", definition.ModuleName);360                            powerShell.Invoke();361 362                            if (powerShell.ErrorBuffer.Count > 0)363                            {364                                ex = powerShell.ErrorBuffer[0].Exception;365                            }366                        }367                    }368                    catch (RuntimeException e)369                    {370                        ex = e;371                    }372                    catch (InvalidOperationException e)373                    {374                        ex = e;375                    }376                    catch (ScriptCallDepthException e)377                    {378                        ex = e;379                    }380                    catch (SecurityException e)381                    {382                        ex = e;383                    }384 385                    if (ex != null)386                    {387                        throw new InvalidOperationException(RemotingErrorIdStrings.JobSourceAdapterNotFound, ex);388                    }389 390                    // Now try getting the job source adapter again.391                    adapter = AssertAndReturnJobSourceAdapter(adapterTypeName);392                }393                else394                {395                    throw new InvalidOperationException(RemotingErrorIdStrings.JobSourceAdapterNotFound);396                }397            }398 399            return adapter;400        }401 402        #region GetJobs403 404        /// <summary>405        /// Get list of all jobs.406        /// </summary>407        /// <param name="cmdlet">Cmdlet requesting this, for error processing.</param>408        /// <param name="writeErrorOnException"></param>409        /// <param name="writeObject"></param>410        /// <param name="jobSourceAdapterTypes">Job source adapter type names.</param>411        /// <returns>Collection of jobs.</returns>412        /// <exception cref="Exception">If cmdlet parameter is null, throws exception on error from413        /// JobSourceAdapter implementation.</exception>414        internal List<Job2> GetJobs(415            Cmdlet cmdlet,416            bool writeErrorOnException,417            bool writeObject,418            string[] jobSourceAdapterTypes)419        {420            return GetFilteredJobs(null, FilterType.None, cmdlet, writeErrorOnException, writeObject, false, jobSourceAdapterTypes);421        }422 423        /// <summary>424        /// Get list of jobs that matches the specified names.425        /// </summary>426        /// <param name="name">Names to match, can support427        ///   wildcard if the store supports.</param>428        /// <param name="cmdlet">Cmdlet requesting this, for error processing.</param>429        /// <param name="writeErrorOnException"></param>430        /// <param name="writeObject"></param>431        /// <param name="recurse"></param>432        /// <param name="jobSourceAdapterTypes">Job source adapter type names.</param>433        /// <returns>Collection of jobs that match the specified434        /// criteria.</returns>435        /// <exception cref="Exception">If cmdlet parameter is null, throws exception on error from436        /// JobSourceAdapter implementation.</exception>437        internal List<Job2> GetJobsByName(438            string name,439            Cmdlet cmdlet,440            bool writeErrorOnException,441            bool writeObject,442            bool recurse,443            string[] jobSourceAdapterTypes)444        {445            return GetFilteredJobs(name, FilterType.Name, cmdlet, writeErrorOnException, writeObject, recurse, jobSourceAdapterTypes);446        }447 448        /// <summary>449        /// Get list of jobs that run the specified command.450        /// </summary>451        /// <param name="command">Command to match.</param>452        /// <param name="cmdlet">Cmdlet requesting this, for error processing.</param>453        /// <param name="writeErrorOnException"></param>454        /// <param name="writeObject"></param>455        /// <param name="recurse"></param>456        /// <param name="jobSourceAdapterTypes">Job source adapter type names.</param>457        /// <returns>Collection of jobs that match the specified458        /// criteria.</returns>459        /// <exception cref="Exception">If cmdlet parameter is null, throws exception on error from460        /// JobSourceAdapter implementation.</exception>461        internal List<Job2> GetJobsByCommand(462            string command,463            Cmdlet cmdlet,464            bool writeErrorOnException,465            bool writeObject,466            bool recurse,467            string[] jobSourceAdapterTypes)468        {469            return GetFilteredJobs(command, FilterType.Command, cmdlet, writeErrorOnException, writeObject, recurse, jobSourceAdapterTypes);470        }471 472        /// <summary>473        /// Get list of jobs that are in the specified state.474        /// </summary>475        /// <param name="state">State to match.</param>476        /// <param name="cmdlet">Cmdlet requesting this, for error processing.</param>477        /// <param name="writeErrorOnException"></param>478        /// <param name="writeObject"></param>479        /// <param name="recurse"></param>480        /// <param name="jobSourceAdapterTypes">Job source adapter type names.</param>481        /// <returns>Collection of jobs with the specified482        /// state.</returns>483        /// <exception cref="Exception">If cmdlet parameter is null, throws exception on error from484        /// JobSourceAdapter implementation.</exception>485        internal List<Job2> GetJobsByState(486            JobState state,487            Cmdlet cmdlet,488            bool writeErrorOnException,489            bool writeObject,490            bool recurse,491            string[] jobSourceAdapterTypes)492        {493            return GetFilteredJobs(state, FilterType.State, cmdlet, writeErrorOnException, writeObject, recurse, jobSourceAdapterTypes);494        }495 496        /// <summary>497        /// Get list of jobs based on the adapter specific498        /// filter parameters.499        /// </summary>500        /// <param name="filter">Dictionary containing name value501        ///   pairs for adapter specific filters.</param>502        /// <param name="cmdlet">Cmdlet requesting this, for error processing.</param>503        /// <param name="writeErrorOnException"></param>504        /// <param name="writeObject"></param>505        /// <param name="recurse"></param>506        /// <returns>Collection of jobs that match the507        /// specified criteria.</returns>508        /// <exception cref="Exception">If cmdlet parameter is null, throws exception on error from509        /// JobSourceAdapter implementation.</exception>510        internal List<Job2> GetJobsByFilter(Dictionary<string, object> filter, Cmdlet cmdlet, bool writeErrorOnException, bool writeObject, bool recurse)511        {512            return GetFilteredJobs(filter, FilterType.Filter, cmdlet, writeErrorOnException, writeObject, recurse, null);513        }514 515        /// <summary>516        /// Get a filtered list of jobs based on adapter name.517        /// </summary>518        /// <param name="id">Job id.</param>519        /// <param name="name">Adapter name.</param>520        /// <returns></returns>521        internal bool IsJobFromAdapter(Guid id, string name)522        {523            lock (_syncObject)524            {525                foreach (JobSourceAdapter sourceAdapter in _sourceAdapters.Values)526                {527                    if (sourceAdapter.Name.Equals(name, StringComparison.OrdinalIgnoreCase))528                    {529                        return (sourceAdapter.GetJobByInstanceId(id, false) != null);530                    }531                }532            }533 534            return false;535        }536 537        /// <summary>538        /// Get a filtered list of jobs based on filter type.539        /// </summary>540        /// <param name="filter">Object to use for filtering.</param>541        /// <param name="filterType">Type of filter, specifies which "get" from542        ///   JobSourceAdapter to call, and dictates the type for filter.</param>543        /// <param name="cmdlet">Cmdlet requesting this, for error processing.</param>544        /// <param name="writeErrorOnException"></param>545        /// <param name="writeObject"></param>546        /// <param name="recurse"></param>547        /// <param name="jobSourceAdapterTypes">Job source adapter type names.</param>548        /// <returns>Filtered list of jobs.</returns>549        /// <exception cref="Exception">If cmdlet parameter is null, throws exception on error from550        /// JobSourceAdapter implementation.</exception>551        private List<Job2> GetFilteredJobs(552            object filter,553            FilterType filterType,554            Cmdlet cmdlet,555            bool writeErrorOnException,556            bool writeObject,557            bool recurse,558            string[] jobSourceAdapterTypes)559        {560            Diagnostics.Assert(cmdlet != null, "Cmdlet should be passed to JobManager");561 562            List<Job2> allJobs = new List<Job2>();563 564            lock (_syncObject)565            {566                foreach (JobSourceAdapter sourceAdapter in _sourceAdapters.Values)567                {568                    List<Job2> jobs = null;569 570                    // Filter search based on job source adapter types if provided.571                    if (!CheckTypeNames(sourceAdapter, jobSourceAdapterTypes))572                    {573                        continue;574                    }575 576#pragma warning disable 56500577                    try578                    {579                        jobs = CallJobFilter(sourceAdapter, filter, filterType, recurse);580                    }581                    catch (Exception exception)582                    {583                        // Since we are calling into 3rd party code584                        // catching Exception is allowed. In all585                        // other cases the appropriate exception586                        // needs to be caught.587 588                        // sourceAdapter.GetJobsByFilter() threw unknown exception.589                        _tracer.TraceException(exception);590                        WriteErrorOrWarning(writeErrorOnException, cmdlet, exception, "JobSourceAdapterGetJobsError", sourceAdapter);591                    }592#pragma warning restore 56500593 594                    if (jobs == null)595                    {596                        continue;597                    }598 599                    allJobs.AddRange(jobs);600                }601            }602 603            if (writeObject)604            {605                foreach (Job2 job in allJobs)606                {607                    cmdlet.WriteObject(job);608                }609            }610 611            return allJobs;612        }613 614        /// <summary>615        /// Compare sourceAdapter name with the provided source adapter type616        /// name list.617        /// </summary>618        /// <param name="sourceAdapter"></param>619        /// <param name="jobSourceAdapterTypes"></param>620        /// <returns></returns>621        private static bool CheckTypeNames(JobSourceAdapter sourceAdapter, string[] jobSourceAdapterTypes)622        {623            // If no type names were specified then allow all adapter types.624            if (jobSourceAdapterTypes == null ||625                jobSourceAdapterTypes.Length == 0)626            {627                return true;628            }629 630            string sourceAdapterName = GetAdapterName(sourceAdapter);631            Diagnostics.Assert(sourceAdapterName != null, "Source adapter should have name or type.");632 633            // Look for name match allowing wildcards.634            foreach (string typeName in jobSourceAdapterTypes)635            {636                WildcardPattern typeNamePattern = WildcardPattern.Get(typeName, WildcardOptions.IgnoreCase);637                if (typeNamePattern.IsMatch(sourceAdapterName))638                {639                    return true;640                }641            }642 643            return false;644        }645 646        private static string GetAdapterName(JobSourceAdapter sourceAdapter)647        {648            return (!string.IsNullOrEmpty(sourceAdapter.Name) ?649                sourceAdapter.Name :650                sourceAdapter.GetType().ToString());651        }652 653        /// <summary>654        /// Gets a filtered list of jobs from the given JobSourceAdapter.655        /// </summary>656        /// <param name="sourceAdapter">JobSourceAdapter to query.</param>657        /// <param name="filter">Filter object.</param>658        /// <param name="filterType">Filter type.</param>659        /// <param name="recurse"></param>660        /// <returns>List of jobs from sourceAdapter filtered on filterType.</returns>661        /// <exception cref="Exception">Throws exception on error from JobSourceAdapter662        /// implementation.</exception>663        private static List<Job2> CallJobFilter(JobSourceAdapter sourceAdapter, object filter, FilterType filterType, bool recurse)664        {665            List<Job2> jobs = new List<Job2>();666            IList<Job2> matches;667 668            switch (filterType)669            {670                case FilterType.Command:671 672                    matches = sourceAdapter.GetJobsByCommand((string)filter, recurse);673                    break;674                case FilterType.Filter:675                    matches = sourceAdapter.GetJobsByFilter((Dictionary<string, object>)filter, recurse);676                    break;677                case FilterType.Name:678                    matches = sourceAdapter.GetJobsByName((string)filter, recurse);679                    break;680                case FilterType.State:681                    matches = sourceAdapter.GetJobsByState((JobState)filter, recurse);682                    break;683                case FilterType.None:684                default:685                    matches = sourceAdapter.GetJobs();686                    break;687            }688 689            if (matches != null)690            {691                jobs.AddRange(matches);692            }693 694            return jobs;695        }696 697        /// <summary>698        /// Get job specified by the session specific id provided.699        /// </summary>700        /// <param name="id">Session specific job id.</param>701        /// <param name="cmdlet">Cmdlet requesting this, for error processing.</param>702        /// <param name="writeErrorOnException"></param>703        /// <param name="writeObject"></param>704        /// <param name="recurse"></param>705        /// <returns>Job that match the specified criteria.</returns>706        /// <exception cref="Exception">If cmdlet parameter is null, throws exception on error from707        /// JobSourceAdapter implementation.</exception>708        internal Job2 GetJobById(int id, Cmdlet cmdlet, bool writeErrorOnException, bool writeObject, bool recurse)709        {710            return GetJobThroughId<int>(Guid.Empty, id, cmdlet, writeErrorOnException, writeObject, recurse);711        }712 713        /// <summary>714        /// Get job that has the specified id.715        /// </summary>716        /// <param name="instanceId">Guid to match.</param>717        /// <param name="cmdlet">Cmdlet requesting this, for error processing.</param>718        /// <param name="writeErrorOnException"></param>719        /// <param name="writeObject"></param>720        /// <param name="recurse"></param>721        /// <returns>Job with the specified guid.</returns>722        /// <exception cref="Exception">If cmdlet parameter is null, throws exception on error from723        /// JobSourceAdapter implementation.</exception>724        internal Job2 GetJobByInstanceId(Guid instanceId, Cmdlet cmdlet, bool writeErrorOnException, bool writeObject, bool recurse)725        {726            return GetJobThroughId<Guid>(instanceId, 0, cmdlet, writeErrorOnException, writeObject, recurse);727        }728 729        private Job2 GetJobThroughId<T>(Guid guid, int id, Cmdlet cmdlet, bool writeErrorOnException, bool writeObject, bool recurse)730        {731            Diagnostics.Assert(cmdlet != null, "Cmdlet should always be passed to JobManager");732            Job2 job = null;733            lock (_syncObject)734            {735                foreach (JobSourceAdapter sourceAdapter in _sourceAdapters.Values)736                {737                    try738                    {739                        if (typeof(T) == typeof(Guid))740                        {741                            Diagnostics.Assert(id == 0, "id must be zero when invoked with guid");742                            job = sourceAdapter.GetJobByInstanceId(guid, recurse);743                        }744                        else if (typeof(T) == typeof(int))745                        {746                            Diagnostics.Assert(guid == Guid.Empty, "Guid must be empty when used with int");747                            job = sourceAdapter.GetJobBySessionId(id, recurse);748                        }749                    }750                    catch (Exception exception)751                    {752                        // Since we are calling into 3rd party code753                        // catching Exception is allowed. In all754                        // other cases the appropriate exception755                        // needs to be caught.756 757                        // sourceAdapter.GetJobByInstanceId threw unknown exception.758                        _tracer.TraceException(exception);759 760                        WriteErrorOrWarning(writeErrorOnException, cmdlet, exception, "JobSourceAdapterGetJobByInstanceIdError", sourceAdapter);761                    }762 763                    if (job == null)764                    {765                        continue;766                    }767 768                    if (writeObject)769                    {770                        cmdlet.WriteObject(job);771                    }772 773                    return job;774                }775            }776 777            return null;778        }779 780        /// <summary>781        /// Gets or creates a Job2 object with the given definition name, path782        /// and definition type if specified, that can be run via the StartJob()783        /// method.784        /// </summary>785        /// <param name="definitionName">Job definition name.</param>786        /// <param name="definitionPath">Job definition file path.</param>787        /// <param name="definitionType">JobSourceAdapter type that contains the job definition.</param>788        /// <param name="cmdlet">Cmdlet making call.</param>789        /// <param name="writeErrorOnException">Whether to write jobsourceadapter errors.</param>790        /// <returns>List of matching Job2 objects.</returns>791        internal List<Job2> GetJobToStart(792            string definitionName,793            string definitionPath,794            string definitionType,795            Cmdlet cmdlet,796            bool writeErrorOnException)797        {798            List<Job2> jobs = new List<Job2>();799            WildcardPattern typeNamePattern = (definitionType != null) ?800                WildcardPattern.Get(definitionType, WildcardOptions.IgnoreCase) : null;801 802            lock (_syncObject)803            {804                foreach (JobSourceAdapter sourceAdapter in _sourceAdapters.Values)805                {806                    try807                    {808                        if (typeNamePattern != null)809                        {810                            string sourceAdapterName = GetAdapterName(sourceAdapter);811                            if (!typeNamePattern.IsMatch(sourceAdapterName))812                            {813                                continue;814                            }815                        }816 817                        Job2 job = sourceAdapter.NewJob(definitionName, definitionPath);818                        if (job != null)819                        {820                            jobs.Add(job);821                        }822 823                        if (typeNamePattern != null)824                        {825                            // Adapter type found, can quit.826                            break;827                        }828                    }829                    catch (Exception exception)830                    {831                        // Since we are calling into 3rd party code832                        // catching Exception is allowed. In all833                        // other cases the appropriate exception834                        // needs to be caught.835 836                        _tracer.TraceException(exception);837 838                        WriteErrorOrWarning(writeErrorOnException, cmdlet, exception, "JobSourceAdapterGetJobByInstanceIdError", sourceAdapter);839                    }840                }841            }842 843            return jobs;844        }845 846        private static void WriteErrorOrWarning(bool writeErrorOnException, Cmdlet cmdlet, Exception exception, string identifier, JobSourceAdapter sourceAdapter)847        {848            try849            {850                if (writeErrorOnException)851                {852                    cmdlet.WriteError(new ErrorRecord(exception, identifier, ErrorCategory.OpenError, sourceAdapter));853                }854                else855                {856                    // Write a warning857                    string message = string.Format(CultureInfo.CurrentCulture,858                                                   RemotingErrorIdStrings.JobSourceAdapterError,859                                                   exception.Message,860                                                   sourceAdapter.Name);861                    cmdlet.WriteWarning(message);862                }863            }864            catch (Exception)865            {866                // if this call is not made from a cmdlet thread or if867                // the cmdlet is closed this will thrown an exception868                // it is fine to eat that exception869            }870        }871 872        /// <summary>873        /// Returns a List of adapter names currently loaded.874        /// </summary>875        /// <param name="adapterTypeNames">Adapter names to filter on.</param>876        /// <returns>List of names.</returns>877        internal List<string> GetLoadedAdapterNames(string[] adapterTypeNames)878        {879            List<string> adapterNames = new List<string>();880            lock (_syncObject)881            {882                foreach (JobSourceAdapter sourceAdapter in _sourceAdapters.Values)883                {884                    if (CheckTypeNames(sourceAdapter, adapterTypeNames))885                    {886                        adapterNames.Add(GetAdapterName(sourceAdapter));887                    }888                }889            }890 891            return adapterNames;892        }893 894        #endregion GetJobs895 896        #region RemoveJob897 898        /// <summary>899        /// Remove a job from the appropriate store.900        /// </summary>901        /// <param name="sessionJobId">Session specific Job ID to remove.</param>902        /// <param name="cmdlet"></param>903        /// <param name="writeErrorOnException"></param>904        internal void RemoveJob(int sessionJobId, Cmdlet cmdlet, bool writeErrorOnException)905        {906            Job2 job = GetJobById(sessionJobId, cmdlet, writeErrorOnException, false, false);907            RemoveJob(job, cmdlet, false);908        }909 910        /// <summary>911        /// Remove a job from the appropriate store.912        /// </summary>913        /// <param name="job">Job object to remove.</param>914        /// <param name="cmdlet"></param>915        /// <param name="writeErrorOnException"></param>916        /// <param name="throwExceptions">If true, will throw all JobSourceAdapter exceptions to caller.917        /// This is needed if RemoveJob is being called from an event handler in Receive-Job.</param>918        /// <returns>True if job is found.</returns>919        internal bool RemoveJob(Job2 job, Cmdlet cmdlet, bool writeErrorOnException, bool throwExceptions = false)920        {921            bool jobFound = false;922 923            lock (_syncObject)924            {925                foreach (JobSourceAdapter sourceAdapter in _sourceAdapters.Values)926                {927                    Job2 foundJob = null;928#pragma warning disable 56500929                    try930                    {931                        foundJob = sourceAdapter.GetJobByInstanceId(job.InstanceId, true);932                    }933                    catch (Exception exception)934                    {935                        // Since we are calling into 3rd party code936                        // catching Exception is allowed. In all937                        // other cases the appropriate exception938                        // needs to be caught.939 940                        // sourceAdapter.GetJobByInstanceId() threw unknown exception.941                        _tracer.TraceException(exception);942                        if (throwExceptions)943                        {944                            throw;945                        }946 947                        WriteErrorOrWarning(writeErrorOnException, cmdlet, exception, "JobSourceAdapterGetJobError", sourceAdapter);948                    }949#pragma warning restore 56500950 951                    if (foundJob == null)952                    {953                        continue;954                    }955 956                    jobFound = true;957                    RemoveJobIdForReuse(foundJob);958 959#pragma warning disable 56500960                    try961                    {962                        sourceAdapter.RemoveJob(job);963                    }964                    catch (Exception exception)965                    {966                        // Since we are calling into 3rd party code967                        // catching Exception is allowed. In all968                        // other cases the appropriate exception969                        // needs to be caught.970                        // sourceAdapter.RemoveJob() threw unknown exception.971 972                        _tracer.TraceException(exception);973                        if (throwExceptions)974                        {975                            throw;976                        }977 978                        WriteErrorOrWarning(writeErrorOnException, cmdlet, exception, "JobSourceAdapterRemoveJobError", sourceAdapter);979                    }980#pragma warning restore 56500981                }982            }983 984            if (!jobFound && throwExceptions)985            {986                var message = PSRemotingErrorInvariants.FormatResourceString(RemotingErrorIdStrings.ItemNotFoundInRepository,987                            "Job repository", job.InstanceId.ToString());988                throw new ArgumentException(message);989            }990 991            return jobFound;992        }993 994        private void RemoveJobIdForReuse(Job job)995        {996            Hashtable duplicateDetector = new Hashtable();997            duplicateDetector.Add(job.Id, job.Id);998 999            RemoveJobIdForReuseHelper(duplicateDetector, job);1000        }1001 1002        private void RemoveJobIdForReuseHelper(Hashtable duplicateDetector, Job job)1003        {1004            lock (s_syncObject)1005            {1006                s_jobIdsForReuse.Remove(job.InstanceId);1007            }1008 1009            foreach (Job child in job.ChildJobs)1010            {1011                if (duplicateDetector.ContainsKey(child.Id))1012                {1013                    continue;1014                }1015 1016                duplicateDetector.Add(child.Id, child.Id);1017 1018                RemoveJobIdForReuse(child);1019            }1020        }1021 1022        #endregion RemoveJob1023 1024        /// <summary>1025        /// Filters available for GetJob, used internally to centralize Exception handling.1026        /// </summary>1027        private enum FilterType1028        {1029            /// <summary>1030            /// Use no filter.1031            /// </summary>1032            None,1033 1034            /// <summary>1035            /// Filter on command (string).1036            /// </summary>1037            Command,1038 1039            /// <summary>1040            /// Filter on custom dictionary (dictionary(string, object)).1041            /// </summary>1042            Filter,1043 1044            /// <summary>1045            /// Filter on name (string).1046            /// </summary>1047            Name,1048 1049            /// <summary>1050            /// Filter on job state (JobState).1051            /// </summary>1052            State1053        }1054    }1055}1056