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 |
#region Using Statements
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Security.Principal;
using System.ServiceProcess;
#endregion
namespace Tasks
{
[assembly: SecurityPermission(SecurityAction.RequestMinimum, UnmanagedCode = true)]
[assembly: PermissionSet(SecurityAction.RequestMinimum, Name = "FullTrust")]
[DebuggerDisplay("Name = {Name}, Id = {Id}, LastRan = {LastRan}")]
public class ServiceUpTask : ITask
{
public string ServiceName { get; set; }
public string UserName { get; set; }
public string DomainName { get; set; }
public string Password { get; set; }
public string MachineName { get; set; }
#region Overrides of Task
public void Run()
{
if (!string.IsNullOrEmpty(ServiceName))
{
WindowsImpersonationContext impersonationContext = null;
try
{
impersonationContext = AssumeIdentity(UserName, DomainName, Password);
using (ServiceController service = ServiceBuilder(ServiceName, MachineName))
{
Debug.Print(string.Format("Service {0}, Status {1}", service.ServiceName, service.Status));
if (service.CanStop)
{
service.Stop();
}
service.Refresh();
if (service.Status == ServiceControllerStatus.Stopped)
{
service.Start();
}
}
}
finally
{
//Make sure we release the identity in case of an exception no matter what.
StopImpersonating(impersonationContext);
}
}
}
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>The name.</value>
public string Name { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this <see cref="ITask"/> is active.
/// </summary>
/// <value><c>true</c> if active; otherwise, <c>false</c>.</value>
public bool Active { get; set; }
/// <summary>
/// Gets or sets the last ran.
/// </summary>
/// <value>The last ran.</value>
public DateTime? LastRan { get; set; }
/// <summary>
/// Gets or sets the id.
/// </summary>
/// <value>The id.</value>
public decimal? Id { get; set; }
/// <summary>
/// Builds the service.
/// </summary>
/// <param name="serviceName">Name of the service.</param>
/// <param name="machineName">Name of the machine.</param>
/// <returns></returns>
private static ServiceController ServiceBuilder(string serviceName, string machineName)
{
ServiceController service = string.IsNullOrEmpty(machineName) ? new ServiceController(serviceName) : new ServiceController(serviceName, machineName);
return service;
}
///<summary>
///Assumes the identity. Steal shamelessly from MSDN.
///</summary>
///<returns></returns>
private static WindowsImpersonationContext AssumeIdentity(string userName, string domain, string password)
{
const int LOGON32_PROVIDER_DEFAULT = 0;
const int dwLogonProvider = LOGON32_PROVIDER_DEFAULT;
//This parameter causes LogonUser to create a primary token.
const int LOGON32_LOGON_INTERACTIVE = 2;
const int dwLogonType = LOGON32_LOGON_INTERACTIVE;
var phToken = new IntPtr();
if (LogonUser(userName, domain, password, dwLogonType, dwLogonProvider, ref phToken))
{
if (phToken != IntPtr.Zero)
{
var windowsIdentity = new WindowsIdentity(phToken);
WindowsImpersonationContext impersonationContext = windowsIdentity.Impersonate();
CloseHandle(phToken);
return impersonationContext;
}
}
return null;
}
/// <summary>
/// Stops the WindowsIdentity impersonating.
/// </summary>
/// <param name="impersonationContext">The impersonation context.</param>
private static void StopImpersonating(WindowsImpersonationContext impersonationContext)
{
//Stop impersonating the user.
if (impersonationContext != null) impersonationContext.Undo();
//Check the identity name.
//Name of the identity after performing an Undo on the impersonation:
//Uncomment for debugging if to check identity if needed
//var identity = WindowsIdentity.GetCurrent();
}
#endregion
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool DuplicateToken(IntPtr ExistingTokenHandle,
int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);
}
} |