Пример #1
0
        } // end _TryLoadAssembly()

        public static void LoadPlugin(string path, IPipelineCallback pipeline)
        {
            _EnsureInitialized();

            pipeline.WriteVerbose("Looking for plugin types in: {0}", path);
            Assembly asm = _TryLoadAssembly(path, pipeline);

            if (null == asm)
            {
                return; // already wrote an error
            }
            Type dtdPluginInterface = typeof(IDbgDerivedTypeDetectionPlugin);

            foreach (var candidateType in asm.GetExportedTypes())
            {
                if (dtdPluginInterface.IsAssignableFrom(candidateType))
                {
                    pipeline.WriteVerbose("Found Derived Type Detection plugin type: {0}", candidateType.FullName);
                    var constructor = candidateType.GetConstructor(Type.EmptyTypes);
                    if (null == constructor)
                    {
                        DbgProviderException dpe = new DbgProviderException(Util.Sprintf("The plugin type '{0}' from '{1}' cannot be used because it has no public, parameterless constructor.",
                                                                                         candidateType.FullName,
                                                                                         path),
                                                                            "PluginTypeMissingDefaultConstructor",
                                                                            System.Management.Automation.ErrorCategory.InvalidData,
                                                                            candidateType);
                        try { throw dpe; } catch (Exception) { }  // give it a stack
                        pipeline.WriteError(dpe);
                    }

                    try
                    {
                        var plugin = (IDbgDerivedTypeDetectionPlugin)constructor.Invoke(null);
                        sm_dtdPlugins.Add(plugin);
                        pipeline.WriteVerbose("Registered Derived Type Detection plugin: {0}", plugin.Name);
                    }
                    catch (Exception e)  // I hate this.
                    {
                        DbgProviderException dpe = new DbgProviderException(Util.Sprintf("The plugin type '{0}' from '{1}' cannot be used because its constructor threw an exception: {2}",
                                                                                         candidateType.FullName,
                                                                                         path,
                                                                                         Util.GetExceptionMessages(e)),
                                                                            "PluginTypeConstructorThrew",
                                                                            System.Management.Automation.ErrorCategory.OpenError,
                                                                            e,
                                                                            candidateType);
                        try { throw dpe; } catch (Exception) { }  // give it a stack
                        pipeline.WriteError(dpe);
                    }
                } // end if( it's a DTD plugin type )
            }     // end foreach( candidateType )
        }         // end LoadPlugin()
Пример #2
0
        } // end AddSourceFile()

        /// <summary>
        ///    Re-runs the list of registered source files, after clearing the internal
        ///    list of registered source files.
        /// </summary>
        /// <remarks>
        ///    It is assumed that when a script runs, it calls some command that causes
        ///    AddSourceFile to be called, thereby re-registering itself. If a script
        ///    produces an error, however, it is kept in the list of source files, so that
        ///    a user can fix the error and call this again without re-registering the
        ///    script.
        ///
        ///    If a script in appendScripts is already in the list, no change is made (the
        ///    script does not get added again to the end of the list, or moved). If a
        ///    script in prependScripts is already in the list, it gets moved from its
        ///    original position to the front.
        /// </remarks>
        public void Reload(CommandInvocationIntrinsics invokeCommand,
                           IList <string> appendScripts,
                           IList <string> prependScripts,
                           string dataDisplayName,  // for verbose messages
                           IPipelineCallback pipe)
        {
            if (null == pipe)
            {
                throw new ArgumentNullException("pipe");
            }

            pipe.WriteVerbose("Dumping old {0}...", dataDisplayName);
            m_DumpContent();

            if (null != appendScripts)
            {
                foreach (var newScript in appendScripts)
                {
                    // Unlike the prepend case, here we don't change the position of the
                    // script in the list if it's already in it.
                    if ((null != newScript) && m_sourceFilesSet.Add(newScript))
                    {
                        pipe.WriteVerbose("Appending script: {0}", newScript);
                        m_sourceFiles.AddLast(newScript);
                    }
                }
            }

            if (null != prependScripts)
            {
                foreach (var newScript in prependScripts)
                {
                    if (null != newScript)
                    {
                        if (m_sourceFilesSet.Remove(newScript))
                        {
                            pipe.WriteVerbose("Prepending (moving) script: {0}", newScript);
                            m_sourceFiles.Remove(newScript);
                        }
                        else
                        {
                            pipe.WriteVerbose("Prepending script: {0}", newScript);
                        }

                        m_sourceFiles.AddFirst(newScript);
                    }
                }
            }

            // It's possible that there's conditional logic in the scripts that causes
            // different scripts to run, so we'd better clear out the existing source
            // files list (after making a copy).
            var oldSourceFiles = m_sourceFiles.ToArray();

            m_sourceFiles.Clear();
            m_sourceFilesSet.Clear();
            foreach (string sourceScript in oldSourceFiles)
            {
                try
                {
                    // If there are errors parsing the file, then it won't be run, and if
                    // it doesn't get run, something won't call AddSourceFile, and if it
                    // doesn't call AddSourceFile, we won't save the script file to run
                    // again next time someone calls Reload. So we'll save the script name
                    // in the "files to run" /now/, instead of later.
                    pipe.WriteVerbose("Adding {0} from: {1}", dataDisplayName, sourceScript);
                    if (AddSourceFile(sourceScript))
                    {
                        ScriptBlockAst ast = InvokeScriptCommand.LoadScript(sourceScript);
                        // TODO: should I do anything with any output?
                        InvokeScriptCommand.InvokeScript(invokeCommand, ast.GetScriptBlock(), true);
                    }
                    else
                    {
                        // I don't think it should be possible to get here.
                        Util.Fail("How did we get here?");
                    }
                }
                catch (DbgProviderException dpe)
                {
                    pipe.WriteError(dpe.ErrorRecord);
                }
                catch (RuntimeException re)
                {
                    pipe.WriteError(re.ErrorRecord);
                }
            }
        } // end Reload()