More Than Four

Areas of Interest, as counted by my cat

Page 12 of 13

Pessimism is Positive

It’s really better to be a pessimist than an optimist. I think pessimists get a bad rap. Sure, everyone likes the idea of being upbeat and happy. But it’s not a good survival perspective. Problems only get solved because people worry about them.

David Brin answered the critics of the pre-millennium Y2K disaster theorists by saying that it was a classic case of a self-defeating prophesy. I agree with him. If everyone had just said, “She’ll be right, mate” and done nothing at all about the problem, then almost certainly IT departments everywhere would have been extremely busy and stressed come Jan 1, 2000. (You just know that’s an understatement.)

Good programmers are pessimists. They have to be – they learn to be very early in their career.

“That will never work, you know.”

“Why not? I’ve debugged it, it runs fine. I’ve tested it. I’m a good programmer…”

“What about more than one user running that screen at a time? What about a user who stays in that screen overnight while your midnight triggers are running? What about machines with no audio card? No installed printer? You’re doomed.”

“Why, I’ll show you, you… you… big fat pessimist, you.”

Techniques for alternate Report Previews in VFP 9.0

Quite a few of the discussions on the Universal Thread Visual FoxPro forum recently have been on the subject of the new Report Preview screen in Visual FoxPro 9.0, and how to control it. A particular concern is the behavior of the preview toolbar when a REPORT FORM.. PREVIEW is issued in a topform application. In my sessions I have striven to show that the default preview application is just that – a default – and that alternative forms of a preview solution are not only possible, but easy to implement. In this article I show an alternative user interface for the report preview window that you can take away and customize to your heart’s content.

Link: Techniques for alternate Report Previews in VFP 9.0

Spanish translation available here:
 http://www.portalfox.com/article.php?sid=1944 

COM Interop

This week I wanted to get my ASP.NET web application to create a text file and return it to the browser. The catch was, the text files are created by some pretty gnarly FoxPro code (sourcing Fox data). The solution seems to be to use COM interop. It’s a lot easier to rework that vintage FoxPro procedural code into a VFP COM server than it is to re-implement it using DataSets in C# (or VB for that matter).

Rick Strahl has a good article discussing this, and there is quite a lot of “high level” information on COM interop out there on the web also. Briefly, here is what I did:

I re-packaged the pertinent FoxPro code into a class method of a COM server. I tested this out in the VFP Command window:

x = CREATEOBJECT("MyServer.MyClass")
_cliptext = x.GetTextDoc("123")

Now, in the web application I wanted a hyperlink that would return the text document to the browser. So I was looking to implement a URL like this:

<a href="CreateTextDoc.aspx?param=1234">Create Text Document</a>

Now, CreateTextDoc.aspx is basically all code-behind – there is no HTML code, just the directives:

<%@ Page language="c#" 
         Codebehind="CreateTextDoc.aspx.cs" 
         AutoEventWireup="false" 
         Inherits="MyCompany.MyProject.MyBasePage" 
         ASPCOMPAT=true
%>

That last page directive is specifically for pages that instantiate COM objects. Some people say it’s optional, only necessary when you are embedding the object into the page directly with <object> tags. Others say that you should use it even if you are using the early binding wrapper classes. I figured, better safe than sorry.

Now, the code-behind:

  using System;
  using System.Web;
  using MyServer;
  :
  private void Page_Load(object sender, System.EventArgs e)
  {

      // get the parameter:
      //
      string cParam = "";
      cParam = Request["param"] ;

      // We're returning a text file:
      //
      Response.ContentType = "text/plain";

      // This forces nicer behavior in IE, prompting to download or open as text.
      // also the filename is now "1234.txt" instead of "CreateTextDoc.aspx"
      //
      Response.AddHeader("content-disposition","attachment; filename="+cParam+".txt" ) ;
		
      // Create the COM server wrapper:
      //
      MyServer.MyClass x = new MyServer.MyClassClass() ;

      // Generate and return the text:
      //
      Response.Write( x.GetTextDoc( cParam )) ;

      return ;
  }

Nothing tricky there, once you understand the odd invocation of the COM server through the .NET wrapper class.

This worked a treat: In FireFox, the text file appears in the browser quite naturally. IE screwed up, however, because it appeared to be trying to recognise the plain text response as some other kind of format. Rather than do the registry hack, I added the content-disposition header to the response. Now the behavior in IE is actually preferable: I get a dialog prompting me to Open or Save As. If I Open, the text file opens in Notepad. This is better for my users – although I would have been content with the Firefox behavior (pardon the pun).

Now we get to the problem: Every time I hit that URL to generate a text file, another instance of my COM server executable was created. Ouch! If I waited long enough – about 20 minutes – they would terminate and disappear from Task Manager. But as it was, this didn’t scale well at all.

I mentioned this behavior to Rick, and he couldn’t explain why the MyServer.exe instances were hanging around. But he did have a good suggestion: “If the object is not releasing you can call Marshal.ReleaseComObject() to make sure it gets cleaned up and doesn’t wait for the GC to clean it up for you.

