栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

如何在Go中管理Windows用户帐户?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

如何在Go中管理Windows用户帐户?

(在我看来)使用Windows DLL是直接使用Win32 API的最佳方法。

如果查看

src/syscall
Go安装目录,则可以找到名为mksyscall_windows.go的文件。Go团队似乎就是这样来管理所有DLL包装器的。

使用
go generate
生成的代码

看一下syscall_windows.go如何使用它。具体来说,它具有以下

gogenerate
命令:

// go:generate go run mksyscall_windows.go -output zsyscall_windows.go
syscall_windows.go security_windows.go

定义Win32 API类型

然后,他们定义自己的类型。您将需要自己手动执行此操作。

有时这是一个挑战,因为保留结构字段的大小和对齐方式至关重要。我使用Visual Studio Community
Edition
在Microsoft定义的众多基本类型中四处寻找,以便确定它们的Go等效项。

Windows使用UTF16作为字符串。因此,您将把它们表示为

*uint16
。用于
syscall.UTF16PtrFromString
从Go字符串生成一个。

注释Win32 API函数以导出

整个过程的重点

mksyscall_windows.go
是生成所有样板代码,因此您最终得到一个Go函数,该函数为您调用DLL。

这可以通过添加注释(转到注释)来完成。

例如,

syscall_windows.go
您具有以下注释:

//sys   GetLastError() (lasterr error)//...//sys   CreateHardlink(filename *uint16, existingfilename *uint16, reserved uintptr) (err error) [failretval&0xff==0] = CreateHardlinkW

mksyscall_windows.go
有文档注释可帮助您了解其工作原理。您还可以在zsyscall_windows.go中查看生成的代码。

go generate

它很容易,只需运行:

go generate

例:

对于您的示例,创建一个名为的文件

win32_windows.go

