diff --git a/utils/osdetail/binmeta_windows.go b/utils/osdetail/binmeta_windows.go index 064d247..056445c 100644 --- a/utils/osdetail/binmeta_windows.go +++ b/utils/osdetail/binmeta_windows.go @@ -16,7 +16,7 @@ func GetBinaryNameFromSystem(path string) (string, error) { } // Clean name. - binName := cleanFileDescription(output) + binName := cleanFileDescription(string(output)) if binName != "" { return binName, nil } @@ -74,5 +74,5 @@ func GetBinaryIconFromSystem(path string) (string, error) { return "", fmt.Errorf("failed to get file properties of %s: %s", path, err) } - return "data:image/png;base64," + output, nil + return "data:image/png;base64," + string(output), nil } diff --git a/utils/osdetail/command.go b/utils/osdetail/command.go new file mode 100644 index 0000000..9285e36 --- /dev/null +++ b/utils/osdetail/command.go @@ -0,0 +1,51 @@ +package osdetail + +import ( + "bytes" + "errors" + "os/exec" + "strings" +) + +// RunCmd runs the given command and run error checks on the output. +func RunCmd(command ...string) (output []byte, err error) { + // Create command to execute. + var cmd *exec.Cmd + switch len(command) { + case 0: + return nil, errors.New("no command supplied") + case 1: + cmd = exec.Command(command[0]) + default: + cmd = exec.Command(command[0], command[1:]...) + } + + // Create and assign output buffers. + var stdoutBuf bytes.Buffer + var stderrBuf bytes.Buffer + cmd.Stdout = &stdoutBuf + cmd.Stderr = &stderrBuf + + // Run command and collect output. + err = cmd.Run() + stdout, stderr := stdoutBuf.Bytes(), stderrBuf.Bytes() + if err != nil { + return nil, err + } + // Command might not return an error, but just write to stdout instead. + if len(stderr) > 0 { + return nil, errors.New(strings.SplitN(string(stderr), "\n", 2)[0]) + } + + // Debugging output: + // fmt.Printf("command stdout: %s\n", stdout) + // fmt.Printf("command stderr: %s\n", stderr) + + // Finalize stdout. + cleanedOutput := bytes.TrimSpace(stdout) + if len(cleanedOutput) == 0 { + return nil, ErrEmptyOutput + } + + return cleanedOutput, nil +} diff --git a/utils/osdetail/powershell_windows.go b/utils/osdetail/powershell_windows.go deleted file mode 100644 index 52ce5c4..0000000 --- a/utils/osdetail/powershell_windows.go +++ /dev/null @@ -1,49 +0,0 @@ -package osdetail - -import ( - "bytes" - "errors" - "os/exec" - "strings" -) - -// RunPowershellCmd runs a powershell command and returns its output. -func RunPowershellCmd(script string) (output string, err error) { - // Create command to execute. - cmd := exec.Command( - "powershell.exe", - "-ExecutionPolicy", "Bypass", - "-NoProfile", - "-NonInteractive", - "[System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8\n"+script, - ) - - // Create and assign output buffers. - var stdoutBuf bytes.Buffer - var stderrBuf bytes.Buffer - cmd.Stdout = &stdoutBuf - cmd.Stderr = &stderrBuf - - // Run command and collect output. - err = cmd.Run() - stdout, stderr := stdoutBuf.String(), stderrBuf.String() - if err != nil { - return "", err - } - // Powershell might not return an error, but just write to stdout instead. - if stderr != "" { - return "", errors.New(strings.SplitN(stderr, "\n", 2)[0]) - } - - // Debugging output: - // fmt.Printf("powershell stdout: %s\n", stdout) - // fmt.Printf("powershell stderr: %s\n", stderr) - - // Finalize stdout. - cleanedOutput := strings.TrimSpace(stdout) - if cleanedOutput == "" { - return "", ErrEmptyOutput - } - - return cleanedOutput, nil -} diff --git a/utils/osdetail/shell_windows.go b/utils/osdetail/shell_windows.go new file mode 100644 index 0000000..926b7c8 --- /dev/null +++ b/utils/osdetail/shell_windows.go @@ -0,0 +1,49 @@ +package osdetail + +import ( + "bytes" + "errors" +) + +// RunPowershellCmd runs a powershell command and returns its output. +func RunPowershellCmd(script string) (output []byte, err error) { + // Create command to execute. + return RunCmd( + "powershell.exe", + "-ExecutionPolicy", "Bypass", + "-NoProfile", + "-NonInteractive", + "[System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8\n"+script, + ) +} + +const outputSeparator = "pwzzhtuvpwdgozhzbnjj" + +// RunTerminalCmd runs a Windows cmd command and returns its output. +// It sets the output of the cmd to UTF-8 in order to avoid encoding errors. +func RunTerminalCmd(command ...string) (output []byte, err error) { + output, err = RunCmd(append([]string{ + "cmd.exe", + "/c", + "chcp", // Set output encoding... + "65001", // ...to UTF-8. + "&", + "echo", + outputSeparator, + "&", + }, + command..., + )...) + if err != nil { + return nil, err + } + + // Find correct start of output and shift start. + index := bytes.IndexAny(output, outputSeparator+"\r\n") + if index < 0 { + return nil, errors.New("failed to post-process output: could not find output separator") + } + output = output[index+len(outputSeparator)+2:] + + return output, nil +}