@@ -1601,7 +1601,7 @@ protected override void ProcessRecord()
1601
1601
bool objServiceShouldBeDisposed = false ;
1602
1602
try
1603
1603
{
1604
- if ( _ParameterSetName . Equals ( "InputObject" , StringComparison . OrdinalIgnoreCase ) && InputObject != null )
1604
+ if ( InputObject != null )
1605
1605
{
1606
1606
service = InputObject ;
1607
1607
Name = service . ServiceName ;
@@ -2167,6 +2167,195 @@ protected override void BeginProcessing()
2167
2167
} // class NewServiceCommand
2168
2168
#endregion NewServiceCommand
2169
2169
2170
+ #region RemoveServiceCommand
2171
+ /// <summary>
2172
+ /// This class implements the Remove-Service command
2173
+ /// </summary>
2174
+ [ Cmdlet ( VerbsCommon . Remove , "Service" , SupportsShouldProcess = true , DefaultParameterSetName = "Name" ) ]
2175
+ public class RemoveServiceCommand : ServiceBaseCommand
2176
+ {
2177
+ #region Parameters
2178
+
2179
+ /// <summary>
2180
+ /// Name of the service to remove
2181
+ /// </summary>
2182
+ [ Parameter ( Position = 0 , Mandatory = true , ValueFromPipeline = true , ValueFromPipelineByPropertyName = true , ParameterSetName = "Name" ) ]
2183
+ [ Alias ( "ServiceName" , "SN" ) ]
2184
+ public string Name { get ; set ; }
2185
+
2186
+ /// <summary>
2187
+ /// The following is the definition of the input parameter "InputObject".
2188
+ /// Specifies ServiceController object representing the services to be removed.
2189
+ /// Enter a variable that contains the objects or type a command or expression
2190
+ /// that gets the objects.
2191
+ /// </summary>
2192
+ [ Parameter ( ValueFromPipeline = true , ParameterSetName = "InputObject" ) ]
2193
+ public ServiceController InputObject { get ; set ; }
2194
+
2195
+ /// <summary>
2196
+ /// The following is the definition of the input parameter "ComputerName".
2197
+ /// Set the properties of service running on the list of computer names
2198
+ /// specified. The default is the local computer.
2199
+ /// Type the NETBIOS name, an IP address, or a fully-qualified domain name of
2200
+ /// one or more remote computers. To indicate the local computer, use the
2201
+ /// computer name, "localhost" or a dot (.). When the computer is in a different
2202
+ /// domain than the user, the fully-qualified domain name is required.
2203
+ /// </summary>
2204
+ [ Parameter ( ValueFromPipelineByPropertyName = true ) ]
2205
+ [ ValidateNotNullOrEmpty ]
2206
+ [ Alias ( "cn" ) ]
2207
+ [ SuppressMessage ( "Microsoft.Performance" , "CA1819:PropertiesShouldNotReturnArrays" ) ]
2208
+ public String [ ] ComputerName { get ; set ; } = new string [ ] { "." } ;
2209
+
2210
+ #endregion Parameters
2211
+
2212
+ #region Overrides
2213
+ /// <summary>
2214
+ /// Remove the service
2215
+ /// </summary>
2216
+ [ ArchitectureSensitive ]
2217
+ protected override void ProcessRecord ( )
2218
+ {
2219
+ ServiceController service = null ;
2220
+ string serviceComputerName = null ;
2221
+ foreach ( string computer in ComputerName )
2222
+ {
2223
+ bool objServiceShouldBeDisposed = false ;
2224
+ try
2225
+ {
2226
+ if ( InputObject != null )
2227
+ {
2228
+ service = InputObject ;
2229
+ Name = service . ServiceName ;
2230
+ serviceComputerName = service . MachineName ;
2231
+ objServiceShouldBeDisposed = false ;
2232
+ }
2233
+ else
2234
+ {
2235
+ serviceComputerName = computer ;
2236
+ // "new ServiceController" will succeed even if there is no such service.
2237
+ // This checks whether the service actually exists.
2238
+ service = new ServiceController ( Name , serviceComputerName ) ;
2239
+ objServiceShouldBeDisposed = true ;
2240
+ }
2241
+ Diagnostics . Assert ( ! String . IsNullOrEmpty ( Name ) , "null ServiceName" ) ;
2242
+ string unusedByDesign = service . DisplayName ;
2243
+ }
2244
+ catch ( ArgumentException ex )
2245
+ {
2246
+ // Cannot use WriteNonterminatingError as service is null
2247
+ ErrorRecord er = new ErrorRecord ( ex , "ArgumentException" , ErrorCategory . ObjectNotFound , computer ) ;
2248
+ WriteError ( er ) ;
2249
+ continue ;
2250
+ }
2251
+ catch ( InvalidOperationException ex )
2252
+ {
2253
+ // Cannot use WriteNonterminatingError as service is null
2254
+ ErrorRecord er = new ErrorRecord ( ex , "InvalidOperationException" , ErrorCategory . ObjectNotFound , computer ) ;
2255
+ WriteError ( er ) ;
2256
+ continue ;
2257
+ }
2258
+
2259
+ try // In finally we ensure dispose, if object not pipelined.
2260
+ {
2261
+ // Confirm the operation first.
2262
+ // This is always false if WhatIf is set.
2263
+ if ( ! ShouldProcessServiceOperation ( service ) )
2264
+ {
2265
+ continue ;
2266
+ }
2267
+
2268
+ NakedWin32Handle hScManager = IntPtr . Zero ;
2269
+ NakedWin32Handle hService = IntPtr . Zero ;
2270
+ try
2271
+ {
2272
+ hScManager = NativeMethods . OpenSCManagerW (
2273
+ lpMachineName : serviceComputerName ,
2274
+ lpDatabaseName : null ,
2275
+ dwDesiredAccess : NativeMethods . SC_MANAGER_ALL_ACCESS
2276
+ ) ;
2277
+ if ( IntPtr . Zero == hScManager )
2278
+ {
2279
+ int lastError = Marshal . GetLastWin32Error ( ) ;
2280
+ Win32Exception exception = new Win32Exception ( lastError ) ;
2281
+ WriteObject ( exception ) ;
2282
+ WriteNonTerminatingError (
2283
+ service ,
2284
+ serviceComputerName ,
2285
+ exception ,
2286
+ "ComputerAccessDenied" ,
2287
+ ServiceResources . ComputerAccessDenied ,
2288
+ ErrorCategory . PermissionDenied ) ;
2289
+ continue ;
2290
+ }
2291
+ hService = NativeMethods . OpenServiceW (
2292
+ hScManager ,
2293
+ Name ,
2294
+ NativeMethods . SERVICE_DELETE
2295
+ ) ;
2296
+ if ( IntPtr . Zero == hService )
2297
+ {
2298
+ int lastError = Marshal . GetLastWin32Error ( ) ;
2299
+ Win32Exception exception = new Win32Exception ( lastError ) ;
2300
+ WriteNonTerminatingError (
2301
+ service ,
2302
+ exception ,
2303
+ "CouldNotRemoveService" ,
2304
+ ServiceResources . CouldNotSetService ,
2305
+ ErrorCategory . PermissionDenied ) ;
2306
+ continue ;
2307
+ }
2308
+
2309
+ bool status = NativeMethods . DeleteService ( hService ) ;
2310
+
2311
+ if ( ! status )
2312
+ {
2313
+ int lastError = Marshal . GetLastWin32Error ( ) ;
2314
+ Win32Exception exception = new Win32Exception ( lastError ) ;
2315
+ WriteNonTerminatingError (
2316
+ service ,
2317
+ exception ,
2318
+ "CouldNotRemoveService" ,
2319
+ ServiceResources . CouldNotRemoveService ,
2320
+ ErrorCategory . PermissionDenied ) ;
2321
+ }
2322
+ }
2323
+ finally
2324
+ {
2325
+ if ( IntPtr . Zero != hService )
2326
+ {
2327
+ bool succeeded = NativeMethods . CloseServiceHandle ( hService ) ;
2328
+ if ( ! succeeded )
2329
+ {
2330
+ int lastError = Marshal . GetLastWin32Error ( ) ;
2331
+ Diagnostics . Assert ( lastError != 0 , "ErrorCode not success" ) ;
2332
+ }
2333
+ }
2334
+
2335
+ if ( IntPtr . Zero != hScManager )
2336
+ {
2337
+ bool succeeded = NativeMethods . CloseServiceHandle ( hScManager ) ;
2338
+ if ( ! succeeded )
2339
+ {
2340
+ int lastError = Marshal . GetLastWin32Error ( ) ;
2341
+ Diagnostics . Assert ( lastError != 0 , "ErrorCode not success" ) ;
2342
+ }
2343
+ }
2344
+ } // Finally
2345
+ } // End try
2346
+ finally
2347
+ {
2348
+ if ( objServiceShouldBeDisposed )
2349
+ {
2350
+ service . Dispose ( ) ;
2351
+ }
2352
+ }
2353
+ } // End for
2354
+ }
2355
+ #endregion Overrides
2356
+ } // class RemoveServiceCommand
2357
+ #endregion RemoveServiceCommand
2358
+
2170
2359
#region ServiceCommandException
2171
2360
/// <summary>
2172
2361
/// Non-terminating errors occurring in the service noun commands
@@ -2264,8 +2453,10 @@ internal static class NativeMethods
2264
2453
internal const int ERROR_SERVICE_NOT_ACTIVE = 1062 ;
2265
2454
internal const DWORD SC_MANAGER_CONNECT = 1 ;
2266
2455
internal const DWORD SC_MANAGER_CREATE_SERVICE = 2 ;
2456
+ internal const DWORD SC_MANAGER_ALL_ACCESS = 0xf003f ;
2267
2457
internal const DWORD SERVICE_QUERY_CONFIG = 1 ;
2268
2458
internal const DWORD SERVICE_CHANGE_CONFIG = 2 ;
2459
+ internal const DWORD SERVICE_DELETE = 0x10000 ;
2269
2460
internal const DWORD SERVICE_NO_CHANGE = 0xffffffff ;
2270
2461
internal const DWORD SERVICE_AUTO_START = 0x2 ;
2271
2462
internal const DWORD SERVICE_DEMAND_START = 0x3 ;
@@ -2297,6 +2488,12 @@ bool CloseServiceHandle(
2297
2488
NakedWin32Handle hSCManagerOrService
2298
2489
) ;
2299
2490
2491
+ [ DllImport ( PinvokeDllNames . DeleteServiceDllName , CharSet = CharSet . Unicode , SetLastError = true ) ]
2492
+ internal static extern
2493
+ bool DeleteService (
2494
+ NakedWin32Handle hService
2495
+ ) ;
2496
+
2300
2497
[ DllImport ( PinvokeDllNames . ChangeServiceConfigWDllName , CharSet = CharSet . Unicode , SetLastError = true ) ]
2301
2498
internal static extern
2302
2499
bool ChangeServiceConfigW (
0 commit comments