A configuration and security inspection tool written in Go
Author: Pecezen.org
Platform: Windows
Language: Go
When preparing for ISO/IEC 27001 certification, under control 8.9 Configuration Management, auditors commonly review the following aspects.
- The operating system versions of servers and personal computers.
- Whether any unauthorized software has been installed.
- Whether firewall and antivirus software are properly enabled.
- Whether any unnecessary system services are running.
So I decided to write a simple configuration and security inspection tool. I recently had some free time, so Iโm sharing it here for everyoneโs reference.
โ Tool Features Overview๏ผ
- ๐ฅ๏ธ Hardware Information
- ๐งฉ Operating System (OS) Information
- ๐ฆ Installed Software List
- ๐ก๏ธ Antivirus Status
- ๐ฅ Firewall Status
- โ๏ธ System Services Status
- ๐ค Supports CSV Export for auditing or record-keeping
- ๐ Multi-language Interface (Traditional Chinese / English / Japanese / German)
๐ฅ๏ธ User Interface๏ผ

๐พ Download the Windows Version
You can use the source code below to compile the program yourself, but weโve also included a ready-to-run Windows executable for your convenience.๏ผ
Download
The downloaded file is a compressed archive.
The extraction password is: pecezen.org
๐Source Code
package main
import (
"bytes"
"encoding/csv"
"image/color"
"os/exec"
"strings"
"syscall"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)
/*
=========================
Theme & Language (i18n)
=========================
*/
type readableTheme struct{}
func (readableTheme) Color(n fyne.ThemeColorName, v fyne.ThemeVariant) color.Color {
if n == theme.ColorNameDisabled {
return color.NRGBA{0, 0, 0, 255}
}
return theme.DefaultTheme().Color(n, v)
}
func (readableTheme) Font(s fyne.TextStyle) fyne.Resource { return theme.DefaultTheme().Font(s) }
func (readableTheme) Icon(n fyne.ThemeIconName) fyne.Resource { return theme.DefaultTheme().Icon(n) }
func (readableTheme) Size(n fyne.ThemeSizeName) float32 { return theme.DefaultTheme().Size(n) }
type Lang string
const (
LangZHTW Lang = "zh-TW"
LangEN Lang = "en"
LangJA Lang = "ja"
LangDE Lang = "de"
)
var langOptions = []string{"็น้ซไธญๆ", "English", "ๆฅๆฌ่ช", "Deutsch"}
var langMap = map[string]Lang{
"็น้ซไธญๆ": LangZHTW,
"English": LangEN,
"ๆฅๆฌ่ช": LangJA,
"Deutsch": LangDE,
}
const prefLangKey = "SelectedLanguage"
type i18n struct{ lang Lang }
func (i i18n) tr(key string) string {
table := map[string]map[Lang]string{
"app.title": {
LangZHTW: "็ตๆ
่ๅฎๅ
จๆงๆชขๆธฌๅทฅๅ
ท V1.0",
LangEN: "Config & Security Audit Tool V1.0",
LangJA: "ๆงๆใจใปใญใฅใชใใฃ่จบๆญ V1.0",
LangDE: "Konfigurations- und Sicherheits-Audit-Tool V1.0",
},
"tab.hardware": {
LangZHTW: "็กฌ้ซ่ณ่จ", LangEN: "Hardware Info", LangJA: "ใใผใใฆใงใขๆ
ๅ ฑ", LangDE: "Hardware-Info",
},
"tab.os": {
LangZHTW: "OS ่ณ่จ", LangEN: "OS Info", LangJA: "OS ๆ
ๅ ฑ", LangDE: "OS-Info",
},
"tab.apps": {
LangZHTW: "่ป้ซๆธ
ๅฎ", LangEN: "Software", LangJA: "ใฝใใไธ่ฆง", LangDE: "Softwareliste",
},
"tab.av": {
LangZHTW: "้ฒๆฏ็ๆ
", LangEN: "Antivirus", LangJA: "ใฆใคใซในๅฏพ็ญ", LangDE: "Virenschutz",
},
"tab.firewall": {
LangZHTW: "้ฒ็ซ็", LangEN: "Firewall", LangJA: "้ฒ็ซๅฃ", LangDE: "Firewall",
},
"tab.service": {
LangZHTW: "็ณป็ตฑๆๅ", LangEN: "Services", LangJA: "ใตใผใใน", LangDE: "Systemdienste",
},
"tab.policy": {
LangZHTW: "ๅฎๅ
จๅๅ", LangEN: "Policies", LangJA: "ใใชใทใผ", LangDE: "Sicherheitsrichtlinien",
},
"btn.export": {
LangZHTW: "ๅฏๅบ็ฎๅๅ้ CSV",
LangEN: "Export Current CSV",
LangJA: "็พๅจใฎใใผใธใCSVๅฏๅบ",
LangDE: "Aktuellen Tab als CSV exportieren",
},
"btn.about": {
LangZHTW: "้ๆผ", LangEN: "About", LangJA: "่ฉณใใ", LangDE: "รber",
},
"loading": {
LangZHTW: "่ณๆ่ผๅ
ฅไธญ...", LangEN: "Loading...", LangJA: "่ชญใฟ่พผใฟไธญ...", LangDE: "Daten werden geladen...",
},
"col.name": {
LangZHTW: "ๅ็จฑ (Name)", LangEN: "Name", LangJA: "ๅๅ", LangDE: "Name",
},
"col.status": {
LangZHTW: "็ๆ
/็ๆฌ (Status/Ver)", LangEN: "Status/Ver", LangJA: "็ถๆ
/็", LangDE: "Status/Ver",
},
"col.detail": {
LangZHTW: "่ฉณ็ดฐ่ณ่จ (Details)", LangEN: "Details", LangJA: "่ฉณ็ดฐๆ
ๅ ฑ", LangDE: "Details",
},
"about.title": {
LangZHTW: "้ๆผ็จๅผ", LangEN: "About App", LangJA: "ใขใใชใซใคใใฆ", LangDE: "รber die App",
},
"about.body": {
LangZHTW: "ไฝ่
: Pecezen.org\n็ๆฌๆๆ ยฉ 2026\n\nๅ
่ฒฌ่ฒๆ:\nไฝ่
ไธๅฐๅ ไฝฟ็จๆฌ็จๅผๆ้ ๆ็ไปปไฝ่ณๆ้บๅคฑใๆๅฃๆๅ
ถไปๅพๆ่ฒ ่ฒฌใ",
LangEN: "Author: Pecezen.org\nCopyright ยฉ 2026\n\nDisclaimer:\nThe author is not responsible for any data loss, damage, or other consequences caused by the use of this program.",
LangJA: "ไฝ่
: Pecezen.org\n่ไฝๆฌ ยฉ 2026\n\nๅ
่ฒฌไบ้
:\nไฝ่
ใฏใๆฌใใญใฐใฉใ ใฎไฝฟ็จใซใใฃใฆ็ใใใใผใฟใฎ็ดๅคฑใ็ ดๆใใพใใฏใใฎไปใฎ็ตๆใซใคใใฆไธๅใฎ่ฒฌไปปใ่ฒ ใใพใใใ",
LangDE: "Autor: Pecezen.org\nUrheberrecht ยฉ 2026\n\nHaftungsausschluss:\nDer Autor haftet nicht fรผr Datenverlust, Schรคden oder andere Folgen, die durch die Verwendung dieses Programms entstehen.",
},
}
return table[key][i.lang]
}
/*
=========================
Custom UI Components
=========================
*/
type fixedWidthLabel struct {
widget.Label
width float32
}
func newFixedWidthLabel(text string, width float32) *fixedWidthLabel {
l := &fixedWidthLabel{width: width}
l.ExtendBaseWidget(l)
l.SetText(text)
l.TextStyle = fyne.TextStyle{Bold: true}
return l
}
func (f *fixedWidthLabel) MinSize() fyne.Size { return fyne.NewSize(f.width, 32) }
/*
=========================
PowerShell Data Logic
=========================
*/
func runCmd(psCmd string) string {
cmd := exec.Command("powershell", "-NoProfile", "-Command", "[Console]::OutputEncoding=[System.Text.Encoding]::UTF8;"+psCmd)
cmd.SysProcAttr = &syscall.SysProcAttr{
HideWindow: true,
CreationFlags: 0x08000000,
}
var out bytes.Buffer
cmd.Stdout = &out
_ = cmd.Run()
return strings.TrimSpace(out.String())
}
func collectHardwareInfo() string {
ps := `
$cpu = (Get-CimInstance Win32_Processor).Name;
$cs = Get-CimInstance Win32_ComputerSystem;
$mem = $cs.TotalPhysicalMemory;
Write-Host "CPU: $cpu";
Write-Host "Total Memory: $([math]::Round($mem/1GB, 2)) GB";
Write-Host "Manufacturer: $($cs.Manufacturer)";
Write-Host "Model: $($cs.Model)";
Write-Host "---------------------------------------------------------------------------";
Write-Host "Disk Partition Info (็กฌ็ขๅๅ่ณ่จ):";
Get-CimInstance Win32_LogicalDisk | Where-Object {$_.DriveType -eq 3} | ForEach-Object {
$size = [math]::Round($_.Size/1GB, 2); $free = [math]::Round($_.FreeSpace/1GB, 2); $used = $size - $free; $per = [math]::Round(($used/$size)*100, 2);
Write-Host "Drive $($_.DeviceID) | Total: $($size)GB | Free: $($free)GB | Used: $($per)%"
} | Out-String`
return runCmd(ps)
}
func collectAntivirusInfo() string {
ps := `
Write-Host "[ ๅฎ่ฃ็้ฒๆฏ่ป้ซๆธ
ๅฎ ]";
$avList = Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntivirusProduct;
if ($avList) { $avList | ForEach-Object { Write-Host "- ่ป้ซๅ็จฑ: $($_.displayName)" } } else { Write-Host "- ๆชๅตๆธฌๅฐ็ฌฌไธๆน้ฒๆฏ่ป้ซ" }
Write-Host ""; Write-Host "[ Windows Defender ็ๆ
]";
Get-MpComputerStatus | Select-Object AntivirusEnabled, RealTimeProtectionEnabled, AntivirusSignatureVersion, AntivirusSignatureLastUpdated | Format-List | Out-String`
return runCmd(ps)
}
func collectListData(psCmd string) [][]string {
raw := runCmd(psCmd + " | ConvertTo-Csv -NoTypeInformation")
r := csv.NewReader(strings.NewReader(raw))
records, err := r.ReadAll()
if err != nil || len(records) <= 1 {
return [][]string{}
}
return records[1:]
}
/*
=========================
Main Application
=========================
*/
func main() {
a := app.NewWithID("org.pecezen.audit.tool")
a.Settings().SetTheme(&readableTheme{})
savedLang := a.Preferences().StringWithFallback(prefLangKey, "็น้ซไธญๆ")
i := i18n{lang: langMap[savedLang]}
w := a.NewWindow(i.tr("app.title"))
if resourceIconPng != nil {
w.SetIcon(resourceIconPng)
}
w.Resize(fyne.NewSize(1100, 560))
appData := [][]string{}
svcData := [][]string{}
var currentTabIndex int = 0
const nameColWidth float32 = 780
const statusColWidth float32 = 250
createTextTab := func() (*widget.Entry, fyne.CanvasObject, *fixedWidthLabel) {
e := widget.NewMultiLineEntry()
e.Disable()
e.TextStyle = fyne.TextStyle{Monospace: true}
headerLabel := newFixedWidthLabel(i.tr("col.detail"), nameColWidth+statusColWidth)
return e, container.NewBorder(container.NewHBox(headerLabel), nil, nil, nil, container.NewScroll(e)), headerLabel
}
createTableTab := func(data *[][]string) (fyne.CanvasObject, *widget.Table, *fixedWidthLabel, *fixedWidthLabel) {
h1 := newFixedWidthLabel(i.tr("col.name"), nameColWidth)
h2 := newFixedWidthLabel(i.tr("col.status"), statusColWidth)
t := widget.NewTable(
func() (int, int) { return len(*data), 2 },
func() fyne.CanvasObject { l := widget.NewLabel(""); l.Truncation = fyne.TextTruncateEllipsis; return l },
func(id widget.TableCellID, o fyne.CanvasObject) {
if id.Row < len(*data) {
o.(*widget.Label).SetText((*data)[id.Row][id.Col])
}
},
)
t.SetColumnWidth(0, nameColWidth)
t.SetColumnWidth(1, statusColWidth)
return container.NewBorder(container.NewHBox(h1, h2), nil, nil, nil, t), t, h1, h2
}
entryHW, uiHW, lblHW := createTextTab()
entryOS, uiOS, lblOS := createTextTab()
entryAV, uiAV, lblAV := createTextTab()
entryFW, uiFW, lblFW := createTextTab()
entryPol, uiPol, lblPol := createTextTab()
uiApps, tableApps, appH1, appH2 := createTableTab(&appData)
uiSvc, tableSvc, svcH1, svcH2 := createTableTab(&svcData)
tabs := container.NewAppTabs(
container.NewTabItem(i.tr("tab.hardware"), uiHW),
container.NewTabItem(i.tr("tab.os"), uiOS),
container.NewTabItem(i.tr("tab.apps"), uiApps),
container.NewTabItem(i.tr("tab.av"), uiAV),
container.NewTabItem(i.tr("tab.firewall"), uiFW),
container.NewTabItem(i.tr("tab.service"), uiSvc),
container.NewTabItem(i.tr("tab.policy"), uiPol),
)
tabs.OnSelected = func(ti *container.TabItem) {
for idx, item := range tabs.Items {
if item == ti {
currentTabIndex = idx
break
}
}
}
refresh := func() {
p := dialog.NewProgressInfinite(i.tr("app.title"), i.tr("loading"), w)
p.Show()
go func() {
sHW := collectHardwareInfo()
sOS := runCmd("Get-ComputerInfo | Select-Object OsName, OsVersion, OsArchitecture, WindowsVersion, OsInstallDate | Format-List | Out-String")
sAV := collectAntivirusInfo()
sFW := runCmd("Get-NetFirewallProfile | Select-Object Name, Enabled | Out-String")
sPol := runCmd("net accounts")
appData = collectListData(`Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object {$_.DisplayName} | Select-Object DisplayName, DisplayVersion`)
svcData = collectListData("Get-Service | Where-Object {$_.Status -eq 'Running'} | Select-Object DisplayName, Status")
fyne.Do(func() {
entryHW.SetText(sHW)
entryOS.SetText(sOS)
entryAV.SetText(sAV)
entryFW.SetText(sFW)
entryPol.SetText(sPol)
lblHW.SetText(i.tr("col.detail"))
lblOS.SetText(i.tr("col.detail"))
lblAV.SetText(i.tr("col.detail"))
lblFW.SetText(i.tr("col.detail"))
lblPol.SetText(i.tr("col.detail"))
appH1.SetText(i.tr("col.name"))
appH2.SetText(i.tr("col.status"))
svcH1.SetText(i.tr("col.name"))
svcH2.SetText(i.tr("col.status"))
tableApps.Refresh()
tableSvc.Refresh()
p.Hide()
})
}()
}
exportBtn := widget.NewButton(i.tr("btn.export"), func() {
save := dialog.NewFileSave(func(uc fyne.URIWriteCloser, err error) {
if uc == nil {
return
}
defer uc.Close()
var buf bytes.Buffer
buf.Write([]byte{0xEF, 0xBB, 0xBF})
writer := csv.NewWriter(&buf)
switch currentTabIndex {
case 0:
writer.Write([]string{"Hardware Info"})
writer.Write([]string{entryHW.Text})
case 1:
writer.Write([]string{"OS Info"})
writer.Write([]string{entryOS.Text})
case 2:
writer.Write([]string{"Software Name", "Version"})
writer.WriteAll(appData)
case 3:
writer.Write([]string{"Antivirus Status"})
writer.Write([]string{entryAV.Text})
case 4:
writer.Write([]string{"Firewall Status"})
writer.Write([]string{entryFW.Text})
case 5:
writer.Write([]string{"Service Name", "Status"})
writer.WriteAll(svcData)
case 6:
writer.Write([]string{"Security Policy"})
writer.Write([]string{entryPol.Text})
}
writer.Flush()
uc.Write(buf.Bytes())
}, w)
tabNames := []string{"Hardware", "OS", "Software", "Antivirus", "Firewall", "Services", "Policies"}
save.SetFileName("Audit_" + tabNames[currentTabIndex] + ".csv")
save.Show()
})
aboutBtn := widget.NewButton(i.tr("btn.about"), func() {
dialog.ShowInformation(i.tr("about.title"), i.tr("about.body"), w)
})
langSelect := widget.NewSelect(langOptions, func(s string) {
a.Preferences().SetString(prefLangKey, s)
i.lang = langMap[s]
w.SetTitle(i.tr("app.title"))
exportBtn.SetText(i.tr("btn.export"))
aboutBtn.SetText(i.tr("btn.about"))
for idx, key := range []string{"tab.hardware", "tab.os", "tab.apps", "tab.av", "tab.firewall", "tab.service", "tab.policy"} {
tabs.Items[idx].Text = " " + i.tr(key) + " "
}
tabs.Refresh()
refresh()
})
langSelect.SetSelected(savedLang)
controls := container.NewHBox(widget.NewLabel("Lang:"), langSelect, exportBtn, aboutBtn)
w.SetContent(container.NewBorder(container.NewVBox(controls), nil, nil, nil, tabs))
w.ShowAndRun()
}
โ ๏ธ Disclaimer
The author is not responsible for any data loss, damage, or other consequences resulting from the use of this program.




