92 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			92 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Go
		
	
	
	
| package procstat
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"regexp"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/StackExchange/wmi"
 | |
| 	"github.com/shirou/gopsutil/process"
 | |
| )
 | |
| 
 | |
| //Timeout is the timeout used when making wmi calls
 | |
| var Timeout = 5 * time.Second
 | |
| 
 | |
| type queryType string
 | |
| 
 | |
| const (
 | |
| 	like     = queryType("LIKE")
 | |
| 	equals   = queryType("=")
 | |
| 	notEqual = queryType("!=")
 | |
| )
 | |
| 
 | |
| //Pattern matches on the process name
 | |
| func (pg *NativeFinder) Pattern(pattern string) ([]PID, error) {
 | |
| 	var pids []PID
 | |
| 	regxPattern, err := regexp.Compile(pattern)
 | |
| 	if err != nil {
 | |
| 		return pids, err
 | |
| 	}
 | |
| 	procs, err := process.Processes()
 | |
| 	if err != nil {
 | |
| 		return pids, err
 | |
| 	}
 | |
| 	for _, p := range procs {
 | |
| 		name, err := p.Name()
 | |
| 		if err != nil {
 | |
| 			//skip, this can be caused by the pid no longer existing
 | |
| 			//or you having no permissions to access it
 | |
| 			continue
 | |
| 		}
 | |
| 		if regxPattern.MatchString(name) {
 | |
| 			pids = append(pids, PID(p.Pid))
 | |
| 		}
 | |
| 	}
 | |
| 	return pids, err
 | |
| }
 | |
| 
 | |
| //FullPattern matches the cmdLine on windows and will find a pattern using a WMI like query
 | |
| func (pg *NativeFinder) FullPattern(pattern string) ([]PID, error) {
 | |
| 	var pids []PID
 | |
| 	procs, err := getWin32ProcsByVariable("CommandLine", like, pattern, Timeout)
 | |
| 	if err != nil {
 | |
| 		return pids, err
 | |
| 	}
 | |
| 	for _, p := range procs {
 | |
| 		pids = append(pids, PID(p.ProcessID))
 | |
| 	}
 | |
| 	return pids, nil
 | |
| }
 | |
| 
 | |
| //GetWin32ProcsByVariable allows you to query any variable with a like query
 | |
| func getWin32ProcsByVariable(variable string, qType queryType, value string, timeout time.Duration) ([]process.Win32_Process, error) {
 | |
| 	var dst []process.Win32_Process
 | |
| 	var query string
 | |
| 	// should look like "WHERE CommandLine LIKE "procstat"
 | |
| 	query = fmt.Sprintf("WHERE %s %s %q", variable, qType, value)
 | |
| 	q := wmi.CreateQuery(&dst, query)
 | |
| 	ctx, cancel := context.WithTimeout(context.Background(), timeout)
 | |
| 	defer cancel()
 | |
| 	err := WMIQueryWithContext(ctx, q, &dst)
 | |
| 	if err != nil {
 | |
| 		return []process.Win32_Process{}, fmt.Errorf("could not get win32Proc: %s", err)
 | |
| 	}
 | |
| 	return dst, nil
 | |
| }
 | |
| 
 | |
| // WMIQueryWithContext - wraps wmi.Query with a timed-out context to avoid hanging
 | |
| func WMIQueryWithContext(ctx context.Context, query string, dst interface{}, connectServerArgs ...interface{}) error {
 | |
| 	errChan := make(chan error, 1)
 | |
| 	go func() {
 | |
| 		errChan <- wmi.Query(query, dst, connectServerArgs...)
 | |
| 	}()
 | |
| 
 | |
| 	select {
 | |
| 	case <-ctx.Done():
 | |
| 		return ctx.Err()
 | |
| 	case err := <-errChan:
 | |
| 		return err
 | |
| 	}
 | |
| }
 |