Tuesday, June 21
Using Internet Explorer in Desktop Applications with Visual FoxPro
Rick Strahl
by Dave Bernard
Why do this? To combine the best of both worlds (desktop and HTML).
Even though the desktop supports a rich UI, HTML can do things that are impossible or
awkward to do in a desktop application. The HTML presentation is customizable (CSS) and often more attractive than what a desktop UI can render. Dynamic, custom
on-the-fly presentations are a snap with HTML. For data entry, you can take advantage of the power of the desktop UI for robust forms control. For data display and reports, HTML might be the better
approach. Mixing them together allows you to apply the best of both worlds. So let's do both!
What kinds of things would we do with this? We can drive web content (hook other web apps in, say, RSS feeds, Google, Mapquest) and handle document centric tasks such
as dynamic content creation, preview data scenarios and content editing. The browser interface is very common and probably familiar to more people than a
desktop interface would be.
The way to accomplish this is to use the InternetExplorer.Application COM object or the Web Browser Control ActiveX
control and embed it in your form. They both use the same browser container and manipulate the document object model (DOM) in the same way.
The ActiveX control allows the developer less control over the IE component than the COM approach.
oIE=CREATEOBJECT("InternetExplorer.Application")
oIE.Height = 700
oIE.Width = 800
oIE.Toolbar = .F.
oIE.AddressBar = .F.
oIE.Visible = .F. && REQUIRED!
*** Web Content
oIE.Navigate("http://www.west-wind.com/")
*** Local HTML Content
oIE.Navigate("d:\temp\_preview.htm")
*** Local Word Doc
oIE.Navigate("d:\temp\MyDocumentation.doc")
Be careful about "lifetime" management. The browser control loads content asynchronously; that is, it begins the load and immediately returns control to
the calling function, continuing the web page load in the background. This could be in issue where, say, you are loading an HTML entry form that takes a long time
to load. The calling function may want to reference something on that form (via the DOM) right away, but will not be able to until the HTML control fully loads the form.
Rick has created a WaitForReadyState function (see the session notes) that hooks the DOM's ReadyState property to make sure the HTML document has been loaded.
Rick demonstrated passing a sentence from a desktop application to an AT&T translation web site, a great example of leveraging existing web functionality
in a way that would be very, very difficult in a pure desktop application. One can easily imagine extending this to mapping, weather and package tracking
services on the web.
Rick then showed how to hook browser events to FoxPro code, so that some FoxPro code fires automatically when a particular browser event occurs. For example,
you could prevent someone from navigating away from the page by hooking the BeforeNavigate browser event and check to see which URL to which they are
attempting to navigate. You could also, for example, keep someone from closing the browser window before you want them to. The same approach could track
which URLs are visited over time. Pretty cool.
Using the Web Browser Control is easy. Embed it on a form and call the Navigate method in the Init method to load the initial web page (or About:Blank).
If you're using a version of VFP prior to 9.0, you need to add NODEFAULT to the Refresh method to avoid a known IE bug. Looks pretty easy to me;
it also looks like a great way for a developer who has not had a lot of web programming experience to get acquainted with HTML and the DOM. You
could probably build a nice web development training tool this way (if someone has not already done so).
Taking the aforementioned BeforeNavigate hook, Rick showed how to create a custom link schema that could be used to create URLs that themselves call back
into VFP methods. He used a vfps: convention, which is very similar to one used in the Task Pane Manager. See the session notes for examples. Leave
it to Rick to come up with this kind of leveraged extensibility.
To create local HTML content can be tedious without a good tool to assist you. Rick showed a way to create HTML templates with embedded TEXTMERGE entries
so that the content can be easily and dynamically rendered by VFP at runtime. In addition, you can change the template and not have to recompile code. I've used
this approach myself, and it's very powerful and efficient. Some purists may
insist that doing XSLT transforms is the "proper" way to do this. but TEXTMERGE is nearly an order of magnitude faster. Challenge these guys to a race,
but make sure you bet them a round of beer first!
The world's software systems are inexorably heading to the Internet. You now have an excuse to go out and get a good understanding of the DOM and HTML
itself. Rich's session notes contain a treasure trove of guidelines and code, so take advantage of it and get
web-savvy, because your customers will be asking you to do that before you know it!
Service Oriented Architecture and Web Services with VFP
Martin Salías
by Dave Bernard
A Service Oriented Architecture (SOA) defines a way of organizing software assets on a network, providing business users with high-level business services
that are easily called into and integrated with other business processes. It grew out of CORBA and DCOM technologies, which were too tightly coupled and
proprietary. The SOA approach is to provide loosely coupled interfaces, is coarse grained (not a lot of little methods, but fewer, business-oriented methods) and is
intrinsically asynchronous in nature. SOA is object oriented and is typically implemented via a set of platform independent web services (HTTP, XML, SOAP) that are highly
detached from the supporting technology (transported over port 80). SOA is not a good idea for very large result sets or for real-time systems, mainly because of the disconnected nature of the network and Internet latency
rates.
VFP developers would start with building COM server-based web services, using either the SOAP 3.0 toolkit (deprecated by the .NET Framework) or through
.NET interop. VFP developers have powerful tools built into the VFP IDE to largely automate both the discovery of web services and the creation of code to
consume them. Martin showed how to use the IntelliSense Manager and the XML Web Service Task Pane to accomplish this. He then showed some example code
that demonstrated an interaction with a bank's web service methods to retrieve account information. Publishing a web service through VFP is similarly
automated, which Martin also demonstrated using the same XML Web Services Task Pane. After this, he showed how to do this in .NET.
When deploying your web service, you'll need to deploy the SOAP toolkit, the VFP runtimes and your WSDL and WSML files. You'll need to set up a virtual directory under IIS to host
the web service. Your web service COM DLL(s) should be installed into Component Services. After this, you should be able to test your web service via
a URL pointing to its WSDL.
A nice overview of this burgeoning technology, Martin.
Migrating VFP Data to SQL Sever
Dan LeClair
by Dave Bernard
Dan LeClair is a long-time VFP and SQL Server developer who has written extensively on SQL Server and VFP issues.
There are a growing number of situations where is it beneficial to migrate your VFP data to SQL Server. You may be tasked to convert an existing legacy
system that has grown too large and/or slow for regular use. Your company may have been acquired by another company that requires the migration. Or any
number of other reasons.
You generally want to migrate your data in the following order: code tables, then first level parent tables (customers, supplies, products) and finally
your second level and child tables (receipts, orders, accounting info).
Possible migration mechanisms include the VFP Upsizing Wizard, SQL Server Bulk Copy/Insert, Data Transformation Services (DTS) and VFP itself. The Upsizing Wizard
is good for porting DBC-bound tables; it reproduces the entire schema pretty well. However, it doesn't handle SQL Server reserved words (which the source
data may be using as column names) well, and empty dates may not be handled properly. And source rows cannot exceed 1962 bytes.
Bulk Copy/Bulk Insert is very fast for large data sets because it bypasses transaction logging and doesn't fire triggers (by default). The data source has
to be text files, it doesn't do transformations and the SQL Server structures have to pre-exist. Bulk Insert can be run from Query Analyzer, while BCP is
command line driven.
DTS provides the most power and flexibility; Micrsoft recommends it as the target solution. You can connect to just about anything via ODBC and OleDB, and
the object model can be integrated into your application. VBScript can be used to perform custom on-the-fly data transformations. However, it can
be difficult to validate incoming data and has performance problems when combining very large data sets with complex transformations. DTS is not
multi-threaded, so processes are serialized, although SQL Server 2005 fixes this. A good idea is to use the DTS Wizard to create a simple package (making
sure to save it before running it), then use the DTS package designer to tweak the result.
Of course, the power of VFP can be brought to bear on the problem. SQL Pass-Through (SPT) is the way to go, although you can only use ODBC, not OleDB, which
reduces performance. First, establish a connection to the SQL Server database. From here, you'll be creating a series of SPT calls using SQLEXEC that
will do things like creating the database, tables, indexes, stored procedures, default options, etc. It is, in effect, a replacement for Query Analyzer.
Database Management Objects (DMO) is an object class that allows you to automate SQL Server itself (see SQL Server Books Online for more detail).
You can use this with VFP to perform a number of interesting things. For example, you could retrieve the exact script text to recreate a particular index or
table. You can also automate DTS by using the DTS.Package object.
Another tool you can take advantage of is the SQLNamespace object, which allows you to hook into the visual components of SQL Server, which could be handy
for displaying, say, a progress bar that corresponds to a running DTS package. You'll need to make sure that the SQL Server Client Tools are installed on
the client machine.
Of course, you can mix and match all of these approaches into a single project plan to accomplish the migration.
Dan's session was a thorough look at the many ways of connecting VFP and SQL Server together.
Static Analysis with VS 2005 and FxCop
Claudio Lassala
by Éric De Carufel
You write code and compile it; the compiler doesn’t complain, so you’re all set, right? Well, not really.
Maybe the code you wrote isn’t optimized for performance, or maybe it has security breaches, or maybe it doesn’t follow best practices (either
the ones accepted in the software development world or the ones required by your company). Long story short, code compiled without compiler errors
isn’t always high-quality code. We address that by using static analysis, and this session shows how to use VS 2005 and FxCop to do that.
When your system compiles, that doesn’t mean that the code is good. The standard build process is well-known to developers: code is written and then
compiled into binary files. During compilation, the compiler does the pre-processing, checks grammar, and raise errors if any is found.
When you employ a static analysis process, you take the binary produced by the standard build, check the code to see if it conforms to certain rules and
raise errors on violations of those rules.
Tools exist to help perform static analysis; FxCop is one of them. It ensures that a certain set of rules is applied. FxCop is free to download and
it can be used on VS 2002 and VS 2003; it is built into VS 2005.
FxCop does three things. First, it analyzes the assemblies to check if all rules are enforced. Second, it allows you to manage these rules.
And finally, it allows you to bend the rules by selecting which ones for which you want to generate error messages. The goal of using FxCop is to
support design guidelines and practices, which it does by examining the IL.
There are many set of rules:
- COM Interop Rules: Detect COM interop issues
- Design Rules: Detect potential design flaws
- Globalization Rules: Detect missing or incorrect usage of information related to globalization and localization
- Naming Rules: Look at casing, keyword collisions, and other issues around public members
- Performance Rules: Detect patterns that will affect or degrade performance
- Usage Rules: Detect potential flaws in the usage of .NET APIs
- Security Rules: Detect programming elements in your assemblies that leave them vulnerable to malicious users or code
- Custom Rules: rules you write!
When you are using FxCop, you have to create an FxCop project for each of your Visual Studio projects. The FxCop project keeps track of all elements
of the static analysis you want to run against your project. To try FxCop, start with your masterpiece project. You will be overwhelmed by the number
of rules it violates. Don’t panic yet, it’s not that bad. Start by sorting the rules by the most important first and resolve them one at a time.
This will be a very instructive experience. You will really learn to write better code.
Sometimes it’s OK to exclude a rule because the static analysis process is not 100% accurate; there can be false positive rule violations. In this case,
FxCop lets you add a comment when you exclude a rule to make sure you are never bothered again by that particular rule in that specific situation.
You can also write your own custom rules. The documentation on that subject is very thin; you’re on your own with this. The best way to create your
own custom rules is to use a reflector tool to check out how the rules that ship with FxCop work.
See Claudio's session notes for a lot of valuable related resources.
Getting Ready for ADO.NET 2.0
Kevin McNeish
by Éric De Carufel
The purpose of this session is to help you get ready for ADO.NET 2.0. Kevin introduced and explained many new features, including asynchronous data fetching, data paging,
bulk import, monitoring of connection-specific statistics and connection pooling enhancements. He will also went over new SQL Server 2005-specific
capabilities in ADO.NET 2.0, such as multiple-active result sets, password changing, promotable transactions, client-failover and support for
user-defined types and other new data types. Kevin provided practical examples demonstrating how to get the most out of these new features.
ADO.Net is not a revolutionary technology; it’s basically an evolution of previous versions. Microsoft ensures that it is compatible to almost every
previous ADO version.
ADO.Net has worked hard to improve performance when you access millions of rows. Even though it’s not usual to return so many rows in a query,
there are still some situations when that capability may be needed. The DataSet class also benefits from this new performance gain. To demonstrate,
Kevin timed a large example using the new StopWatch class of the framework: 48 minuites in in ADO, 35 seconds in ADO.NET 2.0.
Serialization performance is also faster, because there is now a binary formatter that really formats it binary!
Some functionality, like Merge, ReadXML, ReadXMLSchema, WriteXML and WriteXMLSchema are now available directly at the DataTable level. This enables
a DataTable to be passed between a client application and a Web Service. And DataTable and DataSet are now able to directly load data from a
DataReader object.
ADO.Net 2.0 now has an interface for all data access classes, which enables you to refer to a data access class by its interface and make database type
independent access to data. The problem with interface is, if it changes in a new version, the old code won’t compile. But Microsoft provides an
abstract base class implementing each interface. This way, it’s easy to derive from these abstract classes. To help benefit from this new object
structure there is also a DbProviderFactory, which can create any data access abstract factory (SqlClientFactory, OleDbFactory, OdbcFactory, etc.)
With these factories you can create all data access concrete objects (DbConnection, DbCommand, etc.)
ADO.Net 2.0 now allows asynchronous data fetching, useing threading to get data in an asynchronous way. For this to work you must set async=true in
the connection string. Don’t do it if it’s not needed because there’s a performance hit caused by the amount of resources used. A Bulk Copy feature
has also been added to ADO.Net, allowing fast copying of large amounts of data from one table to another, between servers and between different
server types.
Connection statistics are now available directly from ADO.Net instead of having to get it from the server.