0

I wrote a script in PowerShell and I am having various success calling Image Magick's montage.exe on different computers. The computer on which I wrote the script has no problem executing the 'montage' command, however on another computer with IM Installed the script errors out:

montage : The term 'montage' 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 \\Server\Contact_Sheet_Local.ps1:51 char:9
+         montage -verbose -label %t -pointsize 20 -background '#FFFFFF ...
+         ~~~~~~~
+ CategoryInfo          : ObjectNotFound: (montage:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException

I have tried using montage.exe and even tried the entire path C:\Program Files\ImageMagick-7.0.3-Q16\montage.exe. Additionally I tried setting the directory first:

Set-Location -Path 'C:\Program Files\ImageMagick-7.0.3-Q16'
montage...

Each time on a particular computer this fails. I have tried with IM versions 7.0.3-Q16 and 6.9.1-6-Q8 both x64 as both computers are x64

In the past, I have created scripts in .bat that use ImageMagick and I had to define the full path to the .exe as I mentioned above. But this doesn't seem to help in PowerShell.

Does anyone have any advice or experience with this problem?

fmw42
  • 46,825
  • 10
  • 62
  • 80
Garrett
  • 617
  • 12
  • 30

2 Answers2

0

If your path has spaces, it will fail if you're just trying to execute based on that. You'll want to utilize the dot operator

$Exe = 'C:\Program Files\ImageMagick-6.9.1-6-Q8\montage.exe'
If (-not (Test-Path -Path $Exe))
{
    $Exe = 'C:\Program Files\ImageMagick-7.0.3-Q16\montage.exe'
}
. $Exe -arg1 -etc
Maximilian Burszley
  • 18,243
  • 4
  • 34
  • 63
  • Hello again and thanks for the advice @TheIncorrigible1. While I am sure this will work, I ended up finding that the error only occured in ISE, and that right clicking and running with PowerShell did not produce an error. I will keep the dot operator in mind as I am not previously familiar. Thanks! – Garrett Nov 14 '17 at 19:26
  • 1
    You should use `&` to invoke the executable, not `.` to dot-source it. (While this "works," it's not correct semantically speaking.) – Bill_Stewart Nov 14 '17 at 19:31
  • @Bill_Stewart What's your reasoning? – Maximilian Burszley Nov 14 '17 at 19:39
  • @Garrett That's due to where your script is executing. – Maximilian Burszley Nov 14 '17 at 19:41
  • 1
    Dot-sourcing affects scope and executes the following in the current scope instead of creating a new scope (which is the normal and default behavior of scripts). You should not dot-source unless you understand exactly what it does. (Read the `about_Scopes` documentation for details.) – Bill_Stewart Nov 14 '17 at 19:42
  • @Bill_Stewart Executing in a new scope causes issues with concurrency if you want something to execute after the exe completes. I do understand the difference, I wanted to see your reasoning. – Maximilian Burszley Nov 14 '17 at 19:42
  • 1
    If you do understand, then IMO it's not good to recommend it as a solution for this problem when we already have the `&` operator, which does not affect scope. Someone reading this answer might misunderstand the difference between the operators, use `.`, and create some odd problems for themselves. – Bill_Stewart Nov 14 '17 at 19:44
  • 1
    @TheIncorrigible1 *Executing in a new scope causes issues with concurrency if you want something to execute after the exe completes.* Using `.` vs `&` have no effect on `.exe` commands, because external commands have no understanding of PowerShell scopes. And I am agree with @Bill_Stewart: you should prefer `&` over `.` unless you really want dot source semantic. – user4003407 Nov 15 '17 at 00:35
  • @PetSerAl I quite agree; one should prefer the semantically correct operator. – Bill_Stewart Nov 15 '17 at 01:38
  • Thanks for all the great input everyone. – Garrett Nov 15 '17 at 17:08
0

PowerShell does not execute programs in the current directory by default. If you want to run an executable that's sitting in the current directory, prefix the executable's name with .\ or ./. Example:

Set-Location "C:\Program Files\ImageMagick-7.0.3-Q16"
.\montage.exe ...

If you have an executable's name in a string or string variable and you want to execute it, you can do so using the & (call or invocation) operator:

& "C:\Program Files\ImageMagick-7.0.3-Q16\montage.exe" ...

If you specify a path and filename that doesn't contain spaces, the & operator isn't required; example:

C:\ImageMagick\montage.exe ...

You could also write it this way:

& C:\ImageMagick\montage.exe ...

If you have an executable's filename in a string variable and you want to execute it, use &; example:

$execName = "C:\Program Files\ImageMagick-7.0.3-Q16\montage.exe"
& $execName ...
Bill_Stewart
  • 22,916
  • 4
  • 51
  • 62
  • This is all great info @Bill_Stewart . Thanks for the valuable input. – Garrett Nov 15 '17 at 17:10
  • @Garrett if you find an answer helpful it is customary to upvote it. – Bill_Stewart Nov 15 '17 at 17:41
  • Hi @Bill Stewart, I didn't end up using either provided solution as the issue was only occurring in ISE and running the PowerShell script provides the intended output. That said, I found the information you provided helpful and plan use this knowledge in the future. – Garrett Nov 17 '17 at 13:34
  • There is no functional difference in behavior between the console version of PowerShell and the ISE. – Bill_Stewart Nov 17 '17 at 13:37