您知道如果您是系统的管理员用户,您可以右键单击一个批处理脚本,然后以管理员身份运行它,而无需输入管理员密码?

我想知道如何用PowerShell脚本做到这一点。我不想输入我的密码;我只是想模仿右键单击Run As Administrator方法。

到目前为止,我读到的所有内容都要求您提供管理员密码。


当前回答

您可以创建一个批处理文件(*.bat),在双击时使用管理权限运行powershell脚本。通过这种方式,您不需要更改powershell脚本中的任何内容。要做到这一点,创建一个与powershell脚本名称和位置相同的批处理文件,然后将以下内容放入其中:

@echo off

set scriptFileName=%~n0
set scriptFolderPath=%~dp0
set powershellScriptFileName=%scriptFileName%.ps1

powershell -Command "Start-Process powershell \"-ExecutionPolicy Bypass -NoProfile -NoExit -Command `\"cd \`\"%scriptFolderPath%`\"; & \`\".\%powershellScriptFileName%\`\"`\"\" -Verb RunAs"

就是这样!

下面是解释:

假设powershell脚本位于路径C:\Temp\ScriptTest。ps1,您的批处理文件必须有路径C:\Temp\ScriptTest.bat。当有人执行这个批处理文件时,会发生以下步骤:

The cmd will execute the command powershell -Command "Start-Process powershell \"-ExecutionPolicy Bypass -NoProfile -NoExit -Command `\"cd \`\"C:\Temp\`\"; & \`\".\ScriptTest.ps1\`\"`\"\" -Verb RunAs" A new powershell session will open and the following command will be executed: Start-Process powershell "-ExecutionPolicy Bypass -NoProfile -NoExit -Command `"cd \`"C:\Temp\`"; & \`".\ScriptTest.ps1\`"`"" -Verb RunAs Another new powershell session with administrative privileges will open in the system32 folder and the following arguments will be passed to it: -ExecutionPolicy Bypass -NoProfile -NoExit -Command "cd \"C:\Temp\"; & \".\ScriptTest.ps1\"" The following command will be executed with administrative privileges: cd "C:\Temp"; & ".\ScriptTest.ps1" Once the script path and name arguments are double quoted, they can contain space or single quotation mark characters ('). The current folder will change from system32 to C:\Temp and the script ScriptTest.ps1 will be executed. Once the parameter -NoExit was passed, the window wont be closed, even if your powershell script throws some exception.

其他回答

如果当前控制台没有被提升,并且您正在尝试执行的操作需要提升权限,那么您可以使用以管理员身份运行选项启动powershell:

PS> Start-Process powershell -Verb runAs

Microsoft Docs: Start-Process

这种行为是经过设计的。因为微软真的不想让.ps1文件成为最新的电子邮件病毒,所以有多层安全措施。有些人认为这与任务自动化的概念相悖,这是公平的。Vista+安全模型是“去自动化”的,这样用户就可以接受。

但是,我怀疑如果你启动powershell本身作为提升,它应该能够运行批处理文件,而不需要再次要求密码,直到你关闭powershell。

我正在使用下面的解决方案。它通过转录特性处理stdout/stderr,并将退出码正确地传递给父进程。您需要调整文本路径/文件名。

If (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{ 
  echo "* Respawning PowerShell child process with elevated privileges"
  $pinfo = New-Object System.Diagnostics.ProcessStartInfo
  $pinfo.FileName = "powershell"
  $pinfo.Arguments = "& '" + $myinvocation.mycommand.definition + "'"
  $pinfo.Verb = "RunAs"
  $pinfo.RedirectStandardError = $false
  $pinfo.RedirectStandardOutput = $false
  $pinfo.UseShellExecute = $true
  $p = New-Object System.Diagnostics.Process
  $p.StartInfo = $pinfo
  $p.Start() | Out-Null
  $p.WaitForExit()
  echo "* Child process finished"
  type "C:/jenkins/transcript.txt"
  Remove-Item "C:/jenkins/transcript.txt"
  Exit $p.ExitCode
} Else {
  echo "Child process starting with admin privileges"
  Start-Transcript -Path "C:/jenkins/transcript.txt"
}

# Rest of your script goes here, it will be executed with elevated privileges

当然,如果您有管理员帐户,还可以强制以管理员身份打开应用程序。

找到文件,右键单击>属性>快捷方式>高级,并选择以管理员身份运行

单击“确定”。

Benjamin Armstrong发表了一篇关于自提升PowerShell脚本的优秀文章。他的代码有一些小问题;下面是基于评论中建议的修复的修改版本。

基本上,它获取与当前进程相关联的身份,检查它是否是管理员,如果不是,就创建一个具有管理员权限的新PowerShell进程,并终止旧进程。

# Get the ID and security principal of the current user account
$myWindowsID = [System.Security.Principal.WindowsIdentity]::GetCurrent();
$myWindowsPrincipal = New-Object System.Security.Principal.WindowsPrincipal($myWindowsID);

# Get the security principal for the administrator role
$adminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator;

# Check to see if we are currently running as an administrator
if ($myWindowsPrincipal.IsInRole($adminRole))
{
    # We are running as an administrator, so change the title and background colour to indicate this
    $Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)";
    $Host.UI.RawUI.BackgroundColor = "DarkBlue";
    Clear-Host;
}
else {
    # We are not running as an administrator, so relaunch as administrator

    # Create a new process object that starts PowerShell
    $newProcess = New-Object System.Diagnostics.ProcessStartInfo "PowerShell";

    # Specify the current script path and name as a parameter with added scope and support for scripts with spaces in it's path
    $newProcess.Arguments = "& '" + $script:MyInvocation.MyCommand.Path + "'"

    # Indicate that the process should be elevated
    $newProcess.Verb = "runas";

    # Start the new process
    [System.Diagnostics.Process]::Start($newProcess);

    # Exit from the current, unelevated, process
    Exit;
}

# Run your code that needs to be elevated here...

Write-Host -NoNewLine "Press any key to continue...";
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown");