以管理员身份使用PowerShell执行命令?

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

我想知道如何用PowerShell脚本做到这一点。我不想输入我的密码;我只想模拟右击以管理员身份运行方法。

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

1290489 次浏览

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

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

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

PS> Start-Process powershell -Verb runAs

Microsoft Docs: Start-Process . bat:

你可以很容易地添加一些注册表项来获得.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调用脚本。

以下是对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进程(如果当前User具有管理员模式,并且脚本不是以管理员身份启动)。

另一个更简单的解决方案是,你也可以右键单击“C:\Windows\System32\cmd.exe”,并选择“以管理员身份运行”,然后你就可以以管理员身份运行任何应用程序,而无需提供任何密码。

乔纳森和谢伊·列维发布的代码对我不起作用。

请在下面找到工作代码:

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"

您需要使用管理权限重新运行脚本,并检查脚本是否在该模式下启动。下面我写了一个脚本,它有两个函数:DoElevatedOperationsDoStandardOperations。您应该将需要管理权限的代码放在第一个中,将标准操作放在第二个中。IsRunAsAdmin变量用于标识管理模式。

我的代码是微软脚本的简化摘录,当你为Windows Store应用程序创建应用程序包时自动生成。

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
}

使用

#Requires -RunAsAdministrator

还没有声明。它似乎是从PowerShell 4.0开始出现的。

http://technet.microsoft.com/en-us/library/hh847765.aspx

当这个switch参数被添加到你的require语句中, 它指定您所在的Windows PowerShell会话 运行脚本时必须使用提升的用户权限

.(以管理员身份运行)

对我来说,这似乎是一个很好的方法,但我还不确定现场经验。PowerShell 3.0运行时可能会忽略这一点,甚至更糟,会给出一个错误。

当脚本以非管理员身份运行时,会给出以下错误:

