Running a command as Administrator using PowerShell?

后端 未结 26 2852
粉色の甜心
粉色の甜心 2020-11-22 09:41

You know how if you\'re the administrative user of a system and you can just right click say, a batch script and run it as Administrator without entering the administrator p

相关标签:
26条回答
  • 2020-11-22 10:01

    I have found a way to do this...

    Create a batch file to open your script:

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

    Then create a shortcut, on your desktop say (right click New -> Shortcut).

    Then paste this into the location:

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

    When first opening, you will have to enter your password once. This will then save it in the Windows credential manager.

    After this you should then be able to run as administrator without having to enter a administrator username or password.

    0 讨论(0)
  • 2020-11-22 10:03

    The problem with the @pgk and @Andrew Odri's answers is when you have script parameters, specially when they are mandatory. You can solve this problem using the following approach:

    1. The user right-clicks the .ps1 file and selects 'Run with PowerShell': ask him for the parameters through input boxes (this is a much better option than use the HelpMessage parameter attribute);
    2. The user executes the script through the console: allow him to pass the desired parameters and let the console force him to inform the mandatory ones.

    Here is how would be the code if the script had the ComputerName and Port mandatory parameters:

    [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
    
    0 讨论(0)
  • 2020-11-22 10:03

    Here is how to run a elevated powershell command and collect its output form within a windows batch file in a single command(i.e not writing a ps1 powershell script).

    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'
    

    Above you see i first launch a powershell with elevated prompt and then ask that to launch another powershell(sub shell) to run the command.

    0 讨论(0)
  • 2020-11-22 10:04

    You need to rerun the script with administrative privileges and check if the script was launched in that mode. Below I have written a script that has two functions: DoElevatedOperations and DoStandardOperations. You should place your code that requires admin rights into the first one and standard operations into the second. The IsRunAsAdmin variable is used to identify the admin mode.

    My code is an simplified extract from the Microsoft script that is automatically generated when you create an app package for Windows Store apps.

    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
    }
    
    0 讨论(0)
  • 2020-11-22 10:04

    This behavior is by design. There are multiple layers of security since Microsoft really didn't want .ps1 files to be the latest email virus. Some people find this to be counter to the very notion of task automation, which is fair. The Vista+ security model is to "de-automate" things, thus making the user okay them.

    However, I suspect if you launch powershell itself as elevated, it should be able to run batch files without requesting the password again until you close powershell.

    0 讨论(0)
  • 2020-11-22 10:04

    I am using the solution below. It handles stdout/stderr via transcript feature and passes exit code correctly to parent process. You need to adjust transcript path/filename.

    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
    
    0 讨论(0)
提交回复
热议问题