第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在 Go 中管理 Windows 用戶帳戶?

如何在 Go 中管理 Windows 用戶帳戶?

Go
Smart貓小萌 2021-12-07 17:20:12
我需要能夠從 Go 應用程序管理 Windows 本地用戶帳戶,而且似乎不使用 CGo,就沒有本機綁定。我最初的搜索使我發(fā)現(xiàn)人們說最好使用“exec.Command”來運行“net user”命令,但是在解析響應代碼時這似乎很混亂且不可靠。我發(fā)現(xiàn)處理這種類型的函數(shù)在 netapi32.dll 庫中,但是由于 Go 本身不支持 Windows 頭文件,所以調用這些函數(shù)似乎并不容易。以https://github.com/golang/sys/tree/master/windows為例,Go 團隊似乎一直在重新定義其代碼中的所有內容,然后調用 DLL 函數(shù)。我很難將它包裝在一起,但我已經得到了我想要的低級 API 的模板,然后在它上面包裝了一個更高級別的 API,就像核心 Go 運行時所做的那樣。將它包裝在一起的最佳方式是什么?
查看完整描述

1 回答

?
喵喔喔

TA貢獻1735條經驗 獲得超5個贊

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

如果您查看src/syscallGo 安裝目錄,您可以找到一個名為mksyscall_windows.go的文件。這似乎是 Go 團隊管理他們所有 DLL 包裝器的方式。


使用go generate生成的代碼

看看syscall_windows.go如何使用它。具體有以下go generate命令:


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


定義 Win32 API 類型

然后他們定義他們的類型。您需要自己手動執(zhí)行此操作。


有時這是一個挑戰(zhàn),因為保持結構字段的大小和對齊方式至關重要。我使用Visual Studio 社區(qū)版來瀏覽 Microsoft 定義的大量基本類型,以確定它們的 Go 等價物。


Windows 對字符串使用 UTF16。因此,您會將這些表示為*uint16. 用于syscall.UTF16PtrFromString從 Go 字符串生成一個。


注釋要導出的 Win32 API 函數(shù)

重點mksyscall_windows.go是生成所有樣板代碼,以便您最終得到一個為您調用 DLL 的 Go 函數(shù)。


這是通過添加注釋(Go 注釋)來實現(xiàn)的。


例如,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 生成的代碼。


跑 go generate

很簡單,只需運行:


go generate

例子:

對于您的示例,創(chuàng)建一個名為的文件win32_windows.go:


package win32


//go generate go run mksyscall_windows.go -output zwin32_windows.go win32_windows.go


type (

    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 EDIT


package win32


import "unsafe"

import "syscall"


var _ unsafe.Pointer


var (

    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 本身就是一種樂趣。


查看完整回答
反對 回復 2021-12-07
  • 1 回答
  • 0 關注
  • 385 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號