我正在尝试获取当前用户的上次登录时间。我可能是本届 session ,也可能是之前的 session 。
我正在调用 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);
}
最佳答案
您可以尝试使用其他级别作为 2,例如 11。
您也可以尝试 LsaGetLogonSessionData(请参阅 http://msdn.microsoft.com/en-us/library/aa378290.aspx)。结构 SECURITY_LOGON_SESSION_DATA 包含很多对您有帮助的信息。您可以使用 TokenStatistics 从 GetTokenInformation 获取 LUID(LsaGetLogonSessionData 的第一个参数)并获取 AuthenticationId 字段。TOKEN_STATISTICS 结构的
更新:我更仔细地阅读了您的代码,现在我看到了您的主要错误。函数 NetUserGetInfo 非常旧。它存在于 Windows NT 3.1 之前的时间。微软现在命名为“网络管理”的功能组名称为“LAN Manager API”。所有功能都是在没有本地登录的时候引入的。因此,您可以使用 NetUserGetInfo 并将 NULL 作为第一个参数仅在域 Controller 上。因此,在您使用域帐户登录的情况下,您应该调用 NetGetDCName、NetGetAnyDCName 或更好的 DsGetDcName 来获取域 Controller 的名称,并且使用此名称(以两个反斜杠开头)作为 NetUserGetInfo 的第一个参数。如果您使用本地工作站帐户登录,您的程序应该可以运行,但该帐户似乎必须是 UNICODE 字符串,例如 L"Administrator"而不是 "Administrator"。顺便说一下,如果我在我的 Windows 7 64 位计算机上本地登录,您的程序可以正常运行。代码
nStatus = NetUserGetInfo(NULL, L"administrator", dwLevel, (LPBYTE *) & pBuf);
也适用。
我再说一遍,我认为获取用户上次登录的最佳方法是使用 LSA(本地安全机构)API,如 LsaGetLogonSessionData。多么 promise 我为你写了一个代码示例,展示了如何在 C 中使用 LsaGetLogonSessionData:
#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);
}
}
关于c - 获取当前用户的最后一次登录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3371807/
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/
我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数
有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url
我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge
我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c
我安装了ruby版本管理器,并将RVM安装的ruby实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby。有没有办法让emacs像shell一样尊重ruby的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el
假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit
我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。
我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur