PowerShell:以pipe理员身份运行一个命令

你知道如果你是一个系统的pipe理用户,你可以右键点击说一个批处理脚本,并以pipe理员身份运行,而无需inputpipe理员密码?

我想知道如何用PowerShell脚本来做到这一点。 我不想input密码; 我只是想模仿右键单击以pipe理员身份运行的方法。

我目前阅读的所有内容都要求您提供pipe理员密码。

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

PS> Start-Process powershell -Verb runAs 

这是Shay Levi的build议的补充(只需在脚本的开头添加这些行):

 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 } 

这会导致当前脚本以pipe理员模式传递到新的PowerShell进程(如果当前用户有权访问pipe理员模式并且脚本未以pipe理员身份启动)。

自升式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脚本的优秀文章 。 他的代码有一些小问题。 下面是评论中提出的基于修复的修改版本。

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

您可以轻松地添加一些registry项来获取.ps1文件的“以pipe理员身份运行”上下文菜单:

 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调用脚本。

您可以创build一个batch file(* .bat),在双击时使用pipe理权限运行PowerShell脚本。 通过这种方式,您不需要更改PowerShell脚本中的任何内容 。为此,请创build一个与PowerShell脚本具有相同名称和位置的batch file,然后在其中添加以下内容:

 @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脚本位于pathC:\ Temp \ ScriptTest.ps1中 ,那么您的batch file必须具有pathC:\ Temp \ ScriptTest.bat 。 当有人执行这个batch file时,将发生以下步骤:

  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. 另一个新的具有pipe理权限的powershell会话将在system32文件夹中打开,下面的参数将被传递给它:

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

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

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

  5. 当前文件夹将从system32更改为C:\ Temp ,脚本ScriptTest.ps1将被执行。 一旦参数-NoExit被传递,即使你的powershell脚本抛出一些exception,窗口也不会被closures。

Jonathan和Shay Levy发布的代码不适合我。

请find下面的工作代码:

 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" 

您需要重新运行具有pipe理权限的脚本,并检查脚本是否以该模式启动。 下面我写了一个有两个函数的脚本: DoElevatedOperationsDoStandardOperations 。 你应该把需要pipe理权限的代码放到第一个,标准操作放到第二个。 IsRunAsAdminvariables用于标识pipe理员模式。

我的代码是Microsoft脚本的简化提取,当您为Windowsapp store应用创build应用程序包时会自动生成该代码。

 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

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

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

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

脚本“StackOverflow.ps1”无法运行,因为它包含以pipe理员身份运行的“#requires”语句。 当前的Windows PowerShell会话未以pipe理员身份运行。 使用“以pipe理员身份运行”选项启动Windows PowerShell,然后再次运行脚本。

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

C:\Users\"username"\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Windows PowerShellC:\Users\"username"\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Windows PowerShell快捷方式驻留的地方。 它也仍然去不同的位置来调用实际的'exe'( %SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe )。

由于PowerShell在涉及权限时是由用户configuration文件驱动的, 如果您的用户名/configuration文件有权限在该configuration文件下执行某些操作,则在PowerShell中,您通常也可以执行此操作。 这就是说,你应该改变位于用户configuration文件下的快捷方式,例如C:\Users\"username"\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Windows PowerShell

右键单击并单击属性。 点击位于右侧“注释”文本框旁边的“快捷方式”选项卡下的“高级”button,分别位于其他两个button右侧的“打开文件位置”和“更改图标”旁边。

选中“以pipe理员身份运行”checkbox。 单击确定 ,然后单击应用确定 。 再次右键单击位于C:\Users\"username"\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Windows PowerShell “Windows PowerShell”图标,然后select“Pin to Start Menu / Taskbar”。

现在,无论何时单击该图标,它都会调用UAC进行升级。 select“是”后,您会注意到PowerShell控制台已打开,屏幕顶部将标记为“pipe理员”。

若要进一步…您可以右键单击Windows PowerShell的configuration文件位置中的相同图标快捷方式,并指定一个键盘快捷方式,它将执行与点击最近添加的图标完全相同的操作。 所以它说“快捷键”放在一个键盘按键/button组合,如: Ctrl + Alt + P P (对于PowerShell) 。 单击应用确定

现在,您只需按下指定的button组合,即可看到UAC被调用,并且在select“YES”后,您将看到PowerShell控制台出现,标题栏上显示“Administrator”(pipe理员)。

此行为是devise使然。 由于微软真的不希望.ps1文件成为最新的电子邮件病毒,因此有多层安全性。 有些人认为这与任务自动化的概念相反,这是公平的。 Vista +安全模式是“去自动化”的事情,从而使用户没关系。

但是,我怀疑如果你启动PowerShell本身提升,它应该能够运行batch file,而不需要再次请求密码,直到closuresPowerShell。

您也可以强制应用程序以pipe理员身份打开。 如果你有一个pipe理员帐户,当然。

在这里输入图像描述

find该文件,右键单击>属性>快捷方式>高级,然后选中以pipe理员身份运行

然后点击确定。

另一个更简单的解决scheme是,你也可以右键单击“C:\ Windows \ System32 \ cmd.exe”并select“以pipe理员身份运行”,那么你可以运行任何应用程序作为pipe理员,而不提供任何密码。

我find了一种方法来做到这一点…

创build一个batch file来打开你的脚本:

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

然后创build一个快捷方式,在你的桌面上说(右键点击新build – > 快捷方式 )。

然后将其粘贴到该位置:

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

第一次打开时,您必须input一次密码。 这将然后将其保存在Windows凭据pipe理器中。

之后,您可以以pipe理员身份运行,而不必inputpipe理员用户名或密码。

在Shay Levy的回答之上,按照下面的设置(只是一次)

  1. 使用pipe理员权限启动PowerShell。
  2. 遵循堆栈溢出问题PowerShell说:“在这个系统上禁止执行脚本”
  3. 例如,将.ps1文件放在任何PATH文件夹中。 Windows \ System32文件夹

设置完成后:

  1. Win + R
  2. 调用powershell Start-Process powershell -Verb runAs <ps1_file>

你现在可以在一个命令行中运行所有的东西。 上述工作在Windows 8 Basic 64位上。

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

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

如果脚本具有ComputerNamePort必需参数,代码将如何?

 [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 

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

创build脚本的快捷方式并将其configuration为“以pipe理员身份运行”:

  • 创build快捷方式。
  • 右键单击快捷方式并打开Properties...
  • Target<script-path>编辑到powershell <script-path>
  • 单击高级...并启用Run as administrator

我以前从未见过自己的做法,所以试试看。 这是更容易遵循,并有更小的占地面积:

 if([bool]([Security.Principal.WindowsIdentity]::GetCurrent()).Groups -notcontains "S-1-5-32-544") { Start Powershell -ArgumentList "& '$MyInvocation.MyCommand.Path'" -Verb runas } 

非常简单,如果当前的Powershell会话是以pipe理员权限被调用的,当你获取当前的身份时,pipe理员组的知名SID将显示在组中。 即使该帐户是该组的成员,除非使用提升的凭据调用该进程,SID才会显示。

几乎所有这些答案都是微软Ben Armstrong非常stream行的如何实现它的方法的一个变种,而不是真正掌握它实际在做什么以及如何模仿相同的例程。

要将命令的输出追加到包含当前date的文本文件名中,可以这样做:

 $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文件中:

 @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检查你是否已经是pipe理员,如果需要的话,以pipe理员身份重新运行脚本。 它还可以防止多余的“cmd”窗口以ShellExecute()的第四个参数设置为0打开。

这是一个澄清…

PowerShell的RUNAS / SAVECRED凭证“不安全”,尝试了它,并将pipe理员身份和密码添加到凭证caching中,并可以在其他地方使用OOPS !. 如果你这样做,我build议你检查并删除条目。

检查你的程序或代码,因为微软的政策是你不能在没有UAC(入口点)的同一代码块中混合用户和pipe理员代码来以pipe理员身份执行程序。 这将是Linux上的sudo(同样的事情)。

UAC有3种types,不会在程序清单中产生一个提示或入口点。 它不提升程序,所以如果没有UAC,它需要pipe理它将失败。 虽然UAC作为pipe理员要求是好的,但是它防止了没有validation的代码执行,并且防止混合代码场景在用户级执行。

事实certificate这太容易了。 你所要做的就是以pipe理员身份运行cmd。 然后inputexplorer.exe并回车。 这打开了Windows资源pipe理器 。 现在,右键单击要运行的PowerShell脚本,select“使用PowerShell运行”,以pipe理员模式在PowerShell中启动它。

它可能会要求您启用策略运行,inputY并按回车。 现在脚本将以pipe理员身份在PowerShell中运行。 万一它全红了,这意味着你的政策没有影响。 然后再试一次,它应该工作正常。