cEprsCreateWindowsService.psm1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
enum Ensure
{
    Absent
    Present
}
<#
This resource manages a particular windows service in a specific path.
[DscResource()] indicates the class is a DSC resource
#>


[DscResource()]
class cEprsCreateWindowsService
{
[DscProperty(Key)]
[string]$ServiceName 

<#
    This parameter takes the name of the windows service.
 
    The [DscProperty(Key)] attribute indicates the property is a key and its value uniquely identifies a resource instance. Defining this attribute also means the property is required and DSC will ensure a value is set before calling the resource.
 
    A DSC resource must define at least one key property.
#>


[DscProperty(Mandatory)]
[string]$BinaryPath 

<#
    This parameter takes the physical path of windows service.
 
    The [DscProperty(Key)] attribute indicates the property is a key and its value uniquely identifies a resource instance. Defining this attribute also means the property is required and DSC will ensure a value is set before calling the resource.
 
    A DSC resource must define at least one key property.
#>


[DscProperty(Key)]
[string]$ExeName 
<#
    This property takes the name of exe that should run the windows service.
 
    The [DscProperty(Mandatory)] attribute indicates the property is required and DSC will guarantee it is set.
 
    If Mandatory is not specified or if it is defined as Mandatory=$false, the value is not guaranteed to be set when DSC calls the resource.
 
    This is appropriate for optional properties.
 
#>


[DscProperty(Mandatory=$false)]
[string]$Description 
<#
    This value gives the descripion about the windows service.
 
    The [DscProperty(Mandatory=$false)] attribute indicates the property is not guaranteed to be set when DSC calls the resource.
 
#>


[DscProperty(Mandatory=$true)]
[string]$DisplayName 
<#
 
    This property would display the value as Name of the service.
 
    The [DscProperty(Mandatory=$false)] attribute indicates the property is not guaranteed to be set when DSC calls the resource.
 
#>

[DscProperty(Mandatory)]
[ValidateSet("Automatic","Disabled","Manual")]
[string]$StartupType
<#
    This property takes startup type of service(Automatic\Disbaled\Manual).
 
    The [DscProperty(Mandatory)] attribute indicates the property is required and DSC will guarantee it is set.
 
    If Mandatory is not specified or if it is defined as Mandatory=$false, the value is not guaranteed to be set when DSC calls the resource.
 
    This is appropriate for optional properties.
#>


[DscProperty(Mandatory=$false)]
[String]$Domain 
<#
    Property takes the value for Account Domain to run the service on. This is an optional property but it should be provided if logon account type is custom.
#>


[DscProperty(Mandatory=$false)]
[String]$UserName 
<#
    Property takes the UserName for the service to run on. This is an optional property but it should be provided if logon account type is custom.
#>


[DscProperty(Mandatory=$false)]
[String]$Password 
<#
    Property takes the Password for the user account given. This is an optional property but it should be provided if logon account type is custom.
#>


[DscProperty(Mandatory)]
[ValidateSet("Custom","LocalSystem")]
[String]$LogOnAccount 
<#
     
    This property takes the value for type of logon account(Custom or LocalSystem) the service would run on. If Custom type is passed then Domain, username and password should be given.
 
    The [DscProperty(Mandatory)] attribute indicates the property is required and DSC will guarantee it is set.
 
    If Mandatory is not specified or if it is defined as Mandatory=$false, the value is not guaranteed to be set when DSC calls the resource.
 
