在Windows操作系统中,某些应用程序需要在系统启动时自动运行。虽然在Windows XP中实现这一点相对简单,但在Windows Vista中,由于引入了用户账户控制(UAC),这一过程变得更加复杂。本文将探讨如何在Vista中注册需要管理员权限的应用程序,以便在启动时自动运行。
要理解本文内容,读者需要具备一些基础知识。首先,需要了解Windows Vista的用户账户控制(UAC)。UAC机制较为复杂,本文不对其进行深入讨论。其次,需要了解MFC(Microsoft Foundation Classes)和API(应用程序编程接口),因为本文的示例代码将使用MFC和API。
许多程序需要在Windows启动时运行。在Windows XP中,实现这一点并不困难。但在Windows Vista中,由于新的保护特性,需要以管理员身份运行的启动程序受到了限制。如果应用程序不需要管理员权限,迁移到Windows Vista时无需进行任何操作。但如果应用程序需要管理员权限,Vista的新保护机制会阻止程序在启动时运行。
这似乎使得在Vista中以管理员权限运行程序变得不可能。但实际上,有一种方法可以实现这一目标,尽管它与XP中的实现方式不同。本文将描述Windows Vista的保护机制,并提出一种可能的解决方案。
要找到另一种方法,需要考虑保护软件的架构。首先,Windows Vista允许运行不需要管理员权限的软件。因此,一种可能的方法是创建一个不需要管理员权限的普通程序。这个程序需要使用CreateProcess函数提升自己的权限,然后终止。以下伪代码展示了这个过程:
C#
void Main()
{
if (IsVista() == TRUE && Elevation() == FALSE) {
ElevationItself();
Terminate();
}
}
虽然伪代码看起来简单,但实际的代码实现并不简单。以下是使用MFC和API的C++代码示例:
C++
BOOL RunAsAdministrator(LPSTR lpszFileName, LPSTR lpszDirectory)
{
SHELLEXECUTEINFOA TempInfo = {0};
TempInfo.cbSize = sizeof(SHELLEXECUTEINFOA);
TempInfo.fMask = 0;
TempInfo.hwnd = NULL;
TempInfo.lpVerb = "runas";
TempInfo.lpFile = lpszFileName;
TempInfo.lpParameters = "runasadmin";
TempInfo.lpDirectory = lpszDirectory;
TempInfo.nShow = SW_NORMAL;
BOOL bRet = ::ShellExecuteExA(&TempInfo);
return bRet;
}
BOOL CMFCApplication::InitInstance()
{
char szCurFolder[1024] = {0,};
GetModuleFileName(GetModuleHandle(NULL), szCurFolder, 1023);
CString szFullPath = szCurFolder;
szFullPath = szFullPath.Left(szFullPath.ReverseFind('\\'));
g_szProgramFolder = szFullPath;
CCommandLineInfo oCmdLineInfo;
ParseCommandLine(oCmdLineInfo);
g_szCmdLine = oCmdLineInfo.m_strFileName;
if (IsVista()) {
if (stricmp(g_szCmdLine, "elevation") == 0) {
char szCmdLine[1024] = {0,};
char szCurFileName[1024] = {0,};
GetModuleFileName(GetModuleHandle(NULL), szCurFileName, 1023);
BOOL bRet = RunAsAdministrator(szCurFileName, (LPSTR)(LPCTSTR)g_szProgramFolder);
if (bRet == TRUE) {
return FALSE;
}
}
else if (stricmp(g_szCmdLine, "runasadmin") == 0) {
// go through!
}
else {
char szCmdLine[1024] = {0,};
char szCurFileName[1024] = {0,};
GetModuleFileName(GetModuleHandle(NULL), szCurFileName, 1023);
sprintf(szCmdLine, "\"%s\" elevation", szCurFileName);
WinExec(szCmdLine, SW_SHOW);
return FALSE;
}
}
...
}