简体   繁体   English

如何从脚本中提升 Powershell 脚本

[英]How to elevate a Powershell script from within a script

I'm new to Powershell, but in a lot of ways liking it a lot.我是 Powershell 的新手,但在很多方面都非常喜欢它。 For reasons, I have created a script that loads a set of local admin credentials from a file on the hard drive and creates a PSCredential-object, $MyCred.由于某些原因,我创建了一个脚本,该脚本从硬盘驱动器上的文件加载一组本地管理员凭据,并创建一个 PSCredential 对象 $MyCred。

I want to use $MyCred to elevate a separate script (which makes a few registry changes to open RDP connections).我想使用 $MyCred 来提升一个单独的脚本(对注册表进行一些更改以打开 RDP 连接)。 I've tried passing the $MyCred to the Start-Process cmdlet:我尝试将 $MyCred 传递给 Start-Process cmdlet:

Start-Process Powershell.exe -Credential $MyCredential

Then I receive the following error:然后我收到以下错误:

Start-Process : This command cannot be run due to the error: The directory name is invalid. Start-Process :此命令无法运行,因为错误:目录名称无效。

If I run the Start-Process with -credential and an empty variable, I'm prompted for username and password.如果我使用 -credential 和一个空变量运行 Start-Process,系统会提示我输入用户名和密码。 When I type them in, I get an elevated powershell prompt with no issues and am able to make the changes in registry to my test system.当我输入它们时,我会得到一个提升的 powershell 提示,没有任何问题,并且能够在注册表中对我的测试系统进行更改。

I've verified the contents of $myCred and it has both U/N and P/W stored correctly (as in, identical to what I input manually).我已经验证了 $myCred 的内容,并且它正确存储了 U/N 和 P/W(与我手动输入的内容相同)。 Using New-PSSEssion like使用 New-PSSEssion 之类的

New-PSSession -Credential $MyCredential

returns access denied, which I've read is also disabled by default on a lot of systems.返回访问被拒绝,我读过的很多系统默认情况下也禁用了访问。

In an ideal world, the code would look something like:在理想的世界中,代码如下所示:

Start-Process Powershell.exe -Credential $MyCredential -File C:\\MyScript.ps1

This should start an elevated powershell that runs a few commands in the second script and then terminates.这应该启动一个提升的 powershell,它在第二个脚本中运行一些命令,然后终止。 What am I missing here?我在这里想念什么?

Grateful for all help I can get, thanks!感谢我能得到的所有帮助,谢谢! I might be something completely obvious.我可能是完全显而易见的。


Background is, we have some computers that we cannot ourselves get our hands on, and are also not able to reach through RDP.背景是,我们有一些我们自己无法使用的计算机,也无法通过 RDP 访问。 We do have users at the sites that can run the script for us.我们在站点上确实有可以为我们运行脚本的用户。 But it's important that they do not get the local admin-password.但重要的是他们没有获得本地管理员密码。 So we want to create a script that reads an encrypted password file, generates the local admin PSCredential object, and passes that to a script that makes the necessary registry changes to allow for RDP access.因此,我们想创建一个脚本来读取加密的密码文件,生成本地管理员 PSCredential 对象,并将其传递给一个脚本,该脚本进行必要的注册表更改以允许 RDP 访问。

There are many use case articles on this topic.有很多关于这个主题的用例文章。 A quick web search, using 'PowerShell self-elevating script' will show them.使用“PowerShell 自提升脚本”进行快速网络搜索将显示它们。 Even from MS directly甚至直接来自 MS

A self-elevating PowerShell script 一个自提升的 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 Administrator"
 if ($myWindowsPrincipal.IsInRole($adminRole))
    {
    # We are running "as Administrator" - so change the title and background color to indicate this
    $Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)"
    $Host.UI.RawUI.BackgroundColor = "DarkBlue"
    clear-host
    }
 else
    {
    # We are not running "as 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
    $newProcess.Arguments = $myInvocation.MyCommand.Definition;

    # 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")

This code is from a helpful guide: How to Self-Elevate a PowerShell Script此代码来自有用的指南: 如何自我提升 PowerShell 脚本

It checks the current script's security, and if it needs elevation, the script will be re-launched as admin.它会检查当前脚本的安全性,如果需要提升,脚本将以管理员身份重新启动。 If UAC is enabled, it will prompt for your confirmation.如果启用了 UAC,它会提示您确认。 After relaunching, it will have the necessary access and run the code after the check.重新启动后,它将拥有必要的访问权限并在检查后运行代码。

# Self-elevate the script if required
if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
 if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
  $CommandLine = "-File `"" + $MyInvocation.MyCommand.Path + "`" " + $MyInvocation.UnboundArguments
  Start-Process -FilePath PowerShell.exe -Verb Runas -ArgumentList $CommandLine
  Exit
 }
}

# Remainder of script here

Update: I've found that this won't maintain the current working directory after elevation.更新:我发现这不会在提升后维护当前的工作目录。

您在这里缺少 NoExit 参数。

Start-Process -Filepath "Powershell.exe" -ArgumentList "-NoExit -File "C:\myscript.ps1" -Credential $MyCredential 

This is merely an enhancement to @mbomb007's answer, cobbled together from other examples around the web and my own efforts to pass all<\/em> original arguments, with both named and positional parameters.这只是对@mbomb007 答案的增强,由网络上的其他示例和我自己努力传递所有<\/em>原始参数(包括命名参数和位置参数)拼凑而成。 Note that the added function does not encode special characters that may be used in the parameter values.请注意,添加的函数不会对参数值中可能使用的特殊字符进行编码。 Passing arguments is strangely absent from most posts.大多数帖子奇怪地没有传递论点。

function Pass-Parameters {
    Param ([hashtable]$NamedParameters)
    return ($NamedParameters.GetEnumerator()|%{"-$($_.Key) `"$($_.Value)`""}) -join " "
}

# Self-elevate the script if required
if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
 if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
  $CommandLine = "-File `"" + $MyInvocation.MyCommand.Path + "`" " + (Pass-Parameters $MyInvocation.BoundParameters) + " " + $MyInvocation.UnboundArguments
  Start-Process -FilePath PowerShell.exe -Verb Runas -ArgumentList $CommandLine
  Exit
 }
}

# Remainder of script here

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM