Answers:
如果当前控制台未提升,而您要执行的操作需要提升的特权,则可以使用以下Run as administrator选项启动powershell :
PS> Start-Process powershell -Verb runAs
start-process -verb runAs "<cmd>" -argumentlist "<args1> <args2>"
;)
这是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进程(如果当前用户有权访问管理员模式,并且脚本未以管理员身份启动)。
if (-not (([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)))
if
语句,throw
然后在then块中放入一个。
if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))
[Security.Principal.WindowsBuiltInRole]::Administrator)
)而不是字符串参数"Administrator"
-我遇到了具有重命名内置角色的安全性
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
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`" `"$args`"" -Verb RunAs; exit }
本杰明·阿姆斯特朗(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");
$newProcess = new-object System.Diagnostics.ProcessStartInfo “cmd.exe” $newProcess.Arguments = ‘/c ‘ + [System.Environment]::GetCommandLineArgs() $newProcess.WorkingDirectory = [environment]::CurrentDirectory
您可以创建一个批处理文件(*.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
将在该system32
文件夹中打开另一个具有管理特权的新的PowerShell会话,并将以下参数传递给该文件夹:
-ExecutionPolicy Bypass -NoProfile -NoExit -Command "cd \"C:\Temp\"; & \".\ScriptTest.ps1\""
以下命令将以管理特权执行:
cd "C:\Temp"; & ".\ScriptTest.ps1"
一旦脚本路径和名称参数被双引号引起来,它们可以包含空格或单引号字符('
)。
当前文件夹将从更改system32
为C:\Temp
,脚本ScriptTest.ps1
将被执行。-NoExit
传递参数后,即使您的Powershell脚本抛出某些异常,也不会关闭该窗口。
sudo
命令并在文件中配置用于自动过程的用户来实现NOPASSWD: ALL
sudoers
。
这是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
使用
#Requires -RunAsAdministrator
尚未说明。它似乎仅在PowerShell 4.0之后才存在。
http://technet.microsoft.com/zh-CN/library/hh847765.aspx
当将此switch参数添加到require语句时,它指定必须以提升的用户权限(以管理员身份运行)启动运行脚本的Windows PowerShell会话。
对我来说,这似乎是解决问题的一种好方法,但是我不确定现场经验。PowerShell 3.0运行时可能会忽略此错误,或者更糟的是会给出错误。
当脚本以非管理员身份运行时,会出现以下错误:
无法运行脚本“ StackOverflow.ps1”,因为该脚本包含用于以管理员身份运行的“ #requires”语句。当前的Windows PowerShell会话未以管理员身份运行。使用“以管理员身份运行”选项启动Windows PowerShell,然后再次尝试运行脚本。
+ CategoryInfo : PermissionDenied: (StackOverflow.ps1:String) [], ParentContainsErrorRecordException + FullyQualifiedErrorId : ScriptRequiresElevation
Parameter RunAsAdministrator requires an argument
。@akauppi我不能说服他们一直在想。
您可以轻松地添加一些注册表项,以获取文件的“以管理员身份运行”上下文菜单.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调用脚本。
(default)
零件中猜测出来?
"c:\windows\system32\windowspowershell\v1.0\powershell.exe" -noexit -command "& '%1'"
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 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
}
再加上我的2美分。我基于网络会话的简单版本至今在Windows 7 / Windows 10中一直有效。为什么过于复杂?
if (!(net session)) {$path = "& '" + $myinvocation.mycommand.definition + "'" ; Start-Process powershell -Verb runAs -ArgumentList $path ; exit}
只需添加到脚本顶部,它将以管理员身份运行。
if (!(net session 2>&1 | Out-Null)) { ...
ycomp ... } else { echo "your message" }
。
cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policies at https:/go.microsoft.com/fwlink/?LinkID=135170.
Set-ExecutionPolicy -ExecutionPolicy <PolicyName>
,您可以将其设置为,bypass
但是bypass
可能很危险。将其设置为AllSigned
C:\Users\"username"\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Windows PowerShell
是PowerShell 快捷方式所在的位置。它也仍然转到另一个位置来调用实际的“ exe”(%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe
)。
由于考虑到权限,PowerShell是由用户配置文件驱动的;如果您的用户名/配置文件有权执行某项操作,则可以在该配置文件下执行操作。话虽如此,您应该更改位于用户配置文件下的快捷方式,例如,这是很有意义的C:\Users\"username"\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Windows PowerShell
。
右键单击,然后单击属性。单击“快捷方式”选项卡下的“高级”按钮,该选项卡位于与其他两个按钮(分别为“打开文件位置”和“更改图标”)右侧相邻的“注释”文本字段下方。
选中显示为“以管理员身份运行”的复选框。单击OK,然后单击Apply和OK。再次右键单击位于其中的标有“ Windows PowerShell”的图标,C:\Users\"username"\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Windows PowerShell
然后选择“固定到开始菜单/任务栏”。
现在,无论何时单击该图标,它都会调用UAC进行升级。选择“是”后,您会注意到PowerShell控制台已打开,并且在屏幕顶部将其标记为“管理员”。
要更进一步...,您可以在Windows PowerShell的配置文件位置中右键单击相同的图标快捷方式,然后分配一个键盘快捷方式,其作用与单击最近添加的图标完全相同。因此,在显示“快捷键”的地方,将键盘键/按钮组合如下:Ctrl+ Alt+ P P(对于PowerShell)。点击Apply和OK。
现在,您所要做的就是按下分配给您的按钮组合,您将看到UAC被调用,选择“是”后,您将看到一个PowerShell控制台,并且在标题栏上显示“管理员”。
我找到了一种方法来做...
创建一个批处理文件以打开您的脚本:
@echo off
START "" "C:\Scripts\ScriptName.ps1"
然后在桌面上说一个快捷方式(右键单击New- > Shortcut)。
然后将此粘贴到该位置:
C:\Windows\System32\runas.exe /savecred /user:*DOMAIN*\*ADMIN USERNAME* C:\Scripts\BatchFileName.bat
首次打开时,您将必须输入一次密码。然后将其保存在Windows凭据管理器中。
此后,您应该能够以管理员身份运行,而不必输入管理员用户名或密码。
与这个问题@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
我正在使用下面的解决方案。它通过脚本功能处理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
这是运行提升的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)来运行命令。
在Shay Levy的答案之上,请遵循以下设置(仅一次)
PATH
文件夹中。Windows \ System32文件夹设置完成后:
powershell Start-Process powershell -Verb runAs <ps1_file>
现在,您可以在一个命令行中运行所有内容。以上内容适用于Windows 8 Basic 64位。
我找到的最可靠的方法是将其包装在一个自升的.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个参数打开无关的“ cmd”窗口0
。
EXIT
一个更改为a,GOTO :EOF
然后删除了第二个。另外,cd %~dp0
应该将cd /d %~dp0
AND与第一个命令放在后@echo off
。这样,您就不需要两者的绝对路径.ps1
,只需将其放置在与相同的文件夹中即可.bat
。如果需要查看结果,请将第4个参数更改为1
。
mshta
命令?
cmd
过程,因此不会“修复”它,但是我很高兴您能够根据需要对其进行修改。
cmd
(我没有)。但是关于其他更改,我认为已解决,因为我的版本对我们双方都适用,而您的版本对我不适用,即我的版本更通用(针对不同驱动器的情况)。无论如何,这是一个非常聪明的方法。
我以前从未见过自己的方式,因此,请尝试一下。它易于遵循且占用空间小得多:
if([bool]([Security.Principal.WindowsIdentity]::GetCurrent()).Groups -notcontains "S-1-5-32-544") {
Start Powershell -ArgumentList "& '$MyInvocation.MyCommand.Path'" -Verb runas
}
非常简单,如果使用管理员权限调用了当前Powershell会话,则当您获取当前标识时,管理员组众所周知的SID将显示在组中。即使该帐户是该组的成员,也不会显示SID,除非使用提升的凭据来调用该过程。
几乎所有这些答案都是Microsoft 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(入口点)以admin身份执行程序,则不能在同一代码blob中混合用户代码和管理员代码。在Linux上这将是sudo(相同的东西)。
UAC具有3种类型,即“不可见”,在程序清单中生成的提示或入口点。它不会提升程序,因此,如果没有UAC并且需要管理员,它将失败。尽管作为管理员的要求,UAC很好,但是它阻止了未经身份验证的代码执行,并阻止了在用户级别执行混合代码方案。
事实证明,这太简单了。您要做的就是以管理员身份运行cmd。然后输入explorer.exe
并按Enter。这将打开Windows资源管理器。现在,右键单击要运行的PowerShell脚本,选择“使用PowerShell运行”,它将以管理员模式在PowerShell中启动。
它可能会要求您启用该策略以运行,键入Y并按Enter。现在,脚本将以管理员身份在PowerShell中运行。万一它全部变成红色,这意味着您的策略尚未生效。然后重试,它应该可以正常工作。
gsudo
。适用于Windows的免费开源sudo,可从命令行以admin身份执行。将出现一个UAC弹出窗口。