Report Installed Apps Stats on Mac, Windows, and Linux

Rohan SarnadRohan Sarnad
3 min read

Introduction

Tracking installed applications across different operating systems is crucial for system administrators, security analysts, and IT professionals. Whether it’s for software auditing, compliance checks, or system monitoring, a reliable way to retrieve installed applications is essential.

This feature enables fetching installed applications on Windows, macOS, and Linux, providing a standardised API to retrieve application details like name, version, vendor, installation date, and additional metadata.

PR: https://github.com/oshi/oshi/pull/2851

Implementation Overview

The feature is designed to be efficient and consistent across all three major operating systems. It utilizes OS-specific mechanisms to retrieve application data and integrates a memoization technique to optimize performance by caching results.

1. Standardised Data Model

We define a single ApplicationInfo class to represent application details across all OSes:

public class ApplicationInfo {
    private final String name;
    private final String version;
    private final String vendor;
    private final long timestamp;
    private final Map<String, String> additionalInfo;
}

2. Fetching Installed Applications on Different OS

Each operating system uses a unique approach to extract installed applications:

Windows Implementation

On Windows, installed applications are primarily retrieved from the Windows Registry.

macOS Implementation

On macOS, applications are listed in /Applications/ and can be queried using system commands.

Linux Implementation

Linux distributions use different package managers (dpkg, rpm) to manage installed software.

3. Memoization for Performance Optimization

Since installed applications don’t change frequently, memoization is used to cache results and avoid redundant system calls.

oshi.software.os.linux.LinuxOperatingSystem

private final Supplier<List<ApplicationInfo>> installedAppsSupplier = Memoizer
            .memoize(LinuxInstalledApps::queryInstalledApps, installedAppsExpiration());

public List<ApplicationInfo> getInstalledApplications() {
        return installedAppsSupplier.get();
    }

oshi.util.Memoizer

public static long installedAppsExpiration() {
        return TimeUnit.MINUTES.toNanos(1);
    }

Same implementation is done for Windows and Mac OS specific classes.

https://github.com/oshi/oshi/blob/master/oshi-core/src/main/java/oshi/software/os/linux/LinuxOperatingSystem.java

https://github.com/oshi/oshi/blob/master/oshi-core/src/main/java/oshi/software/os/mac/MacOperatingSystem.java

https://github.com/oshi/oshi/blob/master/oshi-core/src/main/java/oshi/software/os/windows/WindowsOperatingSystem.java

  • Caches results for a configured expiration time (default: 1 minute).

  • Reduces unnecessary queries to the registry, system commands, or package managers.

Key Improvements

Unified Data Model – Replaces multiple OS-specific classes with a single ApplicationInfo class.
Efficient Caching – Uses memoization to reduce redundant queries.
Improved Maintainability – OS-specific logic is confined to their respective implementations.

How to use in your Java Apps?

Add the below code snippet in your app to list the installed apps on the respective server.

SystemInfo si = new SystemInfo();
List<ApplicationInfo> apps = si.getOperatingSystem().getInstalledApplications();

Sample Outputs:

Linux:

Ubuntu:

AppInfo{name=zlib1g, version=1:1.3.dfsg-3.1ubuntu2, vendor=Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>, timestamp=1713886044, additionalInfo={source=zlib, installedSize=162, architecture=amd64, homepage=http://zlib.net/}}
AppInfo{name=zstd, version=1.5.5+dfsg2-2build1, vendor=Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>, timestamp=1713886075, additionalInfo={source=libzstd, installedSize=1798, architecture=amd64, homepage=https://github.com/facebook/zstd}}

Redhat:

AppInfo{name=pipewire-alsa, version=1.0.1-1.el9, vendor=Red Hat, Inc. <http://bugzilla.redhat.com/bugzilla>, timestamp=1741429838, additionalInfo={source=pipewire-1.0.1-1.el9.src.rpm, installedSize=177582, architecture=x86_64, homepage=https://pipewire.org/}}
AppInfo{name=pipewire-pulseaudio, version=1.0.1-1.el9, vendor=Red Hat, Inc. <http://bugzilla.redhat.com/bugzilla>, timestamp=1741429838, additionalInfo={source=pipewire-1.0.1-1.el9.src.rpm, installedSize=437665, architecture=x86_64, homepage=https://pipewire.org/}}

Mac:

AppInfo{name=FaceTime, version=36, vendor=Apple, timestamp=1741255560000, additionalInfo={Get Info String=unknown, Kind=Universal, Location=/System/Applications/FaceTime.app}}
AppInfo{name=IntelliJ IDEA CE, version=2023.1.1, vendor=Developer ID Application: JetBrains s.r.o. (2ZEFAR8TH3), Developer ID Certification Authority, Apple Root CA, timestamp=1682607840000, additionalInfo={Get Info String=IntelliJ IDEA 2023.1.1, build IC-231.8770.65. Copyright JetBrains s.r.o., (c) 2000-2023, Kind=Universal, Location=/Applications/IntelliJ IDEA CE.app}}

Windows:

AppInfo{name=Microsoft Visual C++ 2019 X64 Minimum Runtime - 14.29.30153, version=14.29.30153, vendor=Microsoft Corporation, timestamp=1707868800000, additionalInfo={installLocation=unknown, installSource=C:\ProgramData\Package Cache\{...}v14.29.30153\packages\vcRuntimeMinimum_amd64\}}
AppInfo{name=aws-cfn-bootstrap, version=2.0.29, vendor=Amazon Web Services, timestamp=1707868800000, additionalInfo={installLocation=unknown, installSource=C:\ProgramData\Package Cache\{...}v2.0.29\}}

Conclusion

This feature simplifies fetching installed applications across Windows, macOS, and Linux.

With a unified API, optimised queries, and caching, it ensures efficient and reliable apps monitoring on the server.

1
Subscribe to my newsletter

Read articles from Rohan Sarnad directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Rohan Sarnad
Rohan Sarnad