Example #1
0
        public object Convert(DbgSymbol symbol)   // TODO: plumb a CancellationToken through here.
        {
            if (null == m_currentlyProcessingAddresses)
            {
                m_currentlyProcessingAddresses = new HashSet <ulong>();
            }

            if (!m_currentlyProcessingAddresses.Add(symbol.Address))    // TODO: Do we need to worry about enregistered things?
            {
                LogManager.Trace("Detected re-entrant conversion of type {0}; bailing out.", TypeName);
                return(null);
            }

            PowerShell shell;
            var        lease = DbgProvider.LeaseShell(out shell);

            try
            {
                Util.Assert(null != Context);

                Context.Vars["_"]      = new PSVariable("_", symbol);
                Context.Vars["PSItem"] = new PSVariable("PSItem", symbol);

                // Note that StrictMode will be enforced for value converters, because
                // they execute in the scope of Debugger.psm1, which sets StrictMode.
                //
                // The problem with just calling Script.InvokeWithContext directly is that
                // non-terminating errors are hidden from us.
                shell.AddScript(@"$args[ 0 ].InvokeWithContext( $args[ 1 ].Funcs, $args[ 1 ].VarList )",
                                true)
                .AddArgument(Script)
                .AddArgument(Context);

                Collection <PSObject> results = shell.Invoke();

                //  // For some reason, sometimes shell.HadErrors returns true when
                //  // shell.Streams.Error.Count is 0, when the pipeline is stopping.
                //  if( Stopping )
                //      return;

                // INT2d518c4b: shell.HadErrors is clueless.
                //if( shell.HadErrors )
                if (shell.Streams.Error.Count > 0)
                {
                    // TODO TODO: handle more than one
                    // if( 1 == shell.Streams.Error.Count )
                    // {
                    var e = shell.Streams.Error[0];
                    // TODO: tailored exception
                    throw new DbgProviderException(Util.Sprintf("Symbol value conversion for type name {0} failed: {1}",
                                                                TypeName,
                                                                Util.GetExceptionMessages(e.Exception)),
                                                   e);
                    // }
                    // else
                    // {
                    // }
                }

                if (0 == results.Count)
                {
                    return(null); // I guess it didn't work.
                }
                if (1 == results.Count)
                {
                    return(results[0]);
                }
                else
                {
                    // TODO: Hmm... not sure what's the best thing to do here. Return just the
                    // last thing? For now I'll return the collection.
                    LogManager.Trace("Warning: Symbol value conversion for type name {0} yielded multiple results (symbol {1}).", TypeName, symbol);
                    return(results);
                }
            }
            finally
            {
                m_currentlyProcessingAddresses.Remove(symbol.Address);

                if (null != lease)
                {
                    lease.Dispose();
                }

                // Let's not keep the input object rooted.
                Context.Vars.Remove("_");
                Context.Vars.Remove("PSItem");
            }
        } // end Convert()