This change was easy to make. First, I added the reference to the top of the file:

using System.Runtime.InteropServices;

Then, after the call to GetTextDoc(..):

      // Create the COM server wrapper:
      //
      sisserver.ArtForm x = new sisserver.ArtFormClass() ;

      // Call the Artform listing generator:
      //
      Response.Write( x.GetArtFormDoc( cArtform ) ) ;
      
      // Dispose of the COM server manually:
      // 
     System.Runtime.InteropServices.Marshal.ReleaseComObject( x );

This worked beautifully. No more hanging executables in Task Manager! My application scales again. Thanks for the pointer, Rick.

ASP.NET and impersonation trouble

So I have this Asp.NET application that needs to run on the WEBSERVER but see files in a directory on FILESERVER out on the net. (The files are, inevitably, Foxpro tables being accessed through OleDb.)

First cut, the OleDbConnection fails to open the data (\\FILESERVER\Sharename\datafolder) with an “invalid path or file name” error. That’s because the ASP.NET application is running under the WEBSERVER/aspnet user context which does not have permission to see the network share.

“No problem,” we say. “Let’s just use the web.config file to tell Asp.NET to run under a context that does have permission to see the share:

<system.web>
    :
    <identity impersonate="true"
              userName="NETDOMAIN\net_user"
              password="secret"/>
    :
</system.web>

This works – except that every time we uploaded a new version of the .aspx files to the webserver, it threw an exception: “Cannot execute a program. The command being executed was [..]\v1.1.4322\csc.exe /noconfig …”. Basically it didn’t appear to have rights to run the compiler to do that special ASP.NET on-the-fly compilation of the classes.

Investigation seemed to indicate that it should have the appropriate access rights, but all the same, we couldn’t make it work without commenting out the <identity> specification; re-starting the IIS process; then putting it back after the successful compilation so that the network share was visible.

Second cut was to omit the <identity> override, but to bracket the OleDb call with special in-line user impersonation code using Win32 LogonUser() calls. Well that didn’t work (and when I find out why, perhaps I’ll post about it).

