I've not been able to find any information on this, so I apologize if this is a duplicate.
I'm using an ASP website to trigger a WebMethod on my code behind that will trigger the service on the computer to change its state to some state specified on the front-end.
However, I want to make it so that when I call ServiceController.WaitForStatus() on Timeout it returns to the default status it started with prior to the call. So, if something doesn't start/pause/stop fast enough it'll revert to its previous state like nothing happened.
Is there a way to do this? I tried calling ServiceController.close() and that did nothing for me.
Is there a way to manage this gracefully so that if the timeout exception occurs it catches the exception gracefully and returns the service back to its original state prior to the service controller call.
This is the web method code I'm using:
[WebMethod]
public static string ToggleService(string serverName, string serviceName, string newServiceState) {
ServiceController serviceToToggle = null;
if (newServiceState.ToLower().Equals("start")
|| newServiceState.ToLower().Equals("pause")
|| newServiceState.ToLower().Equals("stop")) {
serviceToToggle = new ServiceController(serviceName, serverName);
}
if (serviceToToggle != null)
{
try
{
if (serviceToToggle.Status == ServiceControllerStatus.Paused)
{
if (newServiceState.ToLower().Equals("start"))
{
serviceToToggle.Start();
serviceToToggle.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 1));
}
else if (newServiceState.ToLower().Equals("stop"))
{
serviceToToggle.Stop();
serviceToToggle.WaitForStatus(ServiceControllerStatus.Stopped, new TimeSpan(0, 0, 1));
}
}
else if (serviceToToggle.Status == ServiceControllerStatus.Running)
{
if (newServiceState.ToLower().Equals("pause"))
{
serviceToToggle.Pause();
serviceToToggle.WaitForStatus(ServiceControllerStatus.Paused, new TimeSpan(0, 0, 1));
}
else if (newServiceState.ToLower().Equals("stop"))
{
serviceToToggle.Stop();
serviceToToggle.WaitForStatus(ServiceControllerStatus.Stopped, new TimeSpan(0, 0, 1));
}
}
else if (serviceToToggle.Status == ServiceControllerStatus.Stopped)
{
if (newServiceState.ToLower().Equals("start"))
{
serviceToToggle.Start();
serviceToToggle.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 1));
}
}
return "\"OutputStatus\": \"Success\"";
}
catch (Exception e) {
serviceToToggle.Close();
return "\"OutputStatus\": \"Failed\"";
}
}
return "No service to toggle";
}
I would appreciate any help or insight into this.
In short, no - there is no way to revert or cancel a command already sent to a service.
You could write code to remember the previous state, and initiate a controller request to set that state again if something goes awry or times out, but it doesn't sound particularly robust.
If they're your own services, it's better to write them to properly respond to service requests.
Related
using IPC over local TCP to communicate from Client to a Server thread. The connection itself doesn't seem to be throwing any errors, but every time I try to make one of the associated calls, I get this message:
System.Runtime.Remoting.RemotingException: Could not connect to an IPC Port: The System cannot Find the file specified
What I am attempting to figure out is WHY. Because this WAS working correctly, until I transitioned the projects in question (yes, both) from .NET 3.5 to .NET 4.0.
Listen Code
private void ThreadListen()
{
_listenerThread = new Thread(Listen) {Name = "Listener Thread", Priority = ThreadPriority.AboveNormal};
_listenerThread.Start();
}
private void Listen()
{
_listener = new Listener(this);
LifetimeServices.LeaseTime = TimeSpan.FromDays(365);
IDictionary props = new Hashtable();
props["port"] = 63726;
props["name"] = "AGENT";
TcpChannel channel = new TcpChannel(props, null, null);
ChannelServices.RegisterChannel(channel, false);
RemotingServices.Marshal(_listener, "Agent");
Logger.WriteLog(new LogMessage(MethodBase.GetCurrentMethod().Name, "Now Listening for commands..."));
LogEvent("Now Listening for commands...");
}
Selected Client Code
private void InitializeAgent()
{
try
{
_agentController =
(IAgent)RemotingServices.Connect(typeof(IAgent), IPC_URL);
//Note: IPC_URL was originally "ipc://AGENT/AGENT"
// It has been changed to read "tcp://localhost:63726/Agent"
SetAgentPid();
}
catch (Exception ex)
{
HandleError("Unable to initialize the connected agent.", 3850244, ex);
}
}
//This is the method that throws the error
public override void LoadTimer()
{
// first check to see if we have already set the agent process id and set it if not
if (_agentPid < 0)
{
SetAgentPid();
}
try
{
TryStart();
var tries = 0;
while (tries < RUNCHECK_TRYCOUNT)
{
try
{
_agentController.ReloadSettings();//<---Error occurs here
return;
} catch (RemotingException)
{
Thread.Sleep(2000);
tries++;
if (tries == RUNCHECK_TRYCOUNT)
throw;
}
}
}
catch (Exception ex)
{
HandleError("Unable to reload the timer for the connected agent.", 3850243, ex);
}
}
If you need to see something I haven't shown, please ask, I'm pretty much flying blind here.
Edit: I think the issue is the IPC_URL String. It is currently set to "ipc://AGENT/AGENT". The thing is, I have no idea where that came from, why it worked before, or what might be stopping it from working now.
Update
I was able to get the IPC Calls working correctly by changing the IPC_URL String, but I still lack understanding of why what I did worked. Or rather, why the original code stopped working and I needed to change it in the first place.
The string I am using now is "tcp://localhost:63726/Agent"
Can anyone tell me, not why the new string works, I know that...but Why did the original string work before and why did updating the project target to .NET 4.0 break it?
Here is my problem:
I have a Wcf service on a server that has two methods:
Synchronize() and GetExecutionState().
I also have a client that is to call those operations.
The Synchronize() executes lots of things and in several steps so at each step i update a local (inside the wcf) variable and i publish this variable via the GetExecutionState() operation The operation can fail, can take eons to execute and so on.
So, when i consume this service on the client, say on somebutton_click() event,
what i want to happen is this:
show infinite progressbar (main thread, UI);
start a thread to run Synchronize();
start another thread to keep reading GetExecutionState() every x minutes and in the event of a connection failure (which is the main reason i need this last thread) cancel the whole thing.
I dont know lot about threading, but so far i have implemented 1 and 2. Can someone help me with 3?
I am using devExpress and here is my relevant code.
SERVER PART:
public class SyncServerService :ISyncServer {
protected CsNo Node;
protected SyncState State;
public SyncServerService() {
State = SyncState.None;
Node = null;
}
public SyncState OperationState() {
return State;
}
public void PutComputerName(string value) {
var man = new CsNoManager();
Node = man.GetByMachineName(value);
}
public bool CanSync() {
var man = new ViewSyncLogManager();
var log = man.GetByMachineName(Node.MachineName);
return !log[0].IsInSync;
}
public CommandExecutionResponse Synchronize() {
CommandExecutionResponse res = null;
var logManager = new CsLogSyncManager();
var log = logManager.GetByNode(Node.IDNo);
State=SyncState.Syncing;
//step 1
State = SyncState.State2;
//...step n
State = SyncState.SomeOtherState;
//somewhere along the path create the res object
return res;
}
}
I read somewhere that with WCF, i can call operations both sync and async, so i dont think i have to mess with the server part regarding my requirements.
Client part:
On the button click that starts the process:
private void cmdSync_Click(object sender, EventArgs e) {
pgbSync.Properties.Stopped = false;
backgroundWorker1.RunWorkerAsync();
}
pgbSync is of type MarqueeProgressBar, a DevExpress progressbar that has infinite loop
backgroundWorker1 is of type System.ComponentModel.BackgroundWorker...supposedly runs tasks on the background.
It's start and finish methods are:
START:
private void StartSync(object sender, DoWorkEventArgs e) {
try {
//setting up wcf link properties
var manager = new CsConfiguracaoManager();
var address = manager.SyncAppServiceAddress();
var binding = new NetTcpBinding {
Security = new NetTcpSecurity() { Mode = SecurityMode.None },
CloseTimeout = new TimeSpan(0, 0, 30, 0, 0),
OpenTimeout = new TimeSpan(0, 0, 30, 0, 0),
ReceiveTimeout = new TimeSpan(0, 0, 30, 0, 0),
SendTimeout = new TimeSpan(0, 0, 30, 0, 0)
};
var factory = new ChannelFactory<ISyncServer>(binding, new EndpointAddress(address));
var proxy = factory.CreateChannel();
proxy.PutComputerName(PcName);
//checking if i can sync first
if (proxy.CanSync() == true) {
ExecutionResponse = proxy.Sync();
}
else {
//set up messages to show errors
}
}
catch (DataException dataErr) {
//set up appropriate messages
}
catch (EndpointNotFoundException err) {
//set up appropriate messages
}
catch (Exception masterErr) {
//set up appropriate messages
}
}
FINISH:
private void FinishSync(object sender, RunWorkerCompletedEventArgs e) {
pgbSync.Properties.Stopped = true;
//process ExecutionResponse object from FinishSync
}
This all runs, but if i disconnect the network after the process has started (we are anticipating lots of communication issues) the process will only throw an exception after the 30 minutes set in the service have passed.
Thats why i want to introduce a 3rd step where i check every x minutes for the output of OperationState.
If i cannot read it, i abort the operation, if it has a null or err state i also stop.
Any ideas?
I am note sure if you need a 3rd thread for this.
Have you tried System.Timers.Timer to have an event generated every x seconds and doing your checks?
If that event does not occur you can go with a BackgroundWorker which will have a loop with Thread.Sleep(250) and cancelation checks.
I am troubleshooting an issue on a relatively simple socket application which is listening for status updates from a third party machine. I have set up a TcpListener object to wait for a connection request and then establish the socket to read the data coming in. I get the periodic heartbeat as expected without issue, but whenever there is a sudden change in status the server machine sends out an immediate update which I don't get. The bizarre thing here is that I get the update no problem if I set a breakpoint in the code.
The server itself handles these connections a little strangely and doesn't maintain an open socket connection. when it tries to send data, it opens the connection, sends data, and then closes the connection, which is why I've built this to similarly wait for a connection and close it when the data transfer is done before beginning to listen for another connection request.
private void ListeningThread()
{
bool keep_going = CreateConnection();
CreateTimer();
while (keep_going)
{
try
{
if (m_ThreadShutdownEvent.IsSet)
{
// event was set, so shut down
keep_going = false;
m_Listener.Stop();
bool appshuttingdown = false;
DestroyTimer();
lock (m_Lock)
{
appshuttingdown = m_ApplicationShutDown;
}
if (!appshuttingdown)
{
RunStatusNotification();
}
Connected = false;
}
else
{
if (m_Listener.Pending())
{
Socket socket = m_Listener.AcceptSocket();
if (socket != null)
{
StateObject state = new StateObject();
state.Socket = socket;
try
{
int bytes_read = socket.Receive(state.Buffer, 0, StateObject.BUFFER_SIZE, SocketFlags.None);
DateTime now = DateTime.UtcNow;
if (bytes_read == 14)
{
if (state.Buffer.Count() > 13)
{
int packet = state.Buffer[13];
InterpretRelevantByte(packet, now);
}
}
}
catch (Exception ex)
{
FireUnknownException(ex);
}
finally
{
socket.Close();
}
}
}
}
}
catch (Exception ex)
{
m_Logger.Error(ex);
}
}
}
It's possible that your call to receive gets you some value greater than or less than 14, you should probably add some logic to inspect the data you receive when bytes read is not equal to 14 since in these cases you are discarding what you've read.
int bytes_read = socket.Receive(state.Buffer, 0, StateObject.BUFFER_SIZE, SocketFlags.None);
DateTime now = DateTime.UtcNow;
if (bytes_read == 14)
{
if (state.Buffer.Count() > 13)
{
int packet = state.Buffer[13];
InterpretRelevantByte(packet, now);
}
}
else if (bytes_read > 14)
{
// maybe you received multiple messages in one packet
}
else
{
// maybe there is more data on the way
}
Ok, I've resolved this. Turns out I was closing the socket too soon which led to some weird behavior that, honestly, I don't fully understand, but I do know how I fixed it.
After opening the socket I needed to continue listening for data until receiving a 0 length message which signaled that the server had closed the connection. At that point I could start listening for a new socket connection request. I'm still not sure why I would get the heartbeats only, but everything has been working perfectly since I made the change.
I have highload ASP .NET MVC2 website and WCF service that site uses. Early I created one proxy every time I need it and even didn't close it. Refer to my previous question (with my big thanks for SO user Richard Blewett) I found out that I should close this proxy. In other way it will succeed sessions limit.
Now, I'm creating proxy one time app starts and then just check it and recreate it if is needed. So, here is the code:
public static bool IsProxyValid(MyServ.MyService client) {
bool result = true;
if ((client == null) || (client.State != System.ServiceModel.CommunicationState.Opened) // || (client.InnerChannel.State != CommunicationState.Opened)
)
result = false;
return result;
}
public static AServ.AServClient GetClient(HttpContext http) {
if (!IsProxyValid((MyService)http.Application["client"]))
http.Application["client"] = new MyService();
return (MyService)http.Application["client"];
}
public static MyServ.MyService GetClient(HttpContextBase http)
{
if (!IsProxyValid((MyService)http.Application["client"]))
http.Application["client"] = new MyService();
return (MyService)http.Application["client"];
}
public ActionResult SelectDepartment(string departments)
{
try
{
MyService svc = CommonController.GetClient(this.HttpContext);
Department[] depsArray = svc.GetData(departments);
// .... I cut here ....
return View();
}
catch (Exception exc)
{
// log here
return ActionUnavailable();
}
}
So, what do you guys think about it? Should it work properly? Sometimes my app stucked. I think it is because client proxy state determines uncorrectly and app tries to use broken proxy.
POST EDIT
Also in TCP Monitor I see a lot of established connections from site to service. Why it creates a lot of connectiong insteads of using one global? Maybe some exception occured while invoking service method makes it faulted state?
Hope for your help guys!
I think you need to abort the channel if it gets faulted before creating a new one and
Make sure to close/ abort old client if you creating the new client, use something like this for that (this one is used with DI in singleton)
public class MyServiceClientInitializer : IMyServiceClientInitializer
{
[ThreadStatic]
private static MyServ.MyService _client;
public MyServ.MyService Client
{
get
{
if (_client == null
|| (_client.State != CommunicationState.Opened
&& _client.State != CommunicationState.Opening))
IntializeClient();
return _client;
}
}
private void IntializeClient()
{
if (_client != null)
{
if (_client.State == CommunicationState.Faulted)
{
_client.Abort();
}
else
{
_client.Close();
}
}
string url = //get url;
var binding = new WSHttpBinding();
var address = new EndpointAddress(url);
_client = new MyServ.MyService(binding, address);
}
}
Not quite sure how to do this or if it even is a proper way to program c#. Maybe I need to rethink what I am trying to do, but I need some help.
I have a wpf application that starts/stops a service and also uses a named pipe to open a port and communicate with the service. So when the service needs to it can send a message to the app. I started a new thread to invoke a Wait() method that sits at namedPipeServerStream.WaitForConnection(). This works fine, but when the service is stopped I send a message to the app so it breaks the WaitForConnection, however I dont want to kill this thread, I want to reinvoke the same method and wait in a loop until the service starts again. Not sure of the best way to do this.
The code I have so far is below.
void Wait()
{
while (!ServiceControl.ServiceRunning)
{
Thread.Sleep(250);
if (exitProgram == true)
{
break;
}
}
while (ServiceControl.ServiceRunning)
{
try
{
NamedPipeServerStream namedPipeServerStream = new NamedPipeServerStream("pipeName");
namedPipeServerStream.WaitForConnection();
byte[] buffer = new byte[255];
namedPipeServerStream.Read(buffer, 0, 255);
string request = ASCIIEncoding.ASCII.GetString(buffer);
if (request != null)
{
if (request == "pipeExit")
{
Wait(); //Reinvoke Wait if svc calls to exit
}
else
{
//Do work on message
}
}
namedPipeServerStream.Close();
}
catch (Exception){}
}
if (_opener.exitProgram == true)
{
Application.Current.Dispatcher.InvokeShutdown();
}
Why don't you put a while(!opener.exitProgram) around your entire Wait implementation? That way you'll get back to the start once the pipe is closed.