Monday, July 12, 2010

c++ dll error when using MD[d]

It is possible for any programmer, even one that has been in the "trade" for a loooong time, to be an absolute idiot - especially when they are learning something new. Not always does hard learned skills help when trying something new.

Take my latest gaff as an example. Now I've been coding C++/cli mixed mode dlls since 2005, but I'd taken some time off right before Windows 7 arrived. Well, it was time to get back into the saddle, so I started work on a long dormant project and got it to a Beta state.

I rolled out the debug dll to my testers and when they tested it on Windows 7, Boom!.

Ok, time for some research .... lots of time for research.

Well, I finally found - that in a non-/cli C++ dll, I could use the /MT compiler switch and it would work just fine on XP and Win7. But if I used the /MD compiler switch, which is required to use C++/cli, it would still run on a clean XP install, but not on a clean Win7 install.

Arrrgggg!

After many posts on many different forums, I decided to try making a install package (which I've NEVER had to do before - its just a dll after all!) but Visual Studio pulled in two additional files, that it said were needed to run.

Well - Success!! Sort of. But, I happily posted my results on the various forums. One reply (Thanks Peter) pointed out that they were Debug files and that it may be a licence issue if I were to disseminate them.

That got me to wondering if this was all a Debug/Release mode issue.

Well, it was. I started with a new copy of my Win7 Virtual PC that also installs the C++ runtime files.

I then pushed a debug version to it just to verify that we still had the issue. Yep.

Then I pushed a release version to it and viola! It works. Dumb, dumb, dumb!

Why do I make things so hard for myself?

Wednesday, July 7, 2010

C++/cli -> calling c# dll -> calling OpenFileDialog issue

I write extensions to a Cartography program called Campaign Cartographer 3 (CC3 for short). It is sold by one of the most involved companies I have ever had the pleasure to be associated with ProFantasy.

To program an extension to CC3, you need to be able to write old school windows dlls. You remember the ones! They have a DllMain function? I saw that shudder, you do remember.

Well, whenever I can I use C++/cli (the .net version of C++) and if the extension is very complicated, I do most of my coding in C# and reference the C# dll from C++/cli. You can mix and match plain old C++ and C++/cli (and C#) through IJW (Believe it or not, that stands for "It Just Works"). As a matter of fact all my newer extensions hook into C++/cli, even if I do not use it - I want it there just in case.

Well, in my latest project, a self-contained wiki-like document reader/writer (hard to explain - maybe in a later post), I needed to call the standard .net openFileDialog and saveDileDialog controls.

All of a sudden, I'm getting COM errors!?!?

'System.Threading.ThreadStateException' occurred in System.Windows.Forms.dll

Additional information: Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it. This exception is only raised if a debugger is attached to the process.


OLE calls? How old an error is that!?

Well, it seems that if you try to call the .net file dialogs from C++/cli you need to do it from a STA Thread. But, since I cannot access the main thread, remember this is someone elses application - all I have access to is my DllMain. Well, after searching around and asking about how to deal with this error on StackOverflow.com - I got my answer, sort of.

The helpful people over at StackOverflow pointed out that I needed to start my own thead as an STAThread. They also gave me advice on how to do this via COM.

Well, I'm not adverse to admit that the amount of COM knowledge I have could be held in a teacup. But the Thread advice solved the problem. I just did it the C++/cli way!

First you need to isolate the code you want to run into a class.

ref class StaClass
{
    void CallWiki()
    {
        WikiNotes::FrmWiki fw;
        fw.ShowDialog();
    }
}


Then from my main C++/cli code, I just create a new thread and call "CallWiki"

StaClass wiki = gcnew StaClass;

ThreadStart^ threadDelegate = gcnew ThreadStart(wiki, &StaClass::CallWiki);
Thread^ newThread = gcnew Thread(threadDelegate, 0);
newThread->SetApartmentState(ApartmentState::STA);
newThread->Start();


Remember though, if you want to wait until your new thread finishes, like I did, then you can:

while (!workerThread->IsAlive);
regularThread->Join();

Saturday, June 26, 2010

Fixing "Random" Default Button Behavior (asp.net)

Way back when I first started developing web applications, I quickly determined that you had to have the default button as the first submit button in the HTML markup.

A recent trouble ticket at work detailed that the default button was behaving erratically. It seemed that it was working only every other time. Yet, the location of the button never changed, so how could that be?

Here is a link of an example where I have recreated the issue.

Broken Default Button

To recreate the broken behavior, set the focus in one of the textboxes or a radiobuton and then press the enter key. The panel should minimize and a second panel should now become visible. click on the button in the upper right corner to re-expand the original panel and repeat the test.

every time both panels are visible, the default button switches to the button in the lower panel.

The fix is quite simple. Using asp.net 2.0 or higher simply add this one line to the Page_Load function: Page.Form.DefaultButton = "Button ID";

Fixed Default Button

Tuesday, June 22, 2010

Dynamic type simplifies returning an anonymous type from a function

Ever since Microsoft added anonymous types to C#, I've tried to use them in the manner that Microsoft themselves described: "Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to first explicitly define a type."

And, it seemed to me that one of the best uses for one of these "temporary" objects is as a return type from a function. Yet, Microsoft expressly designed anonymous types to not be usable as a return type. Sure, you could have the return type as Object, but then you could not cast it back as the type because it is "anonymous".

Here is a Blog Post the explains how to return an anonymous type using a casting function.

Now though it is much simpler. All you need to do is set the return value to "dynamic". Since the dynamic type is determined at run time instead of compile time, compiler type checking is bypassed. At run time, when dynamic variables are referenced, they then have their methods and properties verified. So you can, in code, reference a property without having the compiler knowing if the type actually has the property.

One caveat: This will only work within the same assembly. From a design standpoint, this makes sense. Why pass along an anonymous type between assemblies? It just does not make any sense. Inside a single assembly it is local and you are in full control, but between assemblies? You never know who is going to use it. You cannot assume that they would have any idea what is being returned.


Code Snippet



  1. static void Main(string[] args)

  2. {

  3. var d = ReturnAnonamoustype();

  4.  

  5. Console.WriteLine(d.Name);

  6. Console.Read();

  7. }

  8.  

  9. static dynamic ReturnAnonamoustype()

  10. {

  11. return new { Name = "Bob", Age = 50 };

  12. }



Friday, June 18, 2010

Returning a string array to Javascript from Sliverlight

This took a lot of trial and error, but I finally figured out how to return to Javascript a string array. There where many different examples out on the web to call Javascript, passing a string array. But, no examples had Javascript calling a Silverlight function with a string array as the return value.

I first tried the direct approach:

javascript:
function TalkToSilverlight(data) {
var control = document.getElementById("silverlightControl");
var myStringArray = control.Content.Page.ReturningStringArray();
alert('length = ' + myStringArray.length + " : Value of First Element = " + myStringArray[0]);
}


Silverlight C#
public App()
{
HtmlPage.RegisterScriptableObject("Page", this);
//The rest I've elided
}

[ScriptableMember]
public string[] ReturningStringArray()
{
return new [] { "e", "i", "e", "i", "o" };
}


Well to make a long story short, a small little mention of the IList interface on MSDN was the key, all I "needed" to do (as opposed to all the changes I tried) was change the return value from string[] to IList.

Saturday, June 12, 2010

Serendipity strikes again

Can you believe it? After working my free asp.net template example and learning how to take a free web template and integrating it into asp.net, I acquired quite a few skills.

And now the company that I work for has started to work on a new web offering and for the first time decided to use an outside company to do the web UI design. They delivered HTML, CSS and images. So, now I am doing professionally exactly what I did previously for fun.

It is almost as if I was practicing for my current task. If that is not Serendipity, then I do not know what is.

Thursday, May 20, 2010

Closing Down 1and1, Finally!

Warning! I am finally moving my last domain, leesaunders.net, to GoDaddy. I've waited this long because this domain hosts all my examples and I wanted to spare everyone from the pain as long as possible.

Well, last night the domain was transfered to GoDaddy and will be down until GoDaddy can bring it back up in my new hosting package.

Sorry for the blackout - but, it is all for the best.

Wednesday, May 12, 2010

Is UI or AI more important in board game programming?

Board games with a great UI with such a poor AI that you can always win with half your brain tied behind your back. Or, Board games with a great AI with such a poor UI that it is almost physically painful to play.

We've all seen both.

We've all played both.

But what about the great/mediocre combinations? Where should developers spend their time? Perfecting the AI or the UI?

Obviously, (from all the professionally produced board game programs I purchased over the years) the UI sells units.

But, it is the AI keeps you playing. And its the AI that convinces me to buy when the program can be downloaded for a demo. I just recently experienced that with
Empire Builder Pronto. The UI is mediocre ... to be kind.

But the UI! Wow, I have not been able to beat the AI yet and that is why I plunked down the cash to buy the game.

So, all you board game programmers out their: make sure the UI is playable, but make your AI as tough as you possibly can!

Thursday, February 4, 2010

ASP.Net - Multiple Bin Folders support a plug-in website

It was way back in 2001 when I was tasked at my company to implement our internal web application in ASP.Net. This site not only reported on most of the company's critical functions but also contained very complex data management screens. The sheer size of the site precluded it from being in a single dot net solution.

So, after many hours of searching the Internet in vain for a solution, I finally started to experiment on my own. I discovered that any project could be added to the site by copying the compiled DLLs into the sites bin directory. This works, but it is not the most elegant solution.

Well, many years to late, at least for the company site, I've discovered a much more elegant solution. (And when I say I've discovered it, I mean that I've finally found the information on the internet :-))

Here is the link to the original information:
http://www.hanselman.com/

This post refers to ASP.Net 1.1, but I've taken the time to verify that this still does work in ASP.Net 3.5.

Saturday, January 30, 2010

StrSpn & StrCSpn in C#

After converting the c/c++ string tokenizing command strtok to c#, I thought I would look around to see there were any other interesting string commands in c/c++ that had not been integrated into c#. What I found was strspn and strcspn.

strspn (String Span) Returns the length of the longest substring that begins at the start of the string and consists only of the characters found in the supplied character array.

Code Snippet



  1. private int strspn(string InputString, char[] Mask)

  2. {

  3.     int count = 0;

  4.  

  5.     foreach (var c in InputString)

  6.     {

  7.         if (!Mask.Contains(c)) break;

  8.  

  9.         count++;

  10.     }

  11.     return count;

  12. }





strcspn (String Complement Span) Returns the length of the longest substring that begins at the start of the string and contains none of the characters found in the supplied character array.

Code Snippet



  1.     private int strcspn(string InputString, char[] Mask)

  2.     {

  3.         int count = 0;

  4.  

  5.         foreach (var c in InputString)

  6.         {

  7.             if (Mask.Contains(c)) break;

  8.  

  9.             count++;

  10.         }

  11.         return count;

  12.     }

  13. }



