Chinese processing of golang calling windows API

Posted by broc7 on Sat, 07 Dec 2019 08:56:20 +0100

Go language has a strong momentum of development, but there are also many disadvantages. Fortunately, there are many fans who provide numerous libraries, which show their advantages too well. They can use whatever they do, basically ignore the pointer, and the performance is good.

Recently, there is a problem in using Chinese under windows. The first thing we need to know is that the encoding of Golang is utf-8, and the multi byte GBK encoding when the API of Chinese windows returns.

The following is an example of using the API to get the process. The code is online, but there is a garbled code problem when the process name is Chinese.

Post the code first.

package utilities

import (
	"bytes"
	"io"
	"log"
	"net/http"
	"sort"
	"strconv"
	"strings"
	"syscall"

	//	"unicode/utf8"
	"unsafe"

	"github.com/axgle/mahonia"
)

type ulong int32
type ulong_ptr uintptr

type PROCESSENTRY32 struct {
	dwSize              ulong
	cntUsage            ulong
	th32ProcessID       ulong
	th32DefaultHeapID   ulong_ptr
	th32ModuleID        ulong
	cntThreads          ulong
	th32ParentProcessID ulong
	pcPriClassBase      ulong
	dwFlags             ulong
	szExeFile           [260]byte
}

type ProcessStruct struct {
	processName string // Process name
	processID   int    // Process id
}

type ProcessStructSlice []ProcessStruct

func (a ProcessStructSlice) Len() int { // Override Len() method
	return len(a)
}
func (a ProcessStructSlice) Swap(i, j int) { // Override Swap() method
	a[i], a[j] = a[j], a[i]
}
func (a ProcessStructSlice) Less(i, j int) bool { // Override the Less() method to sort from large to small
	if strings.Compare(a[j].processName, a[i].processName) < 0 {
		return true
	} else {
		return false
	}
}

func Upayin_process(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	_, err := r.Form["callsys"]
	if !err {
		io.WriteString(w, "err")
		return
	}

	kernel32 := syscall.NewLazyDLL("kernel32.dll")
	CreateToolhelp32Snapshot := kernel32.NewProc("CreateToolhelp32Snapshot")
	pHandle, _, _ := CreateToolhelp32Snapshot.Call(uintptr(0x2), uintptr(0x0))
	if int(pHandle) == -1 {
		io.WriteString(w, "get process err")
		return
	}
	var data []ProcessStruct
	var buffer bytes.Buffer

	decoder := mahonia.NewDecoder("gbk")

	Process32Next := kernel32.NewProc("Process32Next")
	for {
		var proc PROCESSENTRY32
		proc.dwSize = ulong(unsafe.Sizeof(proc))
		if rt, _, _ := Process32Next.Call(uintptr(pHandle), uintptr(unsafe.Pointer(&proc))); int(rt) == 1 {

			len_szExeFile := 0
			for _, b := range proc.szExeFile {
				if b == 0 {
					break
				}
				len_szExeFile++
			}
			var bytetest []byte = []byte(proc.szExeFile[:len_szExeFile])
			_, newdata, newerr := decoder.Translate(bytetest, true)
			if newerr != nil {
				log.Println(newerr)

			}

			data = append(data, ProcessStruct{
				processName: string(newdata),
				processID:   int(proc.th32ProcessID),
			})

		} else {
			break
		}
	}

	CloseHandle := kernel32.NewProc("CloseHandle")
	_, _, _ = CloseHandle.Call(pHandle)

	sort.Sort(ProcessStructSlice(data))
	for _, v := range data {
		log.Println(v.processName)

		buffer.WriteString("ProcessName : ")
		buffer.WriteString(v.processName)
		buffer.WriteString(" ProcessID : ")
		buffer.WriteString(strconv.Itoa(v.processID))
		buffer.WriteString("\n")
	}

	io.WriteString(w, buffer.String())

}

It is important that

"github.com/axgle/mahonia" / / this library
decoder := mahonia.NewDecoder("gbk") 
//gbk to utf8
var bytetest []byte = []byte(proc.szExeFile[:len_szExeFile]) _, newdata, newerr := decoder.Translate(bytetest, true)

In fact, I made a judgment in it, not just using utf8.encoderun to solve it. At the beginning, I also used utf8 directly to try, but failed

Let's share, hehe

Topics: Go Windows encoding github less