wsmprovhost.exe do not terminate after closing WsManConnectionInfo - c#

I have class (let's call it DbHostWindows) that contains various things about a windows server. I make an instance of this whenever I want to do something remotely on the server. One of the things this class consist of is a WsManConnection - this is part of the constructor:
vWinRM = new WsManConnection(vServerName);
public WsManConnection(string wsManHostName) {
vWsManConnectionInfo = new WSManConnectionInfo(new Uri($"http://{wsManHostName}:5985/wsman")) {
OpenTimeout = WsManDefaultTimeoutInMs,
OperationTimeout = WsManDefaultTimeoutInMs,
IdleTimeout = WsManIdleTimeoutInMs
};
Init();
}
I have noticed that whenever I run the DbHostWindows constructor I get a wsmprovhost.exe process running on the server.
"C:\windows\system32\wsmprovhost.exe -Embedding"
I also noticed that the default timeout of such a process apparently is around 24 days. Setting IdleTimeout to 60000 (minimum value) reduce the timeout to a minute.
My problem is that I would like to get rid of the wsmprovhost.exe process earlier than a minute - in fact as soon as I dispose of the DbHostWindows object and hence the WsManConnectionInfo. I know at this point I will never use this connection again. I can't figure out how to do this, however.
For testing purposes I tried adding these commands in the end of the constructor in order to try and kill it asap and being sure the connection wasn't used for anything:
vWinRm.PowerShell.Stop();
vWinRm.PowerShell.Runspace.Disconnect();
vWinRm.PowerShell.Dispose();
vWinRm.Dispose();
Neither seem to affect the wsmprovhost.exe process at all. The wsmprovhost.exe does close after the IdleTimeout is up. As a workaround I could just raise the MaxProcessesPerShell on the server, but I would rather get these processes to close when the DbHostWindows is disposed.

Related

Crystal Reports reaches job limit despite garbage collection

I have a C# application I recently converted into a service. As part of its normal operation, it creates PDF invoices via CR using the following code:
foreach (string docentry in proformaDocs)
using (ReportDocument prodoc = new ReportDocument()) {
string filename = outputFolder + docentry + ".pdf";
prodoc.Load(/* .rpt file */);
prodoc.SetParameterValue(0, docentry);
prodoc.SetParameterValue(1, 17);
prodoc.SetDatabaseLogon(/* login data */);
prodoc.ExportToDisk(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat,
filename);
prodoc.Close();
prodoc.Dispose();
}
foreach (string docentry in invoiceDocs)
using (ReportDocument invdoc = new ReportDocument()) {
string filename = differentOutputFolder + docentry + ".pdf";
invdoc.Load(/* different .rpt file */);
invdoc.SetParameterValue(0, docentry);
invdoc.SetParameterValue(1, 13);
invdoc.SetDatabaseLogon(/* login data */);
invdoc.ExportToDisk(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat,
filename);
invdoc.Close();
invdoc.Dispose();
}
GC.Collect();
Problem is, after about 3-4 hours of runtime with the above code executing at most every two minutes, the Load() operation hits the processing job limit despite me explicitly disposing the report objects. However, if I leave the service running and launch a non-service instance of the same application, that one executes properly even while the service is still throwing the job limit exception. With the non-service instance having taken care of the processing, the service has nothing to do for the moment - but the instant it does, it throws the error again until I manually stop and restart the service, at which point the error goes away for another 3-4 hours.
How am I hitting the job limit if I'm manually disposing every single report object as soon as I'm done with it and calling garbage collection after each round of processing and disposing? And if the job limit is reached, how can a parallel instance of the same code not be affected by it?
UPDATE: I managed to track down the problem and as it turns out, it's not with CR. I take CR's database login credentials from a SAP Company object inside a Database wrapper class stored in a Dictionary, fetched with this:
public Company GetSAP(string name) {
Database db; //wrapper class
SAP.TryGetValue(name, out db); //fetching from the Dictionary
return db.SAP; //Company object in the wrapper class
}
For some reason, calling this freezes the thread, but the Timer launching the service's normal operation naturally doesn't wait for it to complete and launches another thread, which freezes too upon calling this. This keeps up until the number of frozen threads hits the job limit, at which point an exception is thrown by each new thread due to the still frozen threads filling the job limit. I put in a check to not launch a new thread if one is still running and the application froze upon calling the above function.
The getter of the object the return db.SAP above calls has literally nothing in it other than a return.
Alright, the problem was kinda solved. For some reason, the getters in the COM object I was trying to fetch the login credentials from freeze if accessed from a service but not from a non-service application. Testing this COM-object-stuffed-into-wrapper-class-stuffed-into-Dictionary setup in an IIS application also yielded no freezes. I have no idea why and short of SAP sharing the source code for said COM object, I'm unlikely to ever find out. So I simply declared a few string fields for storing the credentials and cut accessing the COM object out entirely since I didn't need it, only its fields.

Session variables lost - Singleton instance becomes null

I'm working on a Web app using ASP.NET. I have a class called "Sistema" that uses the Singleton pattern.
When the instance of Sistema is created, the database connection is opened and a process runs that loads some static information for later use. This lasts almost 2 minutes.
private static Sistema instance;
private Sistema()
{
OpenDataBase();
LoadStaticInformation();
}
public static Sistema GetInstance()
{
if (instance == null)
{
instance = new Sistema();
}
return instance;
}
The reason why I keep the connection to the database open is because I'm using db4o, that strongly suggests this. Here are some references:
db4o best practice to query objects from db
Is it OK to open a DB4o file for query, insert, update multiple times?
Query regarding database connectivity in db4o
On my Web App I have a Master Page that controls if the user is logged in by checking a Session variable. If this Session is null, then the user is sent to the Login Page.
On the Login Page, the first thing I do is to check if the instance of "Sistema" is null. If it is, then when the user hits the Submit button, a message is shown saying "Login can take up to two minutes. Please wait". If it is not null, then no message is shown as the login action takes only a couple of seconds.
I have been told by the users, that when going through the System, they are sometimes sent back to the login page, and when they try to login, the message saying "Login can take up to two minutes" is displayed and login indeed takes a while.
The fact that they are sent back to the login page means that the Session variable is lost, and the message being displayed means that the instance of "Sistema" is also null.
In order to determine why this is happening, I created a web page that sends an email to me when the instance of Sistema detected to be null. I thought that if I was able to know when this occurred, I might discover what is going on.
This web page is really simple. It runs every 10 minutes and checks if the instance of Sistema is null. If it is, then an email is sent and the instance of Sistema is created.
bool isInstanceNull = Sistema.IsInstanceNull();
if (isInstanceNull)
{
String emailTo = "...";
String emailContent = "...";
Functions.SendMail(emailTo, "Sistema is null", emailContent, "");
Sistema.GetInstance();
Functions.SendMail(emailTo, "Sistema has been created", emailContent, "");
}
The only thing I discovered is that it's not happening at a specific time. For example, last week it happened around 7pm, but today it happened at 2 am.
Regarding the Session timeout, I'm using a solution in the code behind: http://www.beansoftware.com/ASP.NET-Tutorials/Keep-Session-Alive.aspx.
Any suggestions to why is this happening?
The application pool has a property that causes it to be automatically recycled every N minutes (defaults to 1740, or every 29 hours.) Make this zero to disable recycling. The propertry is (on IIS7) under the "Recycling" heading and is called "Regular Time Interval (minutes)"
Apart from that, you should always close connections immediately and dont use static connections at all in ASP.NET (when Connection-Pooling is enabled which is default).
I mention it because of:
private static Sistema instance;
private Sistema()
{
OpenDataBase();
LoadStaticInformation();
}
You should not keep a connection to the database open. Typically a new connection is opened for every request. Maybe the database sometimes decides it has too many users or the connection is open for too long, as a result it closes the connection and your object crashes. An open connection to the database is also a security risk.
I'm not 100% sure about this though...
You should probably move connecting to the database down to some kind of query execute method. Also it seems unwise to load such a blob of data all at once, can't you do it on the background or only load the information a user needs to see at the time?

C# Timer doesn't work correctly

I use Asp .NET Mvc 3 for creating web page and I need to change something in database after each 20 minutes...
I set Timer in my Global.asax.cs file . Here is the code
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
Unit = new UnitOfWork();
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 1200000; //20 minutes
timer.Elapsed += new System.Timers.ElapsedEventHandler(Elapsed);
timer.Start();
}
void Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Unit.Srvc.UpdateUserActivity();
}
Now I run it today, and what a pitty, it works only one time... After 20 minutes it change database and it's all.
P.S.Yesteday I tested it in 20 seconds and it works fine. But,today it don't want to work correctly in 20 minutes interval. Thank you for help.
P.S.2 I used Stored Procedure for updating database.
P.S.3 Just now I detect that it works randomly :D In 5:32Am I run the program... It works in 5:52Am, doesn't work in 6:12Am, and works now(now is 6:49 Am, I don't know when it works).
Most likely cause is that your AppDomain is shutting down due to inactivity, which means the entire application is not running. The idle timeout is 20 minutes of inactivity, I think.
See this question:
How to keep ASP.NET assemblies in AppDomain alive?
To me it looks like your timer will be killed by garbage collection as you are not keeping a reference to it after it goes out of scope from Application_Start. Try adding:
Application["Whatever"] = timer;
You might be finding that your thread (from the IIS AppPool) is being recycled or shut down.
Web applications typically work best when used for request-response processing rather than this type of behaviour. It's not clear what you are up to, but assuming you are using SQL Server perhaps you could look at maintenance tasks or triggers if it involves denormalizing data (i.e. rolling up calculated data). If it involves data collected during the request-response process then perhaps you might look at using the web cache and some cache expiration operations for the delayed persistence.
My guess is too that the session simply expires but I would like to add a little extra.
Reading the code I guess (again) that you are marking the user in the database as 'not active' or disconnected or something like that. If so, do not use a timer to do this, instead, set the session expiration (when the user hasn't sent any requests for a certain period) to the required duration and put the code you want to run when that happens in the Session_OnEnd handler

RasConnectionNotification after computer resumes from sleep

I've got a project called DotRas on CodePlex that exposes a component called RasConnectionWatcher which uses the RasConnectionNotification Win32 API to receive notifications when connections on a machine change. One of my users recently brought to my attention that if the machine comes out of sleep mode, and attempts to redial the connection, the connection goes into a loop indicating the connection is already being dialed even though it isn't. This loop will not end until the application is restarted, even if done through a synchronous call which all values on the structs are unique for that specific call, and none of it is retained once the call completes.
I've done as much as I can to fix the problem, but I fear the problem is something I've done with the RasConnectionNotification API and using ThreadPool.RegisterWaitForSingleObject which might be blocking something else in Windows.
The below method is used to register 1 of the 4 change types the API supports, and the handle to associate with it to monitor. During runtime, the below method would be called 4 times during initialization to register all 4 change types.
private void Register(NativeMethods.RASCN changeType, RasHandle handle)
{
AutoResetEvent waitObject = new AutoResetEvent(false);
int ret = SafeNativeMethods.Instance.RegisterConnectionNotification(handle, waitObject.SafeWaitHandle, changeType);
if (ret == NativeMethods.SUCCESS)
{
RasConnectionWatcherStateObject stateObject = new RasConnectionWatcherStateObject(changeType);
stateObject.WaitObject = waitObject;
stateObject.WaitHandle = ThreadPool.RegisterWaitForSingleObject(waitObject, new WaitOrTimerCallback(this.ConnectionStateChanged), stateObject, Timeout.Infinite, false);
this._stateObjects.Add(stateObject);
}
}
The event passed into the API gets signaled when Windows detects a change in the connections on the machine. The callback used just takes the change type registered from the state object and then processes it to determine exactly what changed.
private void ConnectionStateChanged(object obj, bool timedOut)
{
lock (this.lockObject)
{
if (this.EnableRaisingEvents)
{
try
{
// Retrieve the active connections to compare against the last state that was checked.
ReadOnlyCollection<RasConnection> connections = RasConnection.GetActiveConnections();
RasConnection connection = null;
switch (((RasConnectionWatcherStateObject)obj).ChangeType)
{
case NativeMethods.RASCN.Disconnection:
connection = FindEntry(this._lastState, connections);
if (connection != null)
{
this.OnDisconnected(new RasConnectionEventArgs(connection));
}
if (this.Handle != null)
{
// The handle that was being monitored has been disconnected.
this.Handle = null;
}
this._lastState = connections;
break;
}
}
catch (Exception ex)
{
this.OnError(new System.IO.ErrorEventArgs(ex));
}
}
}
}
}
Everything works perfectly, other than when the machine comes out of sleep. Now the strange thing is when this happens, if a MessageBox is displayed (even for 1 ms and closed by using SendMessage) it will work. I can only imagine something I've done is blocking something else in Windows so that it can't continue processing while the event is being processed by the component.
I've stripped down a lot of the code here, the full source can be found at:
http://dotras.codeplex.com/SourceControl/changeset/view/68525#1344960
I've come for help from people much smarter than myself, I'm outside of my comfort zone trying to fix this problem, any assistance would be greatly appreciated!
Thanks! - Jeff
After a lot of effort, I tracked down the problem. Thankfully it wasn't a blocking issue in Windows.
For those curious, basically once the machine came out of sleep the developer was attempting to immediately dial a connection (via the Disconnected event). Since the network interfaces hadn't finished initializing, an error was returned and the connection handle was not being closed. Any attempts to close the connection would throw an error indicating the connection was already closed, even though it wasn't. Since the handle was left open, any subsequent attempts to dial the connection would cause an actual error.
I just had to make an adjustment in the HangUp code to hide the error thrown when a connection is closed that has already been closed.

CacheItemRemovedCallback causes webserver to crash

THis is an interesting question. I am developing a web-chat software piece and for the past couple of hours I've been trying to figure out why this happens. Basically, I add an actual chat object (the part that does communications) to the Cache collection when you start chatting. In order to detect that you closed the window, I set the sliding expiration to say 10-30 seconds. I also set the callback to let the chat client know that he needs to disconnect to end the chat session. For some odd reason, when I use the code to dispose of the chat client, whatever it is, it causes the entire w3svc process to crash (event log checked). I also tried just sending myself an email when the item is removed, which worked. I even tried to put the entire code in try-catch block but it seems to ignore that as well. Any ideas? O_o
UPD: No, i am not trying to refresh the object (in reference to this).
Adding:
HttpContext.Current.Cache.Insert("ChatClient_" + targetCid + HttpContext.Current.Session.SessionID, cl, null, Cache.NoAbsoluteExpiration,
TimeSpan.FromSeconds(15), CacheItemPriority.Normal, new CacheItemRemovedCallback(removeMyself));
Removing:
public static void removeMyself(string key, Object value, CacheItemRemovedReason reason) {
var wc = (WebClient)value;
try {
wc.Remove();
}
catch { }
}
I am in fact using the lock on HttpContext.Current.cache when adding to the cache objects.
Can you post both the cache.insert and item removed callbacks code? Are you using any kind of locking when inserting into the cache? Have you done anything to the default settings for the ASP.net cache? Are you able to reproduce this on another web server? Are you sure you are expiring the cache in ms instead of seconds...
Is your sliding expiration like this? TimeSpan.FromSeconds(30)

Categories