¿Ejecuta un comando como administrador con PowerShell?


280

¿Sabes cómo si eres el usuario administrativo de un sistema y puedes hacer clic derecho en decir, un script por lotes y ejecutarlo como Administrador sin ingresar la contraseña de administrador?

Me pregunto cómo hacer esto con un script de PowerShell. No quiero tener que ingresar mi contraseña; Solo quiero imitar el método del botón derecho Ejecutar como administrador .

Todo lo que leí hasta ahora requiere que proporciones la contraseña de administrador.


Tratar gsudo. Un sudo de código abierto gratuito para Windows que permite ejecutar como administrador desde la línea de comandos. Aparecerá una ventana emergente UAC.
Gerardo Grignoli

Respuestas:


312

Si la consola actual no está elevada y la operación que está intentando realizar requiere privilegios elevados, puede iniciar PowerShell con la Run as administratoropción:

PS> Start-Process powershell -Verb runAs

1
Esa parece ser la única forma de hacerlo con éxito. Sin embargo, la ventana de shell agregada resulta problemática en muchos casos. Terminé configurando lo que sea que invocaba el script para que se ejecutara como administrador (por ejemplo, a través del registro).
Jacek Gorgoń

17
Esto abrirá una nueva consola en una ubicación diferente. ¿Hay alguna forma de ejecutarse como administrador en el directorio de trabajo actual?
Contenedor codificado

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


1
puede encontrar el documento aquí: docs.microsoft.com/en-us/powershell/module/… para el archivo .exe, los verbos pueden ser: Open, RunAs, RunAsUser
Kevin Xiong

115

Aquí hay una adición a la sugerencia de Shay Levi (solo agregue estas líneas al comienzo de un guión):

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
}

Esto da como resultado que el script actual se pase a un nuevo proceso de PowerShell en modo Administrador (si el Usuario actual tiene acceso al modo Administrador y el script no se inicia como Administrador).


66
Esto funcionó para mí:if (-not (([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)))
G. Lombard

Se modifica fácilmente para arrojar un error cuando no se ejecuta como administrador. Simplemente tome la ifdeclaración y coloque throwdentro del bloque then.
jpmc26

2
El comentario de @ G.Lombard tuvo un sutil error de sintaxis. Esto es lo que funcionó para mí:if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))
angularsen

La única sintaxis que funcionó para mí está en la publicación original, no la de G.Lombard ni otras áreas
Nicolas Mommaerts

2
Estoy de acuerdo con el uso de enum value ( [Security.Principal.WindowsBuiltInRole]::Administrator)) debería preferirse al argumento de cadena "Administrator"- Encontré entornos reforzados de seguridad con roles incorporados renombrados
eXavier

104

Script de PowerShell autoelevante

Windows 8.1 / PowerShell 4.0 +

Una línea :)

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

145
bueno, técnicamente hablando, todo es "una línea" si está formateado de esa manera, pero eso no lo hace real "una línea"
inmigrante ilegal

3
Inconveniente: si ingresa un usuario que no es administrador en la solicitud, termina en un bucle de salida de horquilla sin fin.
Manuel Faux

3
pero esto no pasa
argumentos

2
Para pasar args, lo modifiqué a: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
Esta respuesta no conserva el directorio de trabajo. Vea aquí uno que sí: stackoverflow.com/a/57035712/2441655
Venryx

45

Benjamin Armstrong publicó un excelente artículo sobre scripts de PowerShell de elevación automática . Hay algunos problemas menores con su código; A continuación se incluye una versión modificada basada en las correcciones sugeridas en el comentario.

Básicamente obtiene la identidad asociada con el proceso actual, comprueba si es un administrador y, si no lo es, crea un nuevo proceso de PowerShell con privilegios de administrador y finaliza el proceso anterior.

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

No estaba resolviendo el nombre del script y los parámetros correctamente, así que terminé la ejecución en cmd.exe / c $newProcess = new-object System.Diagnostics.ProcessStartInfo “cmd.exe” $newProcess.Arguments = ‘/c ‘ + [System.Environment]::GetCommandLineArgs() $newProcess.WorkingDirectory = [environment]::CurrentDirectory
xverges

