PowerShell:以管理员身份运行命令

时间:2011-10-07 17:53:03

标签: powershell administrator

您知道如果您是系统的管理用户,您可以右键单击“说”,批处理脚本并以管理员身份运行它而不输入管理员密码吗?

我想知道如何使用PowerShell脚本执行此操作。我不想输入密码;我只想模仿右键单击以管理员身份运行方法。

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

26 个答案:

答案 0 :(得分:244)

如果当前控制台未升级并且您尝试执行的操作需要提升权限,则可以使用“以管理员身份运行”选项启动PowerShell

PS> Start-Process powershell -Verb runAs

答案 1 :(得分:94)

以下是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进程(如果当前用户可以访问管理员模式并且脚本未以管理员身份启动)。

答案 2 :(得分:75)

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

答案 3 :(得分:38)

本杰明阿姆斯特朗张贴了excellent article about self-elevating PowerShell scripts。他的代码有一些小问题;基于评论中建议的修正的修改版本如下。

基本上它获取与当前进程关联的标识,检查它是否是管理员,如果不是,则创建具有管理员权限的新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");

答案 4 :(得分:16)

您可以创建一个批处理文件(*.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脚本抛出一些异常,窗口也不会被关闭。

答案 5 :(得分:13)

您可以轻松添加一些注册表项,以获取.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调用脚本。

答案 6 :(得分:12)

使用

#Requires -RunAsAdministrator

尚未说明。它似乎只有自PowerShell 4.0以来才存在。

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

  

将此开关参数添加到您的require语句时,         它指定您所在的Windows PowerShell会话         必须以提升的用户权限启动运行脚本         (以管理员身份运行)。

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

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

  

脚本'StackOverflow.ps1'无法运行,因为它包含一个   以管理员身份运行的“#requires”语句。目前   Windows PowerShell会话未以管理员身份运行。开始   Windows PowerShell,使用“以管理员身份运行”选项,然后执行   尝试再次运行脚本。

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

答案 7 :(得分:9)

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"

答案 8 :(得分:8)

您需要使用管理权限重新运行脚本,并检查脚本是否以该模式启动。下面我编写了一个包含两个函数的脚本: 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
}

答案 9 :(得分:5)

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

enter image description here

找到该文件,右键单击>属性>捷径>高级并选中以管理员身份运行

然后单击“确定”。

答案 10 :(得分:5)

加我2美分。我的基于网络会话的简单版本到目前为止在Windows 7 / Windows 10中一直有效。为什么会使它复杂化?

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

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

答案 11 :(得分:4)

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 (对于PowerShell的)即可。单击应用确定

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

答案 12 :(得分:3)

这里的一些答案很接近,但是需要的工作量比需要多一些。

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

  • 创建快捷方式。
  • 右键单击快捷方式并打开Properties...
  • Target<script-path>
  • 修改powershell <script-path>
  • 点击高级... 并启用Run as administrator

答案 13 :(得分:3)

此行为是设计使然。由于Microsoft确实不希望.ps1文件成为最新的电子邮件病毒,因此存在多层安全性。有些人认为这与任务自动化的概念背道而驰,这是公平的。 Vista +安全模型是“去自动化”事物,从而使用户可以接受它们。

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

答案 14 :(得分:2)

@pgk@Andrew Odri答案的问题在于您有脚本参数,特别是当它们是必需的时。您可以使用以下方法解决此问题:

  1. 用户右键单击 .ps1 文件并选择&#39;使用PowerShell运行&#39;:通过输入框询问他参数(这是一个比使用 HelpMessage 参数属性);
  2. 用户通过控制台执行脚本:允许他传递所需的参数,并让控制台强制他通知强制性参数。
  3. 如果脚本具有 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
    

答案 15 :(得分:2)

我正在使用以下解决方案。它通过脚本功能处理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

答案 16 :(得分:2)

我找到了办法做到这一点......

创建批处理文件以打开脚本:

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

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

然后将其粘贴到以下位置:

C:\Windows\System32\runas.exe /savecred /user:*DOMAIN*\*ADMIN USERNAME* C:\Scripts\BatchFileName.bat

首次打开时,您必须输入一次密码。然后,它会将其保存在Windows凭据管理器中。

在此之后,您应该能够以管理员身份运行,而无需输入管理员用户名或密码。

答案 17 :(得分:2)

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

答案 18 :(得分:1)

这是Powershell脚本的一个自提升代码段,保留了工作目录

this.list = myNevListFromService

保留工作目录对于执行相对路径操作的脚本很重要。几乎所有其他答案都不会保留该路径,这可能会在脚本的其余部分中导致意外错误。

如果您不想使用自动提升的脚本/代码段,而只是想以一种简单的方式以管理员身份启动脚本(例如,从Explorer上下文菜单中),请在此处查看我的其他答案:{{ 3}}

答案 19 :(得分:1)

这是如何运行提升的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)来运行命令。

答案 20 :(得分:1)

我发现的最可靠的方法是将其包装在一个自我提升的.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检查您是否已经管理,并在需要时以管理员身份重新启动脚本。它还可以防止外来的&#34; cmd&#34;打开的窗口,ShellExecute()的第4个参数设置为0

答案 21 :(得分:1)

除了Shay Levy的回答,请按照以下设置(只需一次)

  1. 以管理员权限启动PowerShell。
  2. 关注Stack Overflow问题 PowerShell says “execution of scripts is disabled on this system.”
  3. 例如,将.ps1文件放在任何PATH文件夹中。 Windows \ System32文件夹
  4. 设置完成后:

    1. + R
    2. 调用powershell Start-Process powershell -Verb runAs <ps1_file>
    3. 现在,您只需在一个命令行中运行所有内容即可。以上适用于Windows 8 Basic 64位。

答案 22 :(得分:0)

这是一个澄清......

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

检查您的程序或代码,因为Microsoft策略是您在同一代码blob中没有混合用户和管理代码,而没有UAC(入口点)以管理员身份执行程序。这在Linux上就是sudo(同样的事情)。

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

答案 23 :(得分:0)

要将命令的输出附加到包含当前日期的文本文件名,您可以执行以下操作:

File file = new File(path);
long = file.length();//in Bytes

答案 24 :(得分:0)

我以前没有看过自己的做法,所以,试试吧。它更容易遵循,占用空间更小:

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非常流行的如何实现它的方法的变体,同时还没有真正理解它实际上在做什么以及如何模仿相同的例程。 / p>

答案 25 :(得分:-3)

事实证明这太容易了。您所要做的就是以管理员身份运行cmd。然后输入explorer.exe并按Enter键。这会打开Windows Explorer。 现在右键单击要运行的PowerShell脚本,选择“使用PowerShell运行”,它将以管理员模式在PowerShell中启动它。

它可能会要求您启用策略运行,键入Y并按Enter键。现在,该脚本将以管理员身份在PowerShell中运行。如果它全部运行为红色,则表示您的策略尚未生效。然后再试一次它应该可以正常工作。