[英]Running a command as Administrator using PowerShell?
您知道如果您是系统的管理用户并且只需右键单击批处理脚本并以管理员身份运行它而无需输入管理员密码,您会怎么做?
我想知道如何使用 PowerShell 脚本执行此操作。 我不想输入我的密码; 我只想模仿右键单击以管理员身份运行的方法。
到目前为止,我阅读的所有内容都需要您提供管理员密码。
如果当前控制台未提升,并且您尝试执行的操作需要提升权限,那么您可以使用“以管理员身份运行”选项启动powershell
:
PS> Start-Process powershell -Verb runAs
这是对 Shay Levi 建议的补充(只需在脚本开头添加这些行):
if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{
$arguments = "& '" +$myinvocation.mycommand.definition + "'"
Start-Process powershell -Verb runAs -ArgumentList $arguments
Break
}
这会导致当前脚本以管理员模式传递给新的 powershell 进程(如果当前用户有权访问管理员模式并且脚本未以管理员身份启动)。
Windows 8.1 / PowerShell 4.0 +
一条线 :)
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs; exit }
# Your script here
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");
这是 Powershell 脚本的自提升片段,它保留了工作目录:
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Start-Process PowerShell -Verb RunAs "-NoProfile -ExecutionPolicy Bypass -Command `"cd '$pwd'; & '$PSCommandPath';`"";
exit;
}
# Your script here
保留工作目录对于执行路径相关操作的脚本很重要。 几乎所有其他答案都不保留此路径,这可能会导致脚本其余部分出现意外错误。
如果您不想使用自提升脚本/代码段,而只想以管理员身份启动脚本的简单方法(例如,从资源管理器上下文菜单中),请在此处查看我的其他答案: https://stackoverflow .com/a/57033941/2441655
您可以创建一个批处理文件 (*.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 。 当有人执行这个批处理文件时,会发生以下步骤:
cmd 将执行命令
powershell -Command "Start-Process powershell \\"-ExecutionPolicy Bypass -NoProfile -NoExit -Command `\\"cd \\`\\"C:\\Temp\\`\\"; & \\`\\".\\ScriptTest.ps1\\`\\"`\\"\\" -Verb RunAs"
将打开一个新的 powershell 会话并执行以下命令:
Start-Process powershell "-ExecutionPolicy Bypass -NoProfile -NoExit -Command `"cd \\`"C:\\Temp\\`"; & \\`".\\ScriptTest.ps1\\`"`"" -Verb RunAs
另一个具有管理权限的新 powershell 会话将在system32文件夹中打开,以下参数将传递给它:
-ExecutionPolicy Bypass -NoProfile -NoExit -Command "cd \\"C:\\Temp\\"; & \\".\\ScriptTest.ps1\\""
以下命令将以管理权限执行:
cd "C:\\Temp"; & ".\\ScriptTest.ps1"
一旦脚本路径和名称参数被双引号,它们就可以包含空格或单引号字符 (')。
当前文件夹将从system32更改为C:\\Temp并且将执行脚本ScriptTest.ps1
。 一旦参数-NoExit
被传递,窗口就不会被关闭,即使你的 powershell 脚本抛出了一些异常。
使用
#Requires -RunAsAdministrator
还没有说出来。 它似乎只在 PowerShell 4.0 之后才存在。
http://technet.microsoft.com/en-us/library/hh847765.aspx
将此开关参数添加到您的 requires 语句时,它指定您在其中运行脚本的 Windows PowerShell 会话必须以提升的用户权限(以管理员身份运行)启动。
对我来说,这似乎是解决这个问题的好方法,但我不确定现场经验。 PowerShell 3.0 运行时可能会忽略这一点,甚至更糟的是,会出现错误。
以非管理员身份运行脚本时,报错如下:
脚本“StackOverflow.ps1”无法运行,因为它包含以管理员身份运行的“#requires”语句。 当前 Windows PowerShell 会话未以管理员身份运行。 使用“以管理员身份运行”选项启动 Windows PowerShell,然后再次尝试运行该脚本。
+ CategoryInfo : PermissionDenied: (StackOverflow.ps1:String) [], ParentContainsErrorRecordException + FullyQualifiedErrorId : ScriptRequiresElevation
您可以轻松添加一些注册表项以获取.ps1
文件的“以管理员身份运行”上下文菜单:
New-Item -Path "Registry::HKEY_CLASSES_ROOT\Microsoft.PowershellScript.1\Shell\runas\command" `
-Force -Name '' -Value '"c:\windows\system32\windowspowershell\v1.0\powershell.exe" -noexit "%1"'
(从@Shay 更新为更简单的脚本)
基本上在HKCR:\\Microsoft.PowershellScript.1\\Shell\\runas\\command
设置默认值以使用 Powershell 调用脚本。
Jonathan 和 Shay Levy 发布的代码对我不起作用。
请在下面找到工作代码:
If (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{
#"No Administrative rights, it will display a popup window asking user for Admin rights"
$arguments = "& '" + $myinvocation.mycommand.definition + "'"
Start-Process "$psHome\powershell.exe" -Verb runAs -ArgumentList $arguments
break
}
#"After user clicked Yes on the popup, your file will be reopened with Admin rights"
#"Put your code here"
您需要以管理权限重新运行脚本并检查脚本是否在该模式下启动。 下面我编写了一个具有两个函数的脚本: DoElevatedOperations和DoStandardOperations 。 您应该将需要管理员权限的代码放在第一个中,将标准操作放在第二个中。 IsRunAsAdmin变量用于标识管理模式。
我的代码是 Microsoft 脚本的简化摘录,该脚本在您为 Windows 应用商店应用程序创建应用程序包时自动生成。
param(
[switch]$IsRunAsAdmin = $false
)
# Get our script path
$ScriptPath = (Get-Variable MyInvocation).Value.MyCommand.Path
#
# Launches an elevated process running the current script to perform tasks
# that require administrative privileges. This function waits until the
# elevated process terminates.
#
function LaunchElevated
{
# Set up command line arguments to the elevated process
$RelaunchArgs = '-ExecutionPolicy Unrestricted -file "' + $ScriptPath + '" -IsRunAsAdmin'
# Launch the process and wait for it to finish
try
{
$AdminProcess = Start-Process "$PsHome\PowerShell.exe" -Verb RunAs -ArgumentList $RelaunchArgs -PassThru
}
catch
{
$Error[0] # Dump details about the last error
exit 1
}
# Wait until the elevated process terminates
while (!($AdminProcess.HasExited))
{
Start-Sleep -Seconds 2
}
}
function DoElevatedOperations
{
Write-Host "Do elevated operations"
}
function DoStandardOperations
{
Write-Host "Do standard operations"
LaunchElevated
}
#
# Main script entry point
#
if ($IsRunAsAdmin)
{
DoElevatedOperations
}
else
{
DoStandardOperations
}
加上我的 2 美分。 我的基于网络会话的简单版本到目前为止一直在 Windows 7 / Windows 10 中工作。为什么让它过于复杂?
if (!(net session)) {$path = "& '" + $myinvocation.mycommand.definition + "'" ; Start-Process powershell -Verb runAs -ArgumentList $path ; exit}
只需添加到脚本的顶部,它就会以管理员身份运行。
此行为是设计使然。 由于 Microsoft 确实不希望 .ps1 文件成为最新的电子邮件病毒,因此存在多层安全性。 有些人发现这与任务自动化的概念背道而驰,这是公平的。 Vista+ 安全模型是“去自动化”事物,从而让用户接受它们。
但是,我怀疑如果您以提升的身份启动 powershell,它应该能够运行批处理文件而无需再次请求密码,直到您关闭 powershell。
这里的一些答案很接近,但比需要的工作要多一些。
创建脚本的快捷方式并将其配置为“以管理员身份运行”:
Properties...
Target
从<script-path>
编辑到powershell <script-path>
Run as administrator
以下是如何在单个命令中运行提升的 powershell 命令并在 Windows 批处理文件中收集其输出形式(即不编写 ps1 powershell 脚本)。
powershell -Command 'Start-Process powershell -ArgumentList "-Command (Get-Process postgres | Select-Object Path | Select-Object -Index 0).Path | Out-File -encoding ASCII $env:TEMP\camp-postgres.tmp" -Verb RunAs'
在上面你看到我首先启动一个带有提升提示的 powershell,然后要求它启动另一个 powershell(子 shell)来运行命令。
我找到了一种方法来做到这一点......
创建一个批处理文件来打开你的脚本:
@echo off
START "" "C:\Scripts\ScriptName.ps1"
然后创建一个快捷方式,在您的桌面上说(右键单击New -> Shortcut )。
然后将其粘贴到位置:
C:\Windows\System32\runas.exe /savecred /user:*DOMAIN*\*ADMIN USERNAME* C:\Scripts\BatchFileName.bat
首次打开时,您必须输入一次密码。 然后将其保存在 Windows 凭据管理器中。
在此之后,您应该能够以管理员身份运行,而无需输入管理员用户名或密码。
C:\\Users\\"username"\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Windows PowerShell
是 PowerShell快捷方式所在的位置。 它仍然会转到不同的位置来调用实际的“exe”( %SystemRoot%\\system32\\WindowsPowerShell\\v1.0\\powershell.exe
)。
由于 PowerShell 在权限方面是由用户配置文件驱动的; 如果您的用户名/配置文件有权在该配置文件下执行某些操作,则在 PowerShell 中您通常也可以执行此操作。 话虽如此,您可以更改位于您的用户配置文件下的快捷方式,例如, C:\\Users\\"username"\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Windows PowerShell
。
右键单击并单击属性。 单击位于“评论”文本字段正下方的“快捷方式”选项卡下的“高级”按钮,该文本字段与另外两个按钮“打开文件位置”和“更改图标”的右侧相邻。
选中“以管理员身份运行”复选框。 单击“确定” ,然后单击“应用”和“确定” 。 再次右键单击位于C:\\Users\\"username"\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Windows PowerShell
中标有“Windows PowerShell”的图标,然后选择“固定到开始菜单/任务栏”。
现在,无论何时单击该图标,它都会调用UAC进行升级。 选择“是”后,您会注意到 PowerShell 控制台打开,它会在屏幕顶部标记为“管理员”。
更进一步...您可以在 Windows PowerShell 的配置文件位置中右键单击相同的图标快捷方式,并分配一个键盘快捷方式,该快捷方式将执行与单击最近添加的图标完全相同的操作。 所以在它说“快捷键”的地方输入一个键盘键/按钮组合,如: Ctrl + Alt + P P (for PowerShell) 。 单击应用和确定。
现在你所要做的就是按下你分配的那个按钮组合,你会看到 UAC 被调用,在你选择“是”后,你会看到一个 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
另一个更简单的解决方案是,您也可以右键单击“C:\\Windows\\System32\\cmd.exe”并选择“以管理员身份运行”,然后您就可以以管理员身份运行任何应用程序,而无需提供任何密码。
@pgk和@Andrew Odri的答案的问题在于您有脚本参数时,特别是当它们是强制性的时。 您可以使用以下方法解决此问题:
如果脚本具有ComputerName和Port强制参数,则代码如下:
[CmdletBinding(DefaultParametersetName='RunWithPowerShellContextMenu')]
param (
[parameter(ParameterSetName='CallFromCommandLine')]
[switch] $CallFromCommandLine,
[parameter(Mandatory=$false, ParameterSetName='RunWithPowerShellContextMenu')]
[parameter(Mandatory=$true, ParameterSetName='CallFromCommandLine')]
[string] $ComputerName,
[parameter(Mandatory=$false, ParameterSetName='RunWithPowerShellContextMenu')]
[parameter(Mandatory=$true, ParameterSetName='CallFromCommandLine')]
[UInt16] $Port
)
function Assert-AdministrativePrivileges([bool] $CalledFromRunWithPowerShellMenu)
{
$isAdministrator = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if ($isAdministrator)
{
if (!$CalledFromRunWithPowerShellMenu -and !$CallFromCommandLine)
{
# Must call itself asking for obligatory parameters
& "$PSCommandPath" @script:PSBoundParameters -CallFromCommandLine
Exit
}
}
else
{
if (!$CalledFromRunWithPowerShellMenu -and !$CallFromCommandLine)
{
$serializedParams = [Management.Automation.PSSerializer]::Serialize($script:PSBoundParameters)
$scriptStr = @"
`$serializedParams = '$($serializedParams -replace "'", "''")'
`$params = [Management.Automation.PSSerializer]::Deserialize(`$serializedParams)
& "$PSCommandPath" @params -CallFromCommandLine
"@
$scriptBytes = [System.Text.Encoding]::Unicode.GetBytes($scriptStr)
$encodedCommand = [Convert]::ToBase64String($scriptBytes)
# If this script is called from another one, the execution flow must wait for this script to finish.
Start-Process -FilePath 'powershell' -ArgumentList "-ExecutionPolicy Bypass -NoProfile -EncodedCommand $encodedCommand" -Verb 'RunAs' -Wait
}
else
{
# When you use the "Run with PowerShell" feature, the Windows PowerShell console window appears only briefly.
# The NoExit option makes the window stay visible, so the user can see the script result.
Start-Process -FilePath 'powershell' -ArgumentList "-ExecutionPolicy Bypass -NoProfile -NoExit -File ""$PSCommandPath""" -Verb 'RunAs'
}
Exit
}
}
function Get-UserParameters()
{
[string] $script:ComputerName = [Microsoft.VisualBasic.Interaction]::InputBox('Enter a computer name:', 'Testing Network Connection')
if ($script:ComputerName -eq '')
{
throw 'The computer name is required.'
}
[string] $inputPort = [Microsoft.VisualBasic.Interaction]::InputBox('Enter a TCP port:', 'Testing Network Connection')
if ($inputPort -ne '')
{
if (-not [UInt16]::TryParse($inputPort, [ref]$script:Port))
{
throw "The value '$inputPort' is invalid for a port number."
}
}
else
{
throw 'The TCP port is required.'
}
}
# $MyInvocation.Line is empty in the second script execution, when a new powershell session
# is started for this script via Start-Process with the -File option.
$calledFromRunWithPowerShellMenu = $MyInvocation.Line -eq '' -or $MyInvocation.Line.StartsWith('if((Get-ExecutionPolicy')
Assert-AdministrativePrivileges $calledFromRunWithPowerShellMenu
# Necessary for InputBox
[System.Reflection.Assembly]::Load('Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a') | Out-Null
if ($calledFromRunWithPowerShellMenu)
{
Get-UserParameters
}
# ... script code
Test-NetConnection -ComputerName $ComputerName -Port $Port
我发现的最可靠的方法是将它包装在一个自我提升的 .bat 文件中:
@echo off
NET SESSION 1>NUL 2>NUL
IF %ERRORLEVEL% EQU 0 GOTO ADMINTASKS
CD %~dp0
MSHTA "javascript: var shell = new ActiveXObject('shell.application'); shell.ShellExecute('%~nx0', '', '', 'runas', 0); close();"
EXIT
:ADMINTASKS
powershell -file "c:\users\joecoder\scripts\admin_tasks.ps1"
EXIT
.bat 检查您是否已经是管理员,并在需要时以管理员身份重新启动脚本。 它还可以防止在ShellExecute()
的第 4 个参数设置为0
打开无关的“cmd”窗口。
在 Shay Levy 的回答之上,按照以下设置(仅一次)
PATH
文件夹中。 Windows\\System32 文件夹设置后:
powershell Start-Process powershell -Verb runAs <ps1_file>
您现在可以在一个命令行中运行所有内容。 以上适用于 Windows 8 Basic 64 位。
我以前从未见过自己的做法,所以,试试这个。 它更容易遵循并且占用空间更小:
if([bool]([Security.Principal.WindowsIdentity]::GetCurrent()).Groups -notcontains "S-1-5-32-544") {
Start Powershell -ArgumentList "& '$MyInvocation.MyCommand.Path'" -Verb runas
}
很简单,如果当前 Powershell 会话是以管理员权限调用的,那么当您获取当前身份时,管理员组众所周知的 SID 将显示在组中。 即使该帐户是该组的成员,除非使用提升的凭据调用该进程,否则 SID 也不会显示。
几乎所有这些答案都是微软的 Ben Armstrong 非常流行的如何完成它的方法的变体,而没有真正掌握它实际在做什么以及如何模拟相同的例程。
要将命令的输出附加到包含当前日期的文本文件名,您可以执行以下操作:
$winupdfile = 'Windows-Update-' + $(get-date -f MM-dd-yyyy) + '.txt'
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -Command `"Get-WUInstall -AcceptAll | Out-File $env:USERPROFILE\$winupdfile -Append`"" -Verb RunAs; exit } else { Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -Command `"Get-WUInstall -AcceptAll | Out-File $env:USERPROFILE\$winupdfile -Append`""; exit }
这是澄清...
powershell RUNAS / SAVECRED 凭证“不安全”,尝试过它并将管理员身份和密码添加到凭证缓存中,并且可以在其他地方使用 OOPS!。 如果您这样做了,我建议您检查并删除该条目。
检查您的程序或代码,因为 Microsoft 的政策是在没有 UAC(入口点)以管理员身份执行程序的情况下,您不能在同一代码 blob 中混合用户和管理员代码。 这将是 Linux 上的 sudo(同样的事情)。
UAC 有 3 种类型,dont'see、提示或在程序清单中生成的入口点。 它不会提升程序,因此如果没有 UAC 并且需要管理员,它将失败。 UAC 虽然作为管理员要求是好的,但它可以防止未经身份验证的代码执行,并防止在用户级别执行混合代码场景。
事实证明这太容易了。 您所要做的就是以管理员身份运行 cmd。 然后输入explorer.exe
并按回车键。 这将打开Windows 资源管理器。 现在右键单击要运行的 PowerShell 脚本,选择“使用 PowerShell 运行”,这将在 PowerShell 中以管理员模式启动它。
它可能会要求您启用策略运行,键入 Y 并按 Enter。 现在脚本将以管理员身份在 PowerShell 中运行。 如果它全部显示为红色,则表示您的政策尚未生效。 然后再试一次,它应该可以正常工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.