I’m sure there’s more than one technique for doing this, but this works for me, so I thought I’d share it.
Depending on how you count them, there are three or four steps to debugging a .net 2.0 console application by using the IDE:
-
Set a breakpoint in an appropriate spot
-
If your solution has more than one project, set your console project as the start-up
-
Set the command-line parameters in the debugger, if any
-
Execute the application in the IDE (of course)
1. Set a breakpoint in an appropriate spot
There’s a few ways of doing this, all of which involve of course selecting the line you want the breakpoint on. Breakpoints are "toggles," meaning that the same action repeated a second time will reverse the original action.
- Click on the line you want the breakpoint on, then press F9. A little red ball will appear to the left of the line. This means there is a breakpoint set here. OR-
- Where that little red ball is, you can directly click with the mouse to toggle it on/off. OR-
- Click on the line you want the breakpoint on, then select the menu item Debug/Toggle Breakpoint.
2. If your solution has more than one project, set your console proejct as the start-up
Go to Solution Explorer, which is the list of projects/files that are in the solution. If it isn’t open already, use CTRL-ALT-L to open it, or, less conveniently, the menu item View/Solution Explorer. Locate the project that is your console application and right-click on it. Select "Set as StartUp Project" from the pop-up menu. The project name will now be in bold. this indicates that it is the startup project. The startup project is the project that the IDE executes when you press F5 to start debugging (Menu: Debug/Start Debugging).
3. Set the command-line parameters in the debugger, if any
This is set on the Debug tab of your Project Properties. To get to Project Properties, first make sure to click on the project name of your console application in the Solution Explorer to select it. Then select the "Project/Properties..." menu item. (Note: The menu item will contain your project’s name, so if your project name is MyConsoleApp, the menu item will be "Project/MyConsoleApp Properties...")
Find the text box in the "Start Options" section called "Command line arguments." Enter your default command line arguments here. These are the command line arguments that will be fed to your console app by the IDE debugger when you start the debugging session by pressing F5.
4. Execute the application in the IDE
As mentioned above, press F5 to start the debugging session. Your default command line parameters will be fed to your app, and execution will pause at your breakpoint. After which, you can step through, examine variables, etc., as you please.
That’s all there is to it, but it’s one of those things that can be frustrating to try to do if you don’t know about it and/or don’t know where to look to find out how to do it.
posted Wednesday, December 12, 2007 1:35 PM by ebuatois | 0 Comments
Persons familiar with TOAD for Oracle know about the fairly elaborate search function that lets you search for particular text in procedures, functions, views, column names, triggers, pretty much anything.
There’s a way to do that in SQL Server as well, though you kind of have to "do it yourself."
Use the query below. Make sure that you are "in" the database that you mean to search before you run this query.
select * from sysobjects o, syscomments c where o.id=c.id
and c.text like '%your search text here%'
You can also limit your search by object type. For example:
select * from sysobjects o, syscomments c where o.id=c.id
and c.text like '%mysearchstring%'
and xtype='P' --search stored procedures only
The complete list of types is below. For more information, see:
http://articles.techrepublic.com.com/5100-9592_11-6142579.html
C: Check constraint D: Default constraint F: Foreign Key constraint L: Log P: Stored procedure PK: Primary Key constraint RF: Replication Filter stored procedure S: System table TR: Trigger U: User table UQ: Unique constraint V: View X: Extended stored procedure
This is something that a friend brought to me out of a Java book. It’s an interesting question that appears subtle at first but it’s obvious (I think) when you think about what’s really going on in the context of OO. I’ve seen this question also on BrainBench tests. It may even come up in an interview – trust me.
The question goes something like this.
"The below will compile but will give a runtime casting error. Why? Assume that class MyDerived is derived from class MyBase."
MyBase theBase = new MyBase();
MyDerived theDerived = (MyDerived)theBase;
Give up?
The reason is because while MyDerived "isa" MyBase, the reverse isn’t true -- MyBase "isn’t" MyDerived.
If you try to do the opposite -- cast theDerived into an object of type MyBase -- that will work. This is because, due to the inherited relationship of MyDerived from MyBase, theDerived contains within it methods and data members that conform fully to the definition of MyBase.
The reverse is not true. If you try to cast theBase into an object of type MyDerived, this will NOT work. This is because theBase does not contain within it ANY of the methods or data members that make MyDerived different from MyBase. Since those members are missing, there’s no way to successfully cast an object of type MyBase to a variable of type MyDerived. Hence the invalid-cast exception.
I'm almost embarrassed to put this up because it's so small, but it's something I used to do all the time and had reason to have to re-learn it recently for something I was doing.
Sometimes -- at least until I find a better way -- I need to be able to get "editable" debugging text out of javascript. Using the "alert" box doesn't work for this because you can't do the ctrl-c trick to get its text. (For some message boxes, you can hit ctrl-c and it'll copy the contents such that you can put it into notepad.)
Anyway, the javascript below will cause a new window to open and will write whatever you want into it. Then you can do whatever you would normally do with what shows up in IE windows. FYI, the contents of the open() method is a double-apostrophe for a required parameter that nevertheless can be empty.
window.open('').document.write('your text here')
I ran into this because I wanted to do something funky. I wanted my Flex app window to change PageStates (and size) whenever the TabIndex changed. Whether doing this kind of thing is wise in a user interface is yet to be seen -- I did it and it even strikes ME as a bit off the wall -- but it did solve the immediate issue. The immediate issue was that some of my tabs required a lot of space and some did not. This left a lot of ugly whitespace.
So, I figured, Flex (Actually Flash under the covers) must have an event handler for changing tabs. And I was rewarded very quickly: There is a "TabIndexChange" inline event handler. For the uninitiated, such a thing looks something like this:
<mx:TabNavigator id="tabnavigator1" tabIndexChange="myHandlerFunction()">
With most other events, this works just fine: When the event fires, the handler is called. But it simply doesn't work in this case. The handler function is never called.
There's a couple of ways to handle this. One way is to use a TabBar control rather than a TabControl. The TabBar basically gives you the look and feel of a tabset but more control over what is tabbed. And the tabIndexChange even calls the handler as one might expect.
I didn't want to do it that way, however. For one thing, I'm stubborn. For another, I already had all my controls arranged on the TabNavigator and I didn't want to rip it half to pieces to get functionality that I should already be getting.
Fortunately, there's a solution: Explicitly declare an event listener. That looks something like this:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="InitApp()">
<mx:Script>
<![CDATA[
import mx.events.IndexChangedEvent;
private function InitApp():void
{
tabnavigator1.addEventListener(IndexChangedEvent.CHANGE,indexChangeHandler);
}
function indexChangeHandler(event:IndexChangedEvent):void
{
this.currentState='HideReminderEntry';
mybutton.label=tabnavigator1.getTabAt(tabnavigator1.selectedIndex ).label
// if (event.triggerEvent is MouseEvent)
// recordAutomatableEvent(event, false);
// else
// recordAutomatableEvent(event.triggerEvent, false);
}
]]>
</mx:Script>
Important things to note:
- The handler must be declared in code, and it should run when the page load is complete. So, in the mx:Application tag, there is the inline event, creationComplete="InitApp()".
- Any function name can be used here, but InitApp() is by convention.
- You'll need the "import mx.events.IndexChangedEvent," or you'll get a class-not-defined error.
- Wire up the event listener with:
- tabnavigator1.addEventListener(IndexChangedEvent.CHANGE,indexChangeHandler);
- Finally, as a very small bonus (I'm learning all this too), there's the commented code talking about "if (event.triggerEvent is MouseEvent)". So it turns out you can distinguish between whether the event occurred as the result of a keyboard event (likely Tab), or as a mouseevent. I don't see a use for it here, but it's applicable to ALL events, including, say, Focus() events, where it might have some use. Flex -- actually, ActionScript, its programming language -- is really nifty.
FYI, as a parting note, as far as I can tell SilverLight is intended to be a direct competitor to Flex. Flex has somewhere around a seven-year head start. Don't count Microsoft out, of course -- how many people really use Netscape anymore? -- but on the other hand, you never hear about J++ anymore either. Bottom line: Those who are considering SilverLight should also consider Flex. It's incredibly robust, easy to use, has a full-featured IDE that includes powerful debugging capabilities, and there's lots of great resources on it to help people learn. I've been using the videos at Lynda.com. In fact, watching one of them got me over the hump on this issue. So, I recommend Lynda.com wholeheartedly.
The full text of the error is:
Invalid postback or callback argument. Event validation is enabled using <pages enableEventValidation="true"/> in configuration or <%@ Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.
I got this error when I built a gridview and did a databind for that control in the Page_Load event for the page. The databind() fired every time Page_load fired -- including on postbacks. I fixed the problem by making it so that I only do the databind on initial load of the page, e.g., when "IsPostBack" is false. The gridview's values are otherwise preserved in ViewState.
What's probably going on is this. The gridview's RowCommand event, which handles the postback event in this case, fires after the page's Page_Load event (naturally). So, in the error case, I was destroying and rebuilding the control on postback. So .net then compared the control that fired the postback to the "new" rebound control that was going to handle the postback event, and decided that they were different, and got haired up over a suspected cross-page scripting attack, hence the error message.
FYI, setting "enableEventValidation=false" as cautiously suggested by the error message doesn't work. The error goes away, but the postback event doesn't fire -- probably because this doesn't resolve the underlying issue, that .net is confused about what control is supposed to be handling the postback. In all likelihood, .net basically doesn't find any handler for the postback event, and it drops out.
So, the way I resolved this is, I no longer allow the control to be rebound on EVERY page_load. I only rebind it on the initial page_load, that is, "if not IsPostback." I don't have to rebind the control on every postback anyway, since its full state is maintained in viewstate.
I am learning Flex 2 for a project I'm working on with a friend. We decided, for simplicity's sake, to have our web service connection to the back-end be relatively simple to begin with: Just use HTTP POST. But we ran into a snag, which, in doing a search on Google, I discovered that many others have run into.
When you use a web service to pull a list of XML nodes into Adobe Flex, what happens is that Flex generates a "result" object that contains the xml you're trying to read in. As the Flex developer, you're expected to declare an object of type ArrayCollection, set it equal to the ArrayCollection in the Result collection, and you're good to go. Frustratingly, that's where a lot of the documentation I found on this ends, and it's not the whole picture. The problem is with that ArrayCollection in the Result object that Flex creates for you: The problem is it does NOT always do it! It only does it in cases where it "has to," that is, for xml containing node lists with a count of 2 or more.
More specifically:
- For node lists of two or more nodes, Flex recognizes that it "needs" an ArrayCollection to contain them, and creates the ArrayCollection in the Result object to contain them.
- For node lists of exactly one node, Flex recognizes that it "needs" to only create a single-object container, and chooses to do this by creating an object of type ObjectProxy in the Result object to contain it. For consistency in your application, I would recommend that you use Flex' toArray() function to convert the ObjectProxy to ArrayCollection.
- For node lists of exactly zero nodes, Flex decides, rightly so, to set its internal representation of the node collection to NULL. In that case, for consistency, I would recommend that you simply create an empty ArrayCollection.
Sample code is below. I've included the web service "mx:HTTPService" definition and its call to the parsing function.
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.utils.ObjectProxy;
import mx.rpc.events.ResultEvent;
import mx.controls.Alert;
import mx.utils.ArrayUtil;
[Bindable]
private var reminderList:ArrayCollection;
private function ParseReminderList(event:ResultEvent):void
{
if (event.result.Reminders == null)
{
reminderList=new ArrayCollection()
}
else if (event.result.Reminders.Reminder is ArrayCollection)
{
reminderList=event.result.Reminders.Reminder;
}
else if (event.result.Reminders.Reminder is ObjectProxy)
{
reminderList = new ArrayCollection(ArrayUtil.toArray(event.result.Reminders.Reminder));
}
}
]]>
</mx:Script>
<mx:HTTPService id="ReminderListService" url="http://localhost/reminders.asp" result="ParseReminderList(event)"/>
Dave asked me to post my experience and my interests, so here it is. Let me take this chance to say thanks to the members of this blog for extending the honor of this invitation!
My interests are wide-ranging. I am working toward an MCPD certification. As Dave said my focus is in .net coding and architecture. A summary of my skills and experience follow. I've been in the industry for about 16 years.
Skills: .net 3.0, Legacy ASP/VB6, SQL Server, Oracle, XSLT, n-tier development, requirements gathering, project management methodologies (Waterfall and Scrum).
Experience:
2007-current: Senior Developer, SchoolOne
2001-2007: Senior Developer, AmTrust Bank
2000-2001: Senior Consultant, MarchFirst
1998-2000: Senior Consultant, Brulant/NewMedia
1996-1998: Consultant, Mcknight Consulting Group
1994-1996: Software Developer, United Dutch Publishing
1991-1994: Software Developer, American Business Technologies
I look forward to blogging on TheRunTime. I particularly like discussions, so don't be shy about jumping in!