怎么获得WINDOWS下所有用户的信息,用C++实现,请给出思路。最好能有参考代码。
信息包括用户名,状态,该账号是否必需密码,上次登录时间,密码是否可更改,密码到期时间。我曾经在一个软件上看到过这种功能,所以它肯定是可以实现的,关键是怎么实现,求思路。这...
信息包括用户名,状态,该账号是否必需密码,上次登录时间,密码是否可更改,密码到期时间。
我曾经在一个软件上看到过这种功能,所以它肯定是可以实现的,关键是怎么实现,求思路。
这两个API我也知道啊,用户名用NetUserEnum或者读注册表都能实现,不过我查了注册表,上面没有记录用户的更多信息。不知道这些信息存在于哪里,怎么获得。
大家都在纠结枚举用户名,我需要的是后面几个信息。状态,该账号是否必需密码,上次登录时间,密码是否可更改,密码到期时间。 展开
我曾经在一个软件上看到过这种功能,所以它肯定是可以实现的,关键是怎么实现,求思路。
这两个API我也知道啊,用户名用NetUserEnum或者读注册表都能实现,不过我查了注册表,上面没有记录用户的更多信息。不知道这些信息存在于哪里,怎么获得。
大家都在纠结枚举用户名,我需要的是后面几个信息。状态,该账号是否必需密码,上次登录时间,密码是否可更改,密码到期时间。 展开
3个回答
展开全部
使用API中的函数:NetUserEnum来枚举用户;NetUserGetInfo来获取用户的信息.
思路应该是这样的。
以下为Windows Conlse Appilication下的枚举所有用户信息的代码(帐户名、帐户状态、是否需要密码(此处可能判断不准确)、上次登录时间、密码是否可更改、密码过期时间):
#include "iostream"
#include "windows.h"
#include "lm.h"
#include "assert.h"
#include "string"
#include "time.h"
using namespace std;
#pragma comment(lib,"netapi32.lib")
string Prev(DWORD n)//帐户权限
{
switch(n)
{
case 0:
return "Guest";
break;
case 1:
return "User";
break;
case 2:
return "Administrator";
break;
default:
return "Unknown";
break;
}
}
string LastLogon(DWORD n)//上次登录时间
{
if(n==0)
return "Unknown Last logon time.";
else
{
time_t last_logon_time;
last_logon_time = n;
return ctime(&last_logon_time);
}
}
string ExpiriedTime(unsigned long n)//密码过期时间
{
if(n==0||n==NULL)
return "Never Expiried.";
else
{
time_t current;
current=n;
return ctime(¤t);
}
}
//判断帐户状态:数组各个值对应的意义如下
/*
UF_SCRIPT 登录脚本执行 1
UF_ACCOUNTDISABLE 用户帐户不可用 2
UF_HOMEDIR_REQUIRED 要求有用户目录 8
UF_LOCKOUT 帐户锁定 16
UF_PASSWD_NOTREQD 不要求用户密码 32
UF_PASSWD_CANT_CHANGE 不能更改密码 64
以下为帐户类型:
UF_TEMP_DUPLICATE_ACCOUNT 域用户帐户 256
UF_NORMAL_ACCOUNT 普通帐户 512
UF_INTERDOMAIN_TRUST_ACCOUNT域内可信任帐户 2048
UF_WORKSTATION_TRUST_ACCOUNT工作组可信任帐户 4096
UF_SERVER_TRUST_ACCOUNT 备份域控制器帐户 8192
UF_DONT_EXPIRE_PASSWD 密码不过期 65536
*/
int ToBinary(long n,int k)
{
int num[17];
int i=16;
//密码永不过期
long m=n;
if(k>17||k<1)
k=1;
while(m!=0)
{
num[i]=m%2;
m=m/2;
i--;
}
num[i]='\0';
return num[17-k];
}
int GetAllUser()
{
LPUSER_INFO_1 pBuf = NULL;
LPUSER_INFO_1 pTmpBuf;
DWORD dwLevel = 1;
DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH;
DWORD dwEntriesRead = 0;
DWORD dwTotalEntries = 0;
DWORD dwResumeHandle = 0;
DWORD i;
DWORD dwTotalCount = 0;
NET_API_STATUS nStatus;
LPTSTR pszServerName = NULL;
do
{
nStatus = NetUserEnum(NULL,
dwLevel,
FILTER_NORMAL_ACCOUNT, // global users
(LPBYTE*)&pBuf,
dwPrefMaxLen,
&dwEntriesRead,
&dwTotalEntries,
&dwResumeHandle);
//
// If the call succeeds,
//
if ((nStatus == NERR_Success) || (nStatus == ERROR_MORE_DATA))
{
if ((pTmpBuf = pBuf) != NULL)
{
//
// Loop through the entries.
//
for (i = 0; (i < dwEntriesRead); i++)
{
assert(pTmpBuf != NULL);
if (pTmpBuf == NULL)
{
fprintf(stderr, "An access violation has occurred\n");
break;
}
//
// Print the name of the user account.
//
/*
typedef struct _USER_INFO_1 {
LPWSTR usri1_name; //用户名
LPWSTR usri1_password; //用户密码
DWORD usri1_password_age; //当前密码使用时间(单位:秒)
DWORD usri1_priv; //用户权限 0 来宾; 1 普通用户; 2 管理员.
LPWSTR usri1_home_dir; //
LPWSTR usri1_comment; //备注,可能为NULL
DWORD usri1_flags; //
LPWSTR usri1_script_path; //返回Unicode string,包含用户登录的脚本。可以为NULL
}USER_INFO_1, *PUSER_INFO_1, *LPUSER_INFO_1;
*/
wprintf(L"Account No.%d\n",dwTotalCount+1);
LPUSER_INFO_3 bufptr=NULL;
LPUSER_INFO_2 buf=NULL;
NET_API_STATUS t3,t2;
t3=NetUserGetInfo(0,pTmpBuf->usri1_name,3,(LPBYTE*)&bufptr);
t2=NetUserGetInfo(0,pTmpBuf->usri1_name,2,(LPBYTE*)&buf);
//帐户名称:
wprintf(L"\t Account Name: %s \n",bufptr->usri3_name);
//上次登录时间:单位,秒;计算起始时间为1970年1月1日00:00
if(bufptr->usri3_last_logon==0)
cout<<"\t Account Last Logon Time: "<<"上次登录时间未知"<<endl;
else
{
long m=bufptr->usri3_last_logon;
time_t last;
last = m;
cout<<"\t Account Last Logon Time: "<<ctime(&last);
}
//密码过期时间:单位,秒;计算起始时间为1970年1月1日00:00. 如果为 0 ,表示永不过期
if(bufptr->usri3_password_expired==0||bufptr->usri3_password_expired==NULL)
cout<<"\t Password Expiried Time: "<<"密码永不过期"<<endl;
else
{
long n=bufptr->usri3_password_expired;
time_t pwd;
pwd = n;
cout<<"\t Password Expiried Time: "<<ctime(&pwd)<<endl;
}
//判断账户过期时间:如果过期时间为:65536*65536-1,表示永不过期
/* if(buf->usri2_acct_expires==4294967295)
cout<<"\t Account Expiried Time:"<<"帐户永不过期"<<endl;
else
{
long k=buf->usri2_acct_expires;
time_t acct;
acct = k;
cout<<"\t Account Expiried Time:"<<ctime(&acct)<<endl;
}
*/
//判断帐户状态 usri2_flags:
/*
value mean int
UF_SCRIPT 登录脚本执行 1
UF_ACCOUNTDISABLE 用户帐户不可用 2
UF_HOMEDIR_REQUIRED 要求有用户目录 8
UF_LOCKOUT 帐户锁定 16
UF_PASSWD_NOTREQD 不要求用户密码 32
UF_PASSWD_CANT_CHANGE 不能更改密码 64
UF_DONT_EXPIRE_PASSWD 密码不过期 65536
以下为帐户类型:
UF_TEMP_DUPLICATE_ACCOUNT 域用户帐户 256
UF_NORMAL_ACCOUNT 普通帐户 512
UF_INTERDOMAIN_TRUST_ACCOUNT域内可信任帐户 2048
UF_WORKSTATION_TRUST_ACCOUNT工作组可信任帐户 4096
UF_SERVER_TRUST_ACCOUNT 备份域控制器帐户 8192
*/
long n=buf->usri2_flags;
//帐户状态:
if(ToBinary(n,2))
cout<<"\t Account Status : "<<"帐户未启用"<<endl;
else
cout<<"\t Account Status : "<<"帐户已启用"<<endl;
//密码是否可更改:
if(ToBinary(n,7))
cout<<"\t Password Need : "<<"不需要密码"<<endl
<<"\t Password Change : "<<"密码不能更改"<<endl;
else
cout<<"\t Password Nedd : "<<"需要密码"<<endl
<<"\t Password Change : "<<"密码可以更改"<<endl;
pTmpBuf++;
dwTotalCount++;
}
}
}
else{
fprintf(stderr, "A system error has occurred: %d\n", nStatus);
}
if (pBuf != NULL)
{
NetApiBufferFree(pBuf);
pBuf = NULL;
}
}while(nStatus == ERROR_MORE_DATA);
fprintf(stderr, "\nTotal of %d entries enumerated\n", dwTotalCount);
return 0;
}
void main()
{
GetAllUser();
cin.get();
}
//以上代码在Visual C++ 6.0 编译下通过。
//另:编程需要耐心,你仔细看看MSDN的说明就知道我上次提供的代码不是在仅仅枚举用户名。
//如果有疑问,就看看NetUserGetInfo、_USER_INFO_2、_USER_INFO_3的定义及对应的值。
思路应该是这样的。
以下为Windows Conlse Appilication下的枚举所有用户信息的代码(帐户名、帐户状态、是否需要密码(此处可能判断不准确)、上次登录时间、密码是否可更改、密码过期时间):
#include "iostream"
#include "windows.h"
#include "lm.h"
#include "assert.h"
#include "string"
#include "time.h"
using namespace std;
#pragma comment(lib,"netapi32.lib")
string Prev(DWORD n)//帐户权限
{
switch(n)
{
case 0:
return "Guest";
break;
case 1:
return "User";
break;
case 2:
return "Administrator";
break;
default:
return "Unknown";
break;
}
}
string LastLogon(DWORD n)//上次登录时间
{
if(n==0)
return "Unknown Last logon time.";
else
{
time_t last_logon_time;
last_logon_time = n;
return ctime(&last_logon_time);
}
}
string ExpiriedTime(unsigned long n)//密码过期时间
{
if(n==0||n==NULL)
return "Never Expiried.";
else
{
time_t current;
current=n;
return ctime(¤t);
}
}
//判断帐户状态:数组各个值对应的意义如下
/*
UF_SCRIPT 登录脚本执行 1
UF_ACCOUNTDISABLE 用户帐户不可用 2
UF_HOMEDIR_REQUIRED 要求有用户目录 8
UF_LOCKOUT 帐户锁定 16
UF_PASSWD_NOTREQD 不要求用户密码 32
UF_PASSWD_CANT_CHANGE 不能更改密码 64
以下为帐户类型:
UF_TEMP_DUPLICATE_ACCOUNT 域用户帐户 256
UF_NORMAL_ACCOUNT 普通帐户 512
UF_INTERDOMAIN_TRUST_ACCOUNT域内可信任帐户 2048
UF_WORKSTATION_TRUST_ACCOUNT工作组可信任帐户 4096
UF_SERVER_TRUST_ACCOUNT 备份域控制器帐户 8192
UF_DONT_EXPIRE_PASSWD 密码不过期 65536
*/
int ToBinary(long n,int k)
{
int num[17];
int i=16;
//密码永不过期
long m=n;
if(k>17||k<1)
k=1;
while(m!=0)
{
num[i]=m%2;
m=m/2;
i--;
}
num[i]='\0';
return num[17-k];
}
int GetAllUser()
{
LPUSER_INFO_1 pBuf = NULL;
LPUSER_INFO_1 pTmpBuf;
DWORD dwLevel = 1;
DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH;
DWORD dwEntriesRead = 0;
DWORD dwTotalEntries = 0;
DWORD dwResumeHandle = 0;
DWORD i;
DWORD dwTotalCount = 0;
NET_API_STATUS nStatus;
LPTSTR pszServerName = NULL;
do
{
nStatus = NetUserEnum(NULL,
dwLevel,
FILTER_NORMAL_ACCOUNT, // global users
(LPBYTE*)&pBuf,
dwPrefMaxLen,
&dwEntriesRead,
&dwTotalEntries,
&dwResumeHandle);
//
// If the call succeeds,
//
if ((nStatus == NERR_Success) || (nStatus == ERROR_MORE_DATA))
{
if ((pTmpBuf = pBuf) != NULL)
{
//
// Loop through the entries.
//
for (i = 0; (i < dwEntriesRead); i++)
{
assert(pTmpBuf != NULL);
if (pTmpBuf == NULL)
{
fprintf(stderr, "An access violation has occurred\n");
break;
}
//
// Print the name of the user account.
//
/*
typedef struct _USER_INFO_1 {
LPWSTR usri1_name; //用户名
LPWSTR usri1_password; //用户密码
DWORD usri1_password_age; //当前密码使用时间(单位:秒)
DWORD usri1_priv; //用户权限 0 来宾; 1 普通用户; 2 管理员.
LPWSTR usri1_home_dir; //
LPWSTR usri1_comment; //备注,可能为NULL
DWORD usri1_flags; //
LPWSTR usri1_script_path; //返回Unicode string,包含用户登录的脚本。可以为NULL
}USER_INFO_1, *PUSER_INFO_1, *LPUSER_INFO_1;
*/
wprintf(L"Account No.%d\n",dwTotalCount+1);
LPUSER_INFO_3 bufptr=NULL;
LPUSER_INFO_2 buf=NULL;
NET_API_STATUS t3,t2;
t3=NetUserGetInfo(0,pTmpBuf->usri1_name,3,(LPBYTE*)&bufptr);
t2=NetUserGetInfo(0,pTmpBuf->usri1_name,2,(LPBYTE*)&buf);
//帐户名称:
wprintf(L"\t Account Name: %s \n",bufptr->usri3_name);
//上次登录时间:单位,秒;计算起始时间为1970年1月1日00:00
if(bufptr->usri3_last_logon==0)
cout<<"\t Account Last Logon Time: "<<"上次登录时间未知"<<endl;
else
{
long m=bufptr->usri3_last_logon;
time_t last;
last = m;
cout<<"\t Account Last Logon Time: "<<ctime(&last);
}
//密码过期时间:单位,秒;计算起始时间为1970年1月1日00:00. 如果为 0 ,表示永不过期
if(bufptr->usri3_password_expired==0||bufptr->usri3_password_expired==NULL)
cout<<"\t Password Expiried Time: "<<"密码永不过期"<<endl;
else
{
long n=bufptr->usri3_password_expired;
time_t pwd;
pwd = n;
cout<<"\t Password Expiried Time: "<<ctime(&pwd)<<endl;
}
//判断账户过期时间:如果过期时间为:65536*65536-1,表示永不过期
/* if(buf->usri2_acct_expires==4294967295)
cout<<"\t Account Expiried Time:"<<"帐户永不过期"<<endl;
else
{
long k=buf->usri2_acct_expires;
time_t acct;
acct = k;
cout<<"\t Account Expiried Time:"<<ctime(&acct)<<endl;
}
*/
//判断帐户状态 usri2_flags:
/*
value mean int
UF_SCRIPT 登录脚本执行 1
UF_ACCOUNTDISABLE 用户帐户不可用 2
UF_HOMEDIR_REQUIRED 要求有用户目录 8
UF_LOCKOUT 帐户锁定 16
UF_PASSWD_NOTREQD 不要求用户密码 32
UF_PASSWD_CANT_CHANGE 不能更改密码 64
UF_DONT_EXPIRE_PASSWD 密码不过期 65536
以下为帐户类型:
UF_TEMP_DUPLICATE_ACCOUNT 域用户帐户 256
UF_NORMAL_ACCOUNT 普通帐户 512
UF_INTERDOMAIN_TRUST_ACCOUNT域内可信任帐户 2048
UF_WORKSTATION_TRUST_ACCOUNT工作组可信任帐户 4096
UF_SERVER_TRUST_ACCOUNT 备份域控制器帐户 8192
*/
long n=buf->usri2_flags;
//帐户状态:
if(ToBinary(n,2))
cout<<"\t Account Status : "<<"帐户未启用"<<endl;
else
cout<<"\t Account Status : "<<"帐户已启用"<<endl;
//密码是否可更改:
if(ToBinary(n,7))
cout<<"\t Password Need : "<<"不需要密码"<<endl
<<"\t Password Change : "<<"密码不能更改"<<endl;
else
cout<<"\t Password Nedd : "<<"需要密码"<<endl
<<"\t Password Change : "<<"密码可以更改"<<endl;
pTmpBuf++;
dwTotalCount++;
}
}
}
else{
fprintf(stderr, "A system error has occurred: %d\n", nStatus);
}
if (pBuf != NULL)
{
NetApiBufferFree(pBuf);
pBuf = NULL;
}
}while(nStatus == ERROR_MORE_DATA);
fprintf(stderr, "\nTotal of %d entries enumerated\n", dwTotalCount);
return 0;
}
void main()
{
GetAllUser();
cin.get();
}
//以上代码在Visual C++ 6.0 编译下通过。
//另:编程需要耐心,你仔细看看MSDN的说明就知道我上次提供的代码不是在仅仅枚举用户名。
//如果有疑问,就看看NetUserGetInfo、_USER_INFO_2、_USER_INFO_3的定义及对应的值。
参考资料: http://hi.baidu.com/ctralt/blog/item/13221fa454a091fa9052ee9d.html
展开全部
一般用 GetUserName(或 GetUserNameEx )函数可得到当前登陆登陆用户名(但不总会得到,下面会分析),此系统函数在Win95、WinNT 及以后所有操作系统中都可用。代码如下:
代码如下:
BOOL CSecurityTool::GetCurrProcessUser(CString& strName)
{
BOOL bRet(TRUE);
strName = _T("");
DWORD dwSize = MAX_PATH;
TCHAR *pszName = new TCHAR[dwSize];
if (!GetUserName(pszName, &dwSize))
{
delete[] pszName;
pszName = new TCHAR[dwSize];
bRet = GetUserName(pszName, &dwSize);
}
strName = pszName;
delete[] pszName;
return bRet;
} 此函数目的准确来说是获取当前线程的用户名(MSDN语:retrieves the user name of the current thread)。如果是NT service(NT服务程序)将此进程启动,得到的结果是NT Service进程的用户名,即“SYSTEM”,而不是登陆用户名;同理,如果此进程是通过CreateProcessAsUser创建的,GetUserName获取的用户将是“AsUser”的用户名。另外,如果当前线程正impersonate其他用户环境(用函数ImpersonateLoggedOnUser可达到此目的),它获取的将是其他用户名。因此,此函数只能在特定环境中才可以获取登陆用户名。
那如何不因进程本身运行环境的不同,而准确地获取登陆用户名呢?
我们首先看看Windows XP操作系统,它提供了WTSQuerySessionInformation函数,这个函数可以获取会话(session)相关信息,其中一个用途是获取会话的登陆用户。代码如下:
//获取win2000登陆用户
BOOL CSecurityTool::GetLogUser2K(CString& strName)
{
BOOL bRet = FALSE;
HANDLE hSnapshot = NULL;
strName = _T("");
__try
{
// Get a snapshot of the processes in the system
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == NULL)
{
__leave;
}
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(pe32);
// Find the "System" process
BOOL fProcess = Process32First(hSnapshot, &pe32);
while (fProcess)
{
if (lstrcmpi(pe32.szExeFile, TEXT("explorer.exe")) == 0)
{
TCHAR szUserName[MAX_PATH];
if (GetProcessUser(pe32.th32ProcessID, szUserName, MAX_PATH))
{
bRet = TRUE;
strName = szUserName;
}
break;
}
fProcess = Process32Next(hSnapshot, &pe32);
}
if (!fProcess)
{
__leave; // Didn''t find "System" process
}
}
__finally
{
// Cleanup the snapshot
if (hSnapshot != NULL)
CloseHandle(hSnapshot);
}
return bRet;
}
//获取进程的用户名
BOOL CSecurityTool::GetProcessUser(DWORD dwProcessID, TCHAR *szUserName, DWORD nNameLen)
{
BOOL fResult = FALSE;
HANDLE hProc = NULL;
HANDLE hToken = NULL;
TOKEN_USER *pTokenUser = NULL;
__try
{
// Open the process with PROCESS_QUERY_INFORMATION access
hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcessID);
if (hProc == NULL)
{
__leave;
}
fResult = OpenProcessToken(hProc, TOKEN_QUERY, &hToken);
if(!fResult)
{
__leave;
}
DWORD dwNeedLen = 0;
fResult = GetTokenInformation(hToken,TokenUser, NULL, 0, &dwNeedLen);
if (dwNeedLen > 0)
{
pTokenUser = (TOKEN_USER*)new BYTE[dwNeedLen];
fResult = GetTokenInformation(hToken,
TokenUser,
pTokenUser,
dwNeedLen,
&dwNeedLen);
if (!fResult)
{
__leave;
}
}
else
{
__leave;
}
SID_NAME_USE sn;
TCHAR szDomainName[MAX_PATH];
DWORD dwDmLen = MAX_PATH;
fResult = LookupAccountSid(NULL,
pTokenUser->User.Sid,
szUserName,
&nNameLen,
szDomainName,
&dwDmLen,
&sn);
}
__finally
{
if (hProc)
::CloseHandle(hProc);
if (hToken)
::CloseHandle(hToken);
if (pTokenUser)
delete[] (char*)pTokenUser;
return fResult;
}
} 如果用户还没有登陆,获取的用户名将为空(譬如在NT service程序中)。虽然MSDN中指明WTSQuerySessionInformation可以在win2000 pro 中使用,但由于安装win2000 professional时,terminal service是没有安装的(除非用特殊方法如第三方工具可以安装terminal service),所以调用此函数会失败,需要寻找其他方法。
再看Win2000:查阅了许多资料,未能发现在Win2000中直接获取登陆用户名的系统函数,看来只有曲线救国了。由于Explorer.exe进程的用户肯定是当前登陆用户,所以获取到它的用户名就等于获取到登陆用户名。具体实现:首先枚举系统所有进程,找到Explorer.exe进程ID,然后通过ID获取此进程的令牌(Token),再获取令牌的用户信息,即为登陆用户名。代码如下:
总结
因此,软件中如果需要获取登陆用户名,要根据具体情况选择不同的方法。如果确信自己的进程一定在登陆用户环境下启动,则GetUserName即可;否则,需要采用后面的两种方法,当然,在使用前需要判断一下操作系统的类型。源码:http://www.vckbase.com/document/viewdoc/?id=1241。
密码或者其他的信息应该不能获得,因为windows系统有一个文件。专门用于储蓄用户号、密码等信息的。windows系统没有给出这个文件的调用方式。
代码如下:
BOOL CSecurityTool::GetCurrProcessUser(CString& strName)
{
BOOL bRet(TRUE);
strName = _T("");
DWORD dwSize = MAX_PATH;
TCHAR *pszName = new TCHAR[dwSize];
if (!GetUserName(pszName, &dwSize))
{
delete[] pszName;
pszName = new TCHAR[dwSize];
bRet = GetUserName(pszName, &dwSize);
}
strName = pszName;
delete[] pszName;
return bRet;
} 此函数目的准确来说是获取当前线程的用户名(MSDN语:retrieves the user name of the current thread)。如果是NT service(NT服务程序)将此进程启动,得到的结果是NT Service进程的用户名,即“SYSTEM”,而不是登陆用户名;同理,如果此进程是通过CreateProcessAsUser创建的,GetUserName获取的用户将是“AsUser”的用户名。另外,如果当前线程正impersonate其他用户环境(用函数ImpersonateLoggedOnUser可达到此目的),它获取的将是其他用户名。因此,此函数只能在特定环境中才可以获取登陆用户名。
那如何不因进程本身运行环境的不同,而准确地获取登陆用户名呢?
我们首先看看Windows XP操作系统,它提供了WTSQuerySessionInformation函数,这个函数可以获取会话(session)相关信息,其中一个用途是获取会话的登陆用户。代码如下:
//获取win2000登陆用户
BOOL CSecurityTool::GetLogUser2K(CString& strName)
{
BOOL bRet = FALSE;
HANDLE hSnapshot = NULL;
strName = _T("");
__try
{
// Get a snapshot of the processes in the system
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == NULL)
{
__leave;
}
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(pe32);
// Find the "System" process
BOOL fProcess = Process32First(hSnapshot, &pe32);
while (fProcess)
{
if (lstrcmpi(pe32.szExeFile, TEXT("explorer.exe")) == 0)
{
TCHAR szUserName[MAX_PATH];
if (GetProcessUser(pe32.th32ProcessID, szUserName, MAX_PATH))
{
bRet = TRUE;
strName = szUserName;
}
break;
}
fProcess = Process32Next(hSnapshot, &pe32);
}
if (!fProcess)
{
__leave; // Didn''t find "System" process
}
}
__finally
{
// Cleanup the snapshot
if (hSnapshot != NULL)
CloseHandle(hSnapshot);
}
return bRet;
}
//获取进程的用户名
BOOL CSecurityTool::GetProcessUser(DWORD dwProcessID, TCHAR *szUserName, DWORD nNameLen)
{
BOOL fResult = FALSE;
HANDLE hProc = NULL;
HANDLE hToken = NULL;
TOKEN_USER *pTokenUser = NULL;
__try
{
// Open the process with PROCESS_QUERY_INFORMATION access
hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcessID);
if (hProc == NULL)
{
__leave;
}
fResult = OpenProcessToken(hProc, TOKEN_QUERY, &hToken);
if(!fResult)
{
__leave;
}
DWORD dwNeedLen = 0;
fResult = GetTokenInformation(hToken,TokenUser, NULL, 0, &dwNeedLen);
if (dwNeedLen > 0)
{
pTokenUser = (TOKEN_USER*)new BYTE[dwNeedLen];
fResult = GetTokenInformation(hToken,
TokenUser,
pTokenUser,
dwNeedLen,
&dwNeedLen);
if (!fResult)
{
__leave;
}
}
else
{
__leave;
}
SID_NAME_USE sn;
TCHAR szDomainName[MAX_PATH];
DWORD dwDmLen = MAX_PATH;
fResult = LookupAccountSid(NULL,
pTokenUser->User.Sid,
szUserName,
&nNameLen,
szDomainName,
&dwDmLen,
&sn);
}
__finally
{
if (hProc)
::CloseHandle(hProc);
if (hToken)
::CloseHandle(hToken);
if (pTokenUser)
delete[] (char*)pTokenUser;
return fResult;
}
} 如果用户还没有登陆,获取的用户名将为空(譬如在NT service程序中)。虽然MSDN中指明WTSQuerySessionInformation可以在win2000 pro 中使用,但由于安装win2000 professional时,terminal service是没有安装的(除非用特殊方法如第三方工具可以安装terminal service),所以调用此函数会失败,需要寻找其他方法。
再看Win2000:查阅了许多资料,未能发现在Win2000中直接获取登陆用户名的系统函数,看来只有曲线救国了。由于Explorer.exe进程的用户肯定是当前登陆用户,所以获取到它的用户名就等于获取到登陆用户名。具体实现:首先枚举系统所有进程,找到Explorer.exe进程ID,然后通过ID获取此进程的令牌(Token),再获取令牌的用户信息,即为登陆用户名。代码如下:
总结
因此,软件中如果需要获取登陆用户名,要根据具体情况选择不同的方法。如果确信自己的进程一定在登陆用户环境下启动,则GetUserName即可;否则,需要采用后面的两种方法,当然,在使用前需要判断一下操作系统的类型。源码:http://www.vckbase.com/document/viewdoc/?id=1241。
密码或者其他的信息应该不能获得,因为windows系统有一个文件。专门用于储蓄用户号、密码等信息的。windows系统没有给出这个文件的调用方式。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
不可能啊 没有权限啊
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询