Which MBeans to use (and how) to programmatically determine memory lows for app (CQ5) deployed inside Weblogic - memory

I have to write a standalone Java app that monitors CQ5, deployed inside Weblogic (especially memory usage).
I was able to connect to the Domain Runtime Server in weblogic, using the class below (as found in the docs).
Now, I want to know which MBeans I need to monitor memory lows, so I can fire an event whenever a certain threshold is being hit.
Can any of you give me some insight? This is a pure JMX / Java question, unrelated to CQ.
I am trying to programmatically recreate what Jconsole already does. But I need it programmatically because I need to talk to an external API in case certain thresholds are being hit.
public class PrintServerState {
private static MBeanServerConnection connection;
private static JMXConnector connector;
private static final ObjectName service;
private static final ObjectName bundleWrite;
static {
try {
service = new ObjectName("com.bea:Name=DomainRuntimeService,Type=weblogic.management.mbeanservers.domainruntime.DomainRuntimeServiceMBean");
} catch (MalformedObjectNameException e) {
throw new AssertionError(e.getMessage());
}
}
/*
* Initialize connection to the Domain Runtime MBean Server
*/
public static void initConnection(String hostname, String portString,
String username, String password) throws IOException,
MalformedURLException {
String protocol = "t3";
Integer portInteger = Integer.valueOf(portString);
int port = portInteger.intValue();
String jndiroot = "/jndi/";
String mserver = "weblogic.management.mbeanservers.domainruntime";
JMXServiceURL serviceURL = new JMXServiceURL(protocol, hostname,
port, jndiroot + mserver);
Hashtable h = new Hashtable();
h.put(Context.SECURITY_PRINCIPAL, username);
h.put(Context.SECURITY_CREDENTIALS, password);
h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,
"weblogic.management.remote");
connector = JMXConnectorFactory.connect(serviceURL, h);
connection = connector.getMBeanServerConnection();
System.out.println("***************** get mbean count ************************* " + connection.getMBeanCount());
Set<ObjectName> mbeans = connection.queryNames(null, null);
for (ObjectName mbeanName : mbeans) {
System.out.println(mbeanName);
}
System.out.println("********************** ---- ***********************");
}
/*
* Print an array of ServerRuntimeMBeans.
* This MBean is the root of the runtime MBean hierarchy, and
* each server in the domain hosts its own instance.
*/
public static ObjectName[] getServerRuntimes() throws Exception {
return (ObjectName[])connection.getAttribute(service,
"ServerRuntimes");
}
/*
* Iterate through ServerRuntimeMBeans and get the name and state
*/
public void printNameAndState() throws Exception {
ObjectName[] serverRT = getServerRuntimes();
System.out.println("got server runtimes");
int length = (int) serverRT.length;
for (int i = 0; i < length; i++) {
String name = (String) connection.getAttribute(serverRT[i],
"Name");
String state = (String) connection.getAttribute(serverRT[i],
"Type");
System.out.println("Server name: " + name + ". Server state: "
+ state);
}
}
public static void main(String[] args) throws Exception {
String hostname = args[0];
String portString = args[1];
String username = args[2];
String password = args[3];
PrintServerState s = new PrintServerState();
System.out.println("hostname " + hostname);
System.out.println("portString " + portString);
System.out.println("username " + username);
System.out.println("password " + password);
initConnection(hostname, portString, username, password);
System.out.println("**************************************************");
s.printNameAndState();
connector.close();
}
}

Would this help -
domainRuntime()
cd('/ServerRuntimes/' + eval('managedServerName') + '/JVMRuntime/' + eval('managedServerName'))
heapFreeCurrentPerOld = str(cmo.getHeapFreePercent())
heapFreeCurrentValOld = str(cmo.getHeapFreeCurrent())

Related

How can I convert an Object to Json in a Rabbit reply?

I have two applications communicating with each other using rabbit.
I need to send (from app1) an object to a listener (in app2) and after some process (on listener) it answer me with another object, now I am receiving this error:
ClassNotFound
I am using this config for rabbit in both applications:
#Configuration
public class RabbitConfiguration {
public final static String EXCHANGE_NAME = "paymentExchange";
public final static String EVENT_ROUTING_KEY = "eventRoute";
public final static String PAYEMNT_ROUTING_KEY = "paymentRoute";
public final static String QUEUE_EVENT = EXCHANGE_NAME + "." + "event";
public final static String QUEUE_PAYMENT = EXCHANGE_NAME + "." + "payment";
public final static String QUEUE_CAPTURE = EXCHANGE_NAME + "." + "capture";
#Bean
public List<Declarable> ds() {
return queues(QUEUE_EVENT, QUEUE_PAYMENT);
}
#Autowired
private ConnectionFactory rabbitConnectionFactory;
#Bean
public AmqpAdmin amqpAdmin() {
return new RabbitAdmin(rabbitConnectionFactory);
}
#Bean
public DirectExchange exchange() {
return new DirectExchange(EXCHANGE_NAME);
}
#Bean
public RabbitTemplate rabbitTemplate() {
RabbitTemplate r = new RabbitTemplate(rabbitConnectionFactory);
r.setExchange(EXCHANGE_NAME);
r.setChannelTransacted(false);
r.setConnectionFactory(rabbitConnectionFactory);
r.setMessageConverter(jsonMessageConverter());
return r;
}
#Bean
public MessageConverter jsonMessageConverter() {
return new Jackson2JsonMessageConverter();
}
private List<Declarable> queues(String... nomes) {
List<Declarable> result = new ArrayList<>();
for (int i = 0; i < nomes.length; i++) {
result.add(newQueue(nomes[i]));
if (nomes[i].equals(QUEUE_EVENT))
result.add(makeBindingToQueue(nomes[i], EVENT_ROUTING_KEY));
else
result.add(makeBindingToQueue(nomes[i], PAYEMNT_ROUTING_KEY));
}
return result;
}
private static Binding makeBindingToQueue(String queueName, String route) {
return new Binding(queueName, DestinationType.QUEUE, EXCHANGE_NAME, route, null);
}
private static Queue newQueue(String nome) {
return new Queue(nome);
}
}
I send the message using this:
String response = (String) rabbitTemplate.convertSendAndReceive(RabbitConfiguration.EXCHANGE_NAME,
RabbitConfiguration.PAYEMNT_ROUTING_KEY, domainEvent);
And await for a response using a cast to the object.
This communication is between two different applications using the same rabbit server.
How can I solve this?
I expected rabbit convert the message to a json in the send operation and the same in the reply, so I've created the object to correspond to a json of reply.
Show, please, the configuration for the listener. You should be sure that ListenerContainer there is supplied with the Jackson2JsonMessageConverter as well to carry __TypeId__ header back with the reply.
Also see Spring AMQP JSON sample for some help.

Flume Custom Interceptor is not Working

