14

I've already read and tried various ways, but it just won't take it... I even tried to escape the spaces as well as trying to add extra quotes (escaped quotes) in front of the path...

$cmd = 'powershell.exe'
$dir = 'C:\Program Files (x86)\W T F'
$inner = "-NoExit -Command cd $dir"
$arguments = "Start-Process powershell -ArgumentList '$inner' -Verb RunAs"
& $cmd $arguments

It keeps giving me this:

x86 : The term 'x86' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the
spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:22
+ cd C:\Program Files (x86)\W T F
+                      ~~~
    + CategoryInfo          : ObjectNotFound: (x86:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

I tried with a different path, say C:\Blah\W T F it would still complaint about the spaces that are inside W T F.

Edit: Basically I needed to start an elevated powershell and then CD into my directory to run some post install script. But I am having a hard time CD into my directory, I was able to start my elevated powershell, but it always goes to c:\windows\system32.

Edit2:

$PSVersionTable

Name                           Value
----                           -----
PSVersion                      4.0
WSManStackVersion              3.0
SerializationVersion           1.1.0.1
CLRVersion                     4.0.30319.42000
BuildVersion                   6.3.9600.18728
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion      2.2

Edit3:

I have this script call load-ems.ps1 (to load Exchange Management Shell), and I'm trying to launch that shell as elevated. But my problem is that:

  1. the shell would start in system32 and won't find my scripts
  2. if i try to CD to my directory, i can't.
. ".\find-exchange.ps1"

$remoteexchangeps1 = Find-Exchange
$commands = @(
    ". '$remoteexchangeps1';",
    "Connect-ExchangeServer -auto -ClientApplication:ManagementShell;",
    ".\plugin-reinstall.ps1;"
)

$command = @($commands | % {$_})
powershell.exe -noexit -command "$command"

6
  • have you tried & "C:\Program Files (x86)\W T F" ? Jul 24, 2017 at 15:27
  • yes, & : The term 'C:\Program Files (x86)\W T F' is not recognized as the name of a cmdlet, Jul 24, 2017 at 15:32
  • What version of PowerShell is this
    – kazaamjt
    Jul 24, 2017 at 15:45
  • @kazaamjt Version 4, also updated my original question with the infomation. Jul 24, 2017 at 16:01
  • 1
    Use environment variable as $env:ProgramFiles(x86).
    – Biswapriyo
    Jul 24, 2017 at 17:18

6 Answers 6

10

You have to enclose the argument to CD in single quotes to preserve spaces. Use Start-Process directly to avoid too much interpolation of variables:

$cmd = 'powershell.exe'
$dir = 'C:\Program Files (x86)\W T F'
$inner = "-NoExit -Command cd '$dir'"
Start-Process $cmd -ArgumentList $inner -Verb RunAs
1

If it's exchange 2013, you could try instead:

$Credential = Get-Credential  
$Session = New-PSSession -ConfigurationName Microsoft.Exchange ` 
-ConnectionUri http://your.exchange.server/PowerShell/ -Credential $Credential
Import-PSSession $Session
1

With the comment from @matandra I modified my script a little and got what I wanted. I needed to wrap the path with ' single quote. Example: "cd '$pwd'"

I'm also posting my full script hope it can help others. I can now find and load the EMS then execute any additional commands that I need. Calling Load-EMS without arguments would just load the EMS for you (programatically, regardless which version of Exchange Server is installed, as long as is installed).

Yes, it does way more than what I originally asked for, but seeing this is the superuser forum, my script might help others:

<#
.SYNOPSIS
Find the Microsoft Exchange that is installed on the current machine

.DESCRIPTION
The function will go through the Windows Registry and try to locate 
the latest installed Microsoft Exchange instances on the current machine,
then locate the RemoteExchange.ps1 powershell script and return its location.

.EXAMPLE
Find-Exchange
C:\Program Files\Microsoft\Exchange Server\V15\bin\RemoteExchange.ps1
#>
function Find-Exchange() {
    $exchangeroot = "HKLM\SOFTWARE\Microsoft\ExchangeServer\"

    $allexchanges = Get-ChildItem -Path Registry::$exchangeroot -Name | Where-Object { $_ -match "^V.." }
    $sorted = $allexchanges | Sort-Object -descending

    If ($sorted.Count -gt 1) { $latest = $sorted[0] } Else { $latest = $sorted }

    $setup = $exchangeroot + $latest + "\Setup"

    $properties = Get-ItemProperty -Path Registry::$setup

    $installPath = $properties.MsiInstallPath

    $bin = $installPath + "bin"

    $remoteexchange = $bin + "\RemoteExchange.ps1"

    echo $remoteexchange
}

<#
.SYNOPSIS
Load Exchange Management Shell (EMS) and execute additional commands

.DESCRIPTION
The script loads the EMS and then execute commands you pass via $AdditionalCommands parameter

.EXAMPLE
Load-EMS -AdditionalCommands @("echo 'HELLO WORLD'", "Get-TransportAgent")  
#>
function Load-EMS($AdditionalCommands) {
    $pwd = (Get-Item -Path "." -verbose).FullName
    $remoteexchangeps1 = Find-Exchange

    # These commands are needed to load the EMS
    # We need to cd to the current directory because we will be starting a
    # brand new elevated powershell session, then we load the EMS script,
    # finally we connect to the exchange server after loading the EMS.
    [System.Collections.ArrayList] 
    $cmdchain = @(
        "cd '$pwd'"
        ". '$remoteexchangeps1'"
        "Connect-ExchangeServer -auto -ClientApplication:ManagementShell"
    )

    # We will also chain the commands passed by the user and run them too
    $cmdchain += $AdditionalCommands;

    # We combine all of the commands into a single line and pass it over
    # to the new elevated powershell session that we are about to launch
    $chained = @($cmdchain | % {"$_;"})
    $arguments = "-noexit -command $chained"

    # Launching the powershell
    Start-Process powershell.exe -Verb RunAs -ArgumentList $arguments
}
1

You can also use an alternative version of your path that doesn't have spaces in it. It's called a short name. It's from the DOS era but the functionality is still alive and well in Windows and PowerShell.

$cmd = 'powershell.exe'
$dir = 'C:\Program Files (x86)\W T F'

#Convert $dir to its short name equivalent
$dir=(New-Object -com scripting.filesystemobject).getFolder($dir).ShortPath

$inner = "-NoExit -Command cd $dir"
$arguments = "Start-Process powershell -ArgumentList '$inner' -Verb RunAs"
& $cmd $arguments

Note that I didn't have to change the quotes.

0

One work around I use is to change your working directory to the path that contains that problematic (x86), then do your Start-Process calls from there. Considering that %1 is the "C:\Program Files (x86)....\application.exe", you can do:

cd /d %~dp1
powershell.exe Start-Process '.\%~nx1' -Verb runAs
0

Another option is to use a script block as argument list:

Start-Process powershell -ArgumentList {
    -NoExit -Command cd 'C:\Program Files (x86)\W T F'
} -Verb RunAs

Some caveats are discussed here.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .