예제 #1
0
파일: Flatten.cs 프로젝트: nofuture-git/31g
        /// <summary>
        /// Creates a new wrapper around the remote process.
        /// </summary>
        /// <param name="ports"></param>
        /// <remarks>
        /// See the detailed notes on its sister type <see cref="AssemblyAnalysis"/> ctor.
        /// While not exact in terms of what its doing - it is exact in terms of how it does it.
        /// </remarks>
        public Flatten(params int[] ports)
        {
            if (string.IsNullOrWhiteSpace(NfConfig.CustomTools.InvokeFlatten) || !File.Exists(NfConfig.CustomTools.InvokeFlatten))
            {
                throw new ItsDeadJim("Don't know where to locate the NoFuture.Util.Tokens.InvokeFlatten.exe, assign " +
                                     "the global variable at NoFuture.Tools.CustomTools.InvokeFlatten.");
            }
            var args           = string.Empty;
            var getFlatAsmPort = DefaultPort;

            if (ports != null && ports.Length > 0)
            {
                getFlatAsmPort = ports[0];
                args           = ConsoleCmd.ConstructCmdLineArgs(GET_FLAT_ASM_PORT_CMD_SWITCH,
                                                                 getFlatAsmPort.ToString(CultureInfo.InvariantCulture));
            }

            MyProcess = StartRemoteProcess(NfConfig.CustomTools.InvokeFlatten, args);

            _invokeGetFlattenAssemblyCmd = new InvokeGetFlattenAssembly()
            {
                ProcessId  = MyProcess.Id,
                SocketPort = getFlatAsmPort
            };
        }
예제 #2
0
        /// <summary>
        /// The ctor both instantiates this type and launches the remote process which does
        /// the actual parsing.
        /// </summary>
        /// <param name="port"></param>
        public NfTypeNameProcess(int?port)
        {
            //is there one already running?
            MyProcess =
                System.Diagnostics.Process.GetProcessesByName("NoFuture.Tokens.InvokeNfTypeName").FirstOrDefault();
            if (MyProcess != null)
            {
                _invokeCmd = new InvokeGetNfTypeName
                {
                    ProcessId  = MyProcess.Id,
                    SocketPort = port.GetValueOrDefault(DefaultPort)
                };
                return;
            }

            if (string.IsNullOrWhiteSpace(NfConfig.CustomTools.InvokeNfTypeName) || !File.Exists(NfConfig.CustomTools.InvokeNfTypeName))
            {
                throw new ItsDeadJim("Don't know where to locate the NoFuture.Tokens.InvokeNfTypeName.exe, assign " +
                                     "the global variable at NoFuture.Tools.CustomTools.InvokeNfTypeName.");
            }

            var cmdPort = port.GetValueOrDefault(DefaultPort);
            var args    = ConsoleCmd.ConstructCmdLineArgs(GET_NF_TYPE_NAME_CMD_SWITCH, cmdPort.ToString());

            MyProcess = StartRemoteProcess(NfConfig.CustomTools.InvokeNfTypeName, args);

            _invokeCmd = new InvokeGetNfTypeName
            {
                ProcessId  = MyProcess.Id,
                SocketPort = cmdPort
            };
        }
예제 #3
0
        /// <summary>
        /// Runs <see cref="AsmDiagram"/> to generate a diagram
        /// on another process to keep the loaded assemblies isolated from the invoking app domain.
        /// </summary>
        /// <param name="assemblyPath"></param>
        /// <returns>This output is JSON and not GraphViz syntax</returns>
        public static string RunIsolatedAsmAdjGraph(string assemblyPath)
        {
            var argPath     = ConsoleCmd.ConstructCmdLineArgs(Settings.INVOKE_ASM_PATH_SWITCH, assemblyPath);
            var diagramType = ConsoleCmd.ConstructCmdLineArgs(Settings.INVOKE_GRAPHVIZ_DIAGRAM_TYPE,
                                                              Settings.ASM_ADJ_GRAPH);

            return(RunGraphViz(argPath, null, diagramType, 60));
        }
예제 #4
0
        /// <summary>
        /// Run its counterpart <see cref="GetClassDiagram"/> in an isolated process
        /// </summary>
        public static string RunIsolatedGetClassDiagram(string assemblyPath, string typeFullName, bool displayEnums, int maxWaitInSeconds = 60)
        {
            var argPath     = ConsoleCmd.ConstructCmdLineArgs(Settings.INVOKE_ASM_PATH_SWITCH, assemblyPath);
            var argType     = ConsoleCmd.ConstructCmdLineArgs(Settings.INVOKE_FULL_TYPE_NAME_SWITCH, typeFullName);
            var diagramType = ConsoleCmd.ConstructCmdLineArgs(Settings.INVOKE_GRAPHVIZ_DIAGRAM_TYPE,
                                                              Settings.CLASS_DIAGRAM);
            var argEn = displayEnums
                ? ConsoleCmd.ConstructCmdLineArgs(Settings.INVOKE_GRAPHVIZ_DISPLAY_ENUMS, null)
                : null;

            return(RunGraphViz(argPath, argType, diagramType, maxWaitInSeconds, argEn));
        }
예제 #5
0
        /// <summary>
        /// Runs <see cref="AsmDiagram"/> to generate a diagram
        /// on another process to keep the loaded assemblies isolated from the invoking app domain.
        /// </summary>
        /// <param name="assemblyPath"></param>
        /// <param name="withNamespaceSubgraphs"></param>
        /// <returns></returns>
        public static string RunIsolatedAsmDiagram(string assemblyPath, bool withNamespaceSubgraphs = false)
        {
            var argPath     = ConsoleCmd.ConstructCmdLineArgs(Settings.INVOKE_ASM_PATH_SWITCH, assemblyPath);
            var diagramType = ConsoleCmd.ConstructCmdLineArgs(Settings.INVOKE_GRAPHVIZ_DIAGRAM_TYPE,
                                                              Settings.ASM_OBJ_GRAPH_DIAGRAM);

            if (withNamespaceSubgraphs)
            {
                var withNsOutlines = ConsoleCmd.ConstructCmdLineArgs(Settings.ASM_OBJ_OUTLINE_NS, null);
                return(RunGraphViz(argPath, null, diagramType, 60, withNsOutlines));
            }

            return(RunGraphViz(argPath, null, diagramType, 60));
        }
예제 #6
0
        /// <summary>
        /// A helper function used to draft the entire command line switch (s)
        /// which are passed to the NoFuture.Hbm.InvokeStoredProc.exe process.
        ///
        /// The function handles wrapping values in double quotes when said value
        /// contains a space.  When the args are assigned to a <see cref="System.Diagnostics.ProcessStartInfo"/>
        /// as a single string and, in turn, received by a console's Main statement as a
        /// string array the values are being split on the space char (0x20) and the double-quotes
        /// are removed.
        /// </summary>
        /// <param name="spItem"></param>
        /// <param name="connectionString"></param>
        /// <returns></returns>
        public static string ConstructCmdLineArgs(StoredProcMetadata spItem, string connectionString)
        {
            var cmdArg = new StringBuilder();

            cmdArg.Append(ConsoleCmd.ConstructCmdLineArgs(CONNECTION_STR_SWITCH, connectionString));

            cmdArg.Append(" ");
            cmdArg.Append(ConsoleCmd.ConstructCmdLineArgs(FILE_PATH_SWITCH, spItem.BinFilePath));

            cmdArg.Append(" ");
            cmdArg.Append(ConsoleCmd.ConstructCmdLineArgs(HBM_STORED_PROX_DIR_SWITCH, Settings.HbmStoredProcsDirectory));

            cmdArg.Append(" ");
            cmdArg.Append(ConsoleCmd.ConstructCmdLineArgs(SEND_MESSAGES_BACK_ON_SOCKET, Boolean.TrueString));

            return(cmdArg.ToString());
        }
예제 #7
0
        /// <summary>
        /// Runs <see cref="Flatten"/>
        /// </summary>
        /// <param name="assemblyPath"></param>
        /// <param name="typeFullName"></param>
        /// <param name="maxDepth">The max recursive depth.</param>
        /// <param name="onlyPrimitivesNamed"></param>
        /// <param name="displayEnums"></param>
        /// <param name="maxWaitInSeconds"></param>
        /// <returns></returns>
        public static string RunIsolatedFlattenTypeDiagram(string assemblyPath, string typeFullName,
                                                           string onlyPrimitivesNamed, bool displayEnums, int maxDepth = FlattenLineArgs.MAX_DEPTH, int maxWaitInSeconds = 60)
        {
            var argPath     = ConsoleCmd.ConstructCmdLineArgs(Settings.INVOKE_ASM_PATH_SWITCH, assemblyPath);
            var argType     = ConsoleCmd.ConstructCmdLineArgs(Settings.INVOKE_FULL_TYPE_NAME_SWITCH, typeFullName);
            var diagramType = ConsoleCmd.ConstructCmdLineArgs(Settings.INVOKE_GRAPHVIZ_DIAGRAM_TYPE,
                                                              Settings.FLATTENED_DIAGRAM);
            var argP = !string.IsNullOrWhiteSpace(onlyPrimitivesNamed)
                ? ConsoleCmd.ConstructCmdLineArgs(Settings.INVOKE_GRAPHVIZ_FLATTENED_LIMIT_TYPE, onlyPrimitivesNamed)
                : null;
            var argEn = displayEnums
                ? ConsoleCmd.ConstructCmdLineArgs(Settings.INVOKE_GRAPHVIZ_DISPLAY_ENUMS, null)
                : null;
            var argMaxDepth = ConsoleCmd.ConstructCmdLineArgs(Settings.INVOKE_GRAPHVIZ_FLATTEN_MAX_DEPTH,
                                                              maxDepth.ToString());

            return(RunGraphViz(argPath, argType, diagramType, maxWaitInSeconds, argP, argEn, argMaxDepth));
        }
예제 #8
0
        public Dpx(string binDir)
        {
            if (string.IsNullOrWhiteSpace(binDir) || !Directory.Exists(binDir))
            {
                throw new ItsDeadJim($"The {binDir} directory was not found");
            }
            if (string.IsNullOrWhiteSpace(NfConfig.CustomTools.InvokeDpx) || !File.Exists(NfConfig.CustomTools.InvokeDpx))
            {
                throw new ItsDeadJim("Don't know where to locate the NoFuture.Tokens.DotNetMeta.InvokeDpx, assign " +
                                     "the global variable at NoFuture.CustomTools.InvokeDpx.");
            }
            var args = string.Join(" ", ConsoleCmd.ConstructCmdLineArgs(BIN_DIR, binDir));

            _si = new ProcessStartInfo
            {
                FileName               = NfConfig.CustomTools.InvokeDpx,
                Arguments              = args,
                UseShellExecute        = false,
                CreateNoWindow         = true,
                RedirectStandardOutput = true,
                RedirectStandardError  = true
            };
        }