Monday, January 25, 2010

C# TechTip #1 Using MaxLength as AutoTab

So, for all those old VB6 programmers out there: Remember The Visual Basic Programmers Journal TechTip publications.

For me, those pamphlets where the most eagerly waited part of my VBPJ publication. Here are the links to PDF versions.

VBPJ TechTips #1
VBPJ TechTips #2
VBPJ TechTips #3
VBPJ TechTips #4
VBPJ TechTips #5
VBPJ TechTips #6
VBPJ TechTips #7
VBPJ TechTips #8
VBPJ TechTips #9
VBPJ TechTips #10
VBPJ TechTips #11
VBPJ TechTips #12

I learned sooooo much from these. The loss of these publications is just one of the reasons that VSM is just a shadow of VBPJ. Just for a walk through memory lane I read through some of them, seeing if any of them would apply to C# today. Most of the tips were not transferable, but a few could be.

So, here is the first "New" C# TechTip: Originally by Karl E. Peterson

How to add an AutoTab feature to textboxes that have a set MaxLength. Connect the textboxes' TextChanged Event to this function:


Code Snippet



  1. private void textBox_TextChanged(object sender, EventArgs e)

  2. {

  3. if((sender as TextBox).MaxLength == (sender as TextBox).TextLength) SendKeys.Send("{TAB}");

  4. }





