Problem Running SSIS Package from Windows Service - windows-services

I created a Windows Service that executes a SSIS Package every five minutes. It works pretty well, but something is tripping it up.
Every week the server restarts, and after the restart, the Service stops working. Events for the SSIS Package beginning/ending executions still appear in the event viewer, but the package doesn't work as it should. When I manually start/stop the service, all works as normal again.
Am I missing something that I should be doing with the Pacakge?
I use a web service to get the location of the SSIS Package. I stripped most of that out of the code below, but left enough of it that the structure of my service is maintained.
Here is the jist of my code:
namespace MyService
{
partial class MyService : ServiceBase
{
private Timer timer;
private Package pkg;
bool executing;
public MyService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
executing = false;
TimerCallback callback = new TimerCallback(Init);
int period = 1000 * 60; //attempt to initialize every minute.
timer = new Timer(callback, null, 0, period);
}
private void Init(object state)
{
try
{
//Get `timeIntervalMinutes` from Parameters table
string mySQLStatement = "...";
DataSet ds = mySQLQuery(...);
int timeIntervalMinutes = Convert.ToInt32(ds.Tables["timeIntervalMinutes"].Rows[0]["Value"]);
//Get `path` from Parameters table
string mySQLStatement = "...";
DataSet ds = mySQLQuery(...);
string path = Convert.ToString(ds.Tables["path"].Rows[0]["Value"]);
//Get `path` from Parameters table
string mySQLStatement = "...";
DataSet ds = mySQLQuery(...);
string server = Convert.ToString(ds.Tables["server"].Rows[0]["Value"]);
//Load the SSIS Package
Application app = new Application();
pkg = app.LoadFromDtsServer(path, server, null);
//If this line is reached, a connection to MyWS has been made, so switch the timer to run the SSIS package
timer.Dispose();
TimerCallback callback = new TimerCallback(OnTimedEvent);
int period = 1000 * 60 * timeIntervalMinutes;
timer = new Timer(callback, null, 0, period);
}
catch (Exception e)
{
return;
}
}
private void OnTimedEvent(object state)
{
if (!executing)
{
executing = true;
DTSExecResult pkgResults = pkg.Execute();
executing = false;
}
}
protected override void OnStop()
{
}
//<MyWS is here>
}
}
Thanks for the help!

Your service or process maybe dependent on another service - say MSDTC. IF this service is not ready as quickly after startup you could get unpredictable results. Either delay the startup of your service or figure out the dependency and set is in the service properties

Related

Xamarin Android IntentService calling OnDestroy while performing large async operation

Im trying to perform a synchronization task without blocking UI thread. I have implemented a Android Service to do so, but I found out, if the synchronization task needs too much computational time, the UI thread was blocked. So I tried the migration to IntentService. This is how my IntentService looks like:
[Service]
public class SynchronizeIntentService : IntentService
{
static readonly string TAG = typeof(SynchronizeIntentService).FullName;
private NotificationCompat.Builder Builder;
private NotificationManagerCompat NotificationManager;
public SynchronizeIntentService() : base("SynchronizeIntentService")
{
}
public override void OnDestroy()
{
var tmp = 5;
base.OnDestroy();
}
private NotificationChannel createNotificationChannel()
{
var channelId = Constants.NOTIFICATION_CHANNELID;
var channelName = "My Notification Service";
var Channel = new NotificationChannel(channelId, channelName, Android.App.NotificationImportance.Default);
Channel.LightColor = Android.Resource.Color.HoloBlueBright;
Channel.LockscreenVisibility = NotificationVisibility.Public;
return Channel;
}
private void createForegroundService()
{
var mNotificationManager = GetSystemService(Context.NotificationService) as NotificationManager;
if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
{
mNotificationManager.CreateNotificationChannel(createNotificationChannel());
}
var notificationBuilder = new NotificationCompat.Builder(this, Constants.NOTIFICATION_CHANNELID);
GenerateNotification();
StartForeground(Constants.SERVICE_RUNNING_NOTIFICATION_ID, Builder.Notification);
}
private void GenerateNotification()
{
NotificationManager = NotificationManagerCompat.From(this);
Builder = new NotificationCompat.Builder(this, Constants.NOTIFICATION_CHANNELID);
Builder.SetContentTitle(ContaScan.Classes.Localize.GetString("Global_SynchProcess", ""))
.SetSmallIcon(Resource.Drawable.icon)
.SetPriority(NotificationCompat.PriorityLow);
}
protected async override void OnHandleIntent(Intent intent)
{
Log.Debug(TAG, "Service Started!");
await Synch();
Log.Debug(TAG, "Service Stopping!");
StopForeground(true);
this.StopSelf();
}
public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
{
base.OnStartCommand(intent, flags, startId);
createForegroundService();
return StartCommandResult.Sticky;
}
private async Task Synch()
{
//Large synch process
}
}
And this is how the service is getting started:
startServiceIntent = new Intent(Android.App.Application.Context, typeof(SynchronizeIntentService));
startServiceIntent.SetAction(Constants.ACTION_START_SERVICE);
ContextWrapper contextWrapper = new ContextWrapper(Android.App.Application.Context);
contextWrapper.StartService(startServiceIntent);
The problem is OnDestroy() method is called while the Synch() task is being performed and looks like the IntentService is being killed before ending the process.
What am I doing wrong?
First, check your API level. This class was deprecated in API level 30.
And then, when you use the OnHandleIntent, do not call Service.stopSelf().
This method is invoked on the worker thread with a request to process. Only one Intent is processed at a time, but the processing happens on a worker thread that runs independently from other application logic. So, if this code takes a long time, it will hold up other requests to the same IntentService, but it will not hold up anything else. When all requests have been handled, the IntentService stops itself, so you should not call Service.stopSelf().
For more details, please check the link below. https://developer.android.com/reference/android/app/IntentService#onHandleIntent(android.content.Intent)

Corda responder flow not answering

I created a very easy flow test with IntelliJ.
#Test
public void dummyTest() throws InterruptedException, ExecutionException {
Party Alice = aliceNode.getServices().getIdentityService().wellKnownPartyFromX500Name(new CordaX500Name("Alice", "London", "GB"));
FlowInitiatorIssueToken flow = new FlowInitiatorIssueToken(30, alice, network.getDefaultNotaryIdentity());
SignedTransaction transaction = bobNode.startFlow(flow).get();
// The error occurs because of this line ....
State state = (State) transaction.getTx().getOutputStates().get(0);
assertEquals(state.getParticipants(), alice);
VaultQueryCriteria criteria = new VaultQueryCriteria(Vault.StateStatus.ALL);
aliceNode.transaction(() -> {
Vault.Page<State> result = aliceNode.getServices().getVaultService().queryBy(State.class, criteria);
assertTrue(result.getStates().size() > 0);
return null;
});
network.runNetwork();
}
IntelliJ is not able to fulfil the test and gives me the error
statemachine.FlowMonitor. - Flow with id 3982ab19-3e5b-4737-9adf-e4a6a97d20e6 has been waiting for 117 seconds to receive messages from parties [O=Alice, L=London, C=GB]
This led to the assumption that the responder flow is not doing anything.
// ******************
// * Initiator flow *
// ******************
#InitiatingFlow
#StartableByRPC
public class FlowInitiatorIssueToken extends FlowLogic<SignedTransaction> {
private final Integer value;
private final Party counterParty;
private final Party notary;
public FlowInitiatorIssuToken(Integer value, Party counterParty, Party notary) {
this.value = value;
this.counterParty = counterParty;
this.notary = notary;
}
/**
* The flow logic is encapsulated within the call() method.
*/
#Suspendable
#Override
public SignedTransaction call() throws FlowException {
/*------------------------------
* SENDING AND RECEIVING DATA *
------------------------------*/
FlowSession issueTokenSession = initiateFlow((Party) counterParty);
/*------------------------------------------
* GATHERING OTHER TRANSACTION COMPONENTS *
------------------------------------------*/
State outputState = new State(this.value, this.counterParty);
Command<ContractToken.Commands.Issue> command = new Command<>(new ContractToken.Commands.Issue(), getOurIdentity().getOwningKey());
/*------------------------
* TRANSACTION BUILDING *
------------------------*/
TransactionBuilder txBuilder = new TransactionBuilder(notary)
.addOutputState(outputState, ContractToken.ID)
.addCommand(command);
/*-----------------------
* TRANSACTION SIGNING *
-----------------------*/
SignedTransaction signedTx = getServiceHub().signInitialTransaction(txBuilder);
/*------------------------------
* FINALISING THE TRANSACTION *
------------------------------*/
System.out.println("Hey World!");
subFlow(new FinalityFlow(signedTx, issueTokenSession));
return null;
}
}
// ******************
// * Responder flow *
// ******************
#InitiatedBy(FlowInitiatorIssueToken.class)
public class FlowResponderIssueToken extends FlowLogic<SignedTransaction> {
private final FlowSession issueTokenSession;
public FlowResponderIssueToken(FlowSession issueTokenSession) {
this.issueTokenSession = issueTokenSession;
}
#Suspendable
#Override
public SignedTransaction call() throws FlowException {
/*-----------------------------------------
* RESPONDING TO COLLECT_SIGNATURES_FLOW *
-----------------------------------------*/
class SignTxFlow extends SignTransactionFlow {
private SignTxFlow(FlowSession issueTokenSession) {
super(issueTokenSession);
}
#Override
protected void checkTransaction(SignedTransaction stx) {
}
}
SecureHash idOfTxWeSigned = subFlow(new SignTxFlow(issueTokenSession, SignTransactionFlow.tracker())).getId();
/*------------------------------
* FINALISING THE TRANSACTION *
------------------------------*/
subFlow(new ReceiveFinalityFlow(issueTokenSession, idOfTxWeSigned));
return null;
}
}
The initiator flow is executed. I can see that, because the System.out.println("Hey World!") command is showing up in the logs. However, I don't know whether the responder flow is never started by the initiator flow or it is just not reacting. Maybe you can help me with that.
Thanks!
You didn't call CollectSignaturesFlow in your initiator; that's why you didn't initiate a "conversation" with the responder for them to sign the transaction. See example here.
SignTransactionFlow that you call in your responder is a "reply" to calling CollectSignaturesFlow in the initiator.
Btw, you must verify a transaction before you sign it in your initiator. See example here.
Another thing missing was the key of the counterParty. When initialising the command, I added
final Command<ContractToken.Commands.Issue> txCommand = new Command<>(
new ContractToken.Commands.Issue(),
ImmutableList.of(getOurIdentity().getOwningKey(), counterParty.getOwningKey()));

apache ignite datastreamer how to set data into ignitefuture?

I am creating a batch data streamer in apache ignite, and need to control what happening after data receive.
My batch has a structure:
public class Batch implements Binarylizable, Serializable {
private String eventKey;
private byte[] bytes;
etc..
Then i trying to stream my data:
try (IgniteDataStreamer<Integer, Batch> streamer = serviceGrid.getIgnite().dataStreamer(cacheName);
StreamBatcher batcher = StreamBatcherFactory.create(event) ){
streamer.receiver(StreamTransformer.from(new BatchDataProcessor(event)));
streamer.autoFlushFrequency(1000);
streamer.allowOverwrite(true);
statusService.updateStatus(event.getKey(), StatusType.EXECUTING);
int counter = 0;
Batch batch = null;
IgniteFuture<?> future = null;
while ((batch = batcher.batch()) != null) {
future = streamer.addData(counter++, batch);
}
Object getted = future.get();
Just for test use lets get only the last future, and try to analyze this object. In the code above I'm using BatchDataProcessor, that look like this:
public class BatchDataProcessor implements CacheEntryProcessor<Integer, Batch, Object> {
private final Event event;
private final String eventKey;
public BatchDataProcessor(Event event) {
this.event = event;
this.eventKey = event.getKey();
}
#Override
public Object process(MutableEntry<Integer, Batch> mutableEntry, Object... objects) throws EntryProcessorException {
Node node = NodeIgniter.node(Ignition.localIgnite().cluster().localNode().id());
ServiceGridContainer container = (ServiceGridContainer) node.getEnvironmentContainer().getContainerObject(ServiceGridContainer.class);
ProcessMarshaller marshaller = (ProcessMarshaller) container.getService(ProcessMarshaller.class);
LocalProcess localProcess = marshaller.intoProccessing(event.getLambdaExecutionKey());
try {
localProcess.addBatch(mutableEntry);
} catch (IOException e) {
e.printStackTrace();
} finally {
return new String("111");
}
}
}
So after localProcess.addBatch(mutableEntry) I want to send back an information about the status of this particular batch, so I think that I should do this in IgniteFuture object, but I don't find any information how to control the future object that's received in addData function.
Can anybody help with understanding, where can I control future that receives in addData function or some other way to realize a callback to streamed batch?
When you do StreamTransformer.from(), you forfeit the result of your BatchDataProcessor, because
for (Map.Entry<K, V> entry : entries)
cache.invoke(entry.getKey(), this, entry.getValue());
// ^ result of cache.invoke() is discarded here
DataStreamer is for one-directional streaming of data. It is not supposed to return values as far as I know.
If you depend on the result of cache.invoke(), I recommend calling it directly instead of relying on DataStreamer.
BTW, be careful with fut.get(). You should do dataStreamer.flush() first, or DataStreamer's futures will wait indefinitely.

EnityManager won't delete records if I put it in a Runnable

I searched for some answer to my question on this site; but failed on every turn. I can delete fine if I don't put this in a ExecutorService, but if I do, it doesn't delete. No error occurs just the records are still in the database. Please advise.
public void deleteAllTrials(List<Trials>list) {
threadList = list;
ExecutorService executor = Executors.newFixedThreadPool(1);
executor.execute(new Job1());
executor.shutdown();
}
public class Job1 implements Runnable {
#Override
public void run() {
//Session session = (Session) entityManager.getDelegate();
EntityManagerFactory emf = entityManager.getEntityManagerFactory();
EntityManager em = emf.createEntityManager();
System.out.println("Size of threadList" + threadList.size());
long start = System.currentTimeMillis();
for(int i =0; i<threadList.size(); i++){
System.out.println("In thread...");
Trials mergedEntity = em.merge(threadList.get(i));
em.remove(mergedEntity);
}
//System.out.println("Result list in service:" + list.size());
//em.close();
long end = System.currentTimeMillis();
System.out.println("Threads took this long:" + (end - start));
}
}
I found out that EJBs are more powerful than I thought. If you just add #Asynchronus on top of the method you want the application to separate in a backing thread, it will be acting as a separate thread allowing the user to continue doing what he wants to do without waiting on the process to finish.
#Asynchronous
public void deleteAllTrials(List<TrialBillet>list) {
List<TrialBillet> threadList = new ArrayList<TrialBillet>();
threadList = list;
for(int i =0; i<threadList.size(); i++){
this.delete(threadList.get(i));
}
}
If you want to go with Executors, java-ee-7 has introduced ManagedExecutorService
From Java EE 7 tutorial
ManagedExecutorService: A managed executor service is used by
applications to execute submitted tasks asynchronously. Tasks are
executed on threads that are started and managed by the container. The
context of the container is propagated to the thread executing the
task. For example, by using an ManagedExecutorService.submit() call, a
task, such as the GenerateReportTask, could be submitted to execute at
a later time and then, by using the Future object callback, retrieve
the result when it becomes available.
code sample:
public class MyClass {
#Resource
private ManagedExecutorService mes;
public void myMethod() {
mes.execute(new Worker());
}
}

How can I programmatically stop/start a windows service on a remote box?

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

Resources