1

I created a java application(.jar) as a windows service using Procrun. This Service get installed and runs successfully when I use a batch(.bat) file. but I have this requirement of creating the same service using windows powerShell.

When I use PowerShell, service get installed but cannot start the service I checked in the windows event viewer and it displays as "Incorrect Function" Can anyone please tell me what could be the reason for this.

This is the string I used in PowerShell script to install the windows service

$CmdInstall=@'

--Description="$Description"
--DisplayName="$DisplayName"
--Install="$DAEMON"
--Startup=auto
--Type=
--DependsOn=
--Environment=
--User=
--Password=
--ServiceUser=
--ServicePassword=
--LibraryPath=
--JavaHome
--Jvm=auto
--JvmOptions=-Xmx1024M
--Classpath=server.jar
--JvmMs=
--JvmMx=
--JvmSs=
--StartMode=jvm
--StartImage=
--StartPath=
--StartClass=at.mrdevelopment.esl.server.Server
--StartMethod=main
--StartParams=
--StopMode=jvm
--StopImage=
--StopPath=
--StopClass=at.mrdevelopment.esl.server.ServerServiceStarter
--StopMethod=stop
--StopParams=
--StopTimeout=120
--LogPath=$LogPath
--LogPrefix=$InstanceName
--LogLevel=DEBUG
--LogJniMessages=
--StdOutput=auto
--StdError=auto
--PidFile=${InstanceName}.pid
'@

Any help would be appreciated.

This is the PowerShell script I used.

  #region Parameters
   [CmdletBinding(SupportsShouldProcess=$true)]
param(
   [ValidateNotNullOrEmpty()]
   [string]$Action="//IS"
   ,
   [ValidateNotNullOrEmpty()]
   [string]$ServiceName="//ESL_SERVICE"
   ,
   [ValidateNotNullOrEmpty()]
   [string]$DisplayName="ESL_SERVICE"
   ,
   [ValidateNotNullOrEmpty()]
   [string]$Description="ESL Service"
   ,
   [ValidateNotNullOrEmpty()]
   [string]$InstanceName="server.jar"
   ,
   [ValidateNotNullOrEmpty()]
   [string]$LogPath='C:\Apachelogs'
   ,
   [string]$Pause=60
)
#endregion

#region Main

$CmdInstall=@'

--Description="$Description"
--DisplayName="$DisplayName"
--Install="$DAEMON"
--Startup=auto
--Type=
--DependsOn=
--Environment=
--User=
--Password=
--ServiceUser=
--ServicePassword=
--LibraryPath=
--JavaHome
--Jvm=auto
--JvmOptions=-Xmx1024M
--Classpath=server.jar
--JvmMs=
--JvmMx=
--JvmSs=
--StartMode=jvm
--StartImage=
--StartPath=
--StartClass=at.mrdevelopment.esl.server.Server
--StartMethod=main
--StartParams=
--StopMode=jvm
--StopImage=
--StopPath=
--StopClass=at.mrdevelopment.esl.server.ServerServiceStarter
--StopMethod=stop
--StopParams=
--StopTimeout=120
--LogPath=$LogPath
--LogPrefix=$InstanceName
--LogLevel=DEBUG
--LogJniMessages=
--StdOutput=auto
--StdError=auto
--PidFile=${InstanceName}.pid
'@

$DAEMON_HOME         = "C:\imagotag\server"
$DAEMON              = "$DAEMON_HOME\prunsrv_64.exe"                                               
$ESL_HOME            = "C:\imagotag\server"  

$CmdArgsDict=@{}

$CmdArgsDict.Add('//IS',      "$Action$ServiceName $CmdInstall")

$CmdArgs             = $CmdArgsDict[$action]
# Convert backslashes in the paths to java-friendly forward slashes
$CmdArgs             = $CmdArgs -replace "\\","/"
# Variable interpolation: expand embedded variables references (need to call this twice)
$CmdArgs             = $ExecutionContext.InvokeCommand.ExpandString($CmdArgs)
$CmdArgs             = $ExecutionContext.InvokeCommand.ExpandString($CmdArgs)
# Split on newlines to convert to an array of lines
$CmdArgsString       = $CmdArgs -split "`n"
# Convert array of lines into a string
$CmdArgsString       = "$CmdArgsString"


