3

I can run this script perfectly from my desktop:

    private void Sleep_Click(object sender, EventArgs e)
    {
         PowerShell ps = PowerShell.Create();
         ps.AddScript(@"D:\Desktop\alllightsoff.ps1");
         ps.Invoke();
    }

But when i change the paths to program files it does nothing.. any ideas?

    private void Sleep_Click(object sender, EventArgs e)
    {
        PowerShell ps = PowerShell.Create();
        ps.AddScript(@"C:\Program Files (x86)\Home Control\alllightsoff.ps1");
        ps.Invoke();
    }

Has proberly something to do with permissions, the script doesnt needs admin rights to run, and when i manually run the ps1 script from the program folder is just works ok.

I even tried %AppData% folder and getting the same result, ps1 file doesnt run.

2
  • So i found out that c:\test\ works and c:\te st\ not, so it has something to do with the spaces, i need to find some replacement code for spaces in c# Commented Mar 10, 2018 at 11:13
  • 4
    AddScript -> AddCommand Commented Mar 10, 2018 at 11:22

1 Answer 1

7

PetSerAl has, as usual, provided the crucial pointer in a comment on the question:

  • Use .AddCommand() to add a command by name or executable / script-file path.

    • In you need to pass (named) arguments to that command, you would then have to use the .AddParameters() method - see example below; you can alternatively add them one by one, using .AddParameter() or, for positional arguments, .AddArgument()
  • By contrast, use the (poorly named) .AddScript() method to add a self-contained piece of PowerShell source code as a string, which is parsed into a script block (a better name for the method would therefore have been .AddScriptBlock()).

    • In you need to pass arguments, you would have to embed them directly in the source-code string - see example at the bottom.

Therefore, simply using .AddCommand() in lieu of .AddScript() is the solution:

ps.AddCommand(@"C:\Program Files (x86)\Home Control\scripts\alllightsoff.ps1");

If you wanted to pass an argument, say -Delay 60, you'd then call:

ps.AddParameter("Delay", 60);

// Alternative, via .AddParameters(), which allows you to 
// specify *multiple* arguments at once, by way of a dictionary.
ps.AddParameters(new Dictionary<string, int> { ["Delay"] = 60 });

In summary:

  • Use .AddCommand() to specify a single command to execute, and use methods to add arguments.

  • Use .AddScript() to specify a piece of PowerShell source code to execute.

While you can use .AddScript() as a more concise alternative to .AddCommand(), you need to be aware of PowerShell syntax and you'll incur PowerShell language-parsing overhead (though that probably won't matter in practice), and if you "bake" arguments into the PowerShell source-code string you pass, you're limited to argument types that have string-literal representations.[1]


Why .AddScript() didn't work:

Since you're passing a piece of PowerShell source code, the usual evaluation rules apply:

A file path with embedded spaces such as
C:\Program Files (x86)\Home Control\alllightsoff.ps1 needs quoting for the PowerShell parser to recognize it as a single argument.

However, once quoted, you must use &, the call operator, for PowerShell to know that the quoted path represents a command (script file) to invoke (otherwise, it would treat it as a string).

Hence, if you want to use .AddScript() in your case, you must use:

ps.AddScript(@"& 'C:\Program Files (x86)\Home Control\scripts\alllightsoff.ps1'");

Note the leading and the '...' around the file path.

If you wanted to pass an argument, say -Delay 60, you'd have to include it in the string:

ps.AddScript(
  @"& 'C:\Program Files (x86)\Home Control\scripts\alllightsoff.ps1' -Delay 60"
);

[1] Note, however, that you can use the .AddParameters(), .AddParameter() and .AddArgument() methods with .AddScript() too, which again allows you to pass arguments of arbitrary data types, this time to the script block that the source-code string is parsed into; however, the source code must then explicitly be designed to handle arguments, such as via a param(...) declaration or via the automatic $args variable.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.