package win32//go generate go run mksyscall_windows.go -output zwin32_windows.go win32_windows.gotype (    LPVOID         uintptr    LMSTR          *uint16    DWORD          uint32    LPBYTE         *byte    LPDWORD        *uint32    LPWSTR         *uint16    NET_API_STATUS DWORD    USER_INFO_1 struct {        Usri1_name         LPWSTR        Usri1_password     LPWSTR        Usri1_password_age DWORD        Usri1_priv         DWORD        Usri1_home_dir     LPWSTR        Usri1_comment      LPWSTR        Usri1_flags        DWORD        Usri1_script_path  LPWSTR    }    GROUP_USERS_INFO_0 struct {        Grui0_name LPWSTR    }    USER_INFO_1003 struct {        Usri1003_password LPWSTR    })const (    // from LMaccess.h    USER_PRIV_GUEST = 0    USER_PRIV_USER  = 1    USER_PRIV_ADMIN = 2    UF_script    = 0x0001    UF_ACCOUNTDISABLE       = 0x0002    UF_HOMEDIR_REQUIRED     = 0x0008    UF_LOCKOUT   = 0x0010    UF_PASSWD_NOTREQD       = 0x0020    UF_PASSWD_CANT_CHANGE   = 0x0040    UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED = 0x0080    UF_TEMP_DUPLICATE_ACCOUNT    = 0x0100    UF_NORMAL_ACCOUNT = 0x0200    UF_INTERDOMAIN_TRUST_ACCOUNT = 0x0800    UF_WORKSTATION_TRUST_ACCOUNT = 0x1000    UF_SERVER_TRUST_ACCOUNT      = 0x2000    UF_ACCOUNT_TYPE_MASK = UF_TEMP_DUPLICATE_ACCOUNT |        UF_NORMAL_ACCOUNT |        UF_INTERDOMAIN_TRUST_ACCOUNT |        UF_WORKSTATION_TRUST_ACCOUNT |        UF_SERVER_TRUST_ACCOUNT    UF_DONT_EXPIRE_PASSWD          = 0x10000    UF_MNS_LOGON_ACCOUNT= 0x20000    UF_SMARTCARD_REQUIRED          = 0x40000    UF_TRUSTED_FOR_DELEGATION      = 0x80000    UF_NOT_DELEGATED    = 0x100000    UF_USE_DES_KEY_onLY = 0x200000    UF_DONT_REQUIRE_PREAUTH        = 0x400000    UF_PASSWORD_EXPIRED = 0x800000    UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 0x1000000    UF_NO_AUTH_DATA_REQUIRED       = 0x2000000    UF_PARTIAL_SECRETS_ACCOUNT     = 0x4000000    UF_USE_AES_KEYS     = 0x8000000    UF_SETTABLE_BITS = UF_script |        UF_ACCOUNTDISABLE |        UF_LOCKOUT |        UF_HOMEDIR_REQUIRED |        UF_PASSWD_NOTREQD |        UF_PASSWD_CANT_CHANGE |        UF_ACCOUNT_TYPE_MASK |        UF_DONT_EXPIRE_PASSWD |        UF_MNS_LOGON_ACCOUNT |        UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED |        UF_SMARTCARD_REQUIRED |        UF_TRUSTED_FOR_DELEGATION |        UF_NOT_DELEGATED |        UF_USE_DES_KEY_onLY |        UF_DONT_REQUIRE_PREAUTH |        UF_PASSWORD_EXPIRED |        UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION |        UF_NO_AUTH_DATA_REQUIRED |        UF_USE_AES_KEYS |        UF_PARTIAL_SECRETS_ACCOUNT    FILTER_TEMP_DUPLICATE_ACCOUNT    = (0x0001)    FILTER_NORMAL_ACCOUNT = (0x0002)    FILTER_INTERDOMAIN_TRUST_ACCOUNT = (0x0008)    FILTER_WORKSTATION_TRUST_ACCOUNT = (0x0010)    FILTER_SERVER_TRUST_ACCOUNT      = (0x0020)    LG_INCLUDE_INDIRECT = (0x0001)    // etc...)//sys NetApiBufferFree(Buffer LPVOID) (status NET_API_STATUS) = netapi32.NetApiBufferFree//sys NetUserAdd(servername LMSTR, level DWORD, buf LPBYTE, parm_err LPDWORD) (status NET_API_STATUS) = netapi32.NetUserAdd//sys NetUserChangePassword(domainname LPCWSTR, username LPCWSTR, oldpassword LPCWSTR, newpassword LPCWSTR) (status NET_API_STATUS) = netapi32.NetUserChangePassword//sys NetUserDel(servername LPCWSTR, username LPCWSTR) (status NET_API_STATUS) = netapi32.NetUserDel//sys NetUserEnum(servername LPCWSTR, level DWORD, filter DWORD, bufptr *LPBYTE, prefmaxlen DWORD, entriesread LPDWORD, totalentries LPDWORD, resume_handle LPDWORD) (status NET_API_STATUS) = netapi32.NetUserEnum//sys NetUserGetGroups(servername LPCWSTR, username LPCWSTR, level DWORD, bufptr *LPBYTE, prefmaxlen DWORD, entriesread LPDWORD, totalentries LPDWORD) (status NET_API_STATUS) = netapi32.NetUserGetGroups//sys NetUserSetGroups(servername LPCWSTR, username LPCWSTR, level DWORD, buf LPBYTE, num_entries DWORD) (status NET_API_STATUS) = netapi32.NetUserSetGroups//sys NetUserSetInfo(servername LPCWSTR, username LPCWSTR, level DWORD, buf LPBYTE, parm_err LPDWORD) (status NET_API_STATUS) = netapi32.NetUserSetInfo

运行后

go generate
(只要您复制
mksyscall_windows.go
到同一目录),您将拥有一个名为“
zwin32_windows.go”的文件(类似这样):

// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDITpackage win32import "unsafe"import "syscall"var _ unsafe.Pointervar (    modnetapi32 = syscall.NewLazyDLL("netapi32.dll")    procNetApiBufferFree      = modnetapi32.NewProc("NetApiBufferFree")    procNetUserAdd = modnetapi32.NewProc("NetUserAdd")    procNetUserChangePassword = modnetapi32.NewProc("NetUserChangePassword")    procNetUserDel = modnetapi32.NewProc("NetUserDel")    procNetUserEnum= modnetapi32.NewProc("NetUserEnum")    procNetUserGetGroups      = modnetapi32.NewProc("NetUserGetGroups")    procNetUserSetGroups      = modnetapi32.NewProc("NetUserSetGroups")    procNetUserSetInfo        = modnetapi32.NewProc("NetUserSetInfo"))func NetApiBufferFree(Buffer LPVOID) (status NET_API_STATUS) {    r0, _, _ := syscall.Syscall(procNetApiBufferFree.Addr(), 1, uintptr(Buffer), 0, 0)    status = NET_API_STATUS(r0)    return}func NetUserAdd(servername LMSTR, level DWORD, buf LPBYTE, parm_err LPDWORD) (status NET_API_STATUS) {    r0, _, _ := syscall.Syscall6(procNetUserAdd.Addr(), 4, uintptr(servername), uintptr(level), uintptr(buf), uintptr(parm_err), 0, 0)    status = NET_API_STATUS(r0)    return}func NetUserChangePassword(domainname LPCWSTR, username LPCWSTR, oldpassword LPCWSTR, newpassword LPCWSTR) (status NET_API_STATUS) {    r0, _, _ := syscall.Syscall6(procNetUserChangePassword.Addr(), 4, uintptr(domainname), uintptr(username), uintptr(oldpassword), uintptr(newpassword), 0, 0)    status = NET_API_STATUS(r0)    return}func NetUserDel(servername LPCWSTR, username LPCWSTR) (status NET_API_STATUS) {    r0, _, _ := syscall.Syscall(procNetUserDel.Addr(), 2, uintptr(servername), uintptr(username), 0)    status = NET_API_STATUS(r0)    return}func NetUserEnum(servername LPCWSTR, level DWORD, filter DWORD, bufptr *LPBYTE, prefmaxlen DWORD, entriesread LPDWORD, totalentries LPDWORD, resume_handle LPDWORD) (status NET_API_STATUS) {    r0, _, _ := syscall.Syscall9(procNetUserEnum.Addr(), 8, uintptr(servername), uintptr(level), uintptr(filter), uintptr(unsafe.Pointer(bufptr)), uintptr(prefmaxlen), uintptr(entriesread), uintptr(totalentries), uintptr(resume_handle), 0)    status = NET_API_STATUS(r0)    return}func NetUserGetGroups(servername LPCWSTR, username LPCWSTR, level DWORD, bufptr *LPBYTE, prefmaxlen DWORD, entriesread LPDWORD, totalentries LPDWORD) (status NET_API_STATUS) {    r0, _, _ := syscall.Syscall9(procNetUserGetGroups.Addr(), 7, uintptr(servername), uintptr(username), uintptr(level), uintptr(unsafe.Pointer(bufptr)), uintptr(prefmaxlen), uintptr(entriesread), uintptr(totalentries), 0, 0)    status = NET_API_STATUS(r0)    return}func NetUserSetGroups(servername LPCWSTR, username LPCWSTR, level DWORD, buf LPBYTE, num_entries DWORD) (status NET_API_STATUS) {    r0, _, _ := syscall.Syscall6(procNetUserSetGroups.Addr(), 5, uintptr(servername), uintptr(username), uintptr(level), uintptr(buf), uintptr(num_entries), 0)    status = NET_API_STATUS(r0)    return}func NetUserSetInfo(servername LPCWSTR, username LPCWSTR, level DWORD, buf LPBYTE, parm_err LPDWORD) (status NET_API_STATUS) {    r0, _, _ := syscall.Syscall6(procNetUserSetInfo.Addr(), 5, uintptr(servername), uintptr(username), uintptr(level), uintptr(buf), uintptr(parm_err), 0)    status = NET_API_STATUS(r0)    return}

显然,大多数工作是将Win32类型转换为它们的Go等效项。

随意浏览

syscall
包装-它们通常已经定义了您可能感兴趣的结构。

ZOMG认真地?? 1!2多工作!

比手动编写代码要好。而且不需要CGo!

声明: 我还没有测试上面的代码来验证它是否确实满足您的要求。使用Win32 API本身就是一件很有趣的事情。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/399594.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号