#--- Execute the command
if ($PSCmdlet.ShouldProcess(
    "`n$DAEMON`n$CmdArgs","Manage ESL Service"
))
{
   "$DAEMON $CmdArgsString"

   $p=Start-Process "$DAEMON" `
         -ArgumentList "$CmdArgsString" `
         -Wait `
         -NoNewWindow `
         -PassThru

   $rc = $p.ExitCode
   "`nExit Code: $rc"
}
#endregion

My PowerShell script is TestPS.ps1 and I execute the script like this

.\TestPS.ps1 //IS
Compo
  • 36,585
  • 5
  • 27
  • 39
diyath.nelaka
  • 193
  • 14

2 Answers2

0

For creating a service , use the following cmdlet in PS:

$username = "Username"
$password = "password"
$secstr = New-Object -TypeName System.Security.SecureString
$password.ToCharArray() | ForEach-Object {$secstr.AppendChar($_)}
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $secstr

new-service -Name [INSERT SERVICE NAME] -DisplayName "[INSERT DISPLAY NAME]" -Description "[INSERT DESCRIPTION]" -BinaryPathName "[INSERT BINARY PATH]" -StartupType Manual -Credential $cred

If you wish to perform it remotely, then use the following function:

function Install-Service(
    [string]$serviceName = $(throw "serviceName is required"), 
    [string]$targetServer = $(throw "targetServer is required"),
    [string]$displayName = $(throw "displayName is required"),
    [string]$physicalPath = $(throw "physicalPath is required"),
    [string]$userName = $(throw "userName is required"),
    [string]$password = "",
    [string]$startMode = "Automatic",
    [string]$description = "",
    [bool]$interactWithDesktop = $false
)
{
    # can't use installutil; only for installing services locally
    #[wmiclass]"Win32_Service" | Get-Member -memberType Method | format-list -property:*    
    #[wmiclass]"Win32_Service"::Create( ... )        

    # todo: cleanup this section 
    $serviceType = 16          # OwnProcess
    $serviceErrorControl = 1   # UserNotified
    $loadOrderGroup = $null
    $loadOrderGroupDepend = $null
    $dependencies = $null

    # description?
    $params = `
        $serviceName, `
        $displayName, `
        $physicalPath, `
        $serviceType, `
        $serviceErrorControl, `
        $startMode, `
        $interactWithDesktop, `
        $userName, `
        $password, `
        $loadOrderGroup, `
        $loadOrderGroupDepend, `
        $dependencies `

    $scope = new-object System.Management.ManagementScope("\\$targetServer\root\cimv2", `
        (new-object System.Management.ConnectionOptions))
    "Connecting to $targetServer"
    $scope.Connect()
    $mgt = new-object System.Management.ManagementClass($scope, `
        (new-object System.Management.ManagementPath("Win32_Service")), `
        (new-object System.Management.ObjectGetOptions))

    $op = "service $serviceName ($physicalPath) on $targetServer"    
    "Installing $op"
    $result = $mgt.InvokeMethod("Create", $params)    
    Test-ServiceResult -operation "Install $op" -result $result
    "Installed $op"

    "Setting $serviceName description to '$description'"
    Set-Service -ComputerName $targetServer -Name $serviceName -Description $description
    "Service install complete"
}

Here is the Guide to Install Windows Service Remotely

Note: Make sure you are running everything with elevated mode.

Hope it helps.

Ranadip Dutta
  • 8,857
  • 3
  • 29
  • 45
0

Your problems came from a misconfigured service. That comes from a problem with the parameters of prunsrv.exe.

The script works well after changing the line

$CmdArgsString       = $CmdArgs -split "`n"

to

$CmdArgsString       = $CmdArgs -split "`r`n"