Add goinfo and gosoft
This commit is contained in:
BIN
tools/go/gosoft/gosoft.exe
Executable file
BIN
tools/go/gosoft/gosoft.exe
Executable file
Binary file not shown.
502
tools/go/gosoft/gosoft.go
Normal file
502
tools/go/gosoft/gosoft.go
Normal file
@@ -0,0 +1,502 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Software holds information about installed software
|
||||
type Software struct {
|
||||
Source string `json:"source"`
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
InstallDate string `json:"install_date"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
var softwareList []Software
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
softwareList = append(softwareList, enumerateWindows()...)
|
||||
} else if runtime.GOOS == "linux" {
|
||||
softwareList = append(softwareList, enumerateLinux()...)
|
||||
}
|
||||
|
||||
output, err := json.MarshalIndent(softwareList, "", " ")
|
||||
if err != nil {
|
||||
log.Println("Error marshalling software list:", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(string(output))
|
||||
}
|
||||
|
||||
// Add to the enumerateWindows function
|
||||
func enumerateWindows() []Software {
|
||||
var softwareList []Software
|
||||
|
||||
// Winget
|
||||
softwareList = append(softwareList, enumerateWinget()...)
|
||||
|
||||
// Chocolatey
|
||||
softwareList = append(softwareList, enumerateChocolatey()...)
|
||||
|
||||
// Scoop
|
||||
softwareList = append(softwareList, enumerateScoop()...)
|
||||
|
||||
// Common Windows Installations
|
||||
softwareList = append(softwareList, enumerateCommonWindows()...)
|
||||
|
||||
// NuGet
|
||||
softwareList = append(softwareList, enumerateNuGet()...)
|
||||
|
||||
// Microsoft Store
|
||||
softwareList = append(softwareList, enumerateMicrosoftStore()...)
|
||||
|
||||
return softwareList
|
||||
}
|
||||
|
||||
// Add to the enumerateLinux function
|
||||
func enumerateLinux() []Software {
|
||||
var softwareList []Software
|
||||
|
||||
// APT
|
||||
softwareList = append(softwareList, enumerateApt()...)
|
||||
|
||||
// Snap
|
||||
softwareList = append(softwareList, enumerateSnap()...)
|
||||
|
||||
// Pip
|
||||
softwareList = append(softwareList, enumeratePip()...)
|
||||
|
||||
// NPM
|
||||
softwareList = append(softwareList, enumerateNpm()...)
|
||||
|
||||
// Flatpak
|
||||
softwareList = append(softwareList, enumerateFlatpak()...)
|
||||
|
||||
// RPM
|
||||
softwareList = append(softwareList, enumerateRpm()...)
|
||||
|
||||
// Pacman
|
||||
softwareList = append(softwareList, enumeratePacman()...)
|
||||
|
||||
// Homebrew
|
||||
softwareList = append(softwareList, enumerateHomebrew()...)
|
||||
|
||||
// Conda
|
||||
softwareList = append(softwareList, enumerateConda()...)
|
||||
|
||||
return softwareList
|
||||
}
|
||||
|
||||
func enumerateNuGet() []Software {
|
||||
var softwareList []Software
|
||||
|
||||
output, err := runCommand("nuget", "list", "-AllVersions")
|
||||
if err != nil {
|
||||
log.Println("Error enumerating NuGet packages:", err)
|
||||
return softwareList
|
||||
}
|
||||
|
||||
lines := strings.Split(output, "\n")
|
||||
for _, line := range lines {
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) < 2 {
|
||||
continue
|
||||
}
|
||||
softwareList = append(softwareList, Software{
|
||||
Source: "nuget",
|
||||
Name: parts[0],
|
||||
Version: parts[1],
|
||||
})
|
||||
}
|
||||
|
||||
return softwareList
|
||||
}
|
||||
|
||||
func enumerateMicrosoftStore() []Software {
|
||||
var softwareList []Software
|
||||
|
||||
output, err := runCommand("powershell", "Get-AppxPackage", "|", "Select-Object", "Name,PackageFullName,InstallDate")
|
||||
if err != nil {
|
||||
log.Println("Error enumerating Microsoft Store packages:", err)
|
||||
return softwareList
|
||||
}
|
||||
|
||||
lines := strings.Split(output, "\n")
|
||||
for _, line := range lines {
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) < 3 {
|
||||
continue
|
||||
}
|
||||
softwareList = append(softwareList, Software{
|
||||
Source: "microsoft store",
|
||||
Name: parts[0],
|
||||
Version: parts[1],
|
||||
InstallDate: parseInstallDate(parts[2]),
|
||||
})
|
||||
}
|
||||
|
||||
return softwareList
|
||||
}
|
||||
|
||||
func enumerateFlatpak() []Software {
|
||||
var softwareList []Software
|
||||
|
||||
output, err := runCommand("flatpak", "list")
|
||||
if err != nil {
|
||||
log.Println("Error enumerating Flatpak packages:", err)
|
||||
return softwareList
|
||||
}
|
||||
|
||||
lines := strings.Split(output, "\n")
|
||||
for _, line := range lines {
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) < 2 {
|
||||
continue
|
||||
}
|
||||
softwareList = append(softwareList, Software{
|
||||
Source: "flatpak",
|
||||
Name: parts[0],
|
||||
Version: parts[1],
|
||||
})
|
||||
}
|
||||
|
||||
return softwareList
|
||||
}
|
||||
|
||||
func enumerateRpm() []Software {
|
||||
var softwareList []Software
|
||||
|
||||
output, err := runCommand("rpm", "-qa", "--queryformat", "%{NAME} %{VERSION}\n")
|
||||
if err != nil {
|
||||
log.Println("Error enumerating RPM packages:", err)
|
||||
return softwareList
|
||||
}
|
||||
|
||||
lines := strings.Split(output, "\n")
|
||||
for _, line := range lines {
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) < 2 {
|
||||
continue
|
||||
}
|
||||
softwareList = append(softwareList, Software{
|
||||
Source: "rpm",
|
||||
Name: parts[0],
|
||||
Version: parts[1],
|
||||
})
|
||||
}
|
||||
|
||||
return softwareList
|
||||
}
|
||||
|
||||
func enumeratePacman() []Software {
|
||||
var softwareList []Software
|
||||
|
||||
output, err := runCommand("pacman", "-Q")
|
||||
if err != nil {
|
||||
log.Println("Error enumerating Pacman packages:", err)
|
||||
return softwareList
|
||||
}
|
||||
|
||||
lines := strings.Split(output, "\n")
|
||||
for _, line := range lines {
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) < 2 {
|
||||
continue
|
||||
}
|
||||
softwareList = append(softwareList, Software{
|
||||
Source: "pacman",
|
||||
Name: parts[0],
|
||||
Version: parts[1],
|
||||
})
|
||||
}
|
||||
|
||||
return softwareList
|
||||
}
|
||||
|
||||
func enumerateHomebrew() []Software {
|
||||
var softwareList []Software
|
||||
|
||||
output, err := runCommand("brew", "list", "--versions")
|
||||
if err != nil {
|
||||
log.Println("Error enumerating Homebrew packages:", err)
|
||||
return softwareList
|
||||
}
|
||||
|
||||
lines := strings.Split(output, "\n")
|
||||
for _, line := range lines {
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) < 2 {
|
||||
continue
|
||||
}
|
||||
softwareList = append(softwareList, Software{
|
||||
Source: "homebrew",
|
||||
Name: parts[0],
|
||||
Version: parts[1],
|
||||
})
|
||||
}
|
||||
|
||||
return softwareList
|
||||
}
|
||||
|
||||
func enumerateConda() []Software {
|
||||
var softwareList []Software
|
||||
|
||||
output, err := runCommand("conda", "list", "--json")
|
||||
if err != nil {
|
||||
log.Println("Error enumerating Conda packages:", err)
|
||||
return softwareList
|
||||
}
|
||||
|
||||
var condaPackages []map[string]interface{}
|
||||
err = json.Unmarshal([]byte(output), &condaPackages)
|
||||
if err != nil {
|
||||
log.Println("Error parsing Conda JSON output:", err)
|
||||
return softwareList
|
||||
}
|
||||
|
||||
for _, pkg := range condaPackages {
|
||||
softwareList = append(softwareList, Software{
|
||||
Source: "conda",
|
||||
Name: pkg["name"].(string),
|
||||
Version: pkg["version"].(string),
|
||||
})
|
||||
}
|
||||
|
||||
return softwareList
|
||||
}
|
||||
|
||||
func runCommand(cmd string, args ...string) (string, error) {
|
||||
out, err := exec.Command(cmd, args...).Output()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(out), nil
|
||||
}
|
||||
|
||||
func parseInstallDate(dateString string) string {
|
||||
layout := "2006-01-02"
|
||||
date, err := time.Parse(layout, dateString)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return date.Format(layout)
|
||||
}
|
||||
|
||||
func enumerateWinget() []Software {
|
||||
var softwareList []Software
|
||||
|
||||
output, err := runCommand("winget", "list", "--source", "winget")
|
||||
if err != nil {
|
||||
log.Println("Error enumerating Winget packages:", err)
|
||||
return softwareList
|
||||
}
|
||||
|
||||
lines := strings.Split(output, "\n")
|
||||
for _, line := range lines {
|
||||
parts := regexp.MustCompile(`\s+`).Split(line, -1)
|
||||
if len(parts) < 4 {
|
||||
continue
|
||||
}
|
||||
softwareList = append(softwareList, Software{
|
||||
Source: "winget",
|
||||
Name: parts[0],
|
||||
Version: parts[1],
|
||||
})
|
||||
}
|
||||
|
||||
return softwareList
|
||||
}
|
||||
|
||||
func enumerateChocolatey() []Software {
|
||||
var softwareList []Software
|
||||
|
||||
output, err := runCommand("choco", "list", "--local-only")
|
||||
if err != nil {
|
||||
log.Println("Error enumerating Chocolatey packages:", err)
|
||||
return softwareList
|
||||
}
|
||||
|
||||
lines := strings.Split(output, "\n")
|
||||
for _, line := range lines {
|
||||
parts := strings.Split(line, "|")
|
||||
if len(parts) < 2 {
|
||||
continue
|
||||
}
|
||||
softwareList = append(softwareList, Software{
|
||||
Source: "chocolatey",
|
||||
Name: parts[0],
|
||||
Version: parts[1],
|
||||
})
|
||||
}
|
||||
|
||||
return softwareList
|
||||
}
|
||||
|
||||
func enumerateScoop() []Software {
|
||||
var softwareList []Software
|
||||
|
||||
output, err := runCommand("scoop", "list")
|
||||
if err != nil {
|
||||
log.Println("Error enumerating Scoop packages:", err)
|
||||
return softwareList
|
||||
}
|
||||
|
||||
lines := strings.Split(output, "\n")
|
||||
for _, line := range lines {
|
||||
if strings.HasPrefix(line, "Installed apps") {
|
||||
continue
|
||||
}
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) < 2 {
|
||||
continue
|
||||
}
|
||||
softwareList = append(softwareList, Software{
|
||||
Source: "scoop",
|
||||
Name: parts[0],
|
||||
Version: parts[1],
|
||||
})
|
||||
}
|
||||
|
||||
return softwareList
|
||||
}
|
||||
|
||||
func enumerateCommonWindows() []Software {
|
||||
var softwareList []Software
|
||||
|
||||
output, err := runCommand("powershell", "Get-WmiObject", "-Class", "Win32_Product", "|", "Select-Object", "Name,Version,InstallDate")
|
||||
if err != nil {
|
||||
log.Println("Error enumerating common Windows installations:", err)
|
||||
return softwareList
|
||||
}
|
||||
|
||||
lines := strings.Split(output, "\n")
|
||||
for _, line := range lines {
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) < 3 {
|
||||
continue
|
||||
}
|
||||
softwareList = append(softwareList, Software{
|
||||
Source: "common windows installation",
|
||||
Name: parts[0],
|
||||
Version: parts[1],
|
||||
InstallDate: parseInstallDate(parts[2]),
|
||||
})
|
||||
}
|
||||
|
||||
return softwareList
|
||||
}
|
||||
|
||||
func enumerateApt() []Software {
|
||||
var softwareList []Software
|
||||
|
||||
output, err := runCommand("dpkg-query", "-W", "-f=${binary:Package} ${Version} ${Installed-Size}\n")
|
||||
if err != nil {
|
||||
log.Println("Error enumerating APT packages:", err)
|
||||
return softwareList
|
||||
}
|
||||
|
||||
lines := strings.Split(output, "\n")
|
||||
for _, line := range lines {
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) < 2 {
|
||||
continue
|
||||
}
|
||||
softwareList = append(softwareList, Software{
|
||||
Source: "apt",
|
||||
Name: parts[0],
|
||||
Version: parts[1],
|
||||
})
|
||||
}
|
||||
|
||||
return softwareList
|
||||
}
|
||||
|
||||
func enumerateSnap() []Software {
|
||||
var softwareList []Software
|
||||
|
||||
output, err := runCommand("snap", "list")
|
||||
if err != nil {
|
||||
log.Println("Error enumerating Snap packages:", err)
|
||||
return softwareList
|
||||
}
|
||||
|
||||
lines := strings.Split(output, "\n")
|
||||
for _, line := range lines {
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) < 3 {
|
||||
continue
|
||||
}
|
||||
softwareList = append(softwareList, Software{
|
||||
Source: "snap",
|
||||
Name: parts[0],
|
||||
Version: parts[1],
|
||||
})
|
||||
}
|
||||
|
||||
return softwareList
|
||||
}
|
||||
|
||||
func enumeratePip() []Software {
|
||||
var softwareList []Software
|
||||
|
||||
output, err := runCommand("pip", "list", "--format=json")
|
||||
if err != nil {
|
||||
log.Println("Error enumerating Pip packages:", err)
|
||||
return softwareList
|
||||
}
|
||||
|
||||
var pipPackages []map[string]string
|
||||
err = json.Unmarshal([]byte(output), &pipPackages)
|
||||
if err != nil {
|
||||
log.Println("Error parsing Pip JSON output:", err)
|
||||
return softwareList
|
||||
}
|
||||
|
||||
for _, pkg := range pipPackages {
|
||||
softwareList = append(softwareList, Software{
|
||||
Source: "pip",
|
||||
Name: pkg["name"],
|
||||
Version: pkg["version"],
|
||||
})
|
||||
}
|
||||
|
||||
return softwareList
|
||||
}
|
||||
|
||||
func enumerateNpm() []Software {
|
||||
var softwareList []Software
|
||||
|
||||
output, err := runCommand("npm", "list", "-g", "--depth=0", "--json")
|
||||
if err != nil {
|
||||
log.Println("Error enumerating NPM packages:", err)
|
||||
return softwareList
|
||||
}
|
||||
|
||||
var npmPackages map[string]interface{}
|
||||
err = json.Unmarshal([]byte(output), &npmPackages)
|
||||
if err != nil {
|
||||
log.Println("Error parsing NPM JSON output:", err)
|
||||
return softwareList
|
||||
}
|
||||
|
||||
dependencies := npmPackages["dependencies"].(map[string]interface{})
|
||||
for name, info := range dependencies {
|
||||
infoMap := info.(map[string]interface{})
|
||||
version := infoMap["version"].(string)
|
||||
softwareList = append(softwareList, Software{
|
||||
Source: "npm",
|
||||
Name: name,
|
||||
Version: version,
|
||||
})
|
||||
}
|
||||
|
||||
return softwareList
|
||||
}
|
||||
Reference in New Issue
Block a user