Exception thrown in referenced project? - c#

I have a Visual Studio 2010 solution consisting of 2 projects:
Core, a C# class library project which handles the functionality and data access
UI, an ASP.NET 4 website (.NET Framework 4) that references the Core, and calls functionality in the Core.
My exception handler is set in Global.asax (Application_Error.)
When an exception occurs in the UI, everything works perfectly, I get filename, line number, etc.
This is not the case for exceptions that occur in the Core.
For this, I get a stacktrace like:
{FillUserCount at offset 2376 in file:line:column <filename unknown>:0:0}
P.S. The Core.dll and Core.pdb are present in the UI Bin folder.
In Visual Studio -> Tools -> Options -> Debugging -> "Enable just my code" is unchecked and "Enable source server support" is checked.
Is there a way to get stackframe info (filename, class, method, line number) also for errors that occured in my referenced project ?

The solution to get this working was to create a new web site and re-referencing the Core project.
Still, the prerequisites that Jon Skeet mentioned remain the same:
the projects have to be built in Debug configuration, and not Release
while referencing a project, make sure PDB files are copied
on code side, when retrieving info about the exception that occured, and using StackTrace, make sure you create the instance with the second parameter set to true (true to capture the file name, line number, and column number; otherwise, false.)
This is my final working code. It may help others:
Exception ex = Server.GetLastError().GetBaseException();
StackTrace trace = new StackTrace(ex, true);
if (trace.FrameCount == 0)
return;
StackFrame stackFrame = trace.GetFrame(0);
string className, fileName, functionName, message;
int line = 0;
// if for some reason, filename is being retrieved as null
if (stackFrame.GetFileName() == null)
{
className = ex.TargetSite.ReflectedType.Name;
fileName = ex.TargetSite.ReflectedType.Name;
functionName = ex.TargetSite.Name;
message = ex.Message;
}
else
{
// Collect data where exception occured
string[] splitFile = stackFrame.GetFileName().Split('\\');
className = splitFile[splitFile.Length - 1];
fileName = stackFrame.GetFileName();
functionName = stackFrame.GetMethod().Name;
message = ex.Message;
line = stackFrame.GetFileLineNumber();
}

How are you referencing Core? If you've added a reference to the "Release" DLL, that would explain it... if you've just added a reference to the project and you're running a build with the "Debug" configuration then it should be okay.

Related

Visual Studio C# if statement not working in Debug

So I have a weird situation, where I get to an if statement while debugging, and I'm finding that even though EM=="M", my if statement if(EM=="E") is being entered anyway... I'm also noticing that some of my code seems to be just getting skipped over when I'm stepping though the code(F11).
I'm using C# in VS2015 and VS2017, it's having the issue in both versions. I was using Framework 4.5, I had switched it to 4.6.1 to build a compatible version for a different program. But switching that back didn't change anything...
public static string EM = "";
Database db = doc.Database;
//db.measureunits is 0 or 1
if (db.measureunits == 1) // english
{
EM = "E";
}
else // metric
{
EM = "M";
}
try
{
if (EM == "E") //If english
{ <-- Breakpoint STOPS Here EM is equal to "M" at this point, which shouldn't allow the break point to be hit, since EM("M")!="E"
topText.TextString = rad + "\" minimum bend radius";
}
if (EM == "M") //Metric
{ <-- Breakpoint never stops Here
topText.TextString = Convert.ToString(Math.Round((Convert.ToDouble(rad)) * 0.3048, 2)) + "\" minimum bend radius";
}
}
catch (IOException e)
{
// Extract some information from this exception, and then
// throw it to the parent method.
if (e.Source != null)
System.Windows.Forms.MessageBox.Show($"IOException source: {0}", e.Source);
throw;
}
If anyone else is aware of this issue or know's what I may be doing wrong, help would be appreciated.
The following workaround might be helpful
Delete bin and obj folder then re-build.
Restart Visual Studio OR PC
A few ideas.
There occures an exception so that it jumps over the code which is coming after. Press Ctrl + Alt + E and check "Common Language Runtime Exceptions". Now it should stop at the moment an exception occures and show it to you.
Your code was optimized during build. Try to build in debug mode or uncheck "optimize code" in the project properties under "Build".
Delete the obj and bin folders. You already tried this.
There is something fishy with the PDB file. The PDB file contains information for the debugger. Project properties -> build -> advanced => set "Debug Info:" to "full" (if you use debug configuration this should already be the case) and rebuild the whole solution.

Changing SSIS package in C# causing LoadFromXML fail

I am attempting to create a copy of an existing dtsx file so I can change a few variables based on input from the user. I am able to make a copy of the file, look at the variables, and set the variables to the correct input. However, when I go to look at the file in Visual Studio I get a few errors.
Microsoft Visual Studio is unable to load this document: The package failed to load to to error 0xC0010014 "One or more error occurred. There should be more specific errors preceding this one that explains the details of the errors. This message is used as a return value from functions that encounter errors". This occurs when CPackage::LoadFromXML fails.
The errors contained in the error list:
Error 3 Error loading test.dtsx: Error loading value "<DTS:Property xmlns:DTS="www.microsoft.com/SqlServer/Dts" DTS:Name="PackageFormatVersion">6</DTS:Property>" from node "DTS:Property". E:\test.dtsx 1 1
The version number in the package is not valid. The version number cannot be greater than current version number.
I looked into these errors and I saw potential issues with the server year and visual studio year. Both of these are the 2008 version.
My code:
string pkgPath = #"\\server\TestFolder\test.dtsx"
app = new Microsoft.SqlServer.Dts.Runtime.Application();
pkg = app.LoadPackage(pkgPath, null);
Console.WriteLine(pkg.Variables["filename"].Value.ToString());
pkg.Variables["filename"].Value = "testFile";
Console.WriteLine(pkg.Variables["filename"].Value.ToString());
app.SaveToXml(pkgPath, pkg, null);
If I open the file I am using to make a copy of in Visual Studio, it works no problem -- something strange is happening when I do app.SaveToXML();
Any ideas or suggestion would be wonderful.
To run this as a process from DTEXEC, it would look something like below. Please check out these two links for further details about ProcessStartInfo and how to use /SET so you can add that to your argument. Test this from the command line first because the syntax can be finicky.
https://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo(v=vs.110).aspx
https://technet.microsoft.com/en-us/library/ms162810(v=sql.105).aspx
Using System.Diagnostics;
string args = #"/F'c:\MyPackage.dtsx' /SET'\package.variables[myvariable].Value;myvalue'";
ProcessStartInfo executePackage = new ProcessStartInfo("dtexec", args);
executePackage.UseShellExecute = false;
executePackage.RedirectStandardError = true;
executePackage.RedirectStandardOutput = true;
executePackage.CreateNoWindow = true;
StringBuilder output = new StringBuilder();
Process executing = Process.Start(executePackage);
while(!executing.StandardOutput.EndOfStream)
{
output.AppendLine(executing.StandardOutput.ReadLine();
}
executing.WaitForExit():

IVsDropdownBarClient and GetEntryText: Problems with text buffers

In my Visual Studio extension, I'm going to read the text that is in the navigation bar. Therefore I listen to window created events and from the IVsCodeWindow object I get the IVsDropdownBar to get the current selection in the dropdown bar. This works fine. Then I'm using the following code snippet to extract the text of the current selection:
string text;
barClient.GetEntryText(MembersDropdown, curSelection, out text);
if (hr == VSConstants.S_OK)
{
Debug.WriteLine("Text: " + text);
} else {
Debug.WriteLine("No text found!");
}
However, this does not work. My extension crashes with an unhandled exception in the second line of the code snippet. I read the documentation and could find the following note:
The text buffer returned in ppszText is typically created by the
IVsDropdownBarClient object and the buffer must persist for the life
of the IVsDropdownBarClient object. If you are implementing this
interface in managed code and you need to have the string disposed of
by the caller, implement the IVsCoTaskMemFreeMyStrings interface on
the IVsDropdownBarClient interface.
I assume that this is part of my problem, but I can't really understand what I have to change in my code to get it working. Any hints?
I'm pretty sure now that the Visual Studio SDK Interop DLLs have the wrong marshalling information for IVsDropDownbarClient.GetEntryText and that there's no way to call that method using that interface.
The best workaround I've found so far is:
Use the tlbimp tool to generate an alternate Interop DLL for textmgr. (You can safely ignore the dozens of warnings including the one about GetTextEntry.)
tlbimp "c:\Program Files (x86)\Microsoft Visual Studio 11.0\VSSDK\VisualStudioIntegration\Common\Inc\textmgr.tlb"
(Optional) If you're using source control, you'll probably want to copy the resulting file (TextManagerInternal.dll) to a subdirectory of your extension project and check it in as an external dependency.
In your Visual Studio extension project, add a reference to the file (TextManagerInternal.dll).
Add the following method that should properly handle the string marshalling.
static public string HackHackGetEntryText(IVsDropdownBarClient client, int iCombo, int iIndex)
{
TextManagerInternal.IVsDropdownBarClient hackHackClient = (TextManagerInternal.IVsDropdownBarClient) client;
string szText = null;
IntPtr ppszText = IntPtr.Zero;
try
{
ppszText = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(IntPtr)));
if(ppszText == IntPtr.Zero)
throw new Exception("Unable to allocate memory for IVsDropDownBarClient.GetTextEntry string marshalling.");
hackHackClient.GetEntryText(iCombo, iIndex, ppszText);
IntPtr pszText = Marshal.ReadIntPtr(ppszText);
szText = Marshal.PtrToStringUni(pszText);
}
finally
{
if(ppszText != IntPtr.Zero)
Marshal.FreeCoTaskMem(ppszText);
}
return szText;
}
}

