CA2202 Warning from Code Analysis for OracleConnection disposal - visual-studio-2010

We are getting the following warning from Code Analysis in Visual Studio 2010 and I'm wondering if this is a false positive that we can safely ignore or the code should be refactored to correctly dispose the object.
The relevant code:
public void MyFunction()
{
OracleConnection oraConnection = null;
OracleCommand oraCommand = null;
try
{
// Connect to the database
oraConnection = new OracleConnection(connectionString);
oraConnection.Open();
// Prepare and run the query
oraCommand = new OracleCommand(sqlQuery, oraConnection);
oraCommand.ExecuteNonQuery();
}
catch { throw; }
finally
{
// Perform a safe cleanup
if (oraCommand != null) { oraCommand.Dispose(); }
if (oraConnection != null)
{
oraConnection.Close();
oraConnection.Dispose();
}
}
}
The relevant error message:
Warning 18 CA2202 : Microsoft.Usage : Object 'oraConnection' can be disposed
more than once in method 'ClassName.MyFunction()'. To avoid generating a
System.ObjectDisposedException you should not call Dispose more than one
time on an object.

If you remove the line:
oraConnection.Close();
it should get rid of the warning, since closing and disposing a connection are essentially the same thing.
You might also want to replace your try/finally by a using statement.
Note that Microsoft's own guidelines say that IDisposable.Dispose should be implemented in such a way that it can safely be called multiple times. Which means that the CA2202 warning can safely be ignored, as noted in the comment by JoeM27 on the MSDN page for CA2202.

Related

Is it possible to execute some code when visual studio enters break mode?

I have a large proces that I need to debug and the proces could stop at anytime. I have configured Visual Studio 2017, to stop at any thrown exception, as in, even if it is handled, because I want to see what caused the exception. What I need is some sort of alarm when this happens, so that I can leave the program to run and then alert me if anything comes up. The only thing I have found is an alarm sound when a break point is hit, but it might not be a break point and I need more than a sound, I need to be able to execute some code, so that I can make my Phone go nuts or whatever. Is there any way I can trigger code when the debugger enters break mode?
Thanks in advance.
It is, using a VS package. You'll need to add this attribute on top of the class in order for code to run on package startup:
[ProvideAutoLoad(Microsoft.VisualStudio.Shell.Interop.UIContextGuids80.SolutionExists)] ///Able to run code on solution startup
Add these class values variables:
private DTE2 applicationObject;
private BuildEvents buildEvents;
private DebuggerEvents debugEvents;
then the following code can run:
protected override void Initialize()
{
base.Initialize();
applicationObject = (DTE2)GetService(typeof(DTE));
buildEvents = applicationObject.Events.BuildEvents;
debugEvents = applicationObject.Events.DebuggerEvents;
SetupEventHandlers();
}
And finally the code we have "all" being waiting for:
private void SetupEventHandlers()
{
//buildEvents.OnBuildDone += (scope, action) =>
//{
//};
debugEvents.OnEnterBreakMode += delegate (dbgEventReason reason, ref dbgExecutionAction action)
{
};
//var componentModel =
// GetGlobalService(typeof(SComponentModel)) as IComponentModel;
//if (componentModel == null)
//{
// Debug.WriteLine("componentModel is null");
// return;
//}
//var operationState = componentModel.GetService<IOperationState>();
//operationState.StateChanged += OperationStateOnStateChanged;
}

Data Fetching Crashes in Xamarin Forms

