这是我最终使用的相当老套的解决方法:
1) 为您的服务运行设置一个访问受限的帐户。由于我正在运行 CruiseControl.NET 服务,因此我将调用我的用户“ccnet”。他没有管理员权限。
2) 创建一个新的本地用户帐户,并分配给管理员组(在此示例中我称他为“iis_helper”)。给他一些密码,并将其设置为永不过期。
3) 将 iis_helper 的访问权限更改为不允许本地登录或远程桌面登录,以及您可能想要执行的任何其他操作来锁定此帐户。
4) 以非管理员用户身份登录(本地或通过远程桌面),在本例中为“ccnet”。
5) 打开命令终端,并使用“runas”命令执行任何需要升级运行的内容。使用 /savecred 选项。指定您的新管理用户。
runas /savecred /user:MYMACHINE\iis_helper "C:\Windows\System32\inetsrv\appcmd.exe"
第一次它会提示您输入 'iis_helper 的密码。之后,由于 /savecred 选项,它将被存储(这就是为什么我们从真正的命令提示符运行它一次,所以我们可以输入一次密码)。
6) 假设命令执行正常,您现在可以注销。然后我以本地管理员身份重新登录,并关闭了本地交互式登录和远程桌面的“ccnet”用户。该帐户仅用于运行服务,但没有真正的登录。这不是强制性步骤。
7) 设置您的服务以作为您的用户帐户 ('ccnet') 运行。
8) 配置任何正在运行的服务(在我的情况下为 CruiseControl.NET)以直接执行“runas”命令而不是“appcmd.exe”,与之前相同:
替换:
"C:\Windows\System32\inetsrv\appcmd.exe" start site "My Super Site"
与:
runas /savecred /user:MYMACHINE\iis_helper "\"C:\Windows\System32\inetsrv\appcmd.exe\" start site \"My Super Site\""
需要注意的是命令应该在一组引号中,所有内部引号都被转义(斜杠引号)。
9) 测试,收工,去当地的酒吧。
编辑:我显然以错误的顺序执行了 #9,并且在测试之前有一些太多...
这种方法也不完全奏效。它确实尝试作为管理帐户运行,但是它仍然作为管理用户下的非升级进程运行,因此仍然没有管理员权限。我最初没有发现失败,因为“runas”命令会生成一个单独的 cmd 窗口,然后立即关闭,所以我没有看到失败输出。
它开始看起来唯一真正的可能性可能是编写一个将以管理员身份运行的 Windows 服务,其唯一目的是运行 appcmd.exe,然后以某种方式调用该服务来启动/停止 IIS。
UAC 保护事物的方式不是很好,但实际上只会使更多服务器不安全,因为您想做的任何事情都必须以管理员身份执行,因此始终以管理员身份运行所有内容并忘记它更容易?