Using CLI Applications: A Guide for Multiple Programming Languages

Jun 6, 2024 5:42:25 PM | Command-Line Interface Using CLI Applications: A Guide for Multiple Programming Languages

Learn how to integrate CLI tools using Python, Java, C#, JavaScript, Bash, PowerShell, Rust, C++, Xojo, Go, Perl, and Ruby in this practical guide

Following our exploration of the advantages of using Command Line Interfaces (CLI) in software development, this article delves into the practical aspects of invoking CLI tools from different programming and scripting languages. We'll cover how to call a CLI application, pass parameters, and handle its outputs across several popular programming environments.

Basics of CLI Invocation

Calling a CLI application involves executing a command line statement from within a program. This process can vary slightly depending on the programming language but typically involves the use of functions or libraries designed to handle external system calls. Key considerations include handling the standard output (STDOUT), standard error (STDERR), and the exit status of the application, which informs if the command was successful.

Calling CLI Applications in Various Languages

Understanding how to interact with CLI tools from within different programming languages is essential for integrating external processes effectively. Below, we provide detailed guides for several languages.

Python

Python uses the subprocess module to invoke external commands. It provides a powerful interface that supports synchronous and asynchronous commands.

import subprocess

# Calling a CLI tool
result = subprocess.run(['echo', 'Hello World'], capture_output=True, text=True)

# Handling output
print('STDOUT:', result.stdout)
print('Return Code:', result.return_code)
        

Java

Java can execute external commands using the Runtime.getRuntime().exec() method.

import java.io.*;

public class Main {
    public static void main(String[] args) {
        try {
            Process process = new ProcessBuilder("echo", "Hello from Java").start();
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            int exitCode = process.waitFor();
            System.out.println("Exit Code: " + exitCode);
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}
        

C#

C# can call external processes using the System.Diagnostics.Process class, which provides methods to start and manage system processes.

using System;
using System.Diagnostics;

class Program {
    static void Main() {
        ProcessStartInfo startInfo = new ProcessStartInfo("echo", "\"Hello from C#\"") {
            RedirectStandardOutput = true,
            UseShellExecute = false
        };
        Process process = Process.Start(startInfo);
        Console.WriteLine(process.StandardOutput.ReadToEnd());
        process.WaitForExit();
        Console.WriteLine("Exit Code: " + process.ExitCode);
    }
}
        

JavaScript (Node.js)

Node.js uses the child_process module to execute system commands, allowing for asynchronous command execution and event-driven results.

const { exec } = require('child_process');

exec('echo "Hello from Node.js"', (error, stdout, stderr) => {
    if (error) {
        console.error(`Error: ${error}`);
        return;
    }
    if (stderr) {
        console.error(`STDERR: ${stderr}`);
        return;
    }
    console.log(`STDOUT: ${stdout}`);
});
        

Bash

In Bash, CLI tools are called directly. You can capture the output for further processing right within the script.

#!/bin/bash
output=$(echo "Hello from Bash")
echo $output
exit_code=$?
echo "Exit Code: $exit_code"
        

PowerShell

PowerShell can execute external commands using the Invoke-Expression cmdlet or directly calling the executable.

$output = & echo "Hello from PowerShell"
echo $output
$exitCode = $LASTEXITCODE
echo "Exit Code: $exitCode"
        

Best Practices

When invoking CLI applications, it’s crucial to handle errors gracefully, secure inputs to avoid injection attacks, and optimize performance by managing process resources effectively. Always validate external inputs and consider using timeouts for external calls to prevent hanging processes.

Conclusion

Integrating CLI tools within various programming languages enhances the functionality and flexibility of your applications. By following the examples and guidelines provided, developers can effectively harness the power of CLI tools across multiple programming environments.

Experiment with these techniques in your projects, and consider the specific needs and constraints of your applications when integrating external CLI tools. Your feedback and experiences are valuable to enhance this guide further.

 

Additional Language Examples

Rust, C++, Xojo, Go, Perl, and Ruby

Rust

Rust uses the std::process module to spawn processes. Here's how to invoke a CLI application and handle the output:

use std::process::Command;

fn main() {
    let output = Command::new("echo")
        .arg("Hello from Rust")
        .output()
        .expect("Failed to execute command");

    if output.status.success() {
        let s = String::from_utf8_lossy(&output.stdout);
        println!("CLI Output: {}", s);
    } else {
        let s = String::from_utf8_lossy(&output.stderr);
        println!("CLI Error: {}", s);
    }
}
        

C++

In C++, you can use the <cstdlib> library to invoke system commands. Here’s an example:

#include <cstdlib>
#include <iostream>

int main() {
    std::cout << "Executing CLI command...\n";
    int result = system("echo Hello from C++");
    std::cout << "Command executed with return code: " << result << std::endl;
    return 0;
}
        

Xojo

Xojo provides a straightforward method to handle shell commands using the Shell class:

Var sh As New Shell

sh.Execute("echo Hello from Xojo")
If sh.ErrorCode = 0 Then
  MessageBox("CLI Output: " + sh.Result)
Else
  MessageBox("Error: " + sh.ErrorCode.ToString)
End If
        

Go (Golang)

Go provides robust support for executing external commands through the os/exec package:

import "os/exec"
import "fmt"

func main() {
    cmd := exec.Command("echo", "Hello from Go")
    output, err := cmd.CombinedOutput()
    if err != nil {
        fmt.Println("Error:", err)
    }
    fmt.Println("CLI Output:", string(output))
}
        

Perl

Perl is traditionally strong in system interaction and text processing:

#!/usr/bin/perl
use strict;
use warnings;

my $output = `echo Hello from Perl`;
if ($?) {
    print "Command failed: $!\n";
} else {
    print "CLI Output: $output";
}
        

Ruby

Ruby provides an easy way to execute system commands:

output = `echo Hello from Ruby`
unless $?.success?
    puts "Command failed"
else
    puts "CLI Output: #{output}"
end
        
Mark Gavin

Written By: Mark Gavin

Appligent Chief Technology Officer and software architect. Mark invented PDF redaction in 1997 and is also the creator of several other first-ever PDF applications, including Appligent’s SecurSign and FDFMerge, EMC’s Documentum IRM for PDF, and Liquent’s CoreDossier.