如何在 Vista 中提升您的应用程序在 Windows 启动时运行






2.50/5 (5投票s)
一篇关于在 Vista 中提升应用程序在 Windows 启动时运行的文章。
引言
本文档描述了如何在 Vista 系统启动时提升你的程序。提升应用程序很容易,但将应用程序注册到启动项并不容易。
背景
阅读本文档需要读者具备一定的背景知识。
首先,理解 Vista 的 UAC 非常重要。UAC 太复杂,难以理解。因此,本文档不包含关于 UAC 的任何信息。
其次,需要 MFC 和 API 知识,因为本文档的示例代码使用了 MFC 和 API。
Vista 和 Windows 启动
许多程序需要在 Windows 启动时运行。
在 Windows XP 中,在启动时运行并不是什么大问题。但在 Windows Vista 中,它成了一个大问题。Windows Vista 的新保护功能限制了想要以管理员身份运行的启动程序。(它需要提升权限。)
如果你的应用程序不需要管理员权限,那么迁移到 Windows Vista 就不需要做任何事情。但是,如果你的应用程序需要管理员权限,那么你的应用程序将无法在启动时运行,因为 Vista 的新保护机制会阻止你的程序。
似乎在 Vista 的 Windows 启动时运行具有管理员权限的程序是不可能的。但实际上有一种方法可以做到这一点(即使它与 XP 不同)。
本文档描述了 Windows Vista 的保护机制以及解决我们问题的一种可能方法。
另一种方法
为了找到另一种方法,我们必须考虑保护软件的架构。从以下原则开始:
“Windows Vista 允许运行不需要管理员权限的软件。”
因此,一种可能的方法如下:
- 我们需要创建一个不需要管理员权限的普通程序。(新的保护机制不会阻止非特权应用程序。)
- 该程序通常需要使用
CreateProcess
提升自身权限并终止。
以下伪代码展示了该方法:
void Main()
{
if(IsVista() == TRUE && Elevation() == FALSE) {
ElevationItself();
Terminate();
}
}
C++ 代码 (MFC)
伪代码很简单,但实际代码却不然。
CString g_szProgramFolder;
CString g_szCmdLine;
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 trough!.
//
} 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;
}
}
.
.
.
}
关注点
RunAsAdministrator
函数在用户选择“取消”时返回 FALSE
。因此,你可以重复执行程序,直到用户选择“允许”。
历史
- 2008-05-16:首次发布