Who knew that the Dot Net designers had included the SendKeys function!?!

Wednesday, January 20, 2010

Bye bye 1and1 - Hello GoDaddy!

I'm done. I've put up with 1and1's broken ASP.Net implementation. GoDaddy is even cheaper! Well, as I go through this painful experience - I'll keep everyone updated!

Now I can finally do all the things I've learned in ASP.Net 3.5. And, I'll be able to use 4.0 additions before I grow old!

Thank you GoDaddy.

And 1and1? Dudes, it has been five years now and you still have not gotten a full implementation of ASP.Net 2.0 up and running? Wow ...

Friday, January 15, 2010

Dynamically update Url Mappings in Web.Config

One of the most useful yet underused additions to ASP.Net 2.0 was Url Mapping. This feature alone has caused a lot of noise in the blogsphere. Complaints range from the fact that you need an entry for every mapping to the fact that the mappings are not dynamic because they reside in the static web.config file.

Well ... that is all true. It is also true that if you update web.config in code, the application object is restarted and users lose Session state.

But, if Url Mappings is say, used for a standard blog webpage:
  A - How many entries are in a Blog? Even if we are talking a thousand or so entries eventually, will that few lines cause the ASP.Net engine problems? I wouldn't think so.
  B - How often would the webmaster be updating the Url Mappings? Once per posting. Even if the visitors loose Session - its not like it is happening every hour or so.
  C - What is a simple site doing with Session in the first place?

