Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Powershell Invoke-Expression mangling command

Tags:

powershell

I am trying to invoke a command from a powershell script. The command works fine when run from a normal command line. Here is the full command (sorry, it's long, but if I truncate it I'm afraid I might leave out something significant.)

C:\Users\Dave.Work\Desktop\wix36-binaries\candle.exe C:\Users\Dave.Work\Developer\MapCreator\install\win\product.wxs -arch x64 -dPlatform=x64 -dProductVersion=0.9.1.0 -dKarteReleaseBinDir=C:\Users\Dave.Work\Developer\MapCreator\karte-build-release\release -out C:\Users\Dave.Work\Developer\MapCreator\install\win\obj\

If I invoke this exact same command using Invoke-Expression, it fails. It gives an error from the executable (candle.exe), but since it works fine from the command line, the problem is clearly that powershell is mangling the string somehow. Here is my call:

Invoke-Expression 'C:\Users\Dave.Work\Desktop\wix36-binaries\candle.exe C:\Users\Dave.Work\Developer\MapCreator\install\win\product.wxs -arch x64 -dPlatform=x64 -dProductVersion=0.9.1.0 -dKarteReleaseBinDir=C:\Users\Dave.Work\Developer\MapCreator\karte-build-release\release -out C:\Users\Dave.Work\Developer\MapCreator\install\win\obj\'

This results in the following error from candle.exe:

candle.exe : error CNDL0103 : The system cannot find the file '.9.1.0' with type 'Source'.

Somehow the numeric version number is getting mangled? Again, it works fine from a command line.

How to I pass this command to Powershell?

[NOTE] Ultimately, this command is generated from variables, i.e. the actual command will be something like:

$WixDir\candle.exe $ScriptDir\product.wxs -arch $Platform -dPlatform=$Platform -dProductVersion=$ProductVersion -dKarteReleaseBinDir=$KarteReleaseBinDir -out $ScriptDir\obj\

I'm using Invoke-Expression because I was having major problems expanding the variables using, for example, the call operator. But I can't get it to work even without the variable expansion. Thus, if the solution is to escape certain parts of the command string, I would need to also know how to apply those escapes to variables.

like image 913
Dave Mateer Avatar asked Jun 21 '26 09:06

Dave Mateer


1 Answers

Try "-dProductVersion=0.9.1.0" enclosed with " or with '. My Get-Arg utility shows that the original command is parsed so that -dProductVersion=0 and .9.1.0 are different arguments.

Just in case, my Get-Arg.exe is (C#):

using System;
class GetArg
{
    static void Main(string[] args)
    {
        foreach(string s in args)
        {
            Console.WriteLine(s);
        }
    }
}

It is useful for checking such cases.


There is even simpler illustration. This code

function Get-Argument {
    $args
}

Get-Argument -dProductVersion=0.9.1.0

gets this output:

-dProductVersion=0
.9.1.0

That is PowerShell treats such a command as having two arguments.


Explanation

In PowerShell 2 0 Language Specification we can see for parameters

parameter-char:
Any Unicode character except
{   }   (   )   ;   ,   |   &   .   [
colon
whitespace
new-line-character

Note: '=' is included, '.' is excluded. In our case we have

-dProductVersion=0.9.1.0

According to the specification all characters before '.' are valid parameter characters. So we get, the first result argument is -dProductVersion=0

Then parser chokes at '.'. Technically, it looks like we do something against the rules including '.' into the argument that starts with '-'. That is why we should enclose the whole argument with ' or ".

This is probably true for the other excluded characters as well.

like image 165
Roman Kuzmin Avatar answered Jun 24 '26 15:06

Roman Kuzmin