Out Of Context Variables In Visual Studio 2010 Debugger - c#

I am having a very odd problem with local variables being out of context in the Visual Studio 2010 debugger for a C# console application targeting .NET 4.0. I've searched for other similar questions on SO, but while some have the same symptoms, none seem to apply directly to this problem (they all appear to have other root causes).
The problem is that for some variables (but not all) I do not get a tooltip with their value, they do not appear in the Locals window, and I get "The name 'xyz' does not exist in the current context" if I add them to the Watch window. It appears to affect some variables but not others, and I can't figure out a pattern (it doesn't seem to be based on member vs. local, class vs. struct, or any other differentiator). I've restarted my computer and Visual Studio, verified I'm in a clean Debug build, made sure the debugging frame is correct, made sure to refresh the variables in the watch screen, and attempted various spells and incantations.
I've included a screenshoot below (bigger version at http://i.stack.imgur.com/JTFBT.png).
Any thoughts?
EDIT:
Adding some additional information:
The problem is repeatable. The exact same variables either work or don't work, even after completely shutting down and restarting Visual Studio. This leads me to believe there's actually something systematic going wrong rather than just memory corruption or something.
I've also discovered that it appears to be related to the try-catch block. If I position the breakpoint outside the try statement I can see any of the in-scope variables normally. As soon as the execution point enters the try statement all the variables outside the try block become inaccessible and I can only access the ones inside the try statement. It's almost as though the debugger is treating the try block as a separate method (though you can see the code/compiler still does have access to in-scope variables). Has anyone seen this behavior before?
ANOTHER EDIT:
I (partially) take back what I said about the try-catch being suspect - it appears that in this portion of the code the debugger exhibits this odd taking stuff out of context for any enclosing block. For example, if I set a breakpoint directly inside the foreach statement in the screenshot I can see the "port" variable value on each iteration, but none of the variables outside the foreach statement (which disappear as soon as I enter the foreach block). Then as soon as you enter the try block, the "port" variable suddenly goes away. This is getting really weird.
Also, as requested, the code for the entire method is below.
private void ConfigureAnnouncerSockets(XDocument configDocument)
{
XElement socketsElement = configDocument.XPathSelectElement("/Configuration/Network/AnnouncerSockets");
bool useDefault = true;
if (socketsElement != null)
{
//Use the default announcers? (they will be added at the end)
XAttribute defaultAttribute = socketsElement.Attribute("useDefault");
if (defaultAttribute != null)
{
useDefault = Convert.ToBoolean(defaultAttribute);
}
//Get the default frequency
int defaultFrequency = Announcer.DefaultFrequency;
XAttribute frequencyAttribute = socketsElement.Attribute("frequency");
if (frequencyAttribute != null)
{
defaultFrequency = Convert.ToInt32(frequencyAttribute.Value);
}
//Get all sockets
foreach (XElement socketElement in socketsElement.XPathSelectElements("./Socket"))
{
//Get the address
IPAddress address = IPAddress.Broadcast;
string addressAttribute = (string)socketElement.Attribute("address");
if(!GetAddress(addressAttribute, ref address, true))
{
Intelliplex.Log.Warn("Invalid announcer socket address: " + addressAttribute);
continue;
}
//Get the local address
IPAddress localAddress = null;
string localAddressAttribute = (string)socketElement.Attribute("localAddress");
if(!GetAddress(localAddressAttribute, ref localAddress, false))
{
Intelliplex.Log.Warn("Invalid announcer socket local address: " + localAddressAttribute);
continue;
}
//Get the port(s)
List<int> ports = new List<int>();
string[] ranges = ((string)socketElement.Attribute("port")).Split(new[] { ',' });
foreach (string range in ranges)
{
string[] portPair = range.Split(new[] { '-' });
int firstPort = Convert.ToInt32(portPair[0]);
int lastPort = portPair.Length > 1 ? Convert.ToInt32(portPair[1]) : firstPort;
do
{
ports.Add(firstPort);
} while (++firstPort <= lastPort);
}
//Get the local port
int localPort = socketElement.Attribute("localPort") != null
? Convert.ToInt32((string)socketElement.Attribute("localPort")) : 0;
//Get the frequency
int frequency = socketElement.Attribute("frequency") != null
? Convert.ToInt32((string)socketElement.Attribute("frequency")) : defaultFrequency;
//Create the socket(s) and add it/them to the manager
foreach (int port in ports)
{
try
{
IPEndPoint endPoint = new IPEndPoint(address, port);
IPEndPoint localEndPoint = localAddress == null
? new IPEndPoint(IPAddress.Any, 0) : new IPEndPoint(localAddress, localPort);
Announcer socket = new Announcer(frequency, endPoint, localEndPoint);
AnnouncerSockets.Add(socket);
}
catch (Exception ex)
{
Intelliplex.Log.Warn("Could not add announcer socket: " + ex.Message);
}
}
}
}
//Add default announcement sockets?
if (useDefault)
{
ConfigureDefaultAnnouncerSockets();
}
}

So it turns out this is related to a bug in PostSharp. I had been using PostSharp but removed all aspects from my code and ensured that none were applied. I also verified with Reflector that the methods were intact in the assembly. However, it appears simply referencing PostSharp triggers some kind of manipulation of the debugging symbols that causes this problem. A (little) more information can be found here:
http://www.sharpcrafters.com/forum/Topic5794-21-1.aspx#bm7927
Also, in the release notes for the latest PostSharp hotfix states one of the fixed issues in hotfix 2.1.5.6 is "Debugging symbols: local variable symbols lost in implicit iterators."
When I installed the latest and greatest PostSharp the problem went away and the universe returned to normal. Hopefully this question/answer will help anyone else using PostSharp who stumbles on this odd behavior before the next official PostSharp release. Make sure you're on hotfix 2.1.5.6 or greater (given the severity of the bug, this probably should have been an actual release).
Thanks for all the help everyone.

Related

Certain GStreamer pipelines not considered to be a bin?

I can run a very simple launch pipeline from the command line thus:
gst-launch-1.0 videotestsrc ! ximagesink
and, from gst-inspect-1.0, the ximagesink appears to support the GstVideoOverlay interface so that I can bind it to a specific Gtk widget.
However, when trying to do that from within some code I happened to find lying around on the net, it seems that the pipeline is not considered to be a bin (and hence, the widget ID is not being given to it).
The code to do it is as follows, first to create the pipeline and set it up to capture bus messages:
Gst.Element playbin = Gst.Parse.Launch("videotestsrc ! ximagesink");
Gst.Bus bus = playbin.Bus;
bus.AddSignalWatch();
bus.Message += MsgCallback;
Then to actually process the bus messages:
private void MsgCallback(object o, MessageArgs args) {
// Only care about window ID binding requests.
Gst.Message msg = args.Message;
if (! Gst.Video.Global.IsVideoOverlayPrepareWindowHandleMessage(msg))
return;
// Get source of message.
Gst.Element src = msg.Src as Gst.Element;
if (src == null)
return;
// Find element supporting interface and notify it to bind.
Gst.Element ov = null;
if (src is Gst.Bin) {
ov = ((Gst.Bin) src).GetByInterface(VideoOverlayAdapter.GType);
VideoOverlayAdapter ad = new VideoOverlayAdapter(ov.Handle);
ad.WindowHandle = windowXId;
}
}
Now, for some reason, the src is Gst.Bin is false, meaning that the windowXId (the widget ID I've previously set) is never being communicated to GStreamer.
However, if I provide a playbin pipeline (playbin uri=XYZZY videosink='videoconvert ! videoflip method=none ! videoconvert ! autovideosink', if you're interested), it works fine.
As far as I can tell from the documentation for Gst.Parse.Launch(), it should give me a pipeline which is a special case of a bin, as per here (after fixing the atrocious grammar):
Returns a new element on success, NULL on failure. If more than one top level element is specified by the pipeline description , all elements are put into a GstPipeline, which is then returned.
I'm pretty certain that videotestsrc and ximagesink are two separate top-level elements but, when I add the following code, after the check for src being null:
Console.WriteLine("is bin " + (src is Gst.Bin));
Console.WriteLine("is element " + (src is Gst.Element));
Console.WriteLine("is pipeline " + (src is Gst.Pipeline));
Console.WriteLine(type is " + src.GetType());
I see:
is bin False
is element True
is pipeline False
type is Gst.Element
for the problematic videotestsrc pipeline and the following for the good playbin one:
is bin True
is element True
is pipeline False
type is Gst.Bin
So everything points to the problematic one giving an element rather than a bin, despite what the documentation states.
What am I missing here? What is the difference between the two pipelines that would cause different behaviour?
Okay, it turns out that the Gst.Parse.Launch function is actually returning a pipeline. This can be seen if you copy those checking statements immediately after the bin creation:
Gst.Element playbin = Gst.Parse.Launch("videotestsrc ! ximagesink");
Console.WriteLine("is bin " + (playbin is Gst.Bin));
Console.WriteLine("is element " + (playbin is Gst.Element));
Console.WriteLine("is pipeline " + (playbin is Gst.Pipeline));
Console.WriteLine(type is " + playbin.GetType());
and you see:
is bin True
is element True
is pipeline True
type is Gst.Pipeline
It's just that, when we get the message in the callback, the source seems to be set to an element instead. I haven't actually figured out why the message source is coming through as an element (or even which element it is) but I at least have a workaround, thanks partly to my advanced intelligence but mostly to a sneaky look at the way Banshee does it :-)
Turns out that the callback can simply access the bin directly rather than trying to get it out of the source. This works in my case since I only have the one video stream (bin) per instance. If you have multiples, it may be a little more difficult.
To achieve this, you first make playbin a member variable (if it isn't already), and you can then modify the callback thus:
private void MsgCallback(object o, MessageArgs args) {
// Only care about window ID binding requests.
Gst.Message msg = args.Message;
if (! Gst.Video.Global.IsVideoOverlayPrepareWindowHandleMessage(msg))
return;
// Get instance bin, interface element, then notify it to bind.
Gst.Bin src = (Gst.Bin)(this.playbin);
if (src == null) return;
Gst.Element ov = src.GetByInterface(VideoOverlayAdapter.GType);
if (ov == null) return;
VideoOverlayAdapter ad = new VideoOverlayAdapter(ov.Handle);
if (ad == null) return;
ad.WindowHandle = windowXId;
}

Multi-threaded C# Selenium WebDriver automation with Uris not known beforehand

I need to perform some simultaneous webdrivers manipulation, but I am uncertain as to how to do this.
What I am asking here is:
What is the correct way to achieve this ?
What is the reason for the exception I am getting (revealed below)
After some research I ended up with:
1. The way I see people doing this (and the one I ended up using after playing with the API, before searching) is to loop over the window handles my WebDriver has at hand, and perform a switch to and out of the window handle I want to process, closing it when I am finished.
2. Selenium Grid does not seem like an option fore me - am I wrong or it is intended for parallel processing ? Since am running everything in a single computer, it will be of no use for me.
In trying the 1st option, I have the following scenario (a code sample is available below, I skipped stuff that is not relevant/repeat itself (where ever I added 3 dots:
I have a html page, with several submit buttons, stacked.
Clicking each of them will open a new browser/tab (interestingly enough, using ChromeDriver opens tabs, while FirefoxDriver opens separate windows for each.)
As a side note: I can't determine the uris of each submit beforehand (they must be determined by javascript, and at this point, let's just assume I want to handle everything knowing nothing about the client code.
Now, after looping over all the submit buttons, and issuing webElement.Click() on the corresponding elements, the tabs/windows open. The code flows to create a list of tasks to be executed, one for each new tab/window.
The problem is: since all tasks all depend upon the same instance of webdriver to switch to the window handles, seems I will need to add resource sharing locks/control. I am uncertain as whether I am correct, since I saw no mention of locks/resource access control in searching for multi-threaded web driver examples.
On the other hand, if I am able to determine the tabs/windows uris beforehand, I would be able to skip all the automation steps needed to reach this point, and then creating a webDriver instance for each thread, via Navigate().GoToUrl() would be straightforward. But this looks like a deadlock! I don't see webDriver's API providing any access to the newly opened tab/window without performing a switch. And I only want to switch if I do not have to repeat all the automation steps that lead me to the current window !
...
In any case, I keep getting the exception:
Element belongs to a different frame than the current one - switch to its containing frame to use it
at
IWebElement element = cell.FindElement
inside the ToDictionary() block.
I obviously checked that all my selectors are returning results, in chrome's console.
foreach (WebElement resultSet in resultSets)
resultSet.Click();
foreach(string windowHandle in webDriver.WindowHandles.Skip(1))
{
dataCollectionTasks.Add(Task.Factory.StartNew<List<DataTable>>(obj =>
{
List<DataTable> collectedData = new List<DataTable>();
string window = obj as string;
if (window != null)
{
webDriver.SwitchTo().Window(windowHandle);
List<WebElement> dataSets = webDriver.FindElements(By.JQuerySelector(utils.GetAppSetting("selectors.ResultSetData"))).ToList();
DataTable data = null;
for (int i = 0; i < dataSets.Count; i += 2)
{
data = new DataTable();
data.Columns.Add("Col1", typeof(string));
data.Columns.Add("Col2", typeof(string));
data.Columns.Add("Col3", typeof(string));
///...
//data set header
if (i % 2 != 0)
{
IWebElement headerElement = dataSets[i].FindElement(OpenQA.Selenium.By.CssSelector(utils.GetAppSetting("selectors.ResultSetDataHeader")));
data.TableName = string.Join(" ", headerElement.Text.Split().Take(3));
}
//data set records
else
{
Dictionary<string, string> cells = dataSets[i]
.FindElements(OpenQA.Selenium.By.CssSelector(utils.GetAppSetting("selectors.ResultSetDataCell")))
.ToDictionary(
cell =>
{
IWebElement element = cell.FindElement(OpenQA.Selenium.By.CssSelector(utils.GetAppSetting("selectors.ResultSetDataHeaderColumn")));
return element == null ? string.Empty : element.Text;
},
cell =>
{
return cell == null ? string.Empty : cell.Text;
});
string col1Value, col2Value, col3Value; //...
cells.TryGetValue("Col1", out col1Value);
cells.TryGetValue("Col2", out col2Value);
cells.TryGetValue("Col3", out col3Value);
//...
data.Rows.Add(col1Value, col2Value, col3Value /*...*/);
}
}
collectedData.Add(data);
}
webDriver.SwitchTo().Window(mainWindow);
webDriver.Close();
return collectedData;
}, windowHandle));
} //foreach
Task.WaitAll(dataCollectionTasks.ToArray());
foreach (Task<List<DataTable>> dataCollectionTask in dataCollectionTasks)
{
results.AddRange(dataCollectionTask.Result);
}
return results;

Performance Counter - Instances; Create/Update without error but not visible in PerfMon

When invoking UpdatePerformanceCounters: In this updater all the counter names for the category and instance counters are the same - they are always derived from an Enum. The updater is passed a "profile" typically with content such as:
{saTrilogy.Core.Instrumentation.PerformanceCounterProfile}
_disposed: false
CategoryDescription: "Timed function for a Data Access process"
CategoryName: "saTrilogy<Core> DataAccess Span"
Duration: 405414
EndTicks: 212442328815
InstanceName: "saTrilogy.Core.DataAccess.ParameterCatalogue..ctor::[dbo].[sp_KernelProcedures]"
LogFormattedEntry: "{\"CategoryName\":\"saTrilogy<Core> DataAccess ...
StartTicks: 212441923401
Note the "complexity" of the Instance name.
The toUpdate.AddRange() of the VerifyCounterExistence method always succeeds and produces the "expected" output so the UpdatePerformanceCounters method continues through to the "successful" incrementing of the counters.
Despite the "catch" this never "fails" - except, when viewing the Category in PerfMon, it shows no instances or, therefore, any "successful" update of an instance counter.
I suspect my problem may be that my instance name is being rejected, without exception, because of its "complexity" - when I run this through a console tester via PerfView it does not show any exception stack and the ETW events associated with counter updates are successfully recorded in an out-of-process sink. Also, there are no entries in the Windows Logs.
This is all being run "locally" via VS2012 on a Windows 2008R2 server with NET 4.5.
Does anyone have any ideas of how else I may try this - or even test if the "update" is being accepted by PerfMon?
public sealed class Performance {
private enum ProcessCounterNames {
[Description("Total Process Invocation Count")]
TotalProcessInvocationCount,
[Description("Average Process Invocation Rate per second")]
AverageProcessInvocationRate,
[Description("Average Duration per Process Invocation")]
AverageProcessInvocationDuration,
[Description("Average Time per Process Invocation - Base")]
AverageProcessTimeBase
}
private readonly static CounterCreationDataCollection ProcessCounterCollection = new CounterCreationDataCollection{
new CounterCreationData(
Enum<ProcessCounterNames>.GetName(ProcessCounterNames.TotalProcessInvocationCount),
Enum<ProcessCounterNames>.GetDescription(ProcessCounterNames.TotalProcessInvocationCount),
PerformanceCounterType.NumberOfItems32),
new CounterCreationData(
Enum<ProcessCounterNames>.GetName(ProcessCounterNames.AverageProcessInvocationRate),
Enum<ProcessCounterNames>.GetDescription(ProcessCounterNames.AverageProcessInvocationRate),
PerformanceCounterType.RateOfCountsPerSecond32),
new CounterCreationData(
Enum<ProcessCounterNames>.GetName(ProcessCounterNames.AverageProcessInvocationDuration),
Enum<ProcessCounterNames>.GetDescription(ProcessCounterNames.AverageProcessInvocationDuration),
PerformanceCounterType.AverageTimer32),
new CounterCreationData(
Enum<ProcessCounterNames>.GetName(ProcessCounterNames.AverageProcessTimeBase),
Enum<ProcessCounterNames>.GetDescription(ProcessCounterNames.AverageProcessTimeBase),
PerformanceCounterType.AverageBase),
};
private static bool VerifyCounterExistence(PerformanceCounterProfile profile, out List<PerformanceCounter> toUpdate) {
toUpdate = new List<PerformanceCounter>();
bool willUpdate = true;
try {
if (!PerformanceCounterCategory.Exists(profile.CategoryName)) {
PerformanceCounterCategory.Create(profile.CategoryName, profile.CategoryDescription, PerformanceCounterCategoryType.MultiInstance, ProcessCounterCollection);
}
toUpdate.AddRange(Enum<ProcessCounterNames>.GetNames().Select(counterName => new PerformanceCounter(profile.CategoryName, counterName, profile.InstanceName, false) { MachineName = "." }));
}
catch (Exception error) {
Kernel.Log.Trace(Reflector.ResolveCaller<Performance>(), EventSourceMethods.Kernel_Error, new PacketUpdater {
Message = StandardMessage.PerformanceCounterError,
Data = new Dictionary<string, object> { { "Instance", profile.LogFormattedEntry } },
Error = error
});
willUpdate = false;
}
return willUpdate;
}
public static void UpdatePerformanceCounters(PerformanceCounterProfile profile) {
List<PerformanceCounter> toUpdate;
if (profile.Duration <= 0 || !VerifyCounterExistence(profile, out toUpdate)) {
return;
}
foreach (PerformanceCounter counter in toUpdate) {
if (Equals(PerformanceCounterType.RateOfCountsPerSecond32, counter.CounterType)) {
counter.IncrementBy(profile.Duration);
}
else {
counter.Increment();
}
}
}
}
From MSDN .Net 4.5 PerformanceCounter.InstanceName Property (http://msdn.microsoft.com/en-us/library/system.diagnostics.performancecounter.instancename.aspx)...
Note: Instance names must be shorter than 128 characters in length.
Note: Do not use the characters "(", ")", "#", "\", or "/" in the instance name. If any of these characters are used, the Performance Console (see Runtime Profiling) may not correctly display the instance values.
The instance name of 79 characters that I use above satisfies these conditions so, unless ".", ":", "[" and "]" are also "reserved" the name would not appear to be the issue. I also tried a 64 character sub-string of the instance name - just in case, as well as a plain "test" string all to no avail.
Changes...
Apart from the Enum and the ProcessCounterCollection I have replaced the class body with the following:
private static readonly Dictionary<string, List<PerformanceCounter>> definedInstanceCounters = new Dictionary<string, List<PerformanceCounter>>();
private static void UpdateDefinedInstanceCounterDictionary(string dictionaryKey, string categoryName, string instanceName = null) {
definedInstanceCounters.Add(
dictionaryKey,
!PerformanceCounterCategory.InstanceExists(instanceName ?? "Total", categoryName)
? Enum<ProcessCounterNames>.GetNames().Select(counterName => new PerformanceCounter(categoryName, counterName, instanceName ?? "Total", false) { RawValue = 0, MachineName = "." }).ToList()
: PerformanceCounterCategory.GetCategories().First(category => category.CategoryName == categoryName).GetCounters().Where(counter => counter.InstanceName == (instanceName ?? "Total")).ToList());
}
public static void InitialisationCategoryVerify(IReadOnlyCollection<PerformanceCounterProfile> etwProfiles){
foreach (PerformanceCounterProfile profile in etwProfiles){
if (!PerformanceCounterCategory.Exists(profile.CategoryName)){
PerformanceCounterCategory.Create(profile.CategoryName, profile.CategoryDescription, PerformanceCounterCategoryType.MultiInstance, ProcessCounterCollection);
}
UpdateDefinedInstanceCounterDictionary(profile.DictionaryKey, profile.CategoryName);
}
}
public static void UpdatePerformanceCounters(PerformanceCounterProfile profile) {
if (!definedInstanceCounters.ContainsKey(profile.DictionaryKey)) {
UpdateDefinedInstanceCounterDictionary(profile.DictionaryKey, profile.CategoryName, profile.InstanceName);
}
definedInstanceCounters[profile.DictionaryKey].ForEach(c => c.IncrementBy(c.CounterType == PerformanceCounterType.AverageTimer32 ? profile.Duration : 1));
definedInstanceCounters[profile.TotalInstanceKey].ForEach(c => c.IncrementBy(c.CounterType == PerformanceCounterType.AverageTimer32 ? profile.Duration : 1));
}
}
In the PerformanceCounter Profile I've added:
internal string DictionaryKey {
get {
return String.Concat(CategoryName, " - ", InstanceName ?? "Total");
}
}
internal string TotalInstanceKey {
get {
return String.Concat(CategoryName, " - Total");
}
}
The ETW EventSource now does the initialisation for the "pre-defined" performance categories whilst also creating an instance called "Total".
PerformanceCategoryProfile = Enum<EventSourceMethods>.GetValues().ToDictionary(esm => esm, esm => new PerformanceCounterProfile(String.Concat("saTrilogy<Core> ", Enum<EventSourceMethods>.GetName(esm).Replace("_", " ")), Enum<EventSourceMethods>.GetDescription(esm)));
Performance.InitialisationCategoryVerify(PerformanceCategoryProfile.Values.Where(v => !v.CategoryName.EndsWith("Trace")).ToArray());
This creates all of the categories, as expected, but in PerfMon I still cannot see any instances - even the "Total" instance and the update always, apparently, runs without error.
I don't know what else I can "change - probably "too close" to the problem and would appreciate comments/corrections.
These are the conclusions and the "answer" insofar as as it explains, to the best of my ability, what I believe is happening and posted by myself - given my recent helpful use of Stack Overflow this, I hope, will be of use to others...
Firstly, there is essentially nothing wrong with the code displayed excepting one proviso - mentioned later. Putting a Console.ReadKey() before program termination and after having done a PerformanceCounterCategory(categoryKey).ReadCategory() it is quite clear that not only are the registry entries correct (for this is where ReadCategory sources its results) but that the instance counters have all been incremented by the appropriate values. If one looks at PerfMon before the program terminates the instance counters are there and they do contain the appropriate Raw Values.
This is the crux of my "problem" - or, rather, my incomplete understanding of the architecture: INSTANCE COUNTERS ARE TRANSIENT - INSTANCES ARE NOT PERSISTED BEYOND THE TERMINATION OF A PROGRAM/PROCESS. This, once it dawned on me, is "obvious" - for example, try using PerfMon to look at an instance counter of one of your IIS AppPools - then stop the AppPool and you will see, in PerfMon, that the Instance for the stopped AppPool is no longer visible.
Given this axiom about instance counters the code above has another completely irrelevant section: When trying the method UpdateDefinedInstanceCounterDictionary assigning the list from an existing counter set is pointless. Firstly, the "else" code shown will fail since we are attempting to return a collection of (instance) counters for which this approach will not work and, secondly, the GetCategories() followed by GetCounters() or/and GetInstanceNames() is an extraordinarily expensive and time-consuming process - even if it were to work. The appropriate method to use is the one mentioned earlier - PerformanceCounterCategory(categoryKey).ReadCategory(). However, this returns an InstanceDataCollectionCollection which is effectively read-only so, as a provider (as opposed to a consumer) of counters it is pointless. In fact, it doesn't matter if you just use the Enum generated new PerformanceCounter list - it works regardless of whether the counters already exist or not.
Anyway, the InstanceDataCollectionCollection (this is essentially that which is demonstrated by the Win32 SDK for .Net 3.5 "Usermode Counter Sample") uses a "Sample" counter which is populated and returned - as per the usage of the System.Diagnostics.PerformanceData Namespace whichi looks like part of the Version 2.0 usage - which usage is "incompatible" with the System.Diagnostics.PerformanceCounterCategory usage shown.
Admittedly, the fact of non-persistance may seem obvious and may well be stated in documentation but, if I were to read all the documentation about everything I need to use beforehand I'd probably end up not actually writing any code! Furthermore, even if such pertinent documentation were easy to find (as opposed to experiences posted on, for example, Stack Overflow) I'm not sure I trust all of it. For example, I noted above that the instance name in the MSDN documentation has a 128 character limit - wrong; it is actually 127 since the underlying string must be null-terminated. Also, for example, for ETW, I wish it were made more obvious that keyword values must be powers of 2 and opcodes with value of less than 12 are used by the system - at least PerfView was able to show me this.
Ultimately this question has no "answer" other than a better understanding of instance counters - especially their persistence. Since my code is intended for use in a Windows Service based Web API then its persistence is not an issue (especially with daily use of LogMan etc.) - the confusing thing is that the damn things didn't appear until I paused the code and checked PerfMon and I could have saved myself a lot of time and hassle if I knew this beforehand. In any event my ETW event source logs all elapsed execution times and instances of what the performance counters "monitor" anyway.

Visual Studio 2012 stackoverflow after entity framework connectionstring missing

I'm working in VS2012 with update 1 on a win2k8 r2 64 bit.
Within a simple class library application i do Add > New Item> ADO.NET Entity Data Model
I select a SQL Server on the network and select the database and add a single table. The table gets added, and I can access it as a class name in my code.
The issue: When I do anything with backend DB, the app using my library crashes with stackoverflow error (no exception). For instance this will crash: var logs =_db_context.LOGs.ToList();
Any ideas?
EDIT: The same projects were working in VS2010 on the same machine. This only started happening when I upgraded to VS2012 which upgraded entity framework as well. Also worth mentioning that if I remove the code the access the database, the app runs just fine.
Also, removing and re-adding .edmx does not help, neither does clean/re-build or restart VS.
EDIT2: After debugging I've noticed when the line LogServerEntities context = new LogServerEntities() is reached, and I try to expand the context variable from "Locals" VS ends debugging saying Managed (v4.0.30319)' has exited with code -2146233082 (0x80131506).
The class library was actually a custom trace listener and looked like following. When I commented the FirstChanceHandler in the constructor, the exception actually made its way to the console output: an assembly reference (System.Management.Automation) was failing to load. I did not really need that assembly and simply removed it, and the stackoverflow error (which I'm guessing is a bug) went away.
public Listener()
{
AppDomain.CurrentDomain.FirstChanceException += FirstChanceHandler;
}
public void FirstChanceHandler(object source, FirstChanceExceptionEventArgs e)
{
WriteException(e.Exception);
}
public void WriteException(Exception e)
{
string app_identity = System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name;
string server_name = System.Environment.MachineName;
using (LogServerEntities context = new LogServerEntities())
{
LOG log = new LOG();
log.DATE = DateTime.Now;
log.THREAD = Thread.CurrentThread.Name;
log.MESSAGE = e.Message;
log.LOGGER = string.Format("{0} {1}", app_identity, server_name);
log.LEVEL = Level.Exception.ToString();
log.EXCEPTION = e.GetType().FullName;
var web_exception = e as WebException;
if (web_exception != null)
{
if (web_exception.Status == WebExceptionStatus.ProtocolError)
{
var response = web_exception.Response as HttpWebResponse;
if (response != null)
log.HTTP_RESPONSE_CODE = ((int)response.StatusCode).ToString();
else
log.HTTP_STATUS = web_exception.Status.ToString();
}
else
{
log.HTTP_STATUS = web_exception.Status.ToString();
}
}
context.LOGs.Add(log);
context.SaveChanges();
}
}

Can not get MSMQ Com to find my Queue

I am trying to get a count of messages in my MSMQ. I have found this code on the internet (many times):
// setup the queue management COM stuff
MSMQManagement _queueManager = new MSMQManagement();
object machine = "MyLaptopComputer";
object path = #"DIRECT=OS:MyLaptopComputer\PRIVATE$\MyQueue";
_queueManager.Init(ref machine, ref path);
Console.WriteLine(_queueManager.MessageCount);
Marshal.ReleaseComObject(_queueManager);
Every time I get to _queueManager.Init it fails with this error:
The queue path name specified is invalid.
I have checked (and double checked) my queue name to see if that is wrong. I have tried different queues, different machines, running remote, running local... Nothing works.
I have also tried variations on the code above. For example I have tried:
_queueManager.Init("MyLaptopComputer", #"DIRECT=OS:MyLaptopComputer\PRIVATE$\MyQueue");
The queues are used with NServiceBus and function just fine when I use NServiceBus to access them.
Does anyone have an Idea on how I can get this to work?
I think the problem is the error you're getting is a little misguiding. MSMQManagement.Init takes 3 parameters. They're all optional which is why in other languages (like VB) you'll sometimes see it called with only 2 parameters.
There is a CodeProject project that shows how to do what you're doing in C#:
private int GetMessageCount(string queueName)
{
int count = 0;
try
{
MSMQ.MSMQManagement mgmt = new MSMQ.MSMQManagement();
MSMQ.MSMQOutgoingQueueManagement outgoing;
String s = "YOURPCNAME";
Object ss = (Object)s;
String pathName = queueName;
Object pn = (Object)pathName;
String format = null;
Object f = (Object)format;
mgmt.Init(ref ss , ref f, ref pn);
outgoing = (MSMQ.MSMQOutgoingQueueManagement)mgmt;
count = outgoing.MessageCount;
}
catch (Exception ee)
{
MessageBox.Show(ee.ToString());
}
return count;
}
It might provide a better starting point.
Turns out it was a combination of issues. The biggest being that I needed to use FormatName not path name.
_queueManager.Init("MyComputer", null, #"DIRECT=OS:MyComputer\PRIVATE$\MyQueue");
Also, it will throw an exception if the queue is empty...
Got to love COM interfaces. :)

Categories