I am building an admin module for an intranet MVC application. This application implements Windows Authentication (users are automatically logged in).
Currently I base all the user experience based around their HttpContext.User.Identity data.
What I need to do is to be able to impersonate an user so I can replicate their experience if they are having problems.
With Forms Authentication this is very straight forward...
I tried replacing the IPrincipal.User object in the HttpContext but this only has a getter not a setter.
any pointers would be greatly appreciated.
Thanks.
using (new Impersonation()){
// now working in context of whatever user you want
}
and this is the class
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public class Impersonation : IDisposable
{
private readonly SafeTokenHandle _handle;
private readonly WindowsImpersonationContext _context;
//const int Logon32LogonNewCredentials = 9;
private const int Logon32LogonInteractive = 2;
public Impersonation()
{
var domain = "your domain;
var username = "the user";
var password = "their password";
var ok = LogonUser(username, domain, password, Logon32LogonInteractive, 0, out _handle);
if (!ok)
{
var errorCode = Marshal.GetLastWin32Error();
throw new ApplicationException(string.Format("Could not impersonate the elevated user. LogonUser returned error code {0}.", errorCode));
}
_context = WindowsIdentity.Impersonate(_handle.DangerousGetHandle());
}
public void Dispose()
{
_context.Dispose();
_handle.Dispose();
}
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private SafeTokenHandle()
: base(true) { }
[DllImport("kernel32.dll")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr handle);
protected override bool ReleaseHandle()
{
return CloseHandle(handle);
}
}
}
Related
In my vaadin application, i need to use #Push, but since i added it, i can't read and write cookies because VaadinService.getSurrentResponse()returns null because of Push. I manager cookies using this class :
import javax.servlet.http.Cookie;
import com.vaadin.server.VaadinResponse;
import com.vaadin.server.VaadinService;
public class CookieManager {
private VaadinResponse response;
public CookieManager(VaadinResponse response){
this.response = response;
}
public Cookie getCookieByName(final String name) {
// Fetch all cookies from the request
Cookie[] cookies = VaadinService.getCurrentRequest().getCookies();
// Iterate to find cookie by its name
for (Cookie cookie : cookies) {
if (name.equals(cookie.getName())) {
return cookie;
}
}
return null;
}
public Cookie createCookie(final String name, final String value, final int maxAge) {
// Create a new cookie
final Cookie cookie = new Cookie(name, value);
cookie.setMaxAge(maxAge);
// Set the cookie path.
cookie.setPath(VaadinService.getCurrentRequest().getContextPath());
// Save cookie
addCookie(cookie);
return cookie;
}
private void addCookie(Cookie cookie){
response.addCookie(cookie);
}
public Cookie updateCookieValue(final String name, final String value) {
// Create a new cookie
Cookie cookie = getCookieByName(name);
cookie.setValue(value);
// Save cookie
addCookie(cookie);
return cookie;
}
public void destroyCookieByName(final String name) {
Cookie cookie = getCookieByName(name);
if (cookie != null) {
cookie.setValue(null);
// By setting the cookie maxAge to 0 it will deleted immediately
cookie.setMaxAge(0);
cookie.setPath(VaadinService.getCurrentRequest().getContextPath());
addCookie(cookie);
}
}
}
When i want to create a cookie (like at user's login), i get a nullPointerException because of the VaadinResponse being null.
So i tried to disable Push in constructor and re-enable it at the end of addCookie()method, but it disabled push for all of my application, even if i re-enable it just after the addCookiemethod.
I saw a ticket on vaadin's trac (http://dev.vaadin.com/ticket/11808) saying that will not be fixed, and someone suggested to create a regular AJAX query from server to create cookie, but i really don't know how to do.
How can i manage my cookies? i need to create AND get cookies, so javascript can't help me there, because i can't get javascript's return in vaadin, so i can't get a cookie.
Here is my solution how to store cookie when #Push is using.
First we create container to storage all instance of client UI. (
This container itself has a great potential)
public class UISession {
private List<WebAppUI> uis = new ArrayList<WebAppUI>();
public void addUI(WebAppUI webAppUI) {
uis.add(webAppUI);
}
public List<WebAppUI> getUIs() {
return uis;
}
public static UISession getInstance() {
try {
UI.getCurrent().getSession().lock();
return (UISession) UI.getCurrent().getSession().getAttribute("userUiSession");
} finally {
UI.getCurrent().getSession().unlock();
}
}
In UI.init() we add new instance to the session (e.g when user open new tab)
#Override
protected void init(VaadinRequest vaadinRequest) {
/** Set singleton uisesison for each browser*/
if(UISession.getInstance()==null){
UI.getCurrent().getSession().setAttribute("userUiSession",new UISession());
}
UISession.getInstance().addUI(this);
System.out.println("UI count fo current browser "+UISession.getInstance().getUIs().size());
...
}
Here is my helper cookie class:
class MyCookie{
private String value;
private String name;
private Date expired;
private String path="/";
public MyCookie(String name, String value) {
this.name=name;
this.value=value;
}
public void setMaxAge(int minute) {
Calendar c = Calendar.getInstance();
c.add(Calendar.MINUTE, minute);
expired=c.getTime();
}
public String getStringToCreateCookie(){
return "document.cookie=\""+getName()+"="+getValue()+"; expires="+expired.toString()+"; path="+path+"\"";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public Date getExpired() {
return expired;
}
public void setExpired(Date expired) {
this.expired = expired;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
}
And on final when we need add new cookie, we just must find Ui that is active and call js function
public static void addCookie(String name, String value, int age){
MyCookie myCookie = new MyCookie(name, value);
myCookie.setMaxAge(age);
for(WebAppUI ui : UISession.getInstance().getUIs()){
if(ui.isAttached()){
ui.getPage().getJavaScript().execute(myCookie.getStringToCreateCookie());
return;
}
}
}
In my case i have access to storage cookie (when user made request). I just only have problem with add new cookie so this is my working solutions.
As mentioned in the ticket, you can use JavaScript to call client code and also request a cookie value back by that. E.g.
#Grapes([
#Grab('org.vaadin.spring:spring-boot-vaadin:0.0.3'),
#Grab('com.vaadin:vaadin-server:7.4.0.beta1'),
#Grab('com.vaadin:vaadin-client-compiled:7.4.0.beta1'),
#Grab('com.vaadin:vaadin-themes:7.4.0.beta1'),
])
import com.vaadin.ui.*
#org.vaadin.spring.VaadinUI
#groovy.transform.CompileStatic
class MyUI extends UI {
protected void init(com.vaadin.server.VaadinRequest request) {
final resultLabel = new Label()
// provide a callback for the client to tell the cookies
JavaScript.current.addFunction("tellCookie", { elemental.json.JsonArray arguments ->
resultLabel.value = arguments?.get(0)?.asString()
} as JavaScriptFunction)
setContent(new VerticalLayout().with{
addComponent(new Button("Set Cookie", {
// just simply set the cookies via JS (attn: quoting etc)
JavaScript.current.execute("document.cookie='mycookie=${System.currentTimeMillis()}'")
} as Button.ClickListener))
addComponent(new Button("Get Cookie", {
// tell the client to tell the server the cookies
JavaScript.current.execute("this.tellCookie(document.cookie)")
} as Button.ClickListener))
addComponent(resultLabel)
return it
})
}
}
This is a running example (e.g. spring run vaadin.groovy) for testing. See the comments for the important parts.
The Viritin add-on contains a helper class called BrowserCookie. It works in pretty much the way suggested by cfrick, but just hides all the cookie handling complexity into a helper class. It don't contain built in "max age" handling yet, but that could be easily added as a workaround you can manually "encode" the age into cookie value.
BTW. Don't know what you are doing, but if you happen to be using TouchKit add-on, it has a helper for html5 local storage. It has rather wide browsers support already and is in many ways better way to store e.g. settings than cookies.
My understanding is that IModel instances are reasonably cheap to create and that's what I started with. I was creating a separate IModel for each class that was ever using it: each Application Service class gets its own IModel, as does every Controller. It was working fine, but having 30+ channels open was a bit worrisome.
I thought about serializing access to a shared IModel:
lock(publisherLock)
publisherModel.BasicPublish(...);
but now there's a point of contention for no good reason.
So, what will be the correct way of publishing messages into a RabbitMQ exchange from an ASP.NET MVC application?
What you must not do is allow a channel to be used by more than one thread, so keeping channels open over several requests is a bad idea.
IModel instances are cheap to create, but not free, so there are a couple of approaches you can take:
The safest thing to do is simply to create a channel each time you want to publish and close it again straight away. Something like this:
using(var model = connection.CreateModel())
{
var properties = model.CreateBasicProperties();
model.BasicPublish(exchange, routingKey, properties, msg);
}
You can keep the connection open for the lifetime of the application, but be sure to detect if you loose the connection and have code to reconnect.
The downside with this approach is that you have the overhead of creating a channel for each publish.
The alternative is to hold a channel open on a dedicated publishing thread and marshal all your publish calls onto that thread using a BlockingCollection or similar. This will be more efficient, but more complex to implement.
Here is something which you can use,
BrokerHelper.Publish("Aplan chaplam, chaliye aai mein :P");
and below is the defination for the BrokerHelper class.
public static class BrokerHelper
{
public static string Username = "guest";
public static string Password = "guest";
public static string VirtualHost = "/";
// "localhost" if rabbitMq is installed on the same server,
// else enter the ip address of the server where it is installed.
public static string HostName = "localhost";
public static string ExchangeName = "test-exchange";
public static string ExchangeTypeVal = ExchangeType.Direct;
public static string QueueName = "SomeQueue";
public static bool QueueExclusive = false;
public static bool QueueDurable = false;
public static bool QueueDelete = false;
public static string RoutingKey = "yasser";
public static IConnection Connection;
public static IModel Channel;
public static void Connect()
{
var factory = new ConnectionFactory();
factory.UserName = Username;
factory.Password = Password;
factory.VirtualHost = VirtualHost;
factory.Protocol = Protocols.FromEnvironment();
factory.HostName = HostName;
factory.Port = AmqpTcpEndpoint.UseDefaultPort;
Connection = factory.CreateConnection();
Channel = Connection.CreateModel();
}
public static void Disconnect()
{
Connection.Close(200, "Goodbye");
}
public static bool IsBrokerDisconnected()
{
if(Connection == null) return true;
if(Connection.IsOpen) return false;
return true;
}
public static void Publish(string message)
{
if (IsBrokerDisconnected()) Connect();
Channel.ExchangeDeclare(ExchangeName, ExchangeTypeVal.ToString());
Channel.QueueDeclare(QueueName, QueueDurable, QueueExclusive, QueueDelete, null);
Channel.QueueBind(QueueName, ExchangeName, RoutingKey);
var encodedMessage = Encoding.ASCII.GetBytes(message);
Channel.BasicPublish(ExchangeName, RoutingKey, null, encodedMessage);
Disconnect();
}
}
Further reading : Introduction to RabbitMQ with C# .NET, ASP.NET and ASP.NET MVC with examples
I ask because I'm noticing on my site, if I hit it with an iPhone, sometimes it shows the mobile views, sometimes it shows regular views.
I've also read that MVC 4's not particularly effective at determining if the browser is from a mobile device or not, is that true? If so, anything we can do about it?
Update: Microsoft have published a workaround package for this bug.
I have added this workaround at here,
public class MyDefaultViewLocationCache : DefaultViewLocationCache, IViewLocationCache
{
public MyDefaultViewLocationCache(TimeSpan timeSpan): base(timeSpan)
{
}
public MyDefaultViewLocationCache()
: base()
{
}
public new string GetViewLocation(HttpContextBase httpContext, string key)
{
var location = base.GetViewLocation(httpContext, key);
if (location == null)
{
var cache = httpContext.Cache;
RemoveAllCacheStartWith(key, cache);
}
return location;
}
private static void RemoveAllCacheStartWith(string key, System.Web.Caching.Cache cache)
{
var keyWithoutDisplayMode = key.Substring(0, key.Substring(0, key.Length - 1).LastIndexOf(':') + 1);
var items = new List<string>();
var enumerator = cache.GetEnumerator();
while (enumerator.MoveNext())
{
var _key = enumerator.Key.ToString();
if (_key.StartsWith(keyWithoutDisplayMode))
{
items.Add(_key);
}
}
foreach (string item in items)
{
cache.Remove(item);
}
}
public new void InsertViewLocation(HttpContextBase httpContext, string key, string virtualPath)
{
base.InsertViewLocation(httpContext, key, virtualPath);
}
}
// In App Start
ViewEngines.Engines.OfType<RazorViewEngine>().First().ViewLocationCache =
new MyDefaultViewLocationCache();
For detail see this.
I want to start another apps when I click this button.
sharebtn = new Custom_ButtonField(share, shareactive, shareactive) {
protected boolean navigationClick(int status, int time) {
//I want to start another apps (Strawberry)
return true;
}
};
add(sharebtn);
Here is the Strawberry Apps
public class StrawBerry extends UiApplication implements ActionListener {
public static void main(String url) {
new StrawBerry(url).enterEventDispatcher();
}
}
I want to pass String url to Strawberry apps. How can I achieve this?
First your main method won't be never called by system. The right signature:
public static void main(String[] arguments){}
Take a look on this article to launch another app with parameters : How To - Launch a third-party application from another third-party application
To post on FB page. You need something like:
private final String NEXT_URL = "http://www.facebook.com/connect/login_success.html";
private final String APPLICATION_ID = "your id";
private final String APPLICATION_SECRET = "your secret";
private Facebook fb;
private User user;
...
fb = Facebook.getInstance(new ApplicationSettings(NEXT_URL, APPLICATION_ID, APPLICATION_SECRET, Facebook.Permissions.PUBLISH_STREAM));
user = fb.getUser(pUserId);
user.publishPost(messageEditField.getText(), linkEditField.getText(), pictureEditField.getText(), nameEditField.getText(), captionEditField.getText(), descriptionEditField.getText(), sourceEditField.getText());
I want to write a console or Click Once WinForms app that will programmatically stop and/or start a windows service on a remote box.
Both boxes are running .NET 3.5 - what .NET API's are available to accomplish this?
in C#:
var sc = new System.ServiceProcess.ServiceController("MyService", "MyRemoteMachine");
sc.Start();
sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running);
sc.Stop();
sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped);
You can also do this from a command console using the sc command:
sc <server> start [service name]
sc <server> stop [service name]
Use
sc <server> query | find "SERVICE_NAME"
to get a list of service names.
The option <server> has the form \\ServerName
Example
sc \\MyServer stop schedule will stop the Scheduler service.
ServiceController.
You need to have permission to administer the services on the remote box.
As Mehrdad says, you can also use WMI. Both methods work for start and stop, but WMI requires more coding and will give you more access to other resources
If you don't want to code it yourself, PsService by Microsoft/Sysinternals is a command line tool that does what you want.
You can use System.Management APIs (WMI) to control services remotely. WMI is the generic API to do administrative tasks.
For this problem, however, I suggest you to use the easier to use System.ServiceProcess.ServiceController class.
if you need to get the name of the Service:
run this from the command line:
sc query
You will see for example, that SQL Server's service name is 'MSSQL$SQLEXPRESS'.
So to stop the SQL Server service in C#:
ServiceController controller = new ServiceController();
controller.MachineName = "Machine1";
controller.ServiceName = "MSSQL$SQLEXPRESS";
if(controller.Status == ServiceControllerStatus.Running)
controller.Stop();
controller.WaitForStatus(ServiceControllerStatus.Stopped);
galets code snippet above is a great start. However, keep in mind it assumes that the service has already started, or, more importantly, that
sc.Status == System.ServiceProcess.ServiceControllerStatus.Running
Also, it may important to, at some point during code execution, call
sc.Refresh();
because the properties values (such as ServiceControllerStatus) may not reflect the actual properties of the service.
For instance, you may call
sc.Start();
and wait indefinitely when this command executes
sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running)
Here is a version of this code that I coded with those considerations in mind.
//Restart Content Service on DEV.
String svcName = "TheServiceName";
String machineName = "TheMachineName";
var sc = new System.ServiceProcess.ServiceController(svcName, machineName);
Console.WriteLine("Stopping Service '{0}' on machine '{1}", svcName, machineName);
sc.Stop();
sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped);
//sc.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running);
do
{
try
{
sc.Refresh();
if (sc.Status == System.ServiceProcess.ServiceControllerStatus.Running)
{
Console.WriteLine("Code has detected that servive start is pending, waiting 5 seconds to see if status changes..");
System.Threading.Thread.Sleep(5000);
}
else
{
Console.WriteLine("waiting 5 seconds and retrying start..");
System.Threading.Thread.Sleep(5000);
Console.WriteLine("Attempt Starting Service '{0}' on machine '{1}", svcName, machineName);
sc.Start();
}
}
catch(Exception ex)
{
//If it is already running, then abort do while
if (ex.InnerException.Message == "An instance of the service is already running")
{
Console.WriteLine(ex.InnerException.Message);
continue;
}
Console.WriteLine(ex.InnerException.ToString());
}
} while (sc.Status != System.ServiceProcess.ServiceControllerStatus.Running);
I have done like below:
Note:
If you didn't start your service if you are trying to stop it will throw exception.
If you configure these things in your web.config ,configuration related exception will not come. No need to do anything in IIS.
In Web.Config under <configuration>
<appSettings>
<add key="ServiceName" value="YourServiceName" />
<add key="MachineName" value="YourMachineName" />
</appSettings>
<system.web>
<authentication mode="Windows"/>
<identity impersonate="true" userName="YourUserName" password="YourPassword"/>
</system.web>
In My Service Class:
private void RestartService()
{
string serviceName = System.Configuration.ConfigurationSettings.AppSettings["ServiceName"];
string machineName = System.Configuration.ConfigurationSettings.AppSettings["MachineName"];
try
{
var service = new ServiceController(serviceName, machineName);
if (service.Status != ServiceControllerStatus.Stopped)
{
service.Stop();
service.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped);
}
service.Start();
service.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running);
}
catch (Exception)
{
}
}
Hope this Helps.
Here is a ServiceExtension that can Start and Stop Services on remote pc's.
And it can set the Startup type of the service, even to "automatic (delayed)"
modified version from this Answer to work on remote machines.
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.ServiceProcess;
namespace Helpers
{
public enum ServiceStartModeEx
{
Automatic = 2,
Manual = 3,
Disabled = 4,
DelayedAutomatic = 99
}
/// <summary>
/// Extensions to the ServiceController class.
/// </summary>
public static class ServiceControlerExtensions
{
/// <summary>
/// Set the start mode for the service.
/// </summary>
/// <param name="serviceController">The service controller.</param>
/// <param name="mode">The desired start mode.</param>
public static void SetStartMode(this ServiceController serviceController, ServiceStartModeEx mode)
{
IntPtr serviceManagerHandle = OpenServiceManagerHandle(serviceController);
IntPtr serviceHandle = OpenServiceHandle(serviceController, serviceManagerHandle);
try
{
if (mode == ServiceStartModeEx.DelayedAutomatic)
{
ChangeServiceStartType(serviceHandle, ServiceStartModeEx.Automatic);
ChangeDelayedAutoStart(serviceHandle, true);
}
else
{
// Delayed auto-start overrides other settings, so it must be set first.
ChangeDelayedAutoStart(serviceHandle, false);
ChangeServiceStartType(serviceHandle, mode);
}
}
finally
{
if (serviceHandle != IntPtr.Zero)
{
CloseServiceHandle(serviceHandle);
}
if (serviceManagerHandle != IntPtr.Zero)
{
CloseServiceHandle(serviceManagerHandle);
}
}
}
private static IntPtr OpenServiceHandle(ServiceController serviceController, IntPtr serviceManagerHandle)
{
var serviceHandle = OpenService(
serviceManagerHandle,
serviceController.ServiceName,
SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG);
if (serviceHandle == IntPtr.Zero)
{
throw new ExternalException("Open Service Error");
}
return serviceHandle;
}
private static IntPtr OpenServiceManagerHandle(ServiceController serviceController)
{
var machineName = string.IsNullOrWhiteSpace(serviceController.MachineName)
? null
: serviceController.MachineName;
IntPtr serviceManagerHandle = OpenSCManager(machineName, null, SC_MANAGER_ALL_ACCESS);
if (serviceManagerHandle == IntPtr.Zero)
{
throw new ExternalException("Open Service Manager Error");
}
return serviceManagerHandle;
}
private static void ChangeServiceStartType(IntPtr serviceHandle, ServiceStartModeEx mode)
{
bool result = ChangeServiceConfig(
serviceHandle,
SERVICE_NO_CHANGE,
(uint)mode,
SERVICE_NO_CHANGE,
null,
null,
IntPtr.Zero,
null,
null,
null,
null);
if (result == false)
{
ThrowLastWin32Error("Could not change service start type");
}
}
private static void ChangeDelayedAutoStart(IntPtr hService, bool delayed)
{
// Create structure that contains DelayedAutoStart property.
SERVICE_DELAYED_AUTO_START_INFO info = new SERVICE_DELAYED_AUTO_START_INFO();
// Set the DelayedAutostart property in that structure.
info.fDelayedAutostart = delayed;
// Allocate necessary memory.
IntPtr hInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SERVICE_DELAYED_AUTO_START_INFO)));
// Convert structure to pointer.
Marshal.StructureToPtr(info, hInfo, true);
// Change the configuration.
bool result = ChangeServiceConfig2(hService, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, hInfo);
// Release memory.
Marshal.FreeHGlobal(hInfo);
if (result == false)
{
ThrowLastWin32Error("Could not set service to delayed automatic");
}
}
private static void ThrowLastWin32Error(string messagePrefix)
{
int nError = Marshal.GetLastWin32Error();
var win32Exception = new Win32Exception(nError);
string message = string.Format("{0}: {1}", messagePrefix, win32Exception.Message);
throw new ExternalException(message);
}
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr OpenService(
IntPtr hSCManager,
string lpServiceName,
uint dwDesiredAccess);
[DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode,
SetLastError = true)]
private static extern IntPtr OpenSCManager(
string machineName,
string databaseName,
uint dwAccess);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern Boolean ChangeServiceConfig(
IntPtr hService,
UInt32 nServiceType,
UInt32 nStartType,
UInt32 nErrorControl,
String lpBinaryPathName,
String lpLoadOrderGroup,
IntPtr lpdwTagId,
[In] char[] lpDependencies,
String lpServiceStartName,
String lpPassword,
String lpDisplayName);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool ChangeServiceConfig2(
IntPtr hService,
int dwInfoLevel,
IntPtr lpInfo);
[DllImport("advapi32.dll", EntryPoint = "CloseServiceHandle")]
private static extern int CloseServiceHandle(IntPtr hSCObject);
private const uint SERVICE_NO_CHANGE = 0xFFFFFFFF;
private const uint SERVICE_QUERY_CONFIG = 0x00000001;
private const uint SERVICE_CHANGE_CONFIG = 0x00000002;
private const uint SC_MANAGER_ALL_ACCESS = 0x000F003F;
private const int SERVICE_CONFIG_DELAYED_AUTO_START_INFO = 3;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct SERVICE_DELAYED_AUTO_START_INFO
{
public bool fDelayedAutostart;
}
}
}
You can start a service like this
using System.ServiceProcess;
serviceName = "the name of the service"
machineName = "the name of the remote/local host"
var service = new ServiceController(serviceName, machineName);
try
{
service.SetStartMode(ServiceStartModeEx.DelayedAutomatic);
service.Start();
}
finally
{
service.Close();
}
You can stop a service like this
var service = new ServiceController(serviceName, machineName);
try
{
if (service.CanStop)
{
service.SetStartMode(ServiceStartModeEx.Disabled);
service.Stop();
}
}
finally
{
service.Close();
}
To grant a user rights to start and stop a service on a remote pc you have to set some service rights, you can google what subinacl.exe is and where to download it.
C:\Program Files (x86)\Windows Resource Kits\Tools>subinacl.exe /service SERVICENAME /grant=MACHINENAME\USERNAME=F