@Override
	public void launch(GhidraApplicationLayout layout, String[] args) throws Exception {
		String projectName = null;
		String rootFolderPath = null;
		URL ghidraURL = null;
		List<File> filesToImport = new ArrayList<>();
		int optionStartIndex;

		// Make sure there are arguments
		if (args.length < 1) {
			usage();
		}

		// Ghidra URL handler registration
		Handler.registerHandler();

		if (args[0].startsWith("ghidra:")) {
			optionStartIndex = 1;
			try {
				ghidraURL = new URI(args[0]).toURL();
			}
			catch (MalformedURLException e) {
				System.err.println("Invalid Ghidra URL: " + args[0]);
				usage();
			}
		}
		else {
			if (args.length < 2) {
				usage();
			}
			optionStartIndex = 2;
			String projectNameAndFolder = args[1];

			// Check to see if projectName uses back-slashes (likely if they are using Windows)
			projectNameAndFolder = projectNameAndFolder.replaceAll("\\\\", DomainFolder.SEPARATOR);
			projectName = projectNameAndFolder;

			rootFolderPath = "/";
			int folderIndex = projectNameAndFolder.indexOf(DomainFolder.SEPARATOR);
			if (folderIndex == 0) {
				System.err.println(args[1] + " is an invalid project_name/folder_path.");
				usage();
			}
			else if (folderIndex > 0) {
				projectName = projectNameAndFolder.substring(0, folderIndex);
				rootFolderPath = projectNameAndFolder.substring(folderIndex);
			}
		}

		// Determine the desired logging.
		File logFile = null;
		File scriptLogFile = null;
		for (int argi = optionStartIndex; argi < args.length; argi++) {
			if (checkArgument(Arg.LOG, args, argi)) {
				logFile = new File(args[++argi]);
			}
			else if (checkArgument(Arg.SCRIPT_LOG, args, argi)) {
				scriptLogFile = new File(args[++argi]);
			}
		}

		// Instantiate new headless analyzer and parse options.
		// NOTE: The application may already be initialized if this is being called 
		// from an integration test
		HeadlessAnalyzer analyzer = null;
		if (Application.isInitialized()) {
			analyzer = HeadlessAnalyzer.getInstance();
		}
		else {
			analyzer = HeadlessAnalyzer.getLoggableInstance(logFile, scriptLogFile, true);
		}
		HeadlessOptions options = analyzer.getOptions();
		parseOptions(options, args, optionStartIndex, ghidraURL, filesToImport);

		Msg.info(AnalyzeHeadless.class,
			"Headless startup complete (" + GhidraLauncher.getMillisecondsFromLaunch() + " ms)");
		ClassSearcher.logStatistics();

		// Do the headless processing
		try {
			if (ghidraURL != null) {
				analyzer.processURL(ghidraURL, filesToImport);
			}
			else {
				analyzer.processLocal(args[0], projectName, rootFolderPath, filesToImport);
			}
		}
		catch (Throwable e) {
			Msg.error(HeadlessAnalyzer.class,
				"Abort due to Headless analyzer error: " + e.getMessage(), e);
			System.exit(EXIT_CODE_ERROR);
		}
	}
The entry point of 'analyzeHeadless.bat'. Parses the command line arguments to the script
and takes the appropriate headless actions.

@param args Detailed list of arguments is in 'analyzeHeadlessREADME.html'
Ghidra/Features/Base/src/main/java/ghidra/app/util/headless/AnalyzeHeadless.java