¿Hay alguna ventaja de hacerlo así en lugar de Start-Process? Tengo curiosidad por las diferencias, entre este método y los otros publicados anteriormente y en otros hilos. Ambos confían en .NET, pero este método es más ...
ZaxLofful

También encontré que varios comentarios asociados con el enlace directo a la publicación de Armstrong (oración inicial de esta publicación) son muy útiles.
BentChainRing

2
Esta respuesta no conserva el directorio de trabajo. Vea aquí uno que sí: stackoverflow.com/a/57035712/2441655
Venryx

22

Puede crear un archivo por lotes ( *.bat) que ejecuta su script de PowerShell con privilegios administrativos cuando se hace doble clic. De esta manera, no necesita cambiar nada en su script de PowerShell . Para hacer esto, cree un archivo por lotes con el mismo nombre y ubicación de su script de PowerShell y luego coloque el siguiente contenido:

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

¡Eso es!

Aquí está la explicación:

Suponiendo que su script de PowerShell esté en la ruta C:\Temp\ScriptTest.ps1, su archivo por lotes debe tener la ruta C:\Temp\ScriptTest.bat. Cuando alguien ejecuta este archivo por lotes, se producirán los siguientes pasos:

  1. El cmd ejecutará el comando

    powershell -Command "Start-Process powershell \"-ExecutionPolicy Bypass -NoProfile -NoExit -Command `\"cd \`\"C:\Temp\`\"; & \`\".\ScriptTest.ps1\`\"`\"\" -Verb RunAs"
  2. Se abrirá una nueva sesión de PowerShell y se ejecutará el siguiente comando:

    Start-Process powershell "-ExecutionPolicy Bypass -NoProfile -NoExit -Command `"cd \`"C:\Temp\`"; & \`".\ScriptTest.ps1\`"`"" -Verb RunAs
  3. Se abrirá otra nueva sesión de PowerShell con privilegios administrativos en la system32carpeta y se le pasarán los siguientes argumentos:

    -ExecutionPolicy Bypass -NoProfile -NoExit -Command "cd \"C:\Temp\"; & \".\ScriptTest.ps1\""
  4. El siguiente comando se ejecutará con privilegios administrativos:

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

    Una vez que la ruta de la secuencia de comandos y los argumentos de nombre están entre comillas dobles, pueden contener espacios o comillas simples ( ').

  5. La carpeta actual cambiará de system32a C:\Tempy ScriptTest.ps1se ejecutará el script . Una vez que -NoExitse pasó el parámetro , la ventana no se cerrará, incluso si su script de PowerShell arroja alguna excepción.


Si hago esto, aparece una ventana emergente que me pregunta si permito que PowerShell realice cambios en mi sistema. Esto lo hace inutilizable para la automatización.
John Slegers

@ JohnSlegers, si necesita automatizarlo, es su responsabilidad asegurarse de que el proceso automatizado se ejecute como administrador. Si pudiera elevar automáticamente un proceso que no sea de administrador a un proceso de administrador sin interacción del usuario, eso anularía el propósito de requerir que un proceso tenga privilegios de administrador en primer lugar.
meustrus

@meustrus: Como ingeniero de lanzamiento , mi trabajo consiste en crear y mantener procesos de compilación que se ejecutan de forma totalmente automática, ya sea periódicamente o cuando se cumplen ciertos criterios. Algunos de estos procesos necesitan privilegios de administrador, y requerir la entrada del usuario hace que un proceso sea inutilizable en este contexto. - En Linux, puede lograr esto utilizando el sudocomando y configurando el usuario que utiliza para el proceso automatizado NOPASSWD: ALLen el sudoersarchivo .
John Slegers

1
Esta es una mejor respuesta que las otras porque conserva el directorio de trabajo.
Aquí reuní

17

Aquí hay un fragmento de elevación automática para los scripts de Powershell que conserva el directorio de trabajo :

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

Preservar el directorio de trabajo es importante para los scripts que realizan operaciones relativas a la ruta. Casi todas las otras respuestas no conservan esta ruta, lo que puede causar errores inesperados en el resto del script.

Si prefiere no usar un script / fragmento autoelevante y, en cambio, solo desea una manera fácil de iniciar un script como administrador (por ejemplo, desde el menú contextual del Explorador), vea mi otra respuesta aquí: https: // stackoverflow .com / a / 57033941/2441655


16

Utilizando

#Requires -RunAsAdministrator

no ha sido declarado, todavía. Parece estar allí solo desde PowerShell 4.0.

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

Cuando este parámetro de cambio se agrega a su declaración require, especifica que la sesión de Windows PowerShell en la que está ejecutando el script debe iniciarse con derechos de usuario elevados (Ejecutar como administrador).

Para mí, esta parece ser una buena manera de hacerlo, pero todavía no estoy seguro de la experiencia de campo. Los tiempos de ejecución de PowerShell 3.0 probablemente ignoren esto o, lo que es peor, den un error.

Cuando el script se ejecuta como no administrador, se produce el siguiente error:

El script 'StackOverflow.ps1' no se puede ejecutar porque contiene una instrucción "#requires" para ejecutarse como Administrador. La sesión actual de Windows PowerShell no se ejecuta como Administrador. Inicie Windows PowerShell utilizando la opción Ejecutar como administrador y luego intente ejecutar el script nuevamente.

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

77
Desafortunadamente, todo lo que hace es hacer que el script falle con un error si el shell no tiene privilegios de administrador. No se eleva por sí mismo.
Jacek Gorgoń

PS3 parece dar un error como se sugiere. Consigo Parameter RunAsAdministrator requires an argument. @akauppi No estoy convencido de que siempre estén pensando.
jpmc26

14

Puede agregar fácilmente algunas entradas de registro para obtener un menú contextual "Ejecutar como administrador" para los .ps1archivos:

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

(actualizado a un script más simple de @Shay)

Básicamente al HKCR:\Microsoft.PowershellScript.1\Shell\runas\commandestablecer el valor predeterminado para invocar el script usando Powershell.


No funciona, está creando una clave '(predeterminada)', no está actualizando el valor de la clave '(predeterminada)'. Pude condensar el código en una línea que funciona para mí. ¿Puedes probarlo? 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 - Hola Shay, gracias por actualizar uno. He actualizado la respuesta con ella. Funciona Pero el que yo también había trabajado, aunque era detallado. No había hecho mucha edición de registro con Powershell, pero hacerlo con "(predeterminado)" era algo que había visto como ejemplo. No creó una nueva clave (que sería algo predeterminado) pero actualizó la clave predeterminada como se esperaba. ¿Lo probaste o simplemente lo adivinaste (default)?
manojlds

Lo intenté. Creó una clave '(predeterminada)' debajo de la tecla de comando.
Shay Levy

Esto funcionó para mí después de algunos cambios menores en el valor del registro: "c: \ windows \ system32 \ windowspowershell \ v1.0 \ powershell.exe" -ExecutionPolicy RemoteSigned -NoExit "& '% 1'"
MikeBaz - MSFT

1
El valor del registro en la respuesta tiene todo tipo de problemas. En realidad, no ejecuta el comando y no cita correctamente el nombre del script (lo que significa que se rompe en las rutas con espacios). Estoy usando con éxito lo siguiente:"c:\windows\system32\windowspowershell\v1.0\powershell.exe" -noexit -command "& '%1'"
Kal Zekdor

10

El código publicado por Jonathan y Shay Levy no funcionó para mí.

Encuentre el código de trabajo a continuación:

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
Solución muy útil y práctica: solo la perpendí a mi script y funciona.
CDuv

3
@Abatonime ¿Qué tal si señala diferencias fáciles de perder para el beneficio de sus lectores? Honestamente, ese cambio no vale más que un comentario sobre la otra respuesta.
jpmc26

8

Debe volver a ejecutar el script con privilegios administrativos y verificar si el script se inició en ese modo. A continuación, he escrito un script que tiene dos funciones: DoElevatedOperations y DoStandardOperations . Debe colocar su código que requiere derechos de administrador en el primero y las operaciones estándar en el segundo. La variable IsRunAsAdmin se usa para identificar el modo administrador.

Mi código es un extracto simplificado del script de Microsoft que se genera automáticamente cuando crea un paquete de aplicaciones para las aplicaciones de la Tienda Windows.

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

Agregando mis 2 centavos. Mi versión simple basada en la sesión de red que funciona todo el tiempo hasta ahora en Windows 7 / Windows 10. ¿Por qué complicarlo más?

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

simplemente agregue a la parte superior de la secuencia de comandos y se ejecutará como administrador.


1
¿Hay alguna forma de enviar un mensaje al usuario después de que se muestre "Acceso denegado"?
ycomp

... o para evitar el mensaje
Günter Zöchbauer

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

obteniendo errores para esto,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>, puede establecerlo en bypass Pero bypasspuede ser peligroso. ConfigurarloAllSigned
AliFurkan

5

Este comportamiento es por diseño. Hay varias capas de seguridad, ya que Microsoft realmente no quería que los archivos .ps1 fueran el último virus de correo electrónico. Algunas personas consideran que esto es contrario a la noción de automatización de tareas, lo cual es justo. El modelo de seguridad de Vista + es "des-automatizar" las cosas, haciendo que el usuario las apruebe.

Sin embargo, sospecho que si inicia powershell en sí mismo como elevado, debería poder ejecutar archivos por lotes sin solicitar la contraseña nuevamente hasta que cierre powershell.


5

También puede forzar que la aplicación se abra como administrador, si tiene una cuenta de administrador, por supuesto.

ingrese la descripción de la imagen aquí

Localice el archivo, haga clic con el botón derecho> propiedades> Acceso directo> Avanzado y marque Ejecutar como administrador

Luego haga clic en Aceptar.


1
¿Cómo se escribe esto?
Dieter

4

C:\Users\"username"\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Windows PowerShelles donde reside el acceso directo de PowerShell. También sigue yendo a una ubicación diferente para invocar el 'exe' real (%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe ).

Dado que PowerShell está controlado por el perfil de usuario cuando se trata de permisos; si su nombre de usuario / perfil tiene los permisos para hacer algo, entonces bajo ese perfil, en PowerShell generalmente también podrá hacerlo. Dicho esto, tendría sentido que altere el acceso directo ubicado debajo de su perfil de usuario, por ejemplo,C:\Users\"username"\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Windows PowerShell ,.

Haga clic derecho y haga clic en propiedades. Haga clic en el botón "Avanzado" debajo de la pestaña "Acceso directo" ubicada justo debajo del campo de texto "Comentarios" adyacente a la derecha de otros dos botones, "Abrir ubicación de archivo" y "Cambiar icono", respectivamente.

Marque la casilla de verificación que dice "Ejecutar como administrador". Haga clic OK, luego Applyy OK. Una vez más, haga clic derecho en el icono etiquetado 'Windows PowerShell' ubicado en C:\Users\"username"\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Windows PowerShelly seleccione "Anclar al menú Inicio / Barra de tareas".

Ahora, cada vez que haga clic en ese icono, invocará el UAC para escalar. Después de seleccionar 'SÍ', notará que la consola de PowerShell se abre y se etiquetará como "Administrador" en la parte superior de la pantalla.

Para ir un paso más allá ... puede hacer clic con el botón derecho en el mismo acceso directo de icono en la ubicación de su perfil de Windows PowerShell y asignar un acceso directo de teclado que hará exactamente lo mismo que si hiciera clic en el icono agregado recientemente. Entonces, donde dice "Atajo de teclado", coloque una combinación de tecla / teclado como: Ctrl+ Alt+ P P(para PowerShell) . Haga clic ApplyyOK .

Ahora todo lo que tiene que hacer es presionar la combinación de botones que asignó y verá que se invoca UAC, y después de seleccionar 'SÍ' verá aparecer una consola PowerShell y se mostrará "Administrador" en la barra de título.


Amigo :) ¡La palabra clave en la pregunta de OP es scripting! No es una solución de clic de mouse UI.
Cristiano

3

He encontrado una manera de hacer esto ...

Cree un archivo por lotes para abrir su script:

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

Luego cree un acceso directo, en su escritorio, por ejemplo (haga clic con el botón derecho en Nuevo -> Acceso directo ).

Luego pegue esto en la ubicación:

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

Cuando abra por primera vez, deberá ingresar su contraseña una vez. Esto lo guardará en el administrador de credenciales de Windows.

Después de esto, debería poder ejecutarse como administrador sin tener que ingresar un nombre de usuario o contraseña de administrador.


/ savecred no es seguro!
Nathan Goings

Esta es la única solución que no utiliza la solicitud de elevación gráfica que podría no ser accesible en una sesión remota.
DustWolf

3

El problema con las respuestas de @pgk y @Andrew Odri es cuando tienes parámetros de script, especialmente cuando son obligatorios. Puede resolver este problema utilizando el siguiente enfoque:

  1. El usuario hace clic con el botón derecho en el archivo .ps1 y selecciona 'Ejecutar con PowerShell': pregúntele los parámetros a través de los cuadros de entrada (esta es una opción mucho mejor que usar el mensaje de ayuda parámetro );
  2. El usuario ejecuta el script a través de la consola: permítale pasar los parámetros deseados y deje que la consola lo obligue a informar los obligatorios.

Así es como sería el código si el script tuviera los parámetros obligatorios ComputerName y 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

Algunas de las respuestas aquí están cerca, pero un poco más de trabajo de lo necesario.

Cree un acceso directo a su script y configúrelo para "Ejecutar como administrador":

  • Crea el atajo.
  • Atajo con el botón derecho y abrir Properties...
  • Editar Targetde <script-path>apowershell <script-path>
  • Haga clic Advanced...y habiliteRun as administrator

2

Otra solución más simple es que también puede hacer clic derecho en "C: \ Windows \ System32 \ cmd.exe" y elegir "Ejecutar como administrador", luego puede ejecutar cualquier aplicación como administrador sin proporcionar ninguna contraseña.


2

Estoy usando la solución a continuación. Maneja stdout / stderr mediante la función de transcripción y pasa el código de salida correctamente al proceso padre. Necesita ajustar la ruta de transcripción / nombre de archivo.

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

Esto pierde todos los argumentos de invocación
Guillermo Prandi

2

Aquí se explica cómo ejecutar un comando powershell elevado y recopilar su formulario de salida dentro de un archivo por lotes de Windows en un solo comando (es decir, no escribir un script de 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'

Como se ve arriba, primero lanzo un PowerShell con un mensaje elevado y luego le pido que inicie otro PowerShell (Sub Shell) para ejecutar el comando.


1

Además de la respuesta de Shay Levy, siga la configuración a continuación (solo una vez)

  1. Inicie un PowerShell con derechos de administrador.
  2. Siga la pregunta de desbordamiento de pila PowerShell dice que "la ejecución de scripts está deshabilitada en este sistema". .
  3. Coloque su archivo .ps1 en cualquiera de las PATHcarpetas, por ejemplo. Carpeta Windows \ System32

Después de la configuración:

  1. Presione Win+R
  2. Invocar powershell Start-Process powershell -Verb runAs <ps1_file>

Ahora puede ejecutar todo en una sola línea de comando. Lo anterior funciona en Windows 8 Basic de 64 bits.


1

La forma más confiable que he encontrado es envolverlo en un archivo .bat de elevación automática:

@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

El .bat comprueba si ya eres administrador y relanza el script como Administrador si es necesario. También evita que se abran ventanas "cmd" extrañas con el cuarto parámetro de ShellExecute()set to 0.


Buena respuesta, pero lo intenté y no funcionó (y salí de la línea de comando desde la que lo llamé). Lo arreglé de esta manera: cambié el primero EXITa GOTO :EOFay eliminé el segundo. Además, se cd %~dp0debe cd /d %~dp0Y colocar el primer comando después de @echo off. De esta manera, tampoco necesita la ruta absoluta de la .ps1, simplemente colóquela en la misma carpeta que la .bat. Si necesita ver el resultado, cambie el cuarto parámetro a 1.
cdlvcdlv

¿Qué O / S y versión estás ejecutando?
Joe Coder

Windows 7 SP1 Ultimate. Tengo un sistema en C: pero también aplicaciones de datos y portátiles en D: principalmente (y varias otras unidades). Por cierto ... ¿y si el programa / script usa parámetros? ¿Cuál sería el mshtacomando?
cdlvcdlv

Creo que puede haber cometido un error en sus pruebas, porque el script funciona bien. Por cierto, está diseñado para salir del cmdproceso de llamada , de modo que eso no lo "arregle", pero me alegra que haya podido modificarlo según sus necesidades.
Joe Coder

Ok si quieres salir de cmd(no lo hice). Pero con respecto a los otros cambios, creo que son correcciones porque mi versión funcionaría para ambos mientras que la suya no lo hace para mí, es decir, la mía es más general (aborde el escenario de diferentes unidades). De todos modos, un enfoque muy inteligente.
cdlvcdlv

0

No he visto mi propia forma de hacerlo antes, así que prueba esto. Es mucho más fácil de seguir y tiene una huella mucho más pequeña:

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

De manera muy simple, si la sesión actual de Powershell se llamó con privilegios de administrador, el conocido SID del grupo de administradores aparecerá en los grupos cuando tome la identidad actual. Incluso si la cuenta es miembro de ese grupo, el SID no aparecerá a menos que el proceso se invoque con credenciales elevadas.

Casi todas estas respuestas son una variación del método inmensamente popular de Ben Armstrong de Microsoft sobre cómo lograrlo sin comprender realmente lo que realmente está haciendo y cómo emular la misma rutina.


0

Para agregar la salida del comando a un nombre de archivo de texto que incluye la fecha actual, puede hacer algo como esto:

$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

Esta es una aclaración ...

La credencial PowerShell RUNAS / SAVECRED "no es segura", la probó y agrega la identidad de administrador y la contraseña en el caché de credenciales y se puede usar en cualquier otro lugar. Si ha hecho esto, le sugiero que verifique y elimine la entrada.

Revise su programa o código porque la política de Microsoft es que no puede mezclar código de usuario y administrador en el mismo blob de código sin el UAC (el punto de entrada) para ejecutar el programa como administrador. Esto sería sudo (lo mismo) en Linux.

El UAC tiene 3 tipos, no ver, un aviso o un punto de entrada generado en el manifiesto del programa. No eleva el programa, por lo que si no hay UAC y necesita administrador, fallará. Sin embargo, el UAC como requisito de administrador es bueno, evita la ejecución de código sin autenticación y evita que el escenario de códigos mixtos se ejecute a nivel de usuario.


Esto debería ser un comentario, no es una solución a la pregunta (solo la forma en que funciona el foro; su contenido es útil, pero no es una solución).
bgmCoder

-2

Resulta que fue demasiado fácil. Todo lo que tiene que hacer es ejecutar un cmd como administrador. Luego escriba explorer.exey presione enter. Eso abre el Explorador de Windows . Ahora haga clic derecho en el script de PowerShell que desea ejecutar, elija "Ejecutar con PowerShell", que lo ejecutará en PowerShell en modo administrador.

Es posible que le pida que habilite la política para ejecutarse, escriba Y y presione enter. Ahora el script se ejecutará en PowerShell como administrador. En caso de que se ejecute todo en rojo, eso significa que su política aún no entró en vigencia. Luego intente nuevamente y debería funcionar bien.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.