Package: cmd-call-graph
cmd-call-graphA simple tool to generate a call graph for calls within Windows CMD (batch) files.The tool is available on PyPI:https://pypi.org/project/cmd-call-graph/By default, it takes the input file as stdin and outputs the resulting file
to stdout, outputting logs and errors to stderr.Output ExamplesGiven the following CMD script:@echo off
call :foo
goto :eof
:bar
    echo "in bar"
    call :baz
    call :baz
:baz
    echo "in baz"
    call powershell.exe Write-Host "Hello World from PowerShell"

:foo
    echo "In foo"
    goto :barThis script would generate the following graph:If the--hide-node-statsoption is enabled, then the following graph would be generated:Invocation ExamplesInvocation example for Ubuntu Linux and WSL (Windows Subsystem for Linux), assumes
Python andpipare installed:$pipinstallcmd-call-graph
$cmd-call-graph<your-file.cmd>your-file-call-graph.dot2>logThe resultingdotfile can be rendered with anydotrenderer. Example with
graphviz (VIEWERcould beexplorer.exeunder Windows):$sudoaptinstallgraphviz
$dot-Tpngyour-file-call-graph.dot>your-file-call-graph.png
$$VIEWERyour-file-call-graph.pngExample with PowerShell:PSC:\>chocoinstallgraphvizpython3pipPSC:\>cmd-call-graph.exe-iyour-file.cmd-oyour-file-call-graph.dotPSC:\>dot.exe-Tpngyour-file-call-graph.dot-OPSC:\>explorer.exeyour-file-call-graph.dot.pngTypes of entities representedThe script analyzes CMD scripts, and represents each block of text under a given label as anodein
the call graph.Node propertiesEach node always contains the line number where it starts, except if the node is never defined in the code,
which can happen in case of programming errors, dynamic node names (e.g.,%command%) and theeofpseudo-node.If a node causes the program to exit, it is marked asterminating.If--show-node-statsis set, extra stats about each node are displayed, if present:number of lines of code (LOC);number of external calls.Special nodesThere are 2 special nodes:_begin_is a pseudo-node inserted at the start of each call graph, which represents the start of the
script, which is by definition without a label;eof, which may or may not be a pseudo-node. In CMD,eofis a special node that is used as target
ofgototo indicate that the current "subroutine" should terminate, or the whole program should
terminate if the call stack is empty.Theeofnode is automatically removed if it's a pseudo-node and it's not reached viacallornestedconnections.The_begin_pseudo-node is removed if there is another node starting at line 1.Types of connectionsgoto: if an edge of typegotogoes fromAtoB, it means that in the code within the labelAthere is an instruction in the formgoto :B.call: if an edge of typecallgoes fromAtoB, it means that in the code within the labelAthere is an instruction in the formcall :B.nested: if an edge of typenestedgoes fromAtoB, it means that in the code within the labelAends directly whereBstarts, and there is nogotoorexitstatement at the end ofAwhich would
prevent the execution from not going intoBasAends.Example of anestedconnection:A:
  echo "foo"
  echo "bar"
B:
  echo "baz"The above code would lead to anestedconnection betweenAandB.Command-line optionsThe input file needs to be passed as an argument.--simplify-calls: create one edge for each type of connection instead of creating one for each
individualcall/goto(which is the default). Leads to a simpler but less accurate graph;--hide-node-stats: removes from each node additional information about itself (i.e., number
of lines of code, number of external calls);--nodes-to-hide: hides the list of nodes passed as a space-separated list after this parameter.-vor--verbose: enable debug output, which will be sent to the log file;-lor--log-file: name of the log file. If not specified, the standard error file is used;-oor--output: name of the output file. If not specified, the standard output file is used.Legend for Output GraphsThe graphs are self-explanatory: all information is codified with descriptive labels, and there is no
information conveyed only with color or other types of non-text graphical hint.Colors are used to make the graph easier to follow, but no information is conveyed only with color.Here is what each color means in the graph:Orange:gotoconnection;Blue:callconnection;Teal:nestedconnection;Light gray: background for terminating nodesWhy?Sometimes legacy code bases may contain old CMD files. This tool allows to
generate a visual representation of the internal calls within the script.ContributingThis project welcomes contributions and suggestions.  Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the rights to use your contribution. For details, visithttps://cla.microsoft.com.When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions
provided by the bot. You will only need to do this once across all repos using our CLA.This project has adopted theMicrosoft Open Source Code of Conduct.
For more information see theCode of Conduct FAQor
contactopencode@microsoft.comwith any additional questions or comments.Unit testsRun unit tests from the project root either with the built-inunittestmodule:python -m unittest discoverOr by usingpytests, which can produce reports both for unit test success and for code coverage, by
using the following invocation:pip install pytest
pip install pytest-cov
pytest tests --doctest-modules --junitxml=junit/test-results.xml --cov=callgraph --cov-report=xml --cov-report=html