Well, I'm adding Url Mapping to my personal website and I've got a page that when called will automatically update the Url Mappings in web.config from the database, but only when a new mapping is needed.

And yes, I have session and viewstate shut off!

Code Snippet



  1. protected void Page_Load(object sender, EventArgs e)

  2. {

  3. var config = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);

  4. var section = (UrlMappingsSection)config.GetSection("system.web/urlMappings");


  5. var catArray = new ArrayList();

  6. var arcArray = new ArrayList();


  7. bool AnyChanges = false;


  8. foreach (var bd in BaseData.BlogDataList)

  9. {

  10. foreach (var strCategory in bd.Categories)

  11. {

  12. if (!catArray.Contains(strCategory) && !section.UrlMappings.AllKeys.Contains("~/" + strCategory))

  13. {

  14. catArray.Add(strCategory);

  15. section.UrlMappings.Add(new UrlMapping("~/" + strCategory, "~/Default.aspx?Category=" + strCategory));

  16. AnyChanges = true;

  17. }

  18. }


  19. var strEntryDate = bd.EntryDate.ToString("MMMM yyyy");

  20. if (!arcArray.Contains(strEntryDate) && !section.UrlMappings.AllKeys.Contains("~/" + strEntryDate))

  21. {

  22. arcArray.Add(strEntryDate);

  23. section.UrlMappings.Add(new UrlMapping("~/" + strEntryDate, "~/Default.aspx?Archives=" + strEntryDate));

  24. AnyChanges = true;

  25. }


  26. }


  27. if (AnyChanges) config.Save();


  28. Response.Redirect("~/Default.aspx");

  29. }

  30. }


Sunday, January 10, 2010

Nearly Free Dot Net Books at Amazon

I eagerly await the time of arrival. Like a kid in a candy store, I make plans on what I want.

No, I'm not talking about my Birthday or another Christmas so soon. No, I'm eagerly awaiting Visual Studio 2010 and the update to C# and the Dot Net Framework. But, not for the reasons you might think.

Hard on the heals of a new Visual Studio release is a flood of new Dot Net Books that are updated for the new release. And with that, all the previous release versions are going to be marked down. If history is any indicator, marked almost to the point of being free.

If you do not believe me, search for ... say .... ASP.Net 2.0 (i.e. Visual Studio 2005) and you will find hoards of books for less that a dollar (Plus 3.99 shipping).

Soon after VS2005 arrived I purchased over $1,000 dollars of 1.1 books (Cover Price) for $107 dollars!

But Wait! Why would you want OLD info? Well, new versions add to, but does not alter the Framework, and the framework is so vast that there are always parts that we wanted to learn but didn't want to fork over the $50+ per book to learn.

So, if your like me and your on a budget and want to learn as much as you can, then after March 22nd hit Amazon and load up on VS2008 books!

Tuesday, January 5, 2010

C# Yields a better StrTok Command

Here is another use of the Yield command which allows us to create looping functions that return a value for each iteration. That is actually a great description of the StrTok command in C/C++.

The C/C++ StrTok command takes two parameters, an input string and a string of delimiting characters. After the first call to StrTok, the C/C++ programmer passes a null for the input string and StrTok returns the next Token in the original input string. Sounds like an attempt to create an Enumerable function. Unfortunately standard C/C++ does not have enumerable functions.

Here is a C# enumerable function that you allows you to iterate through the tokens found in the input string. This C# version takes two parameters as well, the input string and an array of delimiting charaters.

Then using built-in power from the .net framework we:

We split the string into a string array using the delimiting characters and we yield return each element in the string array where the element in the string arrays length is greater than 0.




Code Snippet




  1. private IEnumerable<string> StrToken(string TokenizableString, char[] Delimiters)

  2. {

  3.     foreach (var Token in TokenizableString.Split(Delimiters, StringSplitOptions.RemoveEmptyEntries))

  4.     {

  5.         yield return Token;

  6.     }

  7.  

  8.     yield break;

  9. }