April 2003 - Posts
Borland recently announced that they are releasing C#Builder. An application for creating .Net applications in C# on the Windows 2003 platform.
I'm sorry, but I just don't get it. Sure they will add some features that Microsoft does not currently offer in the stock VS.Net installation. For example: Requirements Management and Collaboration among other items. B
ut from reading the article http://www.adtmag.com/article.asp?id=7597, these are not add-in's into Microsoft's Visual Studio IDE. This is an entirely new IDE created by Borland. This is the part I just don't get, Microsoft has always ruled when it comes to creating IDE's.
Microsoft has assimilated and destroyed so many IDE vendors, what makes Borland think they will be successful. Even if they add features that Microsoft does not support, the VS IDE was built to support plug-ins so that other vendors can create and extend the Microsoft footprint. This capability was brilliant on Microsoft's part and it will enable Microsoft to surpass whatever any other IDE vendor has to offer.
Have I missed something here?
As in a previous post, I discussed a Kiosk framework that myself and Derek Walters ( another dotnet geek ( and a very smart one at that ) ) licensed to Cox Communications for the rollout of their kiosk bill paying solution in several cities around the country. Since the Kiosk application is a touch screen application, its flow between screens is very structured; however, during the development of a working application we needed an approach that enabled us to dynamically change how the screens flowed.
This was absolutely necessary for us. Without a plug-in style architecture, we would have created a static ( and very fragile ) application where any change would have forced us to go through another round of regression testing. This in turn would push out the delivery date and negate the need for the framework in the firstplace.
In this blog, I want to show a nice approach to wrapping a class around a section of a config file. The use of this class then enabled us to dynamically add screens and/or change the flow of the kiosk application without recompiling.
First, ( a portion of ) the config file.
<?xml version="1.0" encoding="Windows-1252" ?>
<configuration>
<configSections>
<sectionGroup name="plugins">
<sectionGroup name="forms">
<sectionGroup name="scanbill">
<section name="plugin" type="System.Configuration.SingleTagSectionHandler" allowLocation="false" />
<section name="navigation" type="System.Configuration.SingleTagSectionHandler" allowLocation="false" />
<section name="form" type="System.Configuration.SingleTagSectionHandler" allowLocation="false" />
</sectionGroup>
<sectionGroup name="language">
<section name="plugin" type="System.Configuration.SingleTagSectionHandler" allowLocation="false" />
<section name="navigation" type="System.Configuration.SingleTagSectionHandler" allowLocation="false" />
<section name="form" type="System.Configuration.SingleTagSectionHandler" allowLocation="false" />
</sectionGroup>
</sectionGroup>
</sectionGroup>
</configSections>
<plugins>
<forms>
<scanbill>
<plugin assembly="CoxPlugins" class="Cox.Kiosk.Forms.CoxScanBillForm" />
<navigation back="language" next="accountinquirywaitform" cancel="start" help="" error="" timeout="start" timeoutvalue="30" touchtocontinueenabled="true"/>
<form nextbutton="false" backbutton="true" cancelbutton="true" helpbutton="false" />
</scanbill>
<language>
<plugin assembly="CoxPlugins" class="Cox.Kiosk.Forms.CoxSelectLanguageForm" />
<navigation back="start" next="scanbill" cancel="start" help="" error="" timeout="start" timeoutvalue="30" touchtocontinueenabled="true"/>
<form nextbutton="false" backbutton="true" cancelbutton="true" helpbutton="false" />
</scanbill>
</forms>
</plugins>
</configuration>
What we are doing here is setting up the app.config file so that we can use the .net classes to interact with it. The first section, configuration/configSections/sectionGroup[name=plugins]/sectionGroup[name=forms]/sectionGroup[name=scanbill], is setting up the configuration section for the plugins section below. I will not go into detail on it because you can find out more about setting up a config file via MSDN.
The items I want you to take note of are the attributes of the navigation sections. The back, next, cancel, help, error and timeout attribute values denote another plug in to move to when the user selects one of the buttons on the touch-screen window. For example configuration/plugins/scanbill/navigation[back=language] points to the language node under plugins. In other words, when the user is using the kiosk and has navigated to the 'Scan Your Bill Form' and decides to select the Back button the framework will look in the config file and navigate to the language form by interrogating the config file.
Now for the code. The following is a constructor for a class that loads information for a form's config section. Once loaded other classes interact with the information. The code below was actually written by Derek, but it is a pattern we both followed throughout the framework.
namespace Cybral.Kiosk.Configuration{ ................................................ ................................................
................................................ ................................................
................................................ ................................................
................................................ ................................................
public NavConfigReader( string strName )
{
string strConfigPath = string.Format( "plugins/{0}/navigation", strName );
string strCurrentNavName=null;
strCurrentNavName = strName;
if( null != strCurrentNavName )
{
strCurrentNavName = strCurrentNavName.Substring(
strCurrentNavName.LastIndexOf( "/" ) + 1 );
}
IDictionary idct = (IDictionary)
ConfigurationSettings.GetConfig( strConfigPath );
m_strCurrentNav = strCurrentNavName;
m_strNextNav = (string) idct["next"];
m_strBackNav = (string) idct["back"];
m_strCancelNav = (string) idct["cancel"];
m_strHelpNav = (string) idct["help"];
m_strErrorNav = (string) idct["error"];
m_strTimeoutNav = (string) idct["timeout"];
m_strActionPlugin = (string) idct["actionplugin"];
try
{
m_intTimeoutValue =
Int32.Parse( (string) idct["timeoutvalue"] );
// The values in the configuration file are in seconds...
// timers typically measure in milliseconds.
m_intTimeoutValue *= 1000;
}
catch
{
m_intTimeoutValue = 0;
}
try
{
string strTrue = Boolean.TrueString.ToLower();
m_blnTouchToContinueEnabled =
( strTrue.CompareTo( idct["touchtocontinueenabled"] ) == 0 );
}
catch
{
m_blnTouchToContinueEnabled = true;
}
} }
Well, I am getting tired of writing. Essentially, what we do next is load the control specified in the config file, destroy what is currently there and display the control to the user. There is actually quite a bit involved in this, but the premise is simple enough.
It has always been an aspiration to write for MSDN magazine as well as some of the other popular Microsoft based publications. I have a great deal of respect for many of the authors and the publication itself. Much of the content is precise and demonstrates real world approaches to situations we all face as Microsoft architects and developers. I have a great deal of experience writing but most of my experience has been writing white papers for a software vendor in the Atlanta market as well as various papers I wrote while getting my masters at Emory University.
If anyone out there in blog worlds knows the person I need to talk to, drop me a response.
In interesting question was posted on www.gotdotnet.com. The post centered around the issue of accessing shared memory located in a win32 c++ dll from a c# application. I answered the post and I felt it was an interesting enough piece of code to warrent a blog.
The example is really straightforward and doesn't require you to be a rocket scientest to figure it out, but it does demonstrate the power and flexibility of .Net and C#.
//==================== Code Excerpt from the main cpp file ======================
#include "stdafx.h"
//================= Here we are setting up the shared memory area =====================
#pragma data_seg (".SHAREDMEMORY")
int gshared_nTest=0;
#pragma data_seg()
#pragma comment(linker,"/SECTION:.SHAREDMEMORY,RWS")
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
{
return TRUE;
}
//=============================================================================================
//====================== Here we are writing wrappers to the shared memory area ===========================
//=You must declare it as an Extern "C" to prevent name mangling. This is absolutely necessary in order to import it into c# =
//=============================================================================================
extern "C" __declspec(dllexport) int __stdcall getMyData()
{
return gshared_nTest;
}
extern "C" __declspec(dllexport) void __stdcall setMyData( int data )
{
gshared_nTest = data;
}
//============== Here is the main piece of code from a simple c# console application =================
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace TestShared {
class TestShared
{
//============== here we are importing the methods from the win32 dll into the c# console application =================
[DllImport(@"C:\VS Projects\Shared\Debug\Shared.dll")]
public static extern int getMyData();
[DllImport(@"C:\VS Projects\Shared\Debug\Shared.dll")]
public static extern void setMyData(int data);
[STAThread]
static void Main(string[] args)
{
//============== here i am incrementing the value =================
setMyData( getMyData() + 100 );
//== i use a message box so that i can have multiple console applications running at once and it will pause at the messagebox (if i don't click ok)
//== i do this so i can see the values changing in the shared memory.
MessageBox.Show( getMyData().ToString() );
}
}
}
That's it. Accessing shared memory in a c++ dll is really not hard. If you are building an application from scratch, then I would probably create a complete .net from the start; however, if you have a great deal of logic in a c++ dll that you wish to have work side-by-side with a new .Net application, this is a plausable approach. It enables you to evolve your existing application while allowing you to use the latest .Net technologies.
Has anyone used this tool. I downloaded it a while ago and I have spent a bit of time with it.
http://www.saurik.com/net/exemplar/
This product will decompile just about any piece of .net code...Even the .Net framework.
My thoughts.
The tool has been out for a little bit and I enjoy the tool because it enables me to garner further insight into how a piece of code works; however, in some ways it scares me because the concept of a "company secret" is now circumspect. Also, I can clearly see its use in converting from vb.net to c#.
Always in search of a good joke. A friend of mine sent me this "eBay Humor" and I thought I would share it with everyone. If you have a few moments, it is definately worth a quick read.
It will give you a good laugh
Click here for a good laugh
Just heard from my brother-in-law in Rhode Island that a friend of his paid his Cox Communications Cable Bill via a Touch-Screen Kiosk that I helped build.
What makes this really sweet is that I own the framework that the Kiosk was built upon. Myself and one other person developed the framework and licensed it to Cox Communications. They have rolled it out to Rhode Island, Las Vegas and New Orleans at their customer service centers.
It supports both Spanish and English and enables Cox Communications Customers to pay with Cash, Visa, Mastercard, American Express and Discover Credit Cards. It prints a receipt to them and pays their bills real-time via Web-Services back at the home office in Atlanta.
We built the framework using C#, SQLServer, Extensive use of Web-Services and a sweet framework that uses the configuration file extensively to configure the flow of screens. For example, each screen is defined in the configuration file with its assembly and class name as well as which screen to go to if the user touches the next, back, cancel or help button as well as the screen to go to if an exception occurs. Each screen is defined with this same information so if we want to change the flow of the application we can change the config file, restart the application, and bot-a-bing-bot-a-boom the application behaves differently. I will be providing further blogs with code snippets on how we built it.
Rock on.
Found this paper from Microsoft Research via a Google search. It goes into detail about the proposed specification for .Net Generics. It was written in September of 2002. So if anyone has anything more current, I'd appreciate an email.
Generics will be a sweet feature and from what I understand the implementation will be sweet too. C++ Templates ( ATL, STL et al ) were awesome but they could bloat the size of your binary. With support built into the CLR, the size of the binaries should shrink too. Rock on.
http://research.microsoft.com/projects/clrgen/generics.pdf
Digital System
Working on a Digital System for company here in Atlanta. Its pretty cool. The web-based application allows the marketing folks to create images, movies and voice that are 5-15 seconds in duration. They are then shot around the country via satellite and eventually end up on your TV set.
The application is all .Net ( except for the machines that actually display the commercials at the cable providers ) with Oracle as a backend. I am always fascinated at how well .Net performs and the number of features it has with a first release. Rock on.
This blogging thing is pretty sweet. It's about time I started using it.
More Posts
Next page »