Skip to content
33 changes: 33 additions & 0 deletions cmd/defender/defender.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package main

import (
"fmt"
"os"

"github.com/goplus/gop/defender"
)

func main() {
if len(os.Args) < 2 {
fmt.Println("Start processing, please wait for a moment ...")
if err := defender.Exclude(); err != nil {
fmt.Println(err)
}
return
}
switch os.Args[1] {
case "add":
fmt.Println("Start processing, please wait for a moment ...")
if err := defender.Exclude(); err != nil {
fmt.Println(err)
}
case "remove":
fmt.Println("Start processing, please wait for a moment ...")
if err := defender.Remove(); err != nil {
fmt.Println(err)
}
default:
fmt.Println("expected 'add' or 'remove' subcommands")
os.Exit(1)
}
}
7 changes: 7 additions & 0 deletions cmd/make.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import (
"runtime"
"strings"
"time"

"github.com/goplus/gop/defender"
)

func checkPathExist(path string, isDir bool) bool {
Expand Down Expand Up @@ -379,6 +381,8 @@ we recommend you add the above install directory into your PATH environment vari
func install() {
installPath := linkGoplusToLocalBin()

defender.Exclude()

println("\nGo+ tools installed successfully!")

if _, err := execCommand("gop", "version"); err != nil {
Expand Down Expand Up @@ -407,6 +411,9 @@ func runTestcases() {
}

func clean() {

defender.Remove()

gopBinPath := detectGopBinPath()
goBinPath := detectGoBinPath()

Expand Down
11 changes: 11 additions & 0 deletions defender/cmdstr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package defender

import "fmt"

func excludeDirString(excludeDir string) string {
return fmt.Sprintf("Add-MpPreference -ExclusionPath '%s'", excludeDir)
}

func excludeExtString(excludeExt string) string {
return fmt.Sprintf("Add-MpPreference -ExclusionExtension '%s'", excludeExt)
}
58 changes: 58 additions & 0 deletions defender/defender.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package defender

import (
"fmt"
"os"
"path/filepath"
"runtime"
)

func excludePSFile() (string, error) {
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
return filepath.Join(home, ".gop/exclude.ps1"), nil
}

func removePSFile() (string, error) {
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
return filepath.Join(home, ".gop/remove.ps1"), nil
}

func Exclude() error {
if runtime.GOOS != "windows" {
return fmt.Errorf("not supported for %s", runtime.GOOS)
}
file, err := excludePSFile()
if err != nil {
return err
}
err = genGopDefenderExcludePSFile(file)
if err != nil {
return err
}
return runDefenderExcludePSFile(file)
}

func Remove() error {
if runtime.GOOS != "windows" {
return fmt.Errorf("not supported for %s", runtime.GOOS)
}
exFile, err := excludePSFile()
if err != nil {
return err
}
file, err := removePSFile()
if err != nil {
return err
}
err = genGopDefenderRemovePSFile(exFile, file)
if err != nil {
return err
}
return runDefenderExcludePSFile(file)
}
176 changes: 176 additions & 0 deletions defender/gen.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package defender

import (
"bufio"
"bytes"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"sync"
)

func genGopDefenderExcludePSFile(psFile string) error {
cmd := exec.Command("powershell", "-nologo", "-noprofile")
stdin, err := cmd.StdinPipe()
if err != nil {
return err
}
resultMap := map[string]string{
"gop env GOCACHE": "",
"gop env GOPROOT": "",
"gop env GOBIN": "",
"gop env GOENV": "",
"gop env GOPATH": ""}
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
defer stdin.Close()
for k := range resultMap {
fmt.Fprintln(stdin, k)
}
wg.Done()
}()
wg.Wait()
out, err := cmd.CombinedOutput()
if err != nil {
return err
}
buf := bytes.NewBuffer(out)
scanner := bufio.NewScanner(buf)
var key = ""
for scanner.Scan() {
lineText := scanner.Text()
index := strings.Index(lineText, "gop env")
if index > 0 {
key = lineText[index:]
} else {
if len(key) > 0 {
resultMap[key] = lineText
}
key = ""
}
}
f, err := os.Create(psFile)
if err != nil {
return err
}
defer f.Close()
for k, v := range resultMap {
if len(v) <= 0 || k == "gop env GOPROOT" {
continue
}
if k == "gop env GOCACHE" {
localDir := filepath.Dir(v)
goplsDir := filepath.Join(localDir, "/gopls")
if err := writeExcludeDirToFile(f, goplsDir); err != nil {
return err
}
}
if err := writeExcludeDirToFile(f, v); err != nil {
return err
}
}
if home, err := os.UserHomeDir(); err == nil {
if err := writeExcludeDirToFile(f, filepath.Join(home, ".gopls")); err != nil {
return err
}
if err := writeExcludeDirToFile(f, filepath.Join(home, ".gop")); err != nil {
return err
}
var exts = [11]string{
"gop",
"go",
"yap",
"spx",
"rdx",
"gmx",
"gox",
"gsh",
"mod",
"sum",
}
for _, extStr := range exts {
if err := writeExcludeExtToFile(f, extStr); err != nil {
return err
}
}
}
return nil
}

func genGopDefenderRemovePSFile(exFile string, file string) error {
if _, err := os.Stat(exFile); err != nil {
return err
}
cmd := exec.Command("powershell", "-nologo", "-noprofile")
stdin, err := cmd.StdinPipe()
if err != nil {
return err
}
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
defer stdin.Close()
cmdStr := fmt.Sprintf("powershell -Command \"(gc %s) -replace 'Add-MpPreference', 'Remove-MpPreference' | Out-File -encoding ASCII %s\"", exFile, file)
fmt.Fprintln(stdin, cmdStr)
wg.Done()
}()
wg.Wait()
_, err = cmd.CombinedOutput()
if err != nil {
return err
}
return nil
}

func writeExcludeDirToFile(f *os.File, dir string) error {
_, err := f.WriteString(excludeDirString(dir))
if err != nil {
return err
}
_, newLineError := f.WriteString("\r\n")
if newLineError != nil {
return newLineError
}
return nil
}

func writeExcludeExtToFile(f *os.File, dir string) error {
_, err := f.WriteString(excludeExtString(dir))
if err != nil {
return err
}
_, newLineError := f.WriteString("\r\n")
if newLineError != nil {
return newLineError
}
return nil
}

func runDefenderExcludePSFile(file string) error {
_, err := os.Stat(file)
if err != nil {
return err
}
cmd := exec.Command("powershell", "-nologo", "-noprofile")
stdin, err := cmd.StdinPipe()
if err != nil {
return err
}
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
defer stdin.Close()
startProcess := fmt.Sprintf("start-process -WindowStyle hidden powershell -verb runas -ArgumentList \"-file %s\"", file)
fmt.Fprintln(stdin, startProcess)
wg.Done()
}()
wg.Wait()
_, err = cmd.CombinedOutput()
if err != nil {
return err
}
return nil
}