From 00e7268caccde3047bffd8bf6547c0c995dd7969 Mon Sep 17 00:00:00 2001 From: Vasily Kaiser <78181427+VasilyKaiser@users.noreply.github.com> Date: Sat, 4 Mar 2023 13:09:31 +0100 Subject: [PATCH 1/3] Make killPort Windows compatible --- main.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/main.go b/main.go index 3588a3a..d87d4a3 100644 --- a/main.go +++ b/main.go @@ -208,7 +208,11 @@ func killPort(pid string) { if err != nil { log.Error("Could not convert to process pid to int") } - syscall.Kill(pidInt, syscall.SIGKILL) + proc, err := os.FindProcess(pidInt) + if err != nil { + log.Error(err) + } + err = proc.Signal(syscall.SIGKILL) if err != nil { log.Error("Could not kill process") } From f8d82841dd90cce9eb42732757a6e2afa50bfaf2 Mon Sep 17 00:00:00 2001 From: Vasily Kaiser <78181427+VasilyKaiser@users.noreply.github.com> Date: Sat, 4 Mar 2023 13:26:43 +0100 Subject: [PATCH 2/3] Split getProcesses based on OS. Add pwsh commands based on privilege. --- main.go | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/main.go b/main.go index d87d4a3..6c98681 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,7 @@ import ( "os" "os/exec" "regexp" + "runtime" "strconv" "strings" "syscall" @@ -61,6 +62,7 @@ var ( Underline(true) docStyle = lipgloss.NewStyle().Padding(1, 2, 1, 2) + asAdmin = true ) type item struct { @@ -178,7 +180,7 @@ func tickCmd() tea.Cmd { }) } -func getProcesses() []list.Item { +func getUnixProcesses() []list.Item { out, _ := exec.Command("lsof", "-i", "-P", "-n", "-sTCP:LISTEN").Output() strStdout := string(out) @@ -203,6 +205,40 @@ func getProcesses() []list.Item { return processes } +func executePowershellCmd() []byte { + var pwshCommand string + // Powershell needs elevated privilege to run "Get-Process" with "-IncludeUserName" parameter + if asAdmin { + pwshCommand = "Get-NetTCPConnection -State Listen | ForEach-Object {$proc=Get-Process -Id $_.OwningProcess -IncludeUserName;[PSCustomObject]@{OwningProcess=$_.OwningProcess;LocalPort=$_.LocalPort;Command=if($proc){$proc.Path};Username=if($proc){$proc.UserName}}} | ConvertTo-Json" + } else { + pwshCommand = "Get-NetTCPConnection -State Listen | ForEach-Object {$proc=Get-Process -Id $_.OwningProcess;[PSCustomObject]@{OwningProcess=$_.OwningProcess;LocalPort=$_.LocalPort;Command=if($proc){$proc.Path};Username=if($proc){$proc.UserName}}} | ConvertTo-Json" + } + out, err := exec.Command("powershell.exe", "-NoLogo", "-Command", pwshCommand).CombinedOutput() + if err != nil { + if strings.Contains(string(out), "requires elevated user rights") { + asAdmin = false + return executePowershellCmd() + } else { + log.Error(err) + } + } + return out +} + +func getWindowsProcesses() []list.Item { + _ = executePowershellCmd() + + return []list.Item{} +} + +func getProcesses() []list.Item { + if runtime.GOOS == "windows" { + return getWindowsProcesses() + } else { + return getUnixProcesses() + } +} + func killPort(pid string) { pidInt, err := strconv.Atoi(pid) if err != nil { From fe3e5a25e6b1001aa93c51fba9dd0c3ea2fb0460 Mon Sep 17 00:00:00 2001 From: Vasily Kaiser <78181427+VasilyKaiser@users.noreply.github.com> Date: Sat, 4 Mar 2023 13:31:11 +0100 Subject: [PATCH 3/3] Unmarshal WindowsProcesses --- main.go | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 6c98681..d456963 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "encoding/json" "fmt" "os" "os/exec" @@ -80,6 +81,13 @@ type model struct { activeButton string } +type WindowsProcesses []struct { + OwningProcess int `json:"OwningProcess"` + LocalPort int `json:"LocalPort"` + Username string `json:"Username"` + Command string `json:"Command"` +} + var doc = strings.Builder{} type tickMsg time.Time @@ -226,9 +234,24 @@ func executePowershellCmd() []byte { } func getWindowsProcesses() []list.Item { - _ = executePowershellCmd() + out := executePowershellCmd() + var winProcesses WindowsProcesses + if err := json.Unmarshal(out, &winProcesses); err != nil { + log.Error(err) + } + var processes []list.Item + for _, proc := range winProcesses { + pid := proc.OwningProcess + port := proc.LocalPort + user := proc.Username + command := proc.Command - return []list.Item{} + titleStr := fmt.Sprintf("Port :%d (%d)", port, pid) + descStr := fmt.Sprintf("User: %s, Command: %s", user, command) + + processes = append(processes, item{title: titleStr, desc: descStr}) + } + return processes } func getProcesses() []list.Item {