/// <summary>
        /// Recursively build the heirarchy of .Net objects in the external process.
        /// </summary>
        /// <param name="proxyService">The proxy service collecting the .Net objects.</param>
        /// <param name="visited">A set of visited object addresses.</param>
        /// <param name="parent">The parent of the current object.</param>
        /// <param name="parentRef">The address of the parent of the current object.</param>
        private void RecursiveBuild(IProxyService proxyService, HashSet <UInt64> visited, DotNetObject parent, UInt64 parentRef)
        {
            // Add all fields
            foreach (UInt64 fieldRef in proxyService.GetObjectFields(parentRef))
            {
                DotNetObject childObject = new DotNetObject(
                    parent,
                    parent.ObjectReference.ToIntPtr().Add(proxyService.GetFieldOffset(fieldRef)).ToUInt64(),
                    Conversions.TypeCodeToType((TypeCode)proxyService.GetFieldType(fieldRef)),
                    proxyService.GetFieldName(fieldRef));
                parent.Children.Add(childObject);
            }

            // Add all nested objects recursively
            foreach (UInt64 childObjectRef in proxyService.GetObjectChildren(parentRef))
            {
                if (childObjectRef == 0 || visited.Contains(childObjectRef))
                {
                    return;
                }

                visited.Add(childObjectRef);

                Type type = Conversions.TypeCodeToType((TypeCode)proxyService.GetObjectType(childObjectRef));

                if (type == null || excludedNameSpaces.Any(X => type.Name.StartsWith(X, StringComparison.OrdinalIgnoreCase)))
                {
                    return;
                }

                DotNetObject child = new DotNetObject(parent, childObjectRef, type, type.Name);
                parent.Children.Add(child);
                this.RecursiveBuild(proxyService, visited, child, childObjectRef);
            }

            parent.Children.Sort();
        }
        /// <summary>
        /// Collects .Net objects in the external process.
        /// </summary>
        /// <param name="cancellationToken">The cancellation token for handling canceled tasks.</param>
        protected override void OnUpdate(CancellationToken cancellationToken)
        {
            this.UpdateInterval = DotNetObjectCollector.PollingTime;

            ProxyCommunicator proxyCommunicator = ProxyCommunicator.GetInstance();
            NormalizedProcess process           = EngineCore.GetInstance()?.Processes?.GetOpenedProcess();
            IProxyService     proxyService      = proxyCommunicator.GetProxyService(EngineCore.GetInstance().Processes.IsOpenedProcess32Bit());

            if (proxyService == null)
            {
                return;
            }

            try
            {
                if (process == null || !proxyService.RefreshHeap(process.ProcessId))
                {
                    return;
                }

                List <DotNetObject> objectTrees = new List <DotNetObject>();
                HashSet <UInt64>    visited     = new HashSet <UInt64>();

                foreach (UInt64 rootRef in proxyService.GetRoots())
                {
                    String rootName = proxyService.GetRootName(rootRef);
                    Type   rootType = Conversions.TypeCodeToType((TypeCode)proxyService.GetRootType(rootRef));

                    if (rootRef == 0 || rootName == null)
                    {
                        continue;
                    }

                    foreach (String excludedPrefix in excludedPrefixes)
                    {
                        if (rootName.StartsWith(excludedPrefix, StringComparison.OrdinalIgnoreCase))
                        {
                            rootName = rootName.Substring(excludedPrefix.Length, rootName.Length - excludedPrefix.Length).Trim();
                        }
                    }

                    if (excludedNameSpaces.Any(x => rootName.StartsWith(x, StringComparison.OrdinalIgnoreCase)))
                    {
                        continue;
                    }

                    if (rootType != null)
                    {
                        if (excludedNameSpaces.Any(x => rootType.Name.StartsWith(x, StringComparison.OrdinalIgnoreCase)))
                        {
                            continue;
                        }
                    }

                    if (visited.Contains(rootRef))
                    {
                        continue;
                    }

                    try
                    {
                        DotNetObject rootObject = new DotNetObject(null, rootRef, rootType, rootName);
                        visited.Add(rootRef);
                        objectTrees.Add(rootObject);

                        this.RecursiveBuild(proxyService, visited, rootObject, rootRef);
                    }
                    catch
                    {
                    }
                }

                this.ObjectTrees = objectTrees;
            }
            catch
            {
            }
        }