예제 #9
0
        /// <summary>
        /// Launches the NoFuture.Tokens.Gia.InvokeAssemblyAnalysis.exe
        /// </summary>
        /// <param name="resolveGacAsmNames"></param>
        /// <param name="ports">
        /// Optional, allows caller to specify the ports used - will use defaults
        /// otherwise.
        /// </param>
        /// <returns></returns>
        /// <remarks>
        /// The ports used are <see cref="DefaultPort"/> to <see cref="DefaultPort"/> + 5.
        /// </remarks>
        /// <remarks>
        /// <![CDATA[
        ///  +------------------------------------------------------------------------------------------------------------+
        ///  |                                           Using AssemblyAnalysis                                           |
        ///  ||+--operating-context(1)--+|+-----new-instance(2)----+|+------remote-exe(3)-----+|+---target-assembly(4)---+|
        ///  ||      new instance of     |                          |                          |                          |
        ///  ||                   ................>                 |                          |                          |
        ///  ||                          |     start new process    |                          |                          |
        ///  ||                          |   provide assembly name  |                          |                          |
        ///  ||                          |                    ................>                |                          |
        ///  ||                          |                          |      launch sockets      |                          |
        ///  ||                          |                          | get asm names on manifest|                          |
        ///  ||                          |                          |                     ................>               |
        ///  ||                          |                          |send AsmIndicies on socket|                          |
        ///  ||                          |                 <................                   |                          |
        ///  ||                          |    receive AsmIndices    |                          |                          |
        ///  ||                          |       save to disk       |                          |                          |
        ///  ||                          |      assign to prop      |                          |                          |
        ///  ||                <................                    |                          |                          |
        ///  ||  invoke GetTokenIds with |                          |                          |                          |
        ///  ||           regex          |                          |                          |                          |
        ///  ||                   ................>                 |                          |                          |
        ///  ||                          | send GetTokenIdsCriteria |                          |                          |
        ///  ||                          |         on socket        |                          |                          |
        ///  ||                          |                    ................>                |                          |
        ///  ||                          |                          |    get types as tokens   |                          |
        ///  ||                          |                          |                     ................>               |
        ///  ||                          |                          |   get members as tokens  |                          |
        ///  ||                          |                          |                     ................>               |
        ///  ||                          |                          |  get callvirts as tokens |                          |
        ///  ||                          |                          |                     ................>               |
        ///  ||                          |                          |  get tokens-of-tokens(a) |                          |
        ///  ||                          |                          |                     ................>               |
        ///  ||                          |                          |send TokenIds on socket(b)|                          |
        ///  ||                          |                 <................                   |                          |
        ///  ||                          |       get TokenIds       |                          |                          |
        ///  ||                          |       save to disk       |                          |                          |
        ///  ||                          |      return TokenIds     |                          |                          |
        ///  ||                <................                    |                          |                          |
        ///  ||   flatten the TokenIds   |                          |                          |                          |
        ///  ||   invoke GetTokenNames   |                          |                          |                          |
        ///  ||                   ................>                 |                          |                          |
        ///  ||                          | send MetadataTokenId[] on|                          |                          |
        ///  ||                          |          socket          |                          |                          |
        ///  ||                          |                    ................>                |                          |
        ///  ||                          |                          | resolve each to a runtime|                          |
        ///  ||                          |                          |           type           |                          |
        ///  ||                          |                          |                     ................>               |
        ///  ||                          |                          | send TokenNames on socket|                          |
        ///  ||                          |                 <................                   |                          |
        ///  ||                          |    receive TokenNames    |                          |                          |
        ///  ||                          |       save to disk       |                          |                          |
        ///  ||                          |     return TokenNames    |                          |                          |
        ///  ||                <................                    |                          |                          |
        ///  ||+------------------------+|+------------------------+|+------------------------+|+------------------------+|
        ///
        /// (1) assume PowerShell
        /// (2) new instance of NoFuture.Tokens.DotNetMeta.AssemblyAnalysis
        /// (3) new process NoFuture.Tokens.DotNetMeta.InvokeAssemblyAnalysis.exe
        /// (4) the assembly whose tokens we want
        ///
        /// (a)  The top-level types already had all thier members resolved to tokens and every virtcall found within the body of those members.
        ///      This is now starting it all over again as if the types found on the callvirts in the body of these members were themselves the top-level types.
        ///      This will continue until we end up on a type which is contained in an assembly whose name doesn't match our regex pattern.
        /// (b)  This is a tree data-struct. Each token has itself a collection of tokens and so on.
        /// ]]>
        /// </remarks>
        /// <example>
        /// <![CDATA[
        ///  # will launch a console
        ///  $myAsmAly = New-Object NoFuture.Tokens.DotNetMeta.AssemblyAnalysis($false)
        ///
        ///  # this is assembly-name-to-index used to reduce the size of socket payloads
        ///  $myAsmIndices = $myAsmAly.GetAsmIndices($AssemblyPath)
        ///
        ///  # this is all the types in a similar form
        ///  $myTokenTypes = $myAsmAly.GetTokenTypes("NoFuture.*")
        ///
        ///  # this will represent the call-stack-tree in terms of just metadata token ids
        ///  $myTokensIds = $myAsmAly.GetTokenIds(0, "NoFuture.*")
        ///
        ///  # translates the metadata token ids into a token name (e.g. type, method, field, etc.)
        ///  $myTokenNames = $myAsmAly.GetTokenNames($myTokensIds.GetAsRoot().SelectDistinct(), $true)
        /// ]]>
        /// </example>
        /// <example>
        /// <![CDATA[
        ///  # example using analysis results
        ///  # say, some app with three layers: web, logic and data
        ///  # have already run the analysis and have all the results on file as JSON
        ///  $myAsmAly = New-Object NoFuture.Tokens.DotNetMeta.AssemblyAnalysis($false)
        ///
        ///  # web layer uses types from logic layer as interfaces
        ///  $myWebTokens = ([NoFuture.Tokens.DotNetMeta.TokenName.TokenNameResponse]::ReadFromFile($webTokensFile)).GetAsRoot()
        ///  $myWebTypes = ([NoFuture.Tokens.DotNetMeta.TokenType.TokenTypeResponse]::ReadFromFile($webTypesFile)).GetAsRoot()
        ///  $myWebAssemblies = [NoFuture.Tokens.DotNetMeta.TokenAsm.TAsmIndexResponse]::ReadFromFile($webAssemblyFile)
        ///
        ///  #logic layer uses types from data layer, likewise, as interfaces
        ///  $myLogicTokens = ([NoFuture.Tokens.DotNetMeta.TokenName.TokenNameResponse]::ReadFromFile($logicTokensFile)).GetAsRoot()
        ///  $myLogicTypes = ([NoFuture.Tokens.DotNetMeta.TokenType.TokenTypeResponse]::ReadFromFile($logicTypesFile)).GetAsRoot()
        ///
        ///  #data layer is as far down as we want to go
        ///  $myDataTokens = ([NoFuture.Tokens.DotNetMeta.TokenName.TokenNameResponse]::ReadFromFile($dataTokensFile)).GetAsRoot()
        ///  $myDataTypes = ([NoFuture.Tokens.DotNetMeta.TokenType.TokenTypeResponse]::ReadFromFile($dataTypesFile)).GetAsRoot()
        ///
        ///  #expand logic layer with data layer's concrete types
        ///  $myLogicTokens = $myAsmAly.ReassignTokenNames($myLogicTokens, $myDataTokens, $myDataTypes).GetAsRoot()
        ///
        ///  #expand web layer with expanded logic layer's concrete types
        ///  $myWebTokens = $myAsmAly.ReassignTokenNames($myWebTokens, $myLogicTokens, $myLogicTypes).GetAsRoot()
        ///
        ///  #get all token names in logic layer as a Set instead of a Data-Tree
        ///  $myFlatLogicTokens = $myLogicTokens.SelectDistinct()
        ///
        ///  #do likewise for the web layer - get tokens as a Set
        ///  $myFlatWebTokens = $myWebTokens.SelectDistinct()
        ///
        ///  #now normal Set-Operations can be applied
        ///  #say, want to find orphaned methods in logic layer no longer used by web layer
        ///  $myOrphanedLogicTokens = $myFlatWebTokens.GetRightSetDiff($myFlatLogicTokens)
        ///
        ///  #this would tell us all the types with at least one orphaned member
        ///  $orphanedTypes = $myOrphanedLogicTokens.GetUniqueTypeNames() | Sort-Object
        ///
        ///  #using NoFuture.Gen, we could remove these systematically if we know where to find the assemblies with .pdb's
        ///  $searchDirs = @(
        ///      "C:\Projects\MyProj\Web\bin",
        ///      "C:\Projects\MyProj\Logic\debug\bin",
        ///      "C:\Projects\MyProj\Data\debug\bin")
        ///
        ///
        ///  #(in actual practice, you would want to perform null-checks, skipped here for brevity)
        ///  $orphanedTypes | % {
        ///     $typeName = $_
        ///
        ///     $tokenType = $myWebTypes.Items | ? {$_.Name -eq $typeName}
        ///
        ///     #PDB data will not be found for interface type def's
        ///     if($tokenType.IsInterfaceType()){
        ///         $tokenType = $tokenTypes.GetFirstInterfaceImplementor($tokenType)
        ///     }
        ///
        ///     #need to go backwards from a type name to some path to some assembly on the drive
        ///     $asmPath = [NoFuture.Tokens.DotNetMeta.TokenAsm.AsmIndexResponse]::GetAssemblyPathFromRoot($typeName, $myWebAssemblies, $tokenType, $searchDirs)
        ///
        ///     #now get this as a NoFuture.Gen code-gen type (assuming .NET code file was C#)
        ///     $nfCgType = New-Object NoFuture.Gen.CgTypeCsSrcCode($asmPath,$typeName)
        ///
        ///     #collect up all the orphaned members now as NoFuture.Gen.CgMember's
        ///     $nfCgMems = New-Object "System.Collections.Generic.List[NoFuture.Gen.CgMember]"
        ///     $orphanedMembersByType = $myOrphanedLogicTokens.SelectTypeNamesThatEndWith(([string[]]@($typeName)))
        ///     $orphanedMembersByType | % {
        ///
        ///         #NoFuture.Gen directly transforms a MetadataTokenName into a CgMember
        ///         $nfCgMems.Add($nfCgType.CgType.FindCgMemberByTokenName($_))
        ///     }
        ///
        ///     #blow away the orphaned members from the original source code file(s)
        ///     [NoFuture.Gen.RefactorExtensions]::RemoveMembers($nfCgMems, $true)
        ///  }
        /// ]]>
        /// </example>
        public AssemblyAnalysis(bool resolveGacAsmNames, params int[] ports)
        {
            if (string.IsNullOrWhiteSpace(NfConfig.CustomTools.InvokeAssemblyAnalysis) || !File.Exists(NfConfig.CustomTools.InvokeAssemblyAnalysis))
            {
                throw new ItsDeadJim("Don't know where to locate the NoFuture.Tokens.DotNetMeta.InvokeAssemblyAnalysis, assign " +
                                     "the global variable at NoFuture.Shared.Cfg.NfConfig.CustomTools.InvokeAssemblyAnalysis.");
            }

            var np       = DefaultPort;
            var usePorts = new int[6];

            for (var i = 0; i < usePorts.Length; i++)
            {
                usePorts[i] = ports != null && ports.Length >= i + 1 ? ports[i] : np + i;
            }
            var args = string.Join(" ",
                                   ConsoleCmd.ConstructCmdLineArgs(GET_ASM_INDICES_PORT_CMD_SWITCH,
                                                                   usePorts[0].ToString(CultureInfo.InvariantCulture)),
                                   ConsoleCmd.ConstructCmdLineArgs(GET_TOKEN_IDS_PORT_CMD_SWITCH,
                                                                   usePorts[1].ToString(CultureInfo.InvariantCulture)),
                                   ConsoleCmd.ConstructCmdLineArgs(GET_TOKEN_NAMES_PORT_CMD_SWITCH,
                                                                   usePorts[2].ToString(CultureInfo.InvariantCulture)),
                                   ConsoleCmd.ConstructCmdLineArgs(GET_TOKEN_PAGE_RANK_PORT_CMD_SWITCH,
                                                                   usePorts[3].ToString(CultureInfo.InvariantCulture)),
                                   ConsoleCmd.ConstructCmdLineArgs(GET_TOKEN_TYPES_PORT_CMD_SWITCH,
                                                                   usePorts[4].ToString(CultureInfo.InvariantCulture)),
                                   ConsoleCmd.ConstructCmdLineArgs(REASSIGN_TOKEN_NAMES_PORT_CMD_SWITCH,
                                                                   usePorts[5].ToString(CultureInfo.InvariantCulture)),
                                   ConsoleCmd.ConstructCmdLineArgs(RESOLVE_GAC_ASM_SWITCH, resolveGacAsmNames.ToString()));

            MyProcess = StartRemoteProcess(NfConfig.CustomTools.InvokeAssemblyAnalysis, args);

            _getAsmIndiciesCmd = new InvokeGetAsmIndicies
            {
                ProcessId  = MyProcess.Id,
                SocketPort = usePorts[0]
            };

            _getTokenIdsCmd = new InvokeGetTokenIds
            {
                ProcessId  = MyProcess.Id,
                SocketPort = usePorts[1]
            };

            _getTokenNamesCmd = new InvokeGetTokenNames
            {
                ProcessId  = MyProcess.Id,
                SocketPort = usePorts[2]
            };

            _getTokenPageRankCmd = new InvokeGetTokenPageRank
            {
                ProcessId  = MyProcess.Id,
                SocketPort = usePorts[3]
            };

            _getTokenTypesCmd = new InvokeGetTokenTypes
            {
                ProcessId  = MyProcess.Id,
                SocketPort = usePorts[4]
            };
            _reassignTokenNamesCmd = new InvokeReassignTokenNames
            {
                ProcessId  = MyProcess.Id,
                SocketPort = usePorts[5]
            };
        }
예제 #10
0
        /// <summary>
        /// Runs its counterpart <see cref="GetCgOfType"/> in an isolated process.
        /// </summary>
        /// <param name="assemblyPath"></param>
        /// <param name="typeFullName"></param>
        /// <param name="resolveDependencies"></param>
        /// <param name="maxWaitInSeconds"></param>
        /// <returns></returns>
        public static CgType GetIsolatedCgOfType(string assemblyPath, string typeFullName,
                                                 bool resolveDependencies = false, int maxWaitInSeconds = 60)
        {
            var tempDebug = NfConfig.TempDirectories.Debug;

            if (string.IsNullOrWhiteSpace(tempDebug) || !Directory.Exists(tempDebug))
            {
                throw new RahRowRagee("The constant value at " +
                                      "'NoFuture.Shared.Cfg.NfConfig.TempDirectories.Debug' is not assigned.");
            }

            var invokeGetCgTypePath = NfConfig.CustomTools.InvokeGetCgType;

            if (string.IsNullOrWhiteSpace(typeFullName))
            {
                throw new ArgumentNullException(nameof(typeFullName));
            }
            if (string.IsNullOrWhiteSpace(invokeGetCgTypePath))
            {
                throw new RahRowRagee("The constants value at " +
                                      "'NoFuture.Shared.Cfg.NfConfig.CustomTools.InvokeGetCgType' is not assigned.");
            }
            if (!File.Exists(invokeGetCgTypePath))
            {
                throw new ItsDeadJim(
                          $"The binary 'NoFuture.Gen.InvokeGetCgOfType.exe' is not at '{invokeGetCgTypePath}'.");
            }

            var argPath    = ConsoleCmd.ConstructCmdLineArgs(Settings.INVOKE_ASM_PATH_SWITCH, assemblyPath);
            var argType    = ConsoleCmd.ConstructCmdLineArgs(Settings.INVOKE_FULL_TYPE_NAME_SWITCH, typeFullName);
            var argResolve = ConsoleCmd.ConstructCmdLineArgs(Settings.INVOKE_RESOLVE_ALL_DEPENDENCIES,
                                                             resolveDependencies.ToString());
            string buffer = null;

            using (var invokeGetCgType = new Process
            {
                StartInfo = new ProcessStartInfo(invokeGetCgTypePath)
                {
                    CreateNoWindow = true,
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    Arguments = string.Join(" ", new[] { argPath, argType, argResolve })
                }
            })
            {
                invokeGetCgType.Start();
                buffer = invokeGetCgType.StandardOutput.ReadToEnd();
                invokeGetCgType.WaitForExit(maxWaitInSeconds);

                if (!invokeGetCgType.HasExited)
                {
                    invokeGetCgType.Kill();
                    throw new ItsDeadJim(
                              "The 'NoFuture.Gen.InvokeGetCgOfType.exe' ran " +
                              $"longer than '{maxWaitInSeconds}' seconds and was shut down.");
                }
            }

            if (string.IsNullOrWhiteSpace(buffer))
            {
                throw new ItsDeadJim("The invocation to 'NoFuture.Gen.InvokeGetCgOfType.exe' didn't " +
                                     "return anything on its standard output.");
            }

            File.WriteAllBytes(Path.Combine(tempDebug, "GetIsolatedCgType.json"),
                               Encoding.UTF8.GetBytes(buffer));

            var dcs = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(CgType));

            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(buffer)))
            {
                var cgTypeOut = dcs.ReadObject(ms) as CgType;
                if (cgTypeOut == null)
                {
                    throw new ItsDeadJim(
                              $"Could not deserialize into a CgType from the standard output text of\n {buffer}");
                }
                return(cgTypeOut);
            }
        }