I found a solution to the problem on a web thread posted by shamrox (http://forums.rainbowportal.net/ShowPost.aspx?PostID=5503) which I reproduce here:

Is this error happening when you try to run your project? I guess what I am asking is that it compiles fine but when it goes to the first screen you get this error. IE would never open if it didn’t compile.

If it is what I think it has to do with the aspnet_wp. It does some weird stuff. You don’t have to restart www to fix it, all you need to do is go to task manager and [terminate the aspnet_wp.exe process]. Don’t worry it restarts automatically. That will fix the problem for now. It comes up from time to time so if there is a better way I would like to know too.

Thanks shamrox – this works! Now we can leave the <identity> switch in place in the web.config in order for my web site to “see” the network resources, and when I upload a new version of the aspxs to my web site – it will stick with the exception on the recompile but a restart of the aspnet_wp.exe process will bring it back, no worries.

I still think ASP.NET is the bomb.

Google; IntelliTxt; and the nature of Evil

I know very few people actually read this, but I am compelled to write anyway. There is currently some controversy erupting among web content authors about a feature in Google’s upcoming toolbar AutoLink offering. Apparently the toolbar has a button on it that, if the user chooses to click on, will parse the current browser content and add additional hyperlinks to the page, things such as map references or ISBN lookups, etc.

This seems to have selected eminent bloggers up in arms on either side of the argument.

Dave Winer writes, negatively: 

The AutoLink feature is the first step down a treacherous slope, that could spell the end of the Web as a publishing environment with integrity, and an environment where commerce can take place.

Cory Doctorow writes, positively: 

I think I should be able to use a proxy that reformats my browsing sessions for viewing on a mobile phone; I think I should be able to use a proxy that finds every ISBN and links it to a comparison-shopping-engine’s best price for that book across ten vendors. I think I should be able to use a proxy that auto-links every proper noun to the corresponding Wikipedia entry.

And so on — it’s my screen, and I should be able to control it; companies like Google and individuals should be able to provide tools and services to let me control it.

Tim Bray writes a pretty good summary of the situation, concluding:  

There just isn’t that much fodder out there for AutoLink to get its teeth into. I haven’t had much time to think about it, but maybe it’s because most people who publish an address or ISBN or whatever that they actually care about take the time to link it to something useful. So, it’s not a game-changer. But it’s still evil.

I have been saving web pages to my local hard disk, editing them, and re-viewing them for some time. Sometimes I even add my own hyperlinks. The content writers can’t stop me from doing this, if I choose to do it. The Google Toolbar AutoLink feature is essentially doing the same thing – remember, I – the user – have to decide to install the toolbar, then browse around the web, and then when I’ve found a page that looks interesting, I have to consciously decide to push the “AutoLink” button to add the additional hyperlinks. I could do this myself if I had infinite time and patience, so what’s the big deal? It’s not like Google is republishing the altered content without the consent of either the author or the viewer. Calling it evil is a bit much.

Whether or not this is a good trend for the web as a whole, I don’t know.

Let me contrast this with something else.

You may have noticed some web sites seem to have weird links in them, that have a double-underline instead of the normal single underline. When you hover your mouse over them, you get an obnoxious popup tool tip with “Sponsored Link” and a bunch of other words. You probably need Javascript to be enabled as well, I don’t really know, I haven’t looked that closely.

This technology is called IntelliTxt by the company that is pushing it. (I won’t link to them – not even with rel=no_link or whatever that Google-juice suppressant thing is – but they call themselves Vibrant Media, a pioneer in contextual keyword advertising.) I’m sure the web site content owner has invited them to insert their links into the page in return for a share in the advertising revenue. For all I know, someone gets a kickback every time I hover my mouse over the link. 

Now, in my opinion, Vibrant/IntelliTxt aren’t evil either, but they are giving me, the end user, a negative browsing experience.

But that’s ok. I use the FireFox browser with the AdBlock plug-in, and I’ve told it to ignore anything that matches the filter “*.intellitxt.com/*” and since then I haven’t seen the pesky links. The web site owner probably isn’t getting any revenue from Vibrant due to my choice to render their links invisible, but that’s a risk they have to take. They don’t own my eyeballs.

You see, we don’t get to have it only one way. If we get to keep our AdBlock plug ins to suppress crap like IntelliTxt, then Google gets to offer their toolbar AutoLink feature. Either way, the web gets richer and more interesting, in my opinion.

Update: I see now that Yoz Grahame made the same point last week.

VFP OleDbDataReader and returning COUNT(*)

I found out something interesting about the VFP OleDb driver yesterday. I’m using a DataReader to return records from a FoxPro table, and one thing about DataReaders in .NET 1.1 is that you can’t get a record count. (There’s a .RowsAffected property but that’s different, as I understand it.)

The usual thing to do is to perform a pre-select to get the record count, and use ExecuteScalar() to return the single count value:

StringBuilder sb = new StringBuilder();
sb.Append("SELECT COUNT(*) FROM customers WHERE name = '");
sb.Append(  cCustomer ) ;
sb.Append(  "'") ;

oCmd = new System.Data.OleDb.OleDbCommand( sb.ToString(), oVfpConn ) ;

int resultCount = (int) oCmd.ExecuteScalar();  

This code works fine if you’re using a SqlClient.SqlDataReader against SQL Server, but here, we get an exception: “specified cast is not valid”.

It turns out that, for the VFP OleDb source, oCmd.ExecuteScalar() returns a System.Decimal object instead of an int. After some experiments, I found this seemed to work best:

	
int resultCount = System.Decimal.ToInt32( (Decimal) oCmd.ExecuteScalar() ); 

if ( resultCount == 0 )
{
	...

This is fun!

Update: David Stevenson has a better solution: Use CAST to force the results to an Integer:

	
StringBuilder sb = new StringBuilder();
sb.Append("SELECT CAST(COUNT(*) AS Integer) FROM customers WHERE name = '");
sb.Append(  cCustomer ) ;
sb.Append(  "'") ;

oCmd = new System.Data.OleDb.OleDbCommand( sb.ToString(), oVfpConn ) ;

int resultCount = (int) oCmd.ExecuteScalar();  

Much cleaner.

No Swap File

So thanks to a recent upgrade, I’ve slightly more than doubled the RAM in my laptop. It’s now running with 1.25 GB of RAM. So why do I still need to worry about virtual memory? Do I need a swap file?

This morning I right-clicked on My Computer and set the Windows XP virtual memory settings to “No Paging File”. Rebooted.

Now I’m defragmenting my hard drive while browsing the web and updating this web site. Narry a glitch or complaint from the operating system.

When it finally barfs (perhaps on one more wafer-thin application) I’ll let you know

bradchoate.com: Moveable Type 3

By now, you probably know that:

  • Movable Type 3.0 Developer Edition is out
  • The licensing for MT 3.0 has changed

The licensing bit has some folks upset. You can tell by the outrage that people are passionate about this product. And the outrage is understandable to an extent. Movable Type has been free for personal use since day 1. Now they’re asking the majority of their users to pay for something that many of them have never had to pay for to begin with. There is bound to be some backlash about that. [..] Some go so far to say, “Six Apart has gotten greedy!”. No, they haven’t. They are a growing company. Growing a company takes dollars. This is no volunteer organization, you know. They have real-world bills to pay. Ben and Mena have poured everything they have into their products. And for nearly three years, they’ve given it away. That’s not greed – that’s generosity. Now they are charging for their product (what a concept!), something they had a right to do with their first release.

Link: bradchoate.com: Moveable Type 3

« Older posts Newer posts »

© 2025 More Than Four

Theme by Anders NorenUp ↑