I am trying to fetch Customer data to parse them into customer object to display on TableView. The following code sometimes works, sometimes not. Whenever it does crash, it shows Customer data is empty in the foreach loop even though I run the same code every time. I do not have clue what could be wrong in this circumstances. I am quite new on this platform. If I am missing anything/ extra information, please let me know.
namespace TableViewExample
{
public partial class MyDataServices : ContentPage
{
private ODataClient mODataClient;
private IEnumerable <IDictionary<string,object>> Customers;
public MyDataServices ()
{
InitializeComponent ();
InitializeDataService ();
GetDataFromOdataService ();
TableView tableView = new TableView{ };
var section = new TableSection ("Customer");
foreach (var customers in Customers) {
//System.Diagnostics.Debug.WriteLine ((string)customers ["ContactName"]);
var name = (string)customers ["ContactName"];
var cell = new TextCell{ Text = name };
section.Add (cell);
}
tableView.Root.Add (section);
Padding = new Thickness (10, 20, 10, 10);
Content = new StackLayout () {
Children = { tableView }
};
}
private void InitializeDataService(){
try {
mODataClient = new ODataClient ("myURL is here");
}
catch {
System.Diagnostics.Debug.WriteLine("ERROR!");
}
}
private void GetDataFromOdataService (){
try {
Customers = mODataClient.For ("Customers").FindEntries ();
}
catch {
System.Diagnostics.Debug.WriteLine("ERROR!");
}
}
}
}
Its hard helping out here, however here are some things to consider:-
It sounds like the dataservice could either be not contactable / offline; too busy or it could even be throwing an exception itself and returning a data response that you are not expecting to receive, that then triggers an exception and crash in your application as your always expecting an exact response without catering for any abnormal responses / events.
If you are contacting an external service over the internet it may just be your internet connection is slow / faulty and not returning the information fast enough as other possibilities.
In your code you are assuming that you always get a response from the server - and that this response will always be of an anticipated structure that your expecting to decode - without factoring in any possibility of abnormal responses returned by the dataservice. I have not used ODataClient personally, so not sure how it behaves in the event of maybe no data received / timeout or in your case the dataservice and how it behaves internally in the response to a bad-request etc.
I am assuming an exception would get thrown, and you do get your debug line executed indicating a failure.
You may want to also adjust this statement so that you write out the exception as well, i.e.:-
private void GetDataFromOdataService ()
{
try
{
Customers = mODataClient.For ("Customers").FindEntries ();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("ERROR!" + ex.ToString());
}
}
If there was a bad response, then the line at Customers = ..... would throw the exception as there may be no Customers returned or some other information packaged in the response from the dataservice.
The Customers variable would also be null at this point I am assuming due to this failing.
So when you get back to your code at foreach (var customers in Customers) { it will then throw a null reference exception as Customers is infact null.
As all your current code executes in the constructor without any try and catch block around this, it will also crash your application at this point as well.
Also you are doing all of this work in the constructor. Try seperating this out. I haven't investigated exactly where the constructor gets called in an iOS page life-cycle, however, if it is in the viewDidLoad, then you have something like 10 seconds for everything to complete, otherwise it will exit automatically. I imagine in your case, this isn't applicable however.
Going forward also try putting your layout controls in the constructor, and move your data task to maybe the OnAppearing override instead.
Using async would definitely be advisable as well, but remember you need to inspect the response from your dataservice, as the error could be embedded within the response also and you will need to detect when it is OK to process the data.

VS2010 Code Coverage Not Accurate

I'm using Visual Studio 2010 Ultimate SP1. I have around 225 unit tests in my project, and they are all passing. One of those tests, however, reports 0% code coverage for the method it hits. When debugging, I can step through and see that it hits every line of the method. Yet in the code coverage report, it shows that the method isn't covered at all. All other tests and methods work just fine with regards to code coverage.
I've tried the following with no success:
Moved the method being tested into another class.
Made the method
static vs. non-static.
Moved the test to another class.
Deleted all of my .testsetting files and recreated them from scratch
Wrote a different test to exercise the same method, with the same results
restarted VS
rebooted
In case it matters, the method was in the Global.asax file. However, I moved it to another class and it made no difference.
Any ideas?
Here is the method being tested.
public void LogError(ILoggingService loggingService, IController controller)
{
if (loggingService == null)
throw new ArgumentNullException("loggingService");
if (controller == null)
throw new ArgumentNullException("controller");
Exception ex = Server.GetLastError();
loggingService.LogException(ex.Message, ex.StackTrace, ApplicationName.VoucherLog, UserInfo.UserName);
HttpException httpException = ex as HttpException;
if (httpException == null)
{
var routeData = new RouteData();
routeData.Values["controller"] = "Error";
routeData.Values["action"] = "HttpError";
Server.ClearError();
var rc = new RequestContext(new HttpContextWrapper(Context), routeData);
controller.Execute(rc);
}
}
The first 4 lines, where the exceptions are thrown, are hit by other tests and show up in the code coverage statistics. The remainder of the method is hit by the following test (as verified by debugging through it and seeing that each and every line is, in fact, executed), but does not show up in code coverage stats. Here is the test:
[TestMethod]
[HostType("Moles")]
public void LogError()
{
DMVCommon.ApplicationName expectedApplication = DMVCommon.ApplicationName.VoucherLog;
string expectedUser = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
NotImplementedException expectedException = null;
System.Web.Moles.MHttpServerUtility.AllInstances.GetLastError = (System.Web.HttpServerUtility server) =>
{
return expectedException;
};
System.Web.Moles.MHttpApplication.AllInstances.ContextGet = (System.Web.HttpApplication application) =>
{
return MvcMockHelpers.FakeHttpCurrentContext();
};
try
{
throw new NotImplementedException();
}
catch (NotImplementedException exc)
{
expectedException = exc;
using (MvcApplication app = new MvcApplication())
{
bool called = false;
Mock<ILoggingService> mockLoggingService = new Mock<ILoggingService>();
mockLoggingService.Setup(a => a.LogException(expectedException.Message, expectedException.StackTrace, expectedApplication, expectedUser)).Callback(() => called = true);
Mock<IController> mockController = new Mock<IController>();
app.LogError(mockLoggingService.Object, mockController.Object);
mockController.Verify(a => a.Execute(It.IsAny<System.Web.Routing.RequestContext>()), Times.Exactly(1));
Assert.IsTrue(called);
}
}
}
This happens probably because of your usage of Moles - As the runner loads the assembly, Moles takes over and profiles the assembly instead of the coverage profiler.
There has been known integration issues with coverage tools and Moles -
In order for two .Net profilers (Moles & coverage) to work together they have to implement specific support for each other.
Try to run without Moles and see what happens...
Also see this as a similar example.

Visual Studio 2010 plugin / code to clear "Error List" warnings before each build

VS2010 is driving me nuts: whenever I rebuild, the "Error List" warnings from the previous compilation are persisted and any new warnings are simply added to the end of the list. Over time, this list becomes ridiculously long and unwieldy.
I'm using the Chirpy 2.0 tools to run JSHint and JSLint on my JS files, and these tools generate a lot of false positives.
I've been looking for an easy way to clear the contents of this window, but the only manual mechanism that works 100% of the time is to close and re-open the solution. Not very elegant.
I'd like to write a small VS Plug-In or some code that gets called right before a compilation to clear out this list so I can focus only on new warnings for the currently loaded file(s).
I see a .Clear() method for the Output window but not for the Error List. Is this doable?
Once upon a time I was an Add-In/VSIX Package/MEF developer ...
The answer is shortly no, but I have to do it on the long way:
Add-Ins, packages (Managed or not) have access to the VS service level separatedly. Every error belongs to the reporter (If they are manage them as Chirpy do), so you can not handle the errors created by Chirpy 2.0
I take a several look to it's source code and it is persist it's erros gained by the tools in a Singleton collection called TaskList.
The deletion of the collection elements is happening in several point of code in the latest release through the RemoveAll method:
First: after the soulution is closed.
by this:
private static string[] buildCommands = new[] { "Build.BuildSelection", "Build.BuildSolution", "ClassViewContextMenus.ClassViewProject.Build" };
private void CommandEvents_BeforeExecute(string guid, int id, object customIn, object customOut, ref bool cancelDefault) {
EnvDTE.Command objCommand = default(EnvDTE.Command);
string commandName = null;
try {
objCommand = this.App.Commands.Item(guid, id);
} catch (System.ArgumentException) {
}
if (objCommand != null) {
commandName = objCommand.Name;
var settings = new Settings();
if (settings.T4RunAsBuild) {
if (buildCommands.Contains(commandName)) {
if (this.tasks != null) {
this.tasks.RemoveAll();
}
Engines.T4Engine.RunT4Template(this.App, settings.T4RunAsBuildTemplate);
}
}
}
}
As you may see, clear of results depends on many thigs.
First on a setting (which I don't know where to set on GUI or configs, but seems to get its value form a check box).
Second the array of names which are not contains every build commands name.
So I see a solution, but only on the way to modify and rebuild/redepeloy your own version from Chirpy (and make a Pull request):
The code souldn't depend on the commands, and their names. (rebuilds are missing for example)
You could change the method above something like this:
this.eventsOnBuild.OnBuildBegin += ( scope, action ) =>
{
if (action != vsBuildAction.vsBuildActionDeploy)
{
if (this.tasks != null)
{
this.tasks.RemoveAll();
}
if (settings.T4RunAsBuild && action != vsBuildAction.vsBuildActionClean)
{
Engines.T4Engine.RunT4Template(this.App, settings.T4RunAsBuildTemplate);
}
}
};
Or with something equivalent handler method instead of lambda expression.
You shold place it into the subscription OnStartupComplete method of Chirp class.
The unsubscription have to placed into OnDisconnection method in the same class. (As for all other subscribed handlers...)
Update:
When an Add-In disconneced, it isn't means the Studio will be closed immediately. The Add-In could be unloaded. So you should call the RemoveAll from OnDisconneconnection too. (Or Remove and Dispose the TaskList...)
Update2:
You can also make a custom command, and bind it to a hotkey.

SaveAs in COM hanging AutoCAD

I'm implementing an application which uses COM in AutoCAD's ObjectARX interface to automate drawing actions, such as open and save as.
According to the documentation, I should be able to call AcadDocument.SaveAs() and pass in a filename, a "save as type" and a security parameter. The documentation explicitly statses that if security is NULL, no security related operation is attempted. It doesn't, however, give any indication of the correct object type to pass as the "save as type" parameter.
I've tried calling SaveAs with a filename and null for the remaining arguments, but my application hangs on that method call and AutoCAD appears to crash - you can still use the ribbon but can't do anything with the toolbar and can't close AutoCAD.
I've got a feeling that it's my NULL parameters causing grief here, but the documentation is severely lacking in the COM/VBA department. In fact it says the AcadDocument class doesn't even have a SaveAs method, which it clearly does.
Has anyone here implemented the same thing? Any guidance?
The alternative is I use the SendCommand() method to send a _SAVEAS command, but my application is managing a batch of drawing and needs to know a) if the save fails, and b) when the save completes (which I'm doing by listening to the EndSave event.)
EDIT
Here's the code as requested - all it's doing is launching AutoCAD (or connecting to the running instance if it's already running), opening an existing drawing, then saving the document to a new location (C:\Scratch\Document01B.dwg.)
using (AutoCad cad = AutoCad.Instance)
{
// Launch AutoCAD
cad.Launch();
// Open drawing
cad.OpenDrawing(#"C:\Scratch\Drawing01.dwg");
// Save it
cad.SaveAs(#"C:\Scratch\Drawing01B.dwg");
}
Then in my AutoCad class (this._acadDocument is an instance of the AcadDocument class.)
public void Launch()
{
this._acadApplication = null;
const string ProgramId = "AutoCAD.Application.18";
try
{
// Connect to a running instance
this._acadApplication = (AcadApplication)Marshal.GetActiveObject(ProgramId);
}
catch (COMException)
{
/* No instance running, launch one */
try
{
this._acadApplication = (AcadApplication)Activator.CreateInstance(
Type.GetTypeFromProgID(ProgramId),
true);
}
catch (COMException exception)
{
// Failed - is AutoCAD installed?
throw new AutoCadNotFoundException(exception);
}
}
/* Listen for the events we need and make the application visible */
this._acadApplication.BeginOpen += this.OnAcadBeginOpen;
this._acadApplication.BeginSave += this.OnAcadBeginSave;
this._acadApplication.EndOpen += this.OnAcadEndOpen;
this._acadApplication.EndSave += this.OnAcadEndSave;
#if DEBUG
this._acadApplication.Visible = true;
#else
this._acadApplication.Visible = false;
#endif
// Get the active document
this._acadDocument = this._acadApplication.ActiveDocument;
}
public void OpenDrawing(string path)
{
// Request AutoCAD to open the document
this._acadApplication.Documents.Open(path, false, null);
// Update our reference to the new document
this._acadDocument = this._acadApplication.ActiveDocument;
}
public void SaveAs(string fullPath)
{
this._acadDocument.SaveAs(fullPath, null, null);
}
From the Autodesk discussion groups, it looks like the second parameter is the type to save as, and may be required:
app = new AcadApplicationClass();
AcadDocument doc = app.ActiveDocument;
doc.SaveAs("d:\Sam.dwg",AcSaveAsType.acR15_dwg,new Autodesk.AutoCAD.DatabaseServices.SecurityParameters());
Since you are in AutoCAD 2010, the type should be incremented to acR17_dwg or acR18_dwg.
Judging by the link to AutoDesk's forum on this topic, it sounds like as you need to close the object after saving...and remove the null's...If I were you, I'd wrap up the code into try/catch blocks to check and make sure there's no exception being thrown!
I have to question the usage of the using clause, as you're Launching another copy aren't you? i.e. within the OpenDrawing and Save functions you are using this._acadApplication or have I misunderstood?
using (AutoCad cad = AutoCad.Instance)
{
try{
// Launch AutoCAD
cad.Launch();
// Open drawing
cad.OpenDrawing(#"C:\Scratch\Drawing01.dwg");
// Save it
cad.SaveAs(#"C:\Scratch\Drawing01B.dwg");
}catch(COMException ex){
// Handle the exception here
}
}
public void Launch()
{
this._acadApplication = null;
const string ProgramId = "AutoCAD.Application.18";
try
{
// Connect to a running instance
this._acadApplication = (AcadApplication)Marshal.GetActiveObject(ProgramId);
}
catch (COMException)
{
/* No instance running, launch one */
try
{
this._acadApplication = (AcadApplication)Activator.CreateInstance(
Type.GetTypeFromProgID(ProgramId),
true);
}
catch (COMException exception)
{
// Failed - is AutoCAD installed?
throw new AutoCadNotFoundException(exception);
}
}
/* Listen for the events we need and make the application visible */
this._acadApplication.BeginOpen += this.OnAcadBeginOpen;
this._acadApplication.BeginSave += this.OnAcadBeginSave;
this._acadApplication.EndOpen += this.OnAcadEndOpen;
this._acadApplication.EndSave += this.OnAcadEndSave;
#if DEBUG
this._acadApplication.Visible = true;
#else
this._acadApplication.Visible = false;
#endif
// Get the active document
// this._acadDocument = this._acadApplication.ActiveDocument;
// Comment ^^^ out? as you're instantiating an ActiveDocument below when opening the drawing?
}
public void OpenDrawing(string path)
{
try{
// Request AutoCAD to open the document
this._acadApplication.Documents.Open(path, false, null);
// Update our reference to the new document
this._acadDocument = this._acadApplication.ActiveDocument;
}catch(COMException ex){
// Handle the exception here
}
}
public void SaveAs(string fullPath)
{
try{
this._acadDocument.SaveAs(fullPath, null, null);
}catch(COMException ex){
// Handle the exception here
}finally{
this._acadDocument.Close();
}
}
Thought I'd include some links for your information.
'Closing Autocad gracefully'.
'Migrating AutoCAD COM to AutoCAD 2010'.
'Saving AutoCAD to another format'
Hope this helps,
Best regards,
Tom.
I've managed to solve this in a non-optimal, very imperfect way so I'd still be interested to hear if anyone knows why the SaveAs method crashes AutoCAD and hangs my application.
Here's how I did it:
When opening a document or creating a new one, turn off the open/save dialog boxes:
this._acadDocument.SetVariable("FILEDIA", 0);
When saving a document, issue the _SAVEAS command passing in "2010" as the format and the filename (fullPath):
string commandString = string.Format(
"(command \"_SAVEAS\" \"{0}\" \"{1}\") ",
"2010",
fullPath.Replace('\\', '/'));
this._acadDocument.SendCommand(commandString);
When exiting AutoCAD turn file dialog prompting back on (probably isn't necessary but just makes sure):
this._acadDocument.SetVariable("FILEDIA", 1);
With C# and COM, when there are optional arguments, you need to use Type.Missing instead of null:
this._acadDocument.SaveAs(fullPath, Type.Missing, Type.Missing);
But since Visual Studio 2010, you can simply omit the optional arguments:
this._acadDocument.SaveAs(fullPath);

Resources