I'm using WMI for monitoring all our servers through a small C# service, which creates a bunch of ManagementScopes (one per server it should monitor) and periodically polls for CPU load etc.
However every once in a while it starts throwing COMExceptions, with the message "The RPC server is unavailable". Now that's fair enough if it was true, however I can manully connect to the server just fine, and if I create a new ManagementScope to the same server, I can reconnect without problems!
There's a problem with this approach though: It leaks memory :-(
ManagementScope has no Close, Dispose or similar cleanup function, and leaks memory when just garbage collected. This is, according to all my google searches, a problem with the underlying WMI components, and as such not a .Net issue.
So I figure my best approach is to solve the COMException issue, and just staying with the original ManagementScope - however if I manually call Connect on the scope after the COMException, it does return true (as in "Yes I've got a connection), but at first attempt at getting data from it, it throws another COMException.
I've tried quite a few things, but I simply cannot figure out why this happens :-(
The code is quite large, therefore I haven't pasted it here (and it's split into a lot of classes)
But basically I create a scope, and then call the following methods:
public ManagementObject GetSingleObject(string query)
{
using (var searcher = CreateSearcher(query))
{
try
{
using (var collection = searcher.Get())
{
return collection
.Cast<ManagementObject>()
.FirstOrDefault();
}
}
catch
{
return null;
}
}
}
private ManagementObjectSearcher CreateSearcher(string query)
{
return new ManagementObjectSearcher(_scope, new ObjectQuery(query), _options);
}
If you need more code, let me know :-)
Related
I've received some C# code from a colleague for interacting with a cRIO device connected over ethernet. I'm trying to improve the code quality to make it a bit more comprehensible for future users, however I'm struggling a little bit to extract some relevant information from the API documentation. My main question is whether there would be problems caused in leaving a NetworkVariableManager in the Connected state?
Right now the code uses a class which looks something like
public class RIOVar<T>
{
public readonly string location;
public RIOVar(string location)
{
this.location = location;
}
public T Get()
{
using(NetworkVariableReader<T> reader = new NetworkVariableReader<T>(location) )
{
reader.Connect();
return reader.ReadData().GetValue()
}
}
public void Write(T value)
{
using(NetworkVariableWriter<T> writer = new NetworkVariableWriter<T>(location) )
{
writer.Connect();
writer.WriteValue(value);
}
}
}
The actual class does a lot more than this, but the part that actually communicates with the cRIO basically boils down to these two methods and the location data member.
What I'm wondering about is whether it would be better to instead have reader and writer as class members and Connect them in the constructor (at the point that they are constructed the connection should be posible), but what I don't know is if this would have some adverse effect on the way the computer and RIO communicate with each other (maybe a connected manager uses some resource or the program must maintain some sort of register...?) and therefore the approach here of having the manager connected only for the read/write operation is better design.
Keeping a variable connected keeps its backing resources in memory:
threads
sockets
data buffers
These resources are listed in the online help, but it's unclear to me if that list is complete:
NationalInstruments.NetworkVariable uses multiple threads to implement the reading and writing infrastructure. When reading or writing in a tight loop insert a Sleep call, passing 0, to allow a context switch to occur thereby giving the network variable threads time to execute.
... snip ...
NationalInstruments.NetworkVariable shares resources such as sockets and data buffers among connections that refer to the same network variable in the same program.
In my opinion, I'd expect better runtime performance by connecting/disconnecting as infrequently as possible. For example, when the network is reachable, connect; when it isn't, disconnect.
I am getting error
80004005 There is a file sharing violation. A different process might be using the file.
when trying to open a SqlCeConnection.
Is there a way to close a SQL Server CE database programmatically, to try to nip that problem in the bud? Something like (pseudocode):
SqlCeDatabase SQLCeDb = "\My Documents\HHSDB003.sdf";
if (SQLCeDb.IsOpen)
{
SQLCeDb.Close();
}
?
Or a way to set the connection so that it doesn't care if the database is open elsewhere/wise, such as:
SqlCeConnection conn = new SqlCeConnection(#"Data Source=\My Documents\HHSDB003.sdf;File Mode = 'shared read'");
...or:
SqlCeConnection conn = new SqlCeConnection(#"Data Source=\My Documents\HHSDB003.sdf;File Mode = 'read write'");
I can't test these at present, because I'm back to getting
Cannot copy HHS.exe The device has either stopped responding or has been disconnected
when I attempt to copy over a new version of the .exe to the handheld.
If there's something more frustrating to program against (and "against" is the correct word here, I think) than the prehistoric versions of Windows CE / Compact Framework / .NET, I'm not at all sure I want to know what it is.
UPDATE
Adding to my frustrusion (haywire combination of confusion and frustration), I found the following at http://www.pocketpcfaq.com/faqs/activesync/exchange_errors.php:
0x80004005 N/A Synchronization failed due to a device software error. Contact your network administrator.
1. Obtain the latest Pocket PC End User Update from your service provider.
UPDATE 2
Is this possibly problematic (than all but the first setting is blank):
UPDATE 3
With this code:
private void menuItemTestSendingXML_Click(object sender, System.EventArgs e)
{
string connStr = "Data Source=My Documents\\HHSDB003.SDF";
SqlCeConnection conn = null;
try
{
try
{
conn = new SqlCeConnection(connStr);
conn.Open();
MessageBox.Show("it must have opened okay");
}
finally
{
conn.Close();
}
}
catch (Exception ex)
{
if (null == ex.InnerException)
{
MessageBox.Show("inner Ex is null");
}
MessageBox.Show(String.Format("msg is {0}", ex.Message));
}
}
...I am now seeing "it must have opened okay" (that's a good thing, but...why it's now working, I have no idea, because the code has not changed since I last ran it and it failed. Something beyond the code must have been at play.
The only thing I can think of that happened that MAY have had a bearing on this change is that, thinking there may have been a rogue instance of either the .exe or its ancillary dll in memory on the handheld device, I wrote an quick-and-dirty utility that looped through the running processes, looking for them and, if finding them, killing them, but they were not there, so the utility really did "nothing" (maybe the Hawthorne effect?).
That is the way working with this combination of tools and technologies seems to go, though: everything is working fine one minute and the next, BAM! It no longer is. Then the reverse can also happen: for no apparent reason it seems to "heal itself".
In the interests of "full disclosure," here is the utility code:
// Got this from http://www.codeproject.com/Articles/36841/Compact-Framework-Process-class-that-supports-full
private void btnKillRogue_Click(object sender, EventArgs e)
{
ProcessInfo[] list = ProcessCE.GetProcesses();
foreach (ProcessInfo item in list)
{
MessageBox.Show("Process item: " + item.FullPath);
if (item.FullPath == #"\Windows\iexplore.exe") item.Kill(); //<= this was the example search; it probably could be a problem, so I'll use it, too
if (item.FullPath.EndsWith("HHS.exe"))
{
MessageBox.Show("about to kill hhs.exe");
item.Kill();
}
if (item.FullPath.EndsWith("HUtilCE.dll"))
{
MessageBox.Show("about to kill hutilce.dll");
item.Kill();
}
}
}
Maybe there was an instance of iexplore.exe resident in memory that was problematic (I'm not showing a messagebox if that is what is found)...?
As an attempt to claim unused bounty ... do not, however, feel obligated to pass around free points on my behalf ...
Aside from force killing of possible tasks, had you rebooted the system amidst your search for an answer? If your tool did not return the message, it is certainly possible that a reboot would have done the very thing that you had attempted with the kill utility - or possible iexplore.exe had something to do with it ... the lack of the additional messagebox may leave you never knowing - unless this issue occurs again.
If no rebooting occurred, then perhaps whatever program/dll was held in memory by some other process concluded its task and released it hold.
There are several scenarios that might have occurred, it is certainly hard to determine with absolution; hence the lack of answers. I would be interested, though, if this problem occurred again.
Occasionally our site slows down and the RAM usage goes up massively high. Then the app pool stops and I have to restart it. Then it's ok for a few days before the RAM suddenly spikes again and the app pool soon stops. The CPU isn't high.
Before the app pool stops I've noticed that one of our pages always hangs. The line it hangs on is a foreach on a ResourceSet :
var englishLocations = Lang.Countries.ResourceManager.GetResourceSet(new CultureInfo("en-GB"),true,true);
foreach(DictionaryEntry entry2 in englishLocations) // THIS LINE HANGS
We have the same code deployed on a different box and this doesn't happen. The main differences between the two boxes are :
Bad box
Window Server 2008 R2 Standard SP 1
IIS 7.5.7600.16385
.NET 4.5
24GB RAM
Good box
Window Server 2008 Server SP 2
IIS 7.0.6000.16386 SP 2
.NET 4.0
24GB RAM
I've tried adding uploadReadAheadSize="0" to the web.config as described here :
http://rionscode.wordpress.com/2013/03/11/resolving-controller-blocking-within-net-4-5-and-asp-net-mvc/
Which didn't work.
Why would foreach hang? It's hanging on the very first item, actually on the foreach.
Thanks.
I know it is an old post, but nevertheless... There is the potential of a deadlock when iterating over a ResourceSet and at the same time retrieving some other object through from the same Resources.
The problem is that when using a ResourceSet the iterator takes out locks on the internal resource cache of the ResourceReader http://referencesource.microsoft.com/#mscorlib/system/resources/resourcereader.cs,1389 and then in the method AllocateStringNameForIndex takes out a lock on the reader itself: http://referencesource.microsoft.com/#mscorlib/system/resources/resourcereader.cs,447
lock (_reader._resCache) {
key = _reader.AllocateStringForNameIndex(_currentName, out _dataPosition); // locks the reader
Getting an object takes out the same locks int the opposite order:
http://referencesource.microsoft.com/#mscorlib/system/resources/runtimeresourceset.cs,300
and http://referencesource.microsoft.com/#mscorlib/system/resources/runtimeresourceset.cs,335
lock(Reader) {
....
lock(_resCache) {
_resCache[key] = resLocation;
}
}
This can lead to a deadlock. We had this exact issue recently..
I experienced very similar problem.
Every once in a while IIS would hang, and I would see number of requests just sitting there. They were all in state ExecuteRequestHandler and with ManagedPipelineHandler module name.
After investigating with process explorer, I could see that all of them were sitting at mscorlib.dll!ResourceEnumerator.get_Entry, additional stack trace suggested some NGen action and then ntdll.dll!WaitForMultipleObjects.
My working hypothesis is that when multiple threads start enumerating those resources, we can run into a deadlock (possibly on some native code file generation), and alll subsequent threads then just keep on piling up.
To resolve it, I just created a critical section around this code block, to ensure that it is executed sequentially - I haven't experienced the issue since.
private static readonly object ResourceLock = new object();
public static MvcHtmlString SerializeGlobalResources(this HtmlHelper helper)
{
lock (ResourceLock)
{
// Existing code goes here ....
}
}
Based upon another answer to give you some idea how about using a try catch model ?
Perhaps it hangs because that resource isnt available / locked /..permissions etc.
var englishLocations = Lang.Countries.ResourceManager.GetResourceSet(new CultureInfo("en-GB"),true,true);
foreach(DictionaryEntry entry2 in englishLocations) // THIS LINE HANGS
ResourceManager CultureResourceManager = new ResourceManager("My.Language.Assembly", System.Reflection.Assembly.GetExecutingAssembly());
ResourceSet resourceSet = CultureResourceManager.GetResourceSet("sv-SE", true, true);
try { resourceSet.GetString("my_language_resource");}
catch (exception ex) { // from here log your error ex to wherever you like with some code }
I've found multiple online tutorials for establishing WMI connections to remote machines using c#. These tutorials describe a process like the following:
ConnectionOptions cOpts = new ConnectionOptions();
ManagementObjectCollection moCollection;
ManagementObjectSearcher moSearcher;
ManagementScope mScope;
ObjectQuery oQuery;
mScope = new ManagementScope(String.Format("\\\\{0}\\{1}", host.hostname, "ROOT\\CIMV2"), cOpts);
oQuery = new ObjectQuery("Select * from Win32_OperatingSystem");
moSearcher = new ManagementObjectSearcher(mScope, oQuery);
moCollection = moSearcher.Get();
The happy path cases - connecting to a local host, or connecting to a remote host with proper credentials - work fine. I'm working on a project where we need to support the case when the currently logged in account does not have access to the remote host we're attempting to connect to. That is, we need to catch this case, bring the bad credentials to the attention of the user, and prompt them to supply credentials again.
When I specify credentials in my ConnectionOptions object that do not have context on the remote machine, my call to moSearcher.Get() hangs (seemingly) indefinitely. Similarly, a call to the Connect() function in ManagementScope hangs in the same manner.
We have similar logic in place to perform the equivalent WMI commands in c++, and I can report that those return almost immediately if improper credentials are supplied. An appropriate "access is denied" message is returned. The hosts I'm using for test purposes right now are the same ones we use when testing our existing c++ logic, so I have no reason to believe that WMI is incorrectly configured in our environment.
I've searched for timeout issues surrounding WMI connections in c#. I've explored the Timeout property of ConnectionOptions and moSearcher.Options. I've also looked at the ReturnImmediately property of the EnumerationOptions object that can be associated with ManagementObjectSearcher instance. These options did not have the desired effect for me.
I suppose I could perform these WMI commands in a separate thread, and surround the thread with monitoring code that kills it if it hasn't returned in a reasonable amount of time. That seems like a fair amount of work that would be pushed to all consumers of the c# WMI routines, and I'm hoping there's an easier way. Plus, I'm not sure that killing an outstanding thread this way properly cleans up the WMI connection.
Pinging the remote host doesn't do me any good, because knowing the host is up and running does not tell me if the credentials I have are appropriate (and if the c# WMI calls will hang). Is there another way to validate the credentials against a remote host?
It's always possible that there's an obvious flag or API I'm missing, because I would think others have run into this problem. Any information/assistance would be appreciated. Thanks for reading this lengthy post.
I don't know what all your special functions are, but here's a little routine to help you troubleshoot that should be able to wrap your routine in a thread and give it 5 seconds to execute:
void Fake() {
bool ok = false;
ConnectionOptions cOpts = new ConnectionOptions();
ManagementObjectCollection moCollection;
ManagementObjectSearcher moSearcher;
ManagementScope mScope;
ObjectQuery oQuery;
if (cOpts != null) {
mScope = new ManagementScope(String.Format("\\\\{0}\\{1}", host.hostname, "ROOT\\CIMV2"), cOpts);
if (mScope != null) {
oQuery = new ObjectQuery("Select * from Win32_OperatingSystem");
if (oQuery != null) {
moSearcher = new ManagementObjectSearcher(mScope, oQuery);
if (moSearcher != null) {
ManualResetEvent mre = new ManualResetEvent(false);
Thread thread1 = new Thread(() => {
moCollection = moSearcher.Get();
mre.Set();
};
thread1.Start();
ok = mre.WaitOne(5000); // wait 5 seconds
} else {
Console.WriteLine("ManagementObjectSearcher failed");
}
} else {
Console.WriteLine("ObjectQuery failed");
}
} else {
Console.WriteLine("ManagementScope failed");
}
} else {
Console.WriteLine("ConnectionOptions failed");
}
}
Hope that helps or gives you some ideas.
I took jp's suggestion to surround the WMI API calls in a separate thread that could be killed if they exceeded a timeout. When testing, the separate thread threw an exception of type System.UnauthorizedAccessException. I removed the threading logic and added a catch statement to handle this exception type. Sure enough, the exception is caught almost immediately following the call to ManagementObjectSearcher.Get().
try
{
moCollection = moSearcher.Get();
}
catch (System.UnauthorizedAccessException)
{
return Program.ERROR_FUNCTION_FAILED;
}
catch (System.Runtime.InteropServices.COMException)
{
MessageBox.Show("Error, caught COMException.");
return Program.ERROR_FUNCTION_FAILED;
}
(Note that the System.Runtime.InteropServices.COMException catch statement already existed in my code)
I don't know why this exception isn't thrown (or at least is not brought to the user's attention through the VS 2010 IDE) when executed as part of the parent thread. In any event, this is exactly what I was looking for, and is consistent with the behavior of the WMI connection routines in c++.
I'm building what could be called the DAL for a new app. Unfortunately, network connectivity to the database is a real problem.
I'd like to be able to temporarily block network access within the scope of my test so that I can ensure my DAL behaves as expected under those circumstances.
UPDATE: There are many manual ways to disable the network, but it sure would be nice if I could enable/disable within the test itself.
For the time being, I'm just "disabling" the network by setting a bogus static IP as follows:
using System.Management;
class NetworkController
{
public static void Disable()
{
SetIP("192.168.0.4", "255.255.255.0");
}
public static void Enable()
{
SetDHCP();
}
private static void SetIP(string ip_address, string subnet_mask)
{
ManagementClass objMC = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection objMOC = objMC.GetInstances();
foreach (ManagementObject objMO in objMOC) {
if ((bool)objMO("IPEnabled")) {
try {
ManagementBaseObject setIP = default(ManagementBaseObject);
ManagementBaseObject newIP = objMO.GetMethodParameters("EnableStatic");
newIP("IPAddress") = new string[] { ip_address };
newIP("SubnetMask") = new string[] { subnet_mask };
setIP = objMO.InvokeMethod("EnableStatic", newIP, null);
}
catch (Exception generatedExceptionName) {
throw;
}
}
}
}
private static void SetDHCP()
{
ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection moc = mc.GetInstances();
foreach (ManagementObject mo in moc) {
// Make sure this is a IP enabled device. Not something like memory card or VM Ware
if ((bool)mo("IPEnabled")) {
ManagementBaseObject newDNS = mo.GetMethodParameters("SetDNSServerSearchOrder");
newDNS("DNSServerSearchOrder") = null;
ManagementBaseObject enableDHCP = mo.InvokeMethod("EnableDHCP", null, null);
ManagementBaseObject setDNS = mo.InvokeMethod("SetDNSServerSearchOrder", newDNS, null);
}
}
}
}
Write a wrapper to the network class connectivity class you're using (e.g. WebClient) with an on-off switch :)
Either that, or block your application in the firewall.
Try blocking the connection with a firewall midway through the session maybe?
I like the wrapper idea as well, but thats kind of abstracting the problem and you prolly might not get exact real world behavior. Also, inserting the wrapper layer and then removing it may be more trouble than its worth.
Edit: Run a script that turns the Network adapter on/off randomly or at set intervals?
If you are trying a complete network outage for your application unplugging the network cable will work. Sometimes you might have a data access layer with multiple data sources (on different machines) in which case you can simulate an exception in your tests with a Mock Framework like Rhino Mocks. Here is some pseudo-code that you may have in your test
void TestUserDBFailure()
{
// ***** THIS IS PSEUDO-CODE *******
//setting up the stage - retrieval of the user info create an exception
Expect.Call(_userRepository.GetUser(null))
.IgnoreArguments()
.Return(new Exception());
// Call that uses the getuser function, see how it reacts
User selectedUser = _dataLoader.GetUserData("testuser", "password");
}
Probably not helpful for simulating "real" network issues, but you could just point your DB connection string to a non-existent machine while within the scope of your test.
Depends on what particular network problem you wish to simulate. For most folks, it's as simple as "server unreachable", in which case you'd just try to connect to a non existent server. Be careful, though, because you want something that is routable but does not answer. Trying to connect to dkjdsjk.com will fail immediately (DNS lookup), but trying to connect to www.google.com:1433 will (probably) time out due to a firewall - which is how your app will behave when your DB server is down.
Try Toxiproxi, it can simulate network outage.
They have REST API and even .NET Client API to change the network simulation programatically (from your test code)
https://github.com/shopify/toxiproxy
Look for a WAN simulator that will allow you to restrict bandwidth (and cut it off completely) I always find it interesting to see how the user experience changes when my apps are run in a bandwidth restricted environment. Look here for some information.
There is a tool you can use for simulating High Latency and Low Bandwidth in Testing of Database Applications as explained in this blog entry.
Just found an alternative that allows to directly close TCP connections:
http://lamahashim.blogspot.ch/2010/03/disabling-network-using-c.html
It is based on Windows IP Helper API (uses DllImport):
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366073(v=vs.85).aspx
Use mock objects to create configurable, destructible versions of the real thing--in this case, the database.