    This is appropriate for optional properties.
 
#>

[DscProperty(Mandatory)]
[ValidateSet("Absent","Present")][Ensure]$Ensure #Ensure value(Give Present for install and Absent for uninstall)


<#
    This method is equivalent of the Get‐TargetResource script function.
    The implementation should use the keys to find appropriate resources.
    This method returns an instance of this class with the updated key properties.
#>


[cEprsCreateWindowsService] Get()
{
    $Service = Get-WmiObject win32_service | where {$_.name -eq $this.ServiceName} -ErrorAction Ignore
    if($service)
    {
        $this.Ensure = [Ensure]::Present
        $this.DisplayName = $Service.DisplayName
        $this.ServiceName = $Service.Name
        $this.UserName = $Service.StartName
    }
    else
    {
        $this.Ensure = [Ensure]::Absent
    }
    return $this
}

<#
    This method is equivalent of the Set‐TargetResource script function.
    It sets the resource to the desired state.
#>


[void] Set()
{
    $filePresent = $this.TestFilePath("$($this.BinaryPath)\$($this.ExeName)")
    if($this.Ensure -eq [Ensure]::Present)
    {
        if($filePresent -eq $true)
        {
            if($this.LogOnAccount -eq "Custom")
            {
                if(!$this.Domain -or !$this.UserName -or !$this.Password)
                {
                    Write-Verbose "pass 'Domain','UserName' and 'Password' parameters for setting up custom account as logon for windows service."
                    exit 1 
                }
            }
            Write-Verbose "Creating windows service '$($this.ServiceName)' $(Get-Date)"
            
            if($this.Description -eq "" -or $null)
            {
                New-Service -Name "$($this.ServiceName)" -BinaryPathName "$($this.BinaryPath)\$($this.ExeName)" -DisplayName "$($this.DisplayName)" -StartupType $this.StartupType
            }
            else
            {
                New-Service -Name "$($this.ServiceName)" -BinaryPathName "$($this.BinaryPath)\$($this.ExeName)" -DisplayName "$($this.DisplayName)" -Description "$($this.Description)" -StartupType $this.StartupType
            }
            if($this.LogOnAccount -eq "Custom")
            {
                $this.UserName=$this.Domain+"\"+ $this.UserName
            }

            $Services = Get-WmiObject win32_service -property name, startname, caption, state | Where-Object { $_.name -eq "$($this.ServiceName)"}
            if($this.UserName -eq "LocalSystem")
            {
                $Services.Change($null,$null,$null,$null,$null,$null, "LocalSystem", $null)
            }
            elseif($this.UserName -eq "NT Authority\Network Service")
            {
                $Services.Change($null,$null,$null,$null,$null,$null, "NT Authority\Network Service", $null)
            }
            else
            {
                $Services.Change($null,$null,$null,$null,$null,$null, $this.UserName, $this.Password)
            }
            Start-Service -Name $($this.ServiceName)
        }
        else
        {
            Write-Error "Path $($this.BinaryPath)\$($this.ExeName) not found."
        }
    }
    else
    {
        Write-Verbose "Ensure Set to Absent... Removing the service"

        $service = Get-WmiObject -Class Win32_Service -Filter "Name='$($this.ServiceName)'"

        $err=Stop-Service $service.Name -force
        if($err -eq $null)
        {
            $service.delete()
                        
        }
        else
        {
            Write-Verbose "$err"
            exit 1
        }
    }
}

<#
    This method is equivalent of the Test‐TargetResource script function.
    It should return True or False, showing whether the resource is in a desired state.
#>


[bool] Test()
{
    $CheckService = Get-WmiObject win32_service | where {$_.name -eq $this.ServiceName} -ErrorAction Ignore
    if($this.Ensure -eq [Ensure]::Present)
    {
        if($CheckService -eq $null)
        {
            Write-Verbose "In if loop 'true'"
            return $false
        }
        else
        {
            Write-Verbose "In if loop 'false'"
            return $true
        }
    }
    else
    {
        if($CheckService -ne $null)
        {
            Write-Verbose "In else loop 'false'"
            return $false
        }
        else
        {
            Write-Verbose "In else loop 'true'"
            return $true
        }
    }
}

<#
    Helper method to check if the file for windows service exists and it is file
#>


[bool] TestFilePath([String]$location)
{
    $present = $true
    $item = Get-ChildItem -Path "$location" -ErrorAction Ignore
    
    if ($item -eq $null)
    {
        $present = $false
    }
    else
    {
        Write-Verbose "Path $($location) found."
    }
    return $present
}
}