golang 调用windows API 中文的处理

Posted C# 风的放松天地

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang 调用windows API 中文的处理相关的知识,希望对你有一定的参考价值。

Go语言发展势头很猛,其实缺点也很多,好在有广大爱好者提供了无数的库,把优点表现得太好了,搞得什么都是拿来就使用,基本完全不理会指针,性能还不错。

最近在windows下使用遇到一个中文的问题,首先要了解的是Golang的编码是utf-8的,而中文windows的API返回时多字节的GBK编码。

下面是利用API 获得进程的示例,代码是网上的,但是使用时出现了,当进程名是中文时出现的乱码问题。

先贴代码。

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 // 进程名称
	processID   int    // 进程id
}

type ProcessStructSlice []ProcessStruct

func (a ProcessStructSlice) Len() int { // 重写 Len() 方法
	return len(a)
}
func (a ProcessStructSlice) Swap(i, j int) { // 重写 Swap() 方法
	a[i], a[j] = a[j], a[i]
}
func (a ProcessStructSlice) Less(i, j int) bool { // 重写 Less() 方法, 从大到小排序
	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("
")
	}

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

}

重要的是

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

其实里面做了判断,并不是单纯的使用utf8.EncodeRune来解决,刚开始我也是直接使用utf8这个库来尝试,没成功.

在这里做个分享,呵呵

 

以上是关于golang 调用windows API 中文的处理的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Golang 中更快地进行 api 调用?

golang 调用顺丰API接口测试

如何在golang中为包含通道、filewalk和api调用的程序编写单元测试?

了解 GoLang Profiling 输出

golang使用reflects调用方法时,方法名需要首字母大写

golang编译dll给C#调用