Esegui un comando come amministratore usando PowerShell?


280

Sai come se sei l'utente amministrativo di un sistema e puoi semplicemente fare clic con il pulsante destro del mouse, dire uno script batch ed eseguirlo come amministratore senza inserire la password dell'amministratore?

Mi chiedo come farlo con uno script di PowerShell. Non voglio inserire la mia password; Voglio solo imitare il tasto destro del mouse Esegui come amministratore .

Tutto ciò che ho letto finora richiede di fornire la password dell'amministratore.


Prova gsudo. Un sudo open source gratuito per Windows che consente di eseguire come amministratore dalla riga di comando. Apparirà un pop-up UAC.
Gerardo Grignoli,

Risposte:


312

Se la console corrente non è elevata e l'operazione che si sta tentando di eseguire richiede privilegi elevati, è possibile avviare PowerShell con l' Run as administratoropzione:

PS> Start-Process powershell -Verb runAs

1
Questo sembra essere l'unico modo per farlo con successo. Tuttavia, la finestra della shell aggiunta si rivela problematica in molti casi. Ho finito per configurare qualunque cosa stesse invocando lo script per essere eseguito come admin (ad es. Tramite il registro).
Jacek Gorgoń,

17
Questo aprirà una nuova console in una posizione diversa. C'è un modo per eseguire come amministratore nella directory di lavoro corrente?
Contenitore codificato

11
start-process -verb runAs "<cmd>" -argumentlist "<args1> <args2>";)
Dev Anand Sadasivam


1
puoi trovare il documento qui: docs.microsoft.com/en-us/powershell/module/… per il file .exe, i verbi possono essere: Open, RunAs, RunAsUser
Kevin Xiong

114

Ecco un'aggiunta al suggerimento di Shay Levi (basta aggiungere queste righe all'inizio di una sceneggiatura):

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
}

Ciò comporta che lo script corrente venga passato a un nuovo processo PowerShell in modalità Amministratore (se l'utente corrente ha accesso alla modalità Amministratore e lo script non viene avviato come Amministratore).


6
Questo ha funzionato per me:if (-not (([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)))
G. Lombard,

Facilmente modificato per generare un errore quando non viene eseguito come amministratore. Basta prendere la ifdichiarazione e inserire un throwblocco allora.
jpmc26,

2
Il commento di @G.Lombard ha avuto un sottile errore di sintassi. Questo è ciò che ha funzionato per me:if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))
angularsen,

L'unica sintassi che ha funzionato per me è nel post originale, non quello di G.Lombard né anjdreas
Nicolas Mommaerts,

2
Sono d'accordo che l'uso di enum value ( [Security.Principal.WindowsBuiltInRole]::Administrator)) dovrebbe essere preferito all'argomento stringa "Administrator"- ho riscontrato ambienti con protezione
avanzata

104

Script PowerShell con elevazione automatica

Windows 8.1 / PowerShell 4.0 +

Una linea :)

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

144
bene, tecnicamente parlando, tutto è "una riga" se formattato in quel modo, ma ciò non lo rende effettivo "una riga"
immigrato clandestino

3
Svantaggio: se si inserisce un non amministratore nel prompt, si termina in un ciclo infinito di fork-exit.
Manuel Faux,

3
ma questo non passa args
kyb

2
Per passare args, l'ho modificato in:if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`" `"$args`"" -Verb RunAs; exit }
ab.

2
Questa risposta non conserva la directory di lavoro. Vedi qui per uno che fa:
stackoverflow.com/a/57035712/2441655

45

Benjamin Armstrong ha pubblicato un eccellente articolo sugli script PowerShell auto-elevanti . C'è qualche piccolo problema con il suo codice; una versione modificata basata sulle correzioni suggerite nel commento è di seguito.

Fondamentalmente ottiene l'identità associata al processo corrente, controlla se si tratta di un amministratore e, in caso contrario, crea un nuovo processo PowerShell con privilegi di amministratore e termina il processo precedente.

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

Non riuscivo a risolvere correttamente il nome dello script e i parametri, quindi ho eseguito l'esecuzione in cmd.exe / c $newProcess = new-object System.Diagnostics.ProcessStartInfo “cmd.exe” $newProcess.Arguments = ‘/c ‘ + [System.Environment]::GetCommandLineArgs() $newProcess.WorkingDirectory = [environment]::CurrentDirectory
xverges il

C'è qualche vantaggio nel farlo in questo modo invece di Start-Process? Sono curioso delle differenze, tra questo metodo e gli altri pubblicati sopra e su altri thread. Entrambi si basano su .NET, ma questo metodo più pesantemente ...
ZaxLofful

Ho trovato molto utili anche vari commenti associati al collegamento diretto al post di Armstrong (frase iniziale di questo post).
BentChainRing

2
Questa risposta non conserva la directory di lavoro. Vedi qui per uno che fa:
stackoverflow.com/a/57035712/2441655

22

È possibile creare un file batch ( *.bat) che esegue lo script PowerShell con privilegi di amministratore quando si fa doppio clic. In questo modo, non è necessario modificare nulla nello script PowerShell . A tale scopo, creare un file batch con lo stesso nome e posizione dello script PowerShell e quindi inserire il seguente contenuto:

@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"

Questo è tutto!

Ecco la spiegazione:

Supponendo che lo script PowerShell sia nel percorso C:\Temp\ScriptTest.ps1, il file batch deve avere il percorso C:\Temp\ScriptTest.bat. Quando qualcuno esegue questo file batch, si verificheranno i seguenti passaggi:

  1. Il cmd eseguirà il comando

    powershell -Command "Start-Process powershell \"-ExecutionPolicy Bypass -NoProfile -NoExit -Command `\"cd \`\"C:\Temp\`\"; & \`\".\ScriptTest.ps1\`\"`\"\" -Verb RunAs"
  2. Si aprirà una nuova sessione di PowerShell e verrà eseguito il seguente comando:

    Start-Process powershell "-ExecutionPolicy Bypass -NoProfile -NoExit -Command `"cd \`"C:\Temp\`"; & \`".\ScriptTest.ps1\`"`"" -Verb RunAs
  3. Un'altra nuova sessione di PowerShell con privilegi di amministratore si aprirà nella system32cartella e gli verranno passati i seguenti argomenti:

    -ExecutionPolicy Bypass -NoProfile -NoExit -Command "cd \"C:\Temp\"; & \".\ScriptTest.ps1\""
  4. Il seguente comando verrà eseguito con privilegi di amministratore:

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

    Una volta che il percorso dello script e gli argomenti dei nomi sono racchiusi tra virgolette doppie, possono contenere spazio o caratteri di virgoletta singola ( ').

  5. La cartella corrente cambierà da system32a C:\Tempe lo script ScriptTest.ps1verrà eseguito. Una volta -NoExitpassato il parametro , la finestra non verrà chiusa, anche se lo script PowerShell genera qualche eccezione.


Se lo faccio, visualizzo un popup che mi chiede se autorizzo PowerShell a modificare il mio sistema. Ciò lo rende inutilizzabile per l'automazione.
John Slegers,

@JohnSlegers, se è necessario automatizzarlo, è responsabilità dell'utente assicurarsi che il processo automatizzato venga eseguito come amministratore. Se potessi elevare automaticamente un processo non amministrativo a un processo amministrativo senza l'interazione dell'utente, ciò annullerebbe in primo luogo lo scopo di richiedere a un processo i privilegi di amministratore.
Meustrus,

@meustrus: In qualità di ingegnere del rilascio , il mio lavoro prevede la creazione e il mantenimento di processi di compilazione che vengono eseguiti in modo completamente automatico, periodicamente o quando vengono soddisfatti determinati criteri. Alcuni di questi processi richiedono privilegi di amministratore e la richiesta di input da parte dell'utente rende un processo inutilizzabile in questo contesto. - In Linux, è possibile ottenere ciò utilizzando il sudocomando e configurando l'utente che si utilizza per il processo automatizzato con NOPASSWD: ALLnel sudoersfile .
John Slegers,

1
Questa è una risposta migliore delle altre perché conserva la directory di lavoro. Ho messo insieme un po 'di una riga le varianti di questo approccio qui (uno per cmd / lotti, uno per Explorer voci del menu contestuale, e uno per PowerShell): stackoverflow.com/a/57033941/2441655
Venryx

17

Ecco uno snippet auto-elevante per gli script Powershell che conserva la directory di lavoro :

if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
    Start-Process PowerShell -Verb RunAs "-NoProfile -ExecutionPolicy Bypass -Command `"cd '$pwd'; & '$PSCommandPath';`"";
    exit;
}

# Your script here

La conservazione della directory di lavoro è importante per gli script che eseguono operazioni relative al percorso. Quasi tutte le altre risposte non conservano questo percorso, che può causare errori imprevisti nel resto dello script.

Se preferisci non utilizzare uno script / snippet con elevazione automatica e desideri invece un modo semplice per avviare uno script come amministratore (ad es. Dal menu contestuale di Explorer), vedi la mia altra risposta qui: https: // stackoverflow .com / a / 57033941/2441655


16

utilizzando

#Requires -RunAsAdministrator

non è stato ancora dichiarato. Sembra esserci solo da PowerShell 4.0.

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

Quando questo parametro switch viene aggiunto alla tua richiesta richiede, specifica che la sessione di Windows PowerShell in cui stai eseguendo lo script deve essere avviata con diritti utente elevati (Esegui come amministratore).

Per me, questo sembra un buon modo di procedere, ma non sono ancora sicuro dell'esperienza sul campo. I runtime di PowerShell 3.0 probabilmente ignorano questo, o peggio ancora, danno un errore.

Quando lo script viene eseguito come non amministratore, viene visualizzato il seguente errore:

Lo script 'StackOverflow.ps1' non può essere eseguito perché contiene un'istruzione "#requires" per l'esecuzione come amministratore. L'attuale sessione di Windows PowerShell non è in esecuzione come amministratore. Avviare Windows PowerShell utilizzando l'opzione Esegui come amministratore, quindi provare a eseguire nuovamente lo script.

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

7
Sfortunatamente tutto ciò che fa è far fallire lo script con un errore se la shell non ha privilegi di amministratore. Non si eleva da solo.
Jacek Gorgoń,

PS3 sembra dare un errore come suggerito. Ho capito Parameter RunAsAdministrator requires an argument. @akauppi Non sono convinto che stiano sempre pensando.
jpmc26,

14

È possibile aggiungere facilmente alcune voci di registro per ottenere un menu di scelta rapida "Esegui come amministratore" per i .ps1file:

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"'

(aggiornato a uno script più semplice da @Shay)

Fondamentalmente a HKCR:\Microsoft.PowershellScript.1\Shell\runas\commandimpostare il valore predefinito per invocare lo script utilizzando Powershell.


Non funziona, stai creando una chiave "(predefinita)", non aggiornando il valore della chiave "(predefinita)". Sono stato in grado di condensare il codice in un one-liner che funziona per me. Puoi provarlo? New-Item -Path "Registro :: HKEY_CLASSES_ROOT \ Microsoft.PowershellScript.1 \ Shell \ runas \ command" -Force -Name '' -Value '"c: \ windows \ system32 \ windowspowershell \ v1.0 \ powershell.exe" -noexit "% 1" '
Shay Levy

@Shay Levy - Ciao Shay, grazie per l'aggiornamento. Ho aggiornato la risposta con esso. Funziona Ma anche quello su cui avevo lavorato, sebbene fosse prolisso. Non avevo fatto molte modifiche al reg con Powershell, ma farlo con "(predefinito)" era qualcosa che avevo visto come esempio. Non ha creato una nuova chiave (che avrebbe qualcosa di simile al default) ma ha aggiornato la chiave predefinita come previsto. Hai provato o hai indovinato dalla (default)parte?
manojlds,

L'ho provato. Ha creato una chiave '(predefinita)' sotto la chiave di comando.
Shay Levy,

Questo ha funzionato per me dopo alcune piccole modifiche al valore del registro: "c: \ windows \ system32 \ windowspowershell \ v1.0 \ powershell.exe" -ExecutionPolicy RemoteSigned -NoExit "& '% 1'"
MikeBaz - MSFT

1
Il valore di registro nella risposta presenta tutti i tipi di problemi. In realtà non esegue il comando e non cita correttamente il nome dello script (nel senso che si interrompe su percorsi con spazi). Sto usando con successo quanto segue:"c:\windows\system32\windowspowershell\v1.0\powershell.exe" -noexit -command "& '%1'"
Kal Zekdor il

10

Il codice pubblicato da Jonathan e Shay Levy non ha funzionato per me.

Di seguito trovi il codice di lavoro:

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"

2
Soluzione molto utile e pratica: l'ho semplicemente inserita nella mia sceneggiatura e funziona.
CDuv,

3
@Abatonime Che ne dici di sottolineare facilmente le differenze a vantaggio dei tuoi lettori? Onestamente, quel cambiamento non vale più di un commento sull'altra risposta.
jpmc26,

8

È necessario rieseguire lo script con privilegi di amministratore e verificare se lo script è stato avviato in quella modalità. Di seguito ho scritto uno script che ha due funzioni: DoElevatedOperations e DoStandardOperations . È necessario inserire il codice che richiede i diritti di amministratore nel primo e le operazioni standard nel secondo. La variabile IsRunAsAdmin viene utilizzata per identificare la modalità amministratore.

Il mio codice è un estratto semplificato dallo script Microsoft che viene generato automaticamente quando si crea un pacchetto di app per le app di Windows Store.

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
}

7

Aggiungendo i miei 2 centesimi. La mia versione semplice basata sulla sessione di rete che funziona fino ad ora in Windows 7 / Windows 10. Perché complicarla?

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

basta aggiungere nella parte superiore dello script e verrà eseguito come amministratore.


1
c'è un modo per mettere un messaggio all'utente dopo che viene visualizzato "Accesso negato"?
ycomp

... o per evitare del tutto il messaggio
Günter Zöchbauer,

1
@ GünterZöchbauer if (!(net session 2>&1 | Out-Null)) { ... @ycomp ... } else { echo "your message" }.
Matthieu,

ottenere errori per questo,cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policies at https:/go.microsoft.com/fwlink/?LinkID=135170.
user2305193

1
@ user2305193 Set-ExecutionPolicy -ExecutionPolicy <PolicyName>, è possibile impostarlo su bypass Ma bypasspotrebbe essere pericoloso. Impostalo suAllSigned
AliFurkan il

5

Questo comportamento è in base alla progettazione. Esistono diversi livelli di sicurezza poiché Microsoft non voleva che i file .ps1 fossero l'ultimo virus di posta elettronica. Alcuni ritengono che ciò sia contrario al concetto stesso di automazione delle attività, che è giusto. Il modello di sicurezza di Vista + consiste nel "disautomatizzare" le cose, rendendo così l'utente a posto.

Tuttavia, sospetto che se avvii PowerShell stesso come elevato, dovrebbe essere in grado di eseguire file batch senza richiedere nuovamente la password fino alla chiusura di PowerShell.


5

Puoi anche forzare l'apertura dell'applicazione come amministratore, ovviamente se disponi di un account amministratore.

inserisci qui la descrizione dell'immagine

Individua il file, fai clic con il pulsante destro del mouse> proprietà> Collegamento> Avanzate e seleziona Esegui come amministratore

Quindi fare clic su OK.


1
Come si scrive questo?
Dieter,

4

C:\Users\"username"\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Windows PowerShellè dove risiede il collegamento di PowerShell. Anche troppo va in una posizione diversa per invocare l'effettivo 'exe' ( %SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe).

Poiché PowerShell è guidato dal profilo utente quando si tratta di autorizzazioni; se il tuo nome utente / profilo ha i permessi per fare qualcosa, allora sotto quel profilo, in PowerShell potresti anche farlo. Detto questo, avrebbe senso che tu modifichi il collegamento situato sotto il tuo profilo utente, ad esempio C:\Users\"username"\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Windows PowerShell.

Fare clic con il tasto destro e selezionare Proprietà. Fai clic sul pulsante "Avanzate" nella scheda "Scorciatoia" situata proprio sotto il campo di testo "Commenti" adiacente alla destra di altri due pulsanti, "Apri posizione file" e "Cambia icona", rispettivamente.

Seleziona la casella di controllo "Esegui come amministratore". Fare clic OK, quindi Applye OK. Ancora una volta fai clic destro sull'icona "Windows PowerShell" situata in C:\Users\"username"\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Windows PowerShelle seleziona "Aggiungi al menu Start / Barra delle applicazioni".

Ora, ogni volta che fai clic su quell'icona, invoca l' UAC per l'escalation. Dopo aver selezionato 'SÌ', noterai che la console di PowerShell è aperta e verrà etichettata "Amministratore" nella parte superiore dello schermo.

Per fare un ulteriore passo avanti ... puoi fare clic con il tasto destro del mouse sulla stessa scorciatoia icona nella posizione del tuo profilo di Windows PowerShell e assegnare una scorciatoia da tastiera che farà esattamente la stessa cosa che se avessi fatto clic sull'icona aggiunta di recente. Quindi, dove si dice "Tasto di scelta rapida" inserire una combinazione tasto / tasto della tastiera come: Ctrl+ Alt+ P P(per PowerShell) . Clicca Applye OK.

Ora tutto ciò che devi fare è premere la combinazione di pulsanti che hai assegnato e vedrai UAC essere invocato, e dopo aver selezionato 'SÌ' vedrai apparire una console di PowerShell e "Amministratore" nella barra del titolo.


Amico :) La parola chiave nella domanda di OP è lo scripting !! Non una soluzione per il clic del mouse dell'interfaccia utente.
Christian,

3

Ho trovato un modo per farlo ...

Crea un file batch per aprire lo script:

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

Quindi creare un collegamento, dire sul desktop (fare clic con il pulsante destro del mouse su Nuovo -> Collegamento ).

Quindi incollalo nella posizione:

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

Alla prima apertura, dovrai inserire la password una volta. Questo lo salverà quindi nel gestore delle credenziali di Windows.

Successivamente, dovresti essere in grado di eseguire come amministratore senza dover inserire un nome utente o una password dell'amministratore.


/ savecred non è sicuro!
Nathan Goings,

Questa è l'unica soluzione che non utilizza il prompt grafico di elevazione che potrebbe non essere accessibile in una sessione remota.
DustWolf,

3

Il problema con le risposte di @pgk e @Andrew Odri è quando si hanno parametri di script, specialmente quando sono obbligatori. È possibile risolvere questo problema utilizzando il seguente approccio:

  1. L'utente fa clic con il pulsante destro del mouse sul file .ps1 e seleziona "Esegui con PowerShell": chiedigli i parametri tramite le caselle di input (questa è un'opzione molto migliore rispetto all'uso dell'attributo del parametro HelpMessage );
  2. L'utente esegue lo script tramite la console: consentigli di passare i parametri desiderati e consenti alla console di obbligarlo a informare quelli obbligatori.

Ecco come sarebbe il codice se lo script avesse i parametri obbligatori ComputerName e 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

3

Alcune risposte qui sono vicine, ma un po 'più di lavoro del necessario.

Crea un collegamento al tuo script e configuralo su "Esegui come amministratore":

  • Crea il collegamento.
  • Tasto di scelta rapida e aprire Properties...
  • Modifica Targetda <script-path>apowershell <script-path>
  • Fai clic Advanced...e abilitaRun as administrator

2

Un'altra soluzione più semplice è che puoi anche fare clic destro su "C: \ Windows \ System32 \ cmd.exe" e scegliere "Esegui come amministratore", quindi puoi eseguire qualsiasi app come amministratore senza fornire alcuna password.


2

Sto usando la soluzione qui sotto. Gestisce stdout / stderr tramite la funzione di trascrizione e passa correttamente il codice di uscita al processo padre. Devi regolare il percorso / nome file della trascrizione.

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

Questo perde tutti gli argomenti di invocazione
Guillermo Prandi,

2

Ecco come eseguire un comando PowerShell elevato e raccogliere il suo modulo di output all'interno di un file batch di Windows in un singolo comando (ovvero non scrivere uno script PowerShell PS1).

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'

Sopra vedi prima lancio una PowerShell con prompt elevato e poi chiedo di lanciare un'altra PowerShell (sottothell) per eseguire il comando.


1

In cima alla risposta di Shay Levy, segui la seguente configurazione (solo una volta)

  1. Avviare una PowerShell con diritti di amministratore.
  2. Segui la domanda Stack Overflow PowerShell afferma che "l'esecuzione degli script è disabilitata su questo sistema". .
  3. Inserisci il tuo file .ps1 in una delle PATHcartelle, ad esempio. Cartella Windows \ System32

Dopo l'installazione:

  1. Premi Win+R
  2. Invocare powershell Start-Process powershell -Verb runAs <ps1_file>

Ora puoi eseguire tutto in una sola riga di comando. Quanto sopra funziona su Windows 8 Basic a 64 bit.


1

Il modo più affidabile che ho trovato è di avvolgerlo in un file .bat auto-elevante:

@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

Il .bat verifica se sei già amministratore e riavvia lo script come amministratore, se necessario. Impedisce inoltre l'apertura di finestre "cmd" estranee con il 4o parametro di ShellExecute()set su 0.


Buona risposta, ma l'ho provato e non ha funzionato (ed è uscito dalla riga di comando da cui l'ho chiamato). Ho risolto in questo modo: ho cambiato il primo EXITin a GOTO :EOFed eliminato il secondo. Inoltre, cd %~dp0dovrebbe essere cd /d %~dp0AND inserito il primo comando dopo il @echo off. In questo modo non è necessario il percorso assoluto di .ps1entrambi, basta inserirlo nella stessa cartella che il file .bat. Se è necessario visualizzare il risultato, modificare il quarto parametro in 1.
cdlvcdlv,

Quale O / S e versione stai utilizzando?
Joe Coder,

Windows 7 SP1 Ultimate. Ho un sistema in C: ma anche dati e applicazioni portatili in D: principalmente (e molte altre unità). A proposito ... cosa succede se il programma / script utilizza i parametri? Quale sarebbe il mshtacomando?
cdlvcdlv,

Penso che potresti aver sbagliato nei tuoi test, perché lo script funziona bene. A proposito, è progettato per uscire dal cmdprocesso di chiamata in modo che non lo "risolva", ma sono contento che tu sia stato in grado di modificarlo in base alle tue esigenze.
Joe Coder,

Ok se vuoi uscire da cmd(non l'ho fatto). Ma per quanto riguarda le altre modifiche, penso che siano correzioni perché la mia versione funzionerebbe per entrambi mentre la tua non funziona per me, vale a dire la mia è più generale (affronta lo scenario di diverse unità). Comunque, un approccio molto intelligente.
cdlvcdlv,

0

Non ho mai visto il mio modo di farlo prima, quindi provalo. È molto più facile da seguire e ha un'impronta molto più piccola:

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

Molto semplicemente, se l'attuale sessione di Powershell è stata chiamata con i privilegi di amministratore, il noto SID del gruppo di amministratori verrà visualizzato nei gruppi quando si acquisisce l'identità corrente. Anche se l'account è un membro di quel gruppo, il SID non verrà visualizzato a meno che il processo non sia stato invocato con credenziali elevate.

Quasi tutte queste risposte sono una variazione del metodo immensamente popolare di Microsoft Ben Armstrong su come realizzarlo senza cogliere realmente ciò che sta realmente facendo e come altrimenti emulare la stessa routine.


0

Per aggiungere l'output del comando a un nome file di testo che include la data corrente, puoi fare qualcosa del genere:

$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 }

0

Questo è un chiarimento ...

La credenziale RUNAS / SALVATA PowerShell "non è sicura", l'ha provata e aggiunge l'identità e la password dell'amministratore nella cache delle credenziali e può essere utilizzata altrove OOPS !. Se lo hai fatto ti suggerisco di controllare e rimuovere la voce.

Rivedi il tuo programma o codice perché, secondo la politica di Microsoft, non puoi avere un codice utente e amministratore misto nello stesso BLOB di codice senza l'UAC (il punto di ingresso) per eseguire il programma come amministratore. Questo sarebbe sudo (stessa cosa) su Linux.

Il controllo dell'account utente ha 3 tipi, non vedere, un prompt o un punto di ingresso generato nel manifest del programma. Non eleva il programma, quindi se non c'è UAC e ha bisogno di amministrazione fallirà. Il controllo dell'account utente sebbene sia un requisito di amministratore buono, impedisce l'esecuzione di codice senza autenticazione e impedisce l'esecuzione dello scenario di codici misti a livello di utente.


Questo dovrebbe essere un commento, non è una soluzione alla domanda (solo il modo in cui funziona il forum; il tuo contenuto è utile, ma non è una soluzione).
bgmCoder

-2

Si scopre che era troppo facile. Tutto quello che devi fare è eseguire un cmd come amministratore. Quindi digitare explorer.exee premere invio. Questo apre Windows Explorer . Ora fai clic con il pulsante destro del mouse sullo script di PowerShell che desideri eseguire, scegli "esegui con PowerShell" che lo avvierà in PowerShell in modalità amministratore.

Potrebbe essere necessario abilitare l'esecuzione del criterio, digitare Y e premere invio. Ora lo script verrà eseguito in PowerShell come amministratore. Nel caso in cui sia tutto rosso, ciò significa che la tua politica non ha ancora avuto effetto. Quindi riprovare e dovrebbe funzionare correttamente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.