Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

One problem leads to another! User help just fixed one issue, which led to another as I continued working on this script. My script runs a check to see if the current user is an Administrator as follows:

If (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{   
$arguments = "& '" + $myinvocation.mycommand.definition + "'" + $loc
Start-Process powershell -Verb runAs -ArgumentList $arguments
Break
}

The argument for $loc is a parameter that was originally passed via a batch file that is as follows:

@setlocal enableextensions
@cd /d "%~dp0"
SET current="%~dp0
START /WAIT powershell.exe -ExecutionPolicy Bypass -File "JavaInstall.ps1" -loc %current%

At the top of the Powershell file, we have:

param(
[string]$loc
)

This works under two conditions:

1) The user is already an Administrator.
2) The folder this is run from at any point in the traversing does not have a space.

When this is run from a folder such as: C:\Users\User\Desktop\Java Test it suddenly fails. If I Write-Host along the way, I can see that the $loc variable is correct until after the elevation. After it elevates, anything after the space is lost. If I run this directly as an Administrator it of course bypasses the elevation and works even with spaces in the folders, but I do not want to require a right-click run-as scenario. Any ideas what might be causing the loss of text after the space during elevation?

share|improve this question
    
For the paths with spaces problem, it might be because you're missing a closing quote in this line SET current="%~dp0 –  Ƭᴇcʜιᴇ007 Apr 28 '14 at 20:25
    
What's odd is that anything but a single quote in that spot causes it to cut off anything with spaces even before elevation. I may be using that command incorrectly to begin with though, as that seems odd. –  Tim P. Apr 28 '14 at 20:29
    
Maybe just ditch the quotes on that line, and instead wrap %current% with them (in the START line of the batch). –  Ƭᴇcʜιᴇ007 Apr 28 '14 at 20:32
    
Why are you starting the batch script in the first place? Can you not just call Powershell directly with the correct permissions? –  Zoredache Apr 28 '14 at 20:36
    
I thought to run a Powershell script on another computer it was necessary to set the ExecutionPolicy, given we do not have the certifications in place and given the default behavior of Powershell. –  Tim P. Apr 28 '14 at 20:53

1 Answer 1

You're dealing with multiple command line parsing here, that's why it's hard to make it work properly. You have to have quotes around your path with spaces when it passed to the PowerShell (from the bat file) and when it passed from the Powershell (to the Start-Process cmdlet). This means some serious escaping:

  1. Remove trailing backslash from the %~dp0, or it will mess with with escaping in P.2
  2. Escape quotes with backslash (\) for the START command because of the way the C command line parser works:

    A double quotation mark preceded by a backslash, \",
    is interpreted as a literal double quotation mark (").

  3. Escape quotes in the PowerShell when using Start-Process cmdlet

    1. For the -File parameter:

      "`"$($MyInvocation.MyCommand.Path)`""
      
    2. For the $Loc argument:

      "\`"$Loc\`""
      

Example below works for me and keeps the path with spaces intact while self-elevating.

Bat launcher :

SETLOCAL EnableExtensions

:: Get current directory
SET current=%~dp0

:: Does "current" variable have a trailing slash? If so, remove it
IF %current:~-1%==\ SET current=%current:~,-1%

cd /d %current%

START /WAIT powershell.exe -ExecutionPolicy Bypass -File "JavaInstall.ps1" -Loc \""%current%\""

PowerShell elevation code:

Param(
    [string]$Loc
)

$Delay = 5
Write-Host "`$Loc argument: $Loc"

if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(
        [Security.Principal.WindowsBuiltInRole] 'Administrator')
)
{
    Write-Host "Not elevated, restarting in $Delay seconds ..."
    Start-Sleep -Seconds $Delay

    $Arguments =  @(
        '-NoProfile',
        '-NoExit',
        '-File',
        "`"$($MyInvocation.MyCommand.Path)`"",
        "\`"$Loc\`""
    )
    Start-Process -FilePath PowerShell.exe -Verb RunAs -ArgumentList $Arguments
    Break
}
else
{
    Write-Host "Already elevated, exiting in $Delay seconds..."
    Start-Sleep -Seconds $Delay
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.