我正在尝试让当前用户上次登录。我可能是本届会议,也可能是之前的会议 我正在调用GetUserName()来获取当前用户名。我将其提供给NetUserGetInfo()以尝试获取上次登录时间。所有这些都失败,错误2221(未找到用户)。当我尝试使用“管理员”时,它可以工作。即使我对用户名进行硬编码,也会返回2221.这就是我正在使用的内容:
nStatus = NetUserGetInfo(NULL, L"administrator", dwLevel, (LPBYTE *) & pBuf);
如何获得当前用户的上次登录时间?
谢谢,代码随时欢迎。以下是我目前正在使用的完整代码:
DWORD dwLevel = 2;
NET_API_STATUS nStatus;
LPTSTR sStringSid = NULL;
LPUSER_INFO_0 pBuf = NULL;
LPUSER_INFO_2 pBuf2 = NULL;
WCHAR UserName[256];
DWORD nUserName = sizeof(UserName);
if(GetUserName(UserName, &nUserName))
{
printf("information for %ls\n", UserName);
nStatus = NetUserGetInfo(NULL, UserName, dwLevel, (LPBYTE *) & pBuf);
if (nStatus == NERR_Success)
{
pBuf2 = (LPUSER_INFO_2) pBuf;
printf("\tUser account name: %ls\n", pBuf2->usri2_name);
printf("\tLast logon (seconds since January 1, 1970 GMT): %d\n", pBuf2->usri2_last_logon);
printf("\tLast logoff (seconds since January 1, 1970 GMT): %d\n", pBuf2->usri2_last_logoff);
}
else
fprintf(stderr, "NetUserGetinfo failed with error: %d\n", nStatus);
if (pBuf != NULL)
NetApiBufferFree(pBuf);
}
答案 0 :(得分:7)
您可以尝试将其他级别用作2,例如11。
您可以尝试LsaGetLogonSessionData
(请参阅http://msdn.microsoft.com/en-us/library/aa378290.aspx)。结构SECURITY_LOGON_SESSION_DATA
有很多信息可以对你有所帮助。 LUID
LsaGetLogonSessionData
的第一个参数GetTokenInformation
可以TokenStatistics
获得AuthenticationId
并获取TOKEN_STATISTICS
结构的NetUserGetInfo
字段。< / p>
更新:我仔细阅读了您的代码,现在我看到了您的主要错误。函数NetUserGetInfo
非常陈旧。它存在于Windows NT 3.1之前的时间。 Microsoft现在命名为“网络管理”的一组功能名称为“LAN Manager API”。所有功能都是在没有本地登录的时候引入的。因此,您可以使用NetGetDCName
将NULL作为第一个参数仅在域控制器上。因此,如果您使用域帐户登录,则应调用NetGetAnyDCName
,DsGetDcName
或更好NetUserGetInfo
以获取域控制器的名称并使用此名称(以两个反斜杠开头)作为nStatus = NetUserGetInfo(NULL, L"administrator", dwLevel, (LPBYTE *) & pBuf);
的第一个参数。如果您使用本地工作站帐户登录,您的程序应该可以使用,但该帐户似乎必须是UNICODE字符串,如L“Administrator”而不是“Administrator”。顺便说一句,如果我在Windows 7 64位计算机上本地登录,您的程序可以毫无问题地工作。代码
LsaGetLogonSessionData
也有效。
我再说一遍,在我看来,获得用户上次登录的最佳方式是使用LSA(本地安全机构)API,如LsaGetLogonSessionData
。承诺我为你写了一个代码示例,演示了如何在C:
#include <windows.h>
#include <Ntsecapi.h>
#include <Sddl.h>
#include <tchar.h>
#include <stdio.h>
//#include <ntstatus.h>
#include <malloc.h>
#include <strsafe.h>
#pragma comment (lib, "Secur32.lib")
#pragma comment (lib, "strsafe.lib")
// The following constant may be defined by including NtStatus.h.
#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#endif
// The LSA authentication functions are available in Unicode only.
BOOL GetLogonLUID (LUID *pLuid)
{
BOOL bSuccess;
HANDLE hThread = NULL;
DWORD cbReturnLength;
TOKEN_STATISTICS ts;
__try {
bSuccess = OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &hThread); // TOKEN_QUERY_SOURCE
if (!bSuccess)
__leave;
cbReturnLength = sizeof(TOKEN_STATISTICS);
bSuccess = GetTokenInformation (hThread, TokenStatistics, &ts, sizeof(TOKEN_STATISTICS), &cbReturnLength);
if (bSuccess)
*pLuid = ts.AuthenticationId;
}
__finally {
if (hThread)
CloseHandle (hThread);
}
return bSuccess;
}
void PrintUnicodeString (LPCTSTR pszPrefix, LSA_UNICODE_STRING lsaString)
{
if (lsaString.MaximumLength >= lsaString.Length + sizeof(WCHAR) &&
lsaString.Buffer[lsaString.Length/sizeof(WCHAR)] == L'\0')
_tprintf (TEXT("%s: %ls\n"), pszPrefix, lsaString.Buffer);
else if (lsaString.Length <= STRSAFE_MAX_CCH * sizeof(TCHAR)) {
LPWSTR sz = (LPWSTR) _alloca (lsaString.Length + sizeof(WCHAR));
StringCbCopyNW (sz, lsaString.Length + sizeof(WCHAR), lsaString.Buffer, lsaString.Length);
_tprintf (TEXT("%s: %ls\n"), pszPrefix, sz);
}
}
void PrintLogonType (SECURITY_LOGON_TYPE type)
{
if (type < Interactive || type > CachedUnlock)
// This is used to specify an undefied logon type
_tprintf (TEXT("LogonType: UndefinedLogonType\n"));
else {
static LPTSTR szTypes[] = {
TEXT("Interactive"), // Interactively logged on (locally or remotely)
TEXT("Network"), // Accessing system via network
TEXT("Batch"), // Started via a batch queue
TEXT("Service"), // Service started by service controller
TEXT("Proxy"), // Proxy logon
TEXT("Unlock"), // Unlock workstation
TEXT("NetworkCleartext"), // Network logon with cleartext credentials
TEXT("NewCredentials"), // Clone caller, new default credentials
TEXT("RemoteInteractive"), // Remote, yet interactive. Terminal server
TEXT("CachedInteractive"), // Try cached credentials without hitting the net.
// The types below only exist in Windows Server 2003 and greater
TEXT("CachedRemoteInteractive"), // Same as RemoteInteractive, this is used internally for auditing purpose
TEXT("CachedUnlock") // Cached Unlock workstation
};
_tprintf (TEXT("LogonType: %s\n"), szTypes[(int)type-Interactive]);
}
}
void PrintFilefime (LPCTSTR pszPrefix, const FILETIME *lpFileTime)
{
SYSTEMTIME st;
FILETIME ft;
BOOL bSuccess;
TCHAR szTime[1024], szDate[1024];
bSuccess = FileTimeToLocalFileTime (lpFileTime, &ft);
if (!bSuccess)
return;
bSuccess = FileTimeToSystemTime (&ft, &st);
if (!bSuccess)
return;
if (GetDateFormat (LOCALE_USER_DEFAULT, // or LOCALE_CUSTOM_UI_DEFAULT
DATE_SHORTDATE,
&st, NULL, szDate, sizeof(szDate)/sizeof(TCHAR)) > 0) {
if (GetTimeFormat (LOCALE_USER_DEFAULT, // or LOCALE_CUSTOM_UI_DEFAULT
0, &st, NULL, szTime, sizeof(szTime)/sizeof(TCHAR)) > 0) {
_tprintf (TEXT("%s: %s, %s\n"), pszPrefix, szDate, szTime);
}
}
}
int main()
{
LUID LogonLuid; // LOGONID_CURRENT
PSECURITY_LOGON_SESSION_DATA pLogonSessionData = NULL;
LPWSTR pszSid = NULL;
NTSTATUS ntStatus;
GetLogonLUID (&LogonLuid);
__try {
ntStatus = LsaGetLogonSessionData (&LogonLuid, &pLogonSessionData);
if (ntStatus == STATUS_SUCCESS) {
if (pLogonSessionData->UserName.Length)
PrintUnicodeString (TEXT("UserName"), pLogonSessionData->UserName);
if (pLogonSessionData->LogonDomain.Length)
PrintUnicodeString (TEXT("LogonDomain"), pLogonSessionData->LogonDomain);
if (pLogonSessionData->AuthenticationPackage.Length)
PrintUnicodeString (TEXT("AuthenticationPackage"), pLogonSessionData->AuthenticationPackage);
PrintLogonType ((SECURITY_LOGON_TYPE)pLogonSessionData->LogonType);
_tprintf (TEXT("Session: %d\n"), pLogonSessionData->Session);
if (ConvertSidToStringSidW (pLogonSessionData->Sid, &pszSid))
_tprintf (TEXT("Sid: %ls\n"), pszSid);
if (pLogonSessionData->LogonTime.QuadPart)
PrintFilefime (TEXT("LogonTime"), (const FILETIME *)&pLogonSessionData->LogonTime);
if (pLogonSessionData->LogonServer.Length)
PrintUnicodeString (TEXT("LogonServer"), pLogonSessionData->LogonServer);
if (pLogonSessionData->DnsDomainName.Length)
PrintUnicodeString (TEXT("DnsDomainName"), pLogonSessionData->DnsDomainName);
if (pLogonSessionData->Upn.Length)
PrintUnicodeString (TEXT("Upn"), pLogonSessionData->Upn);
// one can dump more information like HomeDirectory, ProfilePath and so on
// if _WIN32_WINNT >= 0x0600 and user login a domain
}
}
__finally {
if (pLogonSessionData)
LsaFreeReturnBuffer(pLogonSessionData);
if (pszSid)
pszSid = (LPTSTR)LocalFree (pszSid);
}
}
{{1}}