Adding existing project into new VS2012 solution programmatically fails

We have the following code in wizard to add existing project to a new solution:
//generating files
if (dte.Solution.Projects.Count < 1) // Solution is empty or doesn't exist
{
dte.Solution.Create(oneFolderHigher(Params.OutputDir, solutionName),
solutionFileName(solutionName));
}
// adding created project to solution
dte.Solution.AddFromFile(Path.Combine(Params.ProjectRootFolder,
Params.ProjectName + ".csproj"));
It works just fine under MS Visual Studio 2010, but fails under 2012 (I experimented with second parameter):
System.Runtime.InteropServices.COMException (0x80004004): Operation aborted (Exception from HRESULT: 0x80004004 (E_ABORT))
at EnvDTE.SolutionClass.AddFromFile(String FileName, Boolean Exclusive)
at Wizard.Generator.NewProjectGenerator.Generate(Action`1 logMessage)
at Wizard.Forms.WizardForm.Finish()
After this error I'm adding the new project to the solution manually and everything works OK. But we can not just say, "Sorry, we can not add newly generated project for you so please add it by yourself."
MSDN proposes:
You can use the LaunchWizard method rather than AddFromFile to execute a wizard if you want to suppress its UI during execution. LaunchWizard has a parameter that allows you to disable the UI.
But this method requires some wizard file, so it can not be a solution.
Could someone help?
Wizard is running from "New -> Project" menu.
Here the workaround for the issue (proposed by my boss):
Before adding the project to solution, project file should be converted to
VS2012 format.
But code is little ugly:
using (StreamReader sr = new StreamReader(newFile))
using (StreamWriter sw = new StreamWriter(projectFile, false, Encoding.UTF8))
{
while (sr.Peek() >= 0)
{
string s = sr.ReadLine();
if (s.Contains("<Project ToolsVersion=\"4.0\""))
{
s = s + Environment.NewLine + importProject;
}
... and so on
Maybe someone knows the way to do it awesome? I mean converting. I'll let the question to be unanswered some time. Waiting for your comments.

Uninstalling my Office 2010 plugin leaves a null pointer exception

I've been trying to track down why my Office2010 plugin leaves a null pointer exception during uninstall and the 2007 version does not. (Edit: 2007 is at same state as 2010 - FAIL)
To narrow it down I have put in a couple of eventlog traps, meaning if code reaches this point - I should get something in the Eventlog. No such luck. Now either I written the eventlog trap wrong or code doesn't reach that point.
In the CustomSetupActions - ClickOnceInstaller.cs
public void Uninstall(System.Collections.IDictionary savedState)
{
// write something to eventlog
// This is not being fired, the exception doesn't reach here or writing to eventlog fails.
if (!EventLog.SourceExists("OfficePlugin"))
{
EventLog.CreateEventSource("OfficePlugin", "Application");
}
EventLog.WriteEntry
("OfficePlugin"
, string.Format("Uninstalling: (bug hunting)"), EventLogEntryType.Information);
string deploymentLocation = (string)savedState["deploymentLocation"];
if (deploymentLocation != null)
{
string arguments = String.Format(
"/S /U \"{0}\"", deploymentLocation);
ExecuteVSTOInstaller(arguments);
}
}
As for the ExecuteVSTOInstaller(string arguments)
2007 refers to: string subPath = #"Microsoft Shared\VSTO\9.0\VSTOInstaller.exe";
2010 refers to: string subPath = #"Microsoft Shared\VSTO\10.0\VSTOInstaller.exe";
If the first trap had fired, this is where I would have placed the trap afterwards.
--
I have another method that handles the registration db
RegisterOffice2010AddIn.cs
public void UnRegisterAddIn(string applicationName, string addInName)
{
Next line is precisely the same eventlog trap as I just used/shown.
Difference between the two (2007 vs 2010).
private const string UserSettingsLocation =
#"Software\Microsoft\Office\12.0\User Settings";
vs
private const string UserSettingsLocation =
#"Software\Microsoft\Office\14.0\User Settings";
I can't think of any other place that might be interesting to place the trap. I have a CustomInstaller which doesn't do anything besides Dispose(bool disposing) and InitializeComponent()
Development:
Action start 14:21:00: PublishFeatures.
Action ended 14:21:00: PublishFeatures. Return value 1.
Action start 14:21:00: PublishProduct.
Action ended 14:21:00: PublishProduct. Return value 1.
Action start 14:21:00: InstallExecute.
MSI (c) (B8:BC) [14:21:01:013]: Font created. Charset: Req=0, Ret=0, Font: Req=MS Shell Dlg, Ret=MS Shell Dlg
Error 1001. Error 1001. An exception occurred while uninstalling. This exception will be ignored and the uninstall will continue. However, the application might not be fully uninstalled after the uninstall is complete. --> Object reference not set to an instance of an object.
DEBUG: Error 2769: Custom Action _EE8A0D36_BE55_421F_9A55_95470C001D87.uninstall did not close 1 MSIHANDLEs.
The installer has encountered an unexpected error installing this package. This may indicate a problem with this package. The error code is 2769. The arguments are: _EE8A0D36_BE55_421F_9A55_95470C001D87.uninstall, 1,
Action ended 14:21:05: InstallExecute. Return value 3.
Action ended 14:21:06: INSTALL. Return value 3.
Googling the Error 2769 - gives an answer of "[TARGETDIR]\" , but I dont reference TargetDir, I reference deploymentLocation. And Yes I have tried adding the "\" to places I could think of. Including the setup - Registry - HKLM\Software\MS\Office\12.0\ ...etc... \Addins\Excel/Word/Outlook and the Manifest keyvalue. Gave no feedback, good or bad, errors or otherwise. I'm at a loss what else to try to hunt this one down.
I have a guess it is referencing to this, in the VDPROJ:
{
"Name" = "8:UnregisterOutlookAddIn"
"Condition" = "8:"
"Object" = "8:_73E71A44EB72485AB7367745F7D57F49"
"FileType" = "3:1"
"InstallAction" = "3:4"
"Arguments" = "8:"
"EntryPoint" = "8:"
"Sequence" = "3:3"
"Identifier" = "8:_EE8A0D36_BE55_421F_9A55_95470C001D87"
"InstallerClass" = "11:TRUE"
"CustomActionData" = "8:/addinName=\"OUR.Outlook.Outlook2010AddIn\" /application=\"Outlook\""
}
I found it throws two exception - the secondary under CustomSetupActions and UnregisterAddIn and the primary under ClickOnceInstaller and Uninstall. Howcome I mention them as 2ndary and primary. Well it will do the exception in CustomAction and then the killing one in ClickOnce. I've eliminated the one in CustomActions and I now only have to worry about the ClickOnce. From what I can gather the ClickOnce implements the interface specified in the Setup Project (Install, Rollback, Commit, Uninstall). I only have to figure out how it can run amiss the Uninstall method.
Disclaimer: Unless ofcourse I'm mistaken and is barking up the wrong tree.
Change to WiX. It became a workaround as the original is still true.

Categories

Resources