脚本` StackOverflow. shPs1 '不能运行,因为它包含 以管理员身份运行的“#requires”语句。当前的 Windows PowerShell会话没有以管理员身份运行。开始 Windows PowerShell使用“以管理员身份运行”选项,然后

. sh

. sh

. sh
+ CategoryInfo          : PermissionDenied: (StackOverflow.ps1:String) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ScriptRequiresElevation

本杰明·阿姆斯特朗发布了一个关于自提升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");

我找到了一个方法…

创建一个批处理文件打开你的脚本:

@echo off
START "" "C:\Scripts\ScriptName.ps1"

然后创建一个快捷方式,在桌面上说(右键单击 -> 快捷方式)。

然后粘贴到位置:

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进行升级。选择“YES”后,您将注意到PowerShell控制台打开,屏幕顶部将标记为“Administrator”。

更进一步说……你可以在Windows PowerShell的配置文件中右键单击相同的图标快捷方式,并分配一个键盘快捷方式,该快捷方式将执行与单击最近添加的图标完全相同的操作。所以在说“快捷键”的地方输入键盘键/按钮组合,比如:Ctrl + Alt + PP (PowerShell)。单击应用好吧

现在你所要做的就是按下你分配的按钮组合,你会看到UAC被调用,在你选择'YES'后,你会看到一个PowerShell控制台出现,“Administrator”显示在标题栏上。

自提升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

结果是太简单了。您所要做的就是以管理员身份运行cmd。然后输入explorer.exe并按enter。这将打开Windows 探险家。 现在右键单击你想要运行的PowerShell脚本,选择“运行PowerShell”,这将以管理员模式在PowerShell中启动它

它可能会要求您启用策略以运行,键入Y并按enter。现在脚本将以管理员身份在PowerShell中运行。万一全红了,说明你的政策还没生效。然后再试一次,应该可以正常工作。

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

enter image description here

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

单击“确定”。

我还没见过自己的方法,所以,试试这个。它更容易遵循,占用的空间也更小:

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 }

您可以创建一个批处理文件(*.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。当有人执行这个批处理文件时,会发生以下步骤:

  1. cmd执行命令

    powershell -Command "Start-Process powershell \"-ExecutionPolicy Bypass -NoProfile -NoExit -Command `\"cd \`\"C:\Temp\`\"; & \`\".\ScriptTest.ps1\`\"`\"\" -Verb RunAs"
    
  2. 将打开一个新的powershell会话,并执行以下命令:

    Start-Process powershell "-ExecutionPolicy Bypass -NoProfile -NoExit -Command `"cd \`"C:\Temp\`"; & \`".\ScriptTest.ps1\`"`"" -Verb RunAs
    
  3. 另一个具有管理权限的新的powershell会话将在system32系统文件夹中打开,并将以下参数传递给它:

    -ExecutionPolicy Bypass -NoProfile -NoExit -Command "cd \"C:\Temp\"; & \".\ScriptTest.ps1\""
    
  4. 以下命令将以管理员权限执行:

    cd "C:\Temp"; & ".\ScriptTest.ps1"
    

    一旦脚本路径和名称参数被双引号括起来,它们就可以包含空格或单引号字符(')。

  5. 当前文件夹将从system32系统变为C: \ Temp,脚本ScriptTest.ps1将被执行。一旦传递了参数-NoExit,窗口就不会关闭,即使你的powershell脚本抛出了一些异常。

我发现最可靠的方法是将其包装在一个自动提升的。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()的第四个参数设置为0时打开多余的“cmd”窗口。

这是一个澄清…

powershell的RUNAS / SAVECRED凭据“不安全”,尝试了一下,它将管理员身份和密码添加到凭据缓存中,可以在其他地方使用。如果您已经这样做了,我建议您检查并删除该条目。

请检查您的程序或代码,因为微软的策略是,如果没有UAC(入口点)以管理身份执行程序,则不能将用户代码和管理代码混合在同一个代码blob中。这将是Linux上的sudo(同样的事情)。

UAC有3种类型,在程序清单中生成的提示符或入口点。它不会提升程序,所以如果没有UAC,它需要管理,它将失败。虽然UAC作为管理员需求是好的,但它可以防止在没有身份验证的情况下执行代码,并防止混合代码场景在用户级别执行。

@pgk@Andrew Odri的答案的问题是当你有脚本参数时,特别是当它们是强制性的。可以通过以下方法解决此问题:

  1. 用户右键单击.ps1文件并选择“使用PowerShell运行”:通过输入框向他询问参数(这比使用HelpMessage参数属性要好得多);
  2. 用户通过控制台执行脚本:允许他传递所需的参数,并让控制台强制他通知必须的参数。

下面是如果脚本具有ComputerName港口强制参数,代码将如何:

[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

这里有一些答案是接近的,但比所需的工作多了一些。

为脚本创建一个快捷方式,并将其配置为“以管理员身份运行”:

  • 创建快捷方式。
  • 右键单击快捷方式并打开Properties...
  • 编辑Target<script-path>powershell <script-path>
  • 单击先进的……并启用Run as administrator

我正在使用下面的解决方案。它通过转录特性处理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

加上我的意见。我的简单版本基于net session,到目前为止一直在Windows 7 / Windows 10中工作。为什么要过于复杂呢?

if (!(net session)) {$path =  "& '" + $myinvocation.mycommand.definition + "'" ; Start-Process powershell -Verb runAs -ArgumentList $path ; exit}

只需添加到脚本顶部,它将以管理员身份运行。

下面是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

下面是如何运行一个提升的powershell命令,并在单个命令(i)中收集windows批处理文件中的输出形式。E不写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)运行命令。

我最近需要在ansible上建立一个环境。我说马上——决定权不在我,但我不记得是从哪里得到的。是这样的:

powershell.exe -NoProfile -ExecutionPolicy Unrestricted -Command "& {Start-Process PowerShell -ArgumentList '-NoProfile -ExecutionPolicy Unrestricted -Command Get-Service -Name ssh-agent | Set-Service -StartupType Automatic' -Verb RunAs}";

启用ssh-agent自动启动。 所需的命令在-Command后指定。唯一的问题是启动发生在一个新的PS实例上,但到目前为止,这是我所知道的作为管理员执行命令而不需要额外步骤的唯一方法

从启动运行中提升PowerShell

你不能从“run"在2012年r2或2016年,没有两次炮击:

C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell -Command "saps powershell -Verb RunAs "