34

I want to invoke sc create from a powershell script. Here is the code.

function Execute-Command
{
    param([string]$Command, [switch]$ShowOutput=$True)
    echo $Command
    if ($ShowOutput) {
        Invoke-Expression $Command
    } else {
        $out = Invoke-Expression $Command
    }
}

$cmd="sc create `"$ServiceName`" binpath=`"$TargetPath`" displayname=`"$DisplayName`" "
Execute-Command -Command:$cmd

which gives the following error:

Set-Content : A positional parameter cannot be found that accepts argument 'binpath=...'.
At line:1 char:1

What is the problem? What are positional arguments?

mklement0
  • 382,024
  • 64
  • 607
  • 775
gyozo kudor
  • 6,284
  • 10
  • 53
  • 80
  • 13
    As the error tells you, `sc` is an alias for `Set-Content`. Use the full filename `sc.exe` – Mathias R. Jessen Nov 18 '15 at 14:22
  • 3
    From PS4 on, you can use the `New-Service` cmdlet https://technet.microsoft.com/en-us/library/hh849830(v=wps.630).aspx – sodawillow Nov 18 '15 at 14:25
  • As an aside: Using script blocks (`{ ... }`) is the preferred way to pass commands as arguments; [`Invoke-Expression` should be avoided](https://blogs.msdn.microsoft.com/powershell/2011/06/03/invoke-expression-considered-harmful/). – mklement0 Oct 26 '18 at 12:59

3 Answers3

78

The issue here is not with the sc executable. As the error states, sc resolves to Set-Content. If you issue Get-Alias -Name sc, you'll see:

gal sc

To bypass the alias, use the full name of the executable (including the file extension):

PS C:\> sc.exe query wuauserv

SERVICE_NAME: wuauserv
        TYPE               : 20  WIN32_SHARE_PROCESS
        STATE              : 4  RUNNING
                                (STOPPABLE, NOT_PAUSABLE, ACCEPTS_PRESHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0

You might want to use the -f operator when constructing your command line arguments, to avoid those annoying quote-escaping back ticks all over the place:

$CmdLine = 'sc.exe create "{0}" binpath= "{1}" displayname= "{2}" ' -f $ServiceName,$TargetPath,$DisplayName
Execute-Command -Command $CmdLine
Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
0

The exact command worked for me from a simple Command Prompt console while it fails on PowerShell and VS Code Integrated Terminal. In fact, all sc commands had to be run from Command Prompt as Administrator.

sc create MyService binPath= "C:\svc\sampleapp.exe"
sc start MyService
Michael
  • 8,362
  • 6
  • 61
  • 88
Si Zi
  • 1,109
  • 10
  • 6
0

I know Mathias's script works fine, but there is a reason that it would work and the one posted by Gyozo did not. It has to do with a gotcha in sc.exe.

The space after the equals in binPath and displayName are NOT optional.

For me this snippet would not work:

$cmd="sc create `"$ServiceName`" binpath=`"$TargetPath`" displayname=`"$DisplayName`" "

However this one would:

$cmd="sc create `"$ServiceName`" binpath= `"$TargetPath`" displayname= `"$DisplayName`" "

This issue continues to rise up every once in a while to vex me until I remember this.

Ed Ajaz
  • 11
  • 1