http://qs321.pair.com?node_id=1206384


in reply to Error compiling script running powershell command

The powershell command runs from a cmd prompt fine

Did you manually try the command in a command prompt or a PowerShell prompt? There's a significant difference between two. That may or may not be a factor in your situation.

As far as I can tell, perl really ought to treat the "command" as a string and not attempt to compile it.

The contents inside of the backticks is interpolated by Perl. You can get more information by reading the documentation on Quote and Quote-like Operators. Based on the error message that you've provided, it looks like Perl is trying to interpolate PowerShell syntax (in particular your data type casting step) and is getting confused. If you follow Happy-the-monk's suggestion, that should fix that issue. However, I suspect that you've got bigger issues to deal with once you get past this issue. And those issues are with the PowerShell environment.

I think your biggest problem lies with the contents of your $un and $jpeg variables. Both variables contain a blank space and are intended to be used as input for PowerShell cmdlet options. When typing this in a PowerShell prompt, input strings with blanks need to be quoted.

Things get further complicated by the fact that your Perl script is calling the powershell.exe to run a PowerShell cmdlet. In that case, the full syntax of the PowerShell cmdlet needs to be inside double quotes. So if you want/need to use double quotes inside of the double quotes, now you need escape the inner double quotes. And the needed escape character will depend on the environment that's interpreting the string. In this case, its PowerShell's escape character that needs to be used and that character is the backtick. And that brings the next level of complication, which is using backticks within backticks.

My first thought is to just use PowerShell instead of trying to get Perl to call and use PowerShell. That will be a huge help in simplifying the quoting problem. My second thought would be to run the Perl script from a PowerShell prompt. Doing so allows Perl to directly call PowerShell cmdlets, which eliminates one level of quoting.

If you really want to use a command prompt to run a Perl script that calls PowerShell cmdlet, here's how I would approach it. Work on figuring out the syntax needed to properly use powershell.exe from a command prompt where the inputs to the PowerShell cmdlets need to be quoted due to blank spaces. Once you have that figured out, figure out how to build that syntax in Perl, store the entire command in a single variable and then use system instead of using backticks. If you need/want the output of the PowerShell command, consider using something like Capture::Tiny.

Here's two other suggestions that you can try. One route would be to write a new PowerShell script that takes two inputs (the AD user name and the image file path) and then have it do the actual PowerShell cmdlet (with the data type casting). Then the Perl script can call the new PowerShell script with a simpler syntax. Of course, you probably need to change the execution policy of your PowerShell environment (possibly to Remote Signed). An alternative suggestion would be to use a tool to bundle the new PowerShell script into an executable and have the Perl script call the executable. I personally have not done this myself, but have stumbled across free "tools" that claim to be able to do that.

As I think about what you're trying to do, I suspect that you'll hit yet another issue. Calling the powershell.exe lets you run PowerShell cmdlets from a command prompt, but the PowerShell cmdlet that you're trying to use (Set-ADUser) might not available by default. Instead, you might have to import the ActiveDirectory module in order to use that cmdlet. If I'm right about that, then your code isn't going to work as is. A simple modification to correct this would be to change Set-ADUser to Import-Module ActiveDirectory; Set-ADUser, which would import the needed module before running the desired cmdlet.