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时,将发生以下步骤:
-
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
-
另一个新的具有pipe理权限的powershell会话将在system32文件夹中打开,下面的参数将被传递给它:
-ExecutionPolicy Bypass -NoProfile -NoExit -Command "cd \"C:\Temp\"; & \".\ScriptTest.ps1\""
-
以下命令将以pipe理权限执行:
cd "C:\Temp"; & ".\ScriptTest.ps1"
一旦脚本path和名称参数被双引号,它们可以包含空格或单引号字符(')。
-
当前文件夹将从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理权限的脚本,并检查脚本是否以该模式启动。 下面我写了一个有两个函数的脚本: DoElevatedOperations和DoStandardOperations 。 你应该把需要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 PowerShell
是C:\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的回答之上,按照下面的设置(只是一次)
- 使用pipe理员权限启动PowerShell。
- 遵循堆栈溢出问题PowerShell说:“在这个系统上禁止执行脚本” 。
- 例如,将.ps1文件放在任何
PATH
文件夹中。 Windows \ System32文件夹
设置完成后:
- 按Win + R
- 调用
powershell Start-Process powershell -Verb runAs <ps1_file>
你现在可以在一个命令行中运行所有的东西。 上述工作在Windows 8 Basic 64位上。
@pgk和@Andrew Odri的答案的问题是当你有脚本参数时,特别是当它们是强制性的。 您可以使用以下方法解决此问题:
- 用户右键单击.ps1文件并select“使用PowerShell运行”:通过input框询问参数(这比使用HelpMessage参数属性更好);
- 用户通过控制台执行脚本:允许他传递所需的参数,并让控制台强制他通知强制的参数。
如果脚本具有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
这里的答案很接近,但比需要多一点的工作。
创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中运行。 万一它全红了,这意味着你的政策没有影响。 然后再试一次,它应该工作正常。