I want to change IP address in data by its mask IP. This is done in the "backup" part of my Flume agent (see below).
In this configuration there are 2 channels: the first channel dumps data to HBase, while the second one is used for backup:
a1.sources = r1 r2
a1.channels = channel1 Backup_channel
a1.sinks = FSink
a1.sources.r1.handler = com.flume.handler.JSONHandler
a1.sources.r1.type = avro
a1.sources.r1.bind = x.x.x.x
a1.sources.r1.port = 10008
a1.sources.r2.handler = com.flume.handler.JSONHandler
a1.sources.r2.type = avro
a1.sources.r2.bind = x.x.x.x
a1.sources.r2.port = 10009
a1.sources.r2.interceptors = i1
a1.sources.r2.interceptors.i1.type = com.flume.interceptor.DcInterceptor
a1.channels.channel1.type = file
a1.channels.channel1.checkpointDir = /root/flume/channels/Livechannel/checkpoint
a1.channels.channel1.dataDirs = /root/flume/channels/Livechannel/data
a1.sinks.FSink.type = hbase
a1.sinks.FSink.table = Temp_Test
a1.sinks.FSink.batchSize = 300
a1.sinks.FSink.columnFamily = T
a1.sinks.FSink.serializer = com.flume.sink.TestTP
a1.sources.r1.channels = channel1
a1.sources.r2.channels = Backup_channel
a1.channels.Backup_channel.type = file
a1.channels.Backup_channel.checkpointDir = /data/disk/flume/backup/checkpoint
a1.channels.Backup_channel.dataDirs = /data/disk/flume/backup/data
a1.sinks.FSink.channel = channel1
Following is my custom Java Interceptor Code. It implements the interception method, which get an IP address from the body, calculates its IP mask and then adds it to the body. But somehow it's not working:
public class DcInterceptor implements Interceptor {
private byte[] jsonTestBeans;
private final Type listType = new TypeToken < List < TestBeans >> () {}.getType();
#Override
public void close() {
// TODO Auto-generated method stub
}
#Override
public void initialize() {
// TODO Auto-generated method stub
new Logger();
}
#Override
public Event intercept(Event event) {
// TODO Auto-generated method stub
List < Row > actions = new ArrayList < Row > ();
this.jsonTestBeans = event.getBody();
Logger.logger.debug("In Interceptor");
System.out.println("In Interceptor");
Gson _Gson = new Gson();
String jsonstr = "";
try {
jsonstr = new String(jsonTestBeans, "UTF-8");
} catch (Exception e) {
// TODO: handle exception
Logger.logger.error(e.getMessage() + "In Interceptor");
jsonstr = new String(jsonTestBeans);
}
List < TestBeans > TestBeanss = _Gson.fromJson(jsonstr, listType);
System.out.println("Json String :" + jsonstr);
List < String > gTouch = new ArrayList < String > ();
for (TestBeans TestBeans: TestBeanss) {
String str = TestBeans.getIp();
Logger.logger.debug("IP : " + str);
String st = (str.substring(0, str.lastIndexOf(".") + 1) + "x");
Logger.logger.debug("Mask IP : " + st);
TestBeans.setRemoteIp(st);
}
event.setBody(_Gson.toJson(TestBeanss).getBytes());
Logger.logger.debug("Interceptor Ends");
return event;
}
#Override
public List < Event > intercept(List < Event > events) {
// TODO Auto-generated method stub
System.out.println("In List Interceptor");
Logger.logger.debug("In List Interceptor");
for (Event event: events) {
intercept(event);
}
return events;
}
public static class CounterInterceptorBuilder implements Interceptor.Builder {
private Context ctx;
#Override
public Interceptor build() {
Logger.logger.debug("In Interceptor Build");
System.out.println("In Build Interceptor");
return new DcInterceptor();
}
#Override
public void configure(Context context) {
this.ctx = context;
}
}
At least, I can see:
The configuration lines regarding your interceptor refer to an agent called ECircleTp_Test, while the rest of the configuration refer to a1.
You have configured com.flume.interceptor.DcInterceptor2, but the interceptor class you have developed is called DcInterceptor (without the final 2).
You have configured com.flume.interceptor.DcInterceptor2 as the fully qualified class name of your custom interceptor. Nevertheless, the code of the interceptor does not declare any package for the DcInterceptor(2) class.

AWS Cognito user authentication Missing required parameter SRP_A

I am trying to use AWS Cognito services for user authentication through ruby SDK.
I could able to sign_up, confirm sign_up process using the methods
resp = client.sign_up({ client_id: "ClientIdType",
secret_hash: "SecretHashType",
username: "UsernameType",
password: "PasswordType",
user_attributes: [{ name:"AttributeNameType",
value: "AttributeValueType",
}],
validation_data: [{
name: "AttributeNameType",
value: "AttributeValueType",
}]
})
and confirm_sign_up using
resp = client.confirm_sign_up({client_id: "ClientIdType",
secret_hash: "SecretHashType",
username: "UsernameType",
confirmation_code: "ConfirmationCodeType"
})
But while trying to sign in the user through initiate_auth I am getting an error Missing required parameter SRP_A
cog_provider.initiate_auth({client_id: "xxxxxxxxx", auth_parameters: { username: "xxx", password: "xxx"}, auth_flow: "USER_SRP_AUTH"})
What does SRP_A indicate where to find it.
I have searched for this problem and It is suggested to use the admin_initiate_auth method for signing in a user which I don't believe a best practice.
Yes, SRP_A is a large integer as defined by the Secure Remote Password Protocol. Are you trying to do SRP or just authenticate with username and password. For username/password authentication you should use the AdminInitiateAuth operation.
In our SDKs, you can see the parameters that need to be computed and passed. Take for example the Javascript SDK:
https://github.com/aws/amazon-cognito-identity-js/blob/master/src/CognitoUser.js#L152
Or in the Android SDK:
https://github.com/aws/aws-sdk-android/blob/master/aws-android-sdk-cognitoidentityprovider/src/main/java/com/amazonaws/mobileconnectors/cognitoidentityprovider/CognitoUser.java#L2123
For AWS Java SDK:
here is the class to manage this:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.math.pro.ak.util.cognito;
import com.amazonaws.AmazonClientException;
import com.amazonaws.util.StringUtils;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
/**
*
* #author marcus
*/
public class AuthenticationHelper {
private BigInteger a;
private BigInteger A;
private String poolName;
public AuthenticationHelper(String userPoolName) {
do {
a = new BigInteger(EPHEMERAL_KEY_LENGTH, SECURE_RANDOM).mod(N);
A = GG.modPow(a, N);
} while (A.mod(N).equals(BigInteger.ZERO));
if (userPoolName.contains("_")) {
poolName = userPoolName.split("_", 2)[1];
} else {
poolName = userPoolName;
}
}
public BigInteger geta() {
return a;
}
public BigInteger getA() {
return A;
}
private static final String HEX_N = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
+ "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
+ "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
+ "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
+ "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
+ "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
+ "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
+ "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
+ "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
+ "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF";
private static final BigInteger N = new BigInteger(HEX_N, 16);
private static final BigInteger GG = BigInteger.valueOf(2);
private static final BigInteger KK;
private static final int EPHEMERAL_KEY_LENGTH = 1024;
private static final int DERIVED_KEY_SIZE = 16;
private static final String DERIVED_KEY_INFO = "Caldera Derived Key";
private static final ThreadLocal<MessageDigest> THREAD_MESSAGE_DIGEST = new ThreadLocal<MessageDigest>() {
#Override
protected MessageDigest initialValue() {
try {
return MessageDigest.getInstance("SHA-256");
} catch (final NoSuchAlgorithmException e) {
throw new AmazonClientException("Exception in authentication", e);
}
}
};
private static final SecureRandom SECURE_RANDOM;
static {
try {
SECURE_RANDOM = SecureRandom.getInstance("SHA1PRNG");
final MessageDigest messageDigest = THREAD_MESSAGE_DIGEST.get();
messageDigest.reset();
messageDigest.update(N.toByteArray());
final byte[] digest = messageDigest.digest(GG.toByteArray());
KK = new BigInteger(1, digest);
} catch (final NoSuchAlgorithmException e) {
throw new AmazonClientException(e.getMessage(), e);
}
}
public byte[] getPasswordAuthenticationKey(String userId,
String userPassword,
BigInteger B,
BigInteger salt) {
// Authenticate the password
// u = H(A, B)
final MessageDigest messageDigest = THREAD_MESSAGE_DIGEST.get();
messageDigest.reset();
messageDigest.update(A.toByteArray());
final BigInteger u = new BigInteger(1, messageDigest.digest(B.toByteArray()));
if (u.equals(BigInteger.ZERO)) {
throw new AmazonClientException("Hash of A and B cannot be zero");
}
// x = H(salt | H(poolName | userId | ":" | password))
messageDigest.reset();
messageDigest.update(poolName.getBytes(StringUtils.UTF8));
messageDigest.update(userId.getBytes(StringUtils.UTF8));
messageDigest.update(":".getBytes(StringUtils.UTF8));
final byte[] userIdHash = messageDigest.digest(userPassword.getBytes(StringUtils.UTF8));
messageDigest.reset();
messageDigest.update(salt.toByteArray());
final BigInteger x = new BigInteger(1, messageDigest.digest(userIdHash));
final BigInteger s = (B.subtract(KK.multiply(GG.modPow(x, N)))
.modPow(a.add(u.multiply(x)), N)).mod(N);
Hkdf hkdf = null;
try {
hkdf = Hkdf.getInstance("HmacSHA256");
} catch (final NoSuchAlgorithmException e) {
throw new AmazonClientException(e.getMessage(), e);
}
hkdf.init(s.toByteArray(), u.toByteArray());
final byte[] key = hkdf.deriveKey(DERIVED_KEY_INFO, DERIVED_KEY_SIZE);
return key;
}
}
And call this the method:
userAuth.put("SRP_A", new AuthenticationHelper(request.getUsername()).getA().toString(16));

SignalR: can't connect to local or any other ip address

I am trying to make SignalR server and client architecture in which i am able to connect to "http://localhost:8080" or http://127.0.0.1:8080/ but i am not able to connect my local ip address like "192. x.x.x" so what could be reason?
please help me i am also placing my code overhere...
public partial class WinFormsServer : Form
{
private IDisposable SignalR { get; set; }
const string ServerURI = "http://localhost:8080";
private void ButtonStart_Click(object sender, EventArgs e)
{
WriteToConsole("Starting server...");
ButtonStart.Enabled = false;
Task.Run(() => StartServer());
}
private void StartServer()
{
try
{
SignalR = WebApp.Start(ServerURI);
}
catch (TargetInvocationException)
{
WriteToConsole("Server failed to start. A server is already running on " + ServerURI);
//Re-enable button to let user try to start server again
this.Invoke((Action)(() => ButtonStart.Enabled = true));
return;
}
this.Invoke((Action)(() => ButtonStop.Enabled = true));
WriteToConsole("Server started at " + ServerURI);
}
class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();
}
}
}
I tried different solutions but could not find correct one.
Finally I found the issue that was only related to the permission.
Run your SignalR server application as administrator. It will start running on the local IP like 192.168.X.X:9090 and then your client application can connect this server from any other PC using this IP address.
class Program
{
static void Main(string[] args)
{
var url = $"http://{GetLocalIPAddress()}:8080";
using (WebApp.Start<Startup>(url))
{
Console.WriteLine($"Server running at {{{url}}}");
Console.ReadLine();
}
}
public static string GetLocalIPAddress()
{
var host = Dns.GetHostEntry(Dns.GetHostName());
foreach (var ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
return ip.ToString();
}
}
throw new Exception("Local IP Address Not Found!");
}
}
To get your local IP address you could use this function:
public static string GetLocalIPAddress()
{
var host = Dns.GetHostEntry(Dns.GetHostName());
foreach (var ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
return ip.ToString();
}
}
throw new Exception("Local IP Address Not Found!");
}
If you want to use FQDN - Fully Qualified Domain Name, then you could use this function:
public static string GetLocalFQDN()
{
var props = IPGlobalProperties .GetIPGlobalProperties();
return props.HostName + (string.IsNullOrWhiteSpace(props.DomainName) ? "" : "." + props.DomainName);
}
After that you could use:
SignalR = WebApp.Start("http://" + GetLocalFQDN() + ":8080");
or
SignalR = WebApp.Start("http://" + GetLocalIPAddress() + ":8080");
I hope this helps.
Since you are using this source i used the same too.
-For FQDN, first create the function below.
public static string GetLocalFQDN()
{
var props = IPGlobalProperties.GetIPGlobalProperties();
return props.HostName + (string.IsNullOrWhiteSpace(props.DomainName) ? "" : "." + props.DomainName);
}
Then modify the const string ServerURI to:
string ServerURI =String.Concat("http://",GetLocalFQDN(),":8080");
-For LocalIPAdress, first create the function below which will the your local address:
public static string GetLocalIPAddress()
{
var host = Dns.GetHostEntry(Dns.GetHostName());
foreach (var ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
return ip.ToString();
}
}
throw new Exception("Local IP Address Not Found!");
}
and change the string ServerURI =String.Concat("http://",GetLocalFQDN(),":8080"); to:
string ServerURI =String.Concat("http://",GetLocalIPAddress(),":8080");
Hope this helps you.
Note: The changes should be done in the WinFormsServer:Form class on the WinFormsServer project.

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