Category Archives: Software

Trouble with Licenses

Hmm – so I’ve activated a Microsoft product by REJECTing the license.

Am I now in breach of the license? Can I be said to have “hacked” the software to make it work? Am I now free to do whatever I want with the files?

These are legal riddles which should keep a Microsoft lawyer busy for a few minutes before bedtime…

Trouble with Localization

My darling better half is enjoying her new MacBook – but the Apple “Pages” software turned out to be less popular.  After Jens pointed out to me that I can buy a cheap license for Office through the Home-Use Program, I bought a license and downloaded the Mac Office and installed it.

Mac Office 2011 License accept dialog

Note the buttons: ACCEPT (Godta) and REJECT (Avslå)

English version

The same dialog, in English this time.

Notice the subtle difference? (Microsoft has helpfully highlighted it for us)

This explains why I completely failed to complete registration until I clicked the REJECT (Avslå) button. The translation team at Microsoft has transposed the labels – making the task impossible to complete unless you disobey the instructions.

The problem has been reported to Microsoft, so hopefully in the future Norwegians won’t be baffled by the difficulty in activating the software.

The confusion probably arises from the MS Windows habit of having the OK/CANCEL buttons in the opposite order from the Mac, which tends to put them in the reverse order: CANCEL/OK.

Norwegian/Norsk mode engaged: Hvis du har problemer med å registrere/aktivere Mac Office 2011 på OSX, så må du altså trykke på AVSLÅ knappen i dialogen som sier “Du må godta betingelsene i lisensavtalen for å fortsette.”

Democracy and Technology

I had an interesting dream last night – I dreamed about democratic decision making support software. Instead of my regularly scheduled dreams of – well, nevermind. The whole thing is (like all dreams) a bit fuzzy now, but the gist of it was this: a bottom-up wiki-like decision support system with real-time animation and graphics (a bit like an RTS). The wiki enabled reasoning and supporting arguments to be filed and voted on, and allowed alternatives to arise and float up as they gathered support. i.e. avoiding false dichotomies seemed important to my dream.

As people (supporters and opponents) argue and lobby for positions, the decision makers can see the ebb and flow of support on an RTS like map. The map – the terrain – is not fixed, since the appearance of a new consensus position can change the lay of the land. Also, stretching the map metaphor is probably not wise. In reality you would want multiple maps or views on the current state of  opinion.

Democracy is not a simple popularity contest – and the underlying wiki information should provide useful input to the decision-makers.

After waking up, and a bit of googling – there does not seem to be anything quite like this:

  • The Center for Democracy and Technology is more concerned with Internet regulation than with the Democracy part of its name.
  • The Democracy Journal has an interesting article about the topic: how open source wiki technology can make government decisions more expert and more democratic.

The dream is probably affected by some of the projects I’m working on at SuperOffice – and some political discussions before bedtime, but this seems like a generally interesting area.

  • Automatically summarizing information, presenting digests on demand to decision makers. Something like N6 – but wikified.
  • Automatically distilling votes or participant activity into clusters, presenting clusters graphically or as simple charts.
  • Allowing bottom-up participation in the decision making process, and allowing everyone to see the decision basis.

Laws and politics have been likened to a sausage factory before, and while it is easy to ignore where the sausage comes from, we are obliged (I think) as citizens to keep an eye on what goes on inside the factory.

If we can help people make better decisions as well as improve people’s involvement in government, that sounds like a worthwhile goal.

A brief look at the current state of decision-support systems is not exactly encouraging. There is a lot of graphics and statistical modeling and analysis, but the user interaction seems to be very much stuck in the 80s. This is probably just a naïve impression. I hope.

Useless Error Messages

Our own software is guilty of this kind of stuff too, but this one is particularly annoying, since the message promises to specify the module that’s causing the problems. But does it appear? Nooooooo. Of course not.

A curse on the Microsoft developer who wrote this error message. May your capslock key become stuck at random intervals!
ASP error message

ADSI and WMI

I’m improving the installer for a web application. It’s a windows installer. It needs to register a MIME type with the server. This is important to do, since Windows 2003 server will not serve unknown Mime types. (Neither will Windows 2000 after the Lockdown tool has been used).

WMI is the preferred mechanism for diddling IIS settings, but it turns out you can’t rely on WMI being installed. So we need to user ADSI, the underlying technology.

ADSI is a maze of little automation objects, all poorly documented. There’s plenty of documentation. It’s just that most of it is pointless drivel. Undocumentation as some have called it.

The ADSI incantations necessary have been recorded by wizened elders.

Unfortunately these incantations need to be converted to C++ in order to work inside an installer. There is a heavy bias against using script in installers. Partly because script may not be installed, or if it is installed, it’s a lower version than we require. So a hardened C++ version is needed.

In case anyone needs to know, here is how to tweak ADSI to add a mime-type to IIS from C++. It’s not pretty – being a frankenstein monster of cut-and-paste snippets from various places.

char buf[BUFLEN];
strcpy(buf, "");

_bstr_t rdfType = ".rdf";

CoInitialize(NULL);
_bstr_t bsMimePath = "IIS://localhost/MimeMap";

IADs* pContainer = NULL;
HRESULT hr = ADsGetObject( bsMimePath, IID_IADs, (void**) &pContainer);
if( SUCCEEDED(hr) && pContainer != NULL )
{
_variant_t varMimeMap;
_bstr_t nameMimeMap = "MimeMap";
hr = pContainer->GetEx( nameMimeMap, &varMimeMap);
if( SUCCEEDED(hr) && ((varMimeMap.vt & VT_ARRAY) == VT_ARRAY) )
{
bool bFoundRdfType = false;

// MIME map is an array that we can redim and add an item to the end
SAFEARRAY* pArrMimeMap = varMimeMap.parray;
LONG lIdx, lHigh;
::SafeArrayGetLBound(pArrMimeMap, 1, &lIdx);
::SafeArrayGetUBound(pArrMimeMap, 1, &lHigh);
for(LONG i = lIdx; i < = lHigh; i++)
{
_variant_t elem;
hr = ::SafeArrayGetElement(pArrMimeMap, &i, (void*) &elem);
if( SUCCEEDED(hr) && ((elem.vt & VT_DISPATCH) == VT_DISPATCH) )
{

IDispatchPtr pMimeType = elem.pdispVal;
if(pMimeType != NULL)
{
DISPID idExtension = 0;
_bstr_t propName = "Extension";
BSTR pName = (BSTR)propName;
BSTR* ppName = & pName;
hr = pMimeType->GetIDsOfNames( IID_NULL, ppName, 1, LOCALE_USER_DEFAULT, &idExtension );
if( SUCCEEDED(hr) )
{
DISPPARAMS dispparamsNoArgs;
memset( &dispparamsNoArgs, 0, sizeof(dispparamsNoArgs));
_variant_t varResult;
hr = pMimeType->Invoke( idExtension, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispparamsNoArgs, &varResult, NULL, NULL);
if( SUCCEEDED(hr) )
{
_bstr_t tmp = varResult.bstrVal;
if( tmp == rdfType )
bFoundRdfType = true;
}
}

}
}

}
// add one element
if( ! bFoundRdfType )
{
_bstr_t fileType = ".rdf";
_bstr_t mimeType = "application/octet-stream";
_variant_t varFileType = fileType;
_variant_t varMimeType = mimeType;

CLSID CLSID_MimeType;
hr = CLSIDFromProgID( nameMimeMap, &CLSID_MimeType );
if( SUCCEEDED(hr) )
{
IDispatchPtr pMimeType;
hr = ::CoCreateInstance( CLSID_MimeType, NULL, CLSCTX_ALL, IID_IDispatch, (void**) &pMimeType );

DISPID idExtension = -1;
DISPID idMimeType = -1;
DISPID propPut = DISPID_PROPERTYPUT;

_bstr_t propName = "Extension";
BSTR pName = (BSTR)propName;
BSTR* ppName = & pName;
if( SUCCEEDED(hr) )
hr = pMimeType->GetIDsOfNames( IID_NULL, ppName, 1, LOCALE_USER_DEFAULT, &idExtension );
if( SUCCEEDED(hr) )
{
DISPPARAMS dispParam;
dispParam.cArgs = 1;
dispParam.cNamedArgs = 1;
dispParam.rgvarg = & varFileType;
dispParam.rgdispidNamedArgs = &propPut;
hr = pMimeType->Invoke( idExtension, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &dispParam, NULL, NULL, NULL);
}
if( SUCCEEDED(hr) )
{
propName = "MimeType";
pName = (BSTR)propName;
ppName = & pName;
hr = pMimeType->GetIDsOfNames( IID_NULL, ppName, 1, LOCALE_USER_DEFAULT, &idMimeType );
}
if( SUCCEEDED(hr) )
{
DISPPARAMS dispParam;
dispParam.cArgs = 1;
dispParam.cNamedArgs = 1;
dispParam.rgvarg = & varMimeType;
dispParam.rgdispidNamedArgs = &propPut;
hr = pMimeType->Invoke( idMimeType, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &dispParam, NULL, NULL, NULL);
}
if( SUCCEEDED(hr) )
{
SAFEARRAYBOUND bounds;
bounds.lLbound = lIdx;
bounds.cElements = lHigh - lIdx + 1 + 1;
hr = ::SafeArrayRedim(pArrMimeMap, &bounds);
if( SUCCEEDED(hr) )
hr = ::SafeArrayGetUBound(pArrMimeMap, 1, &lHigh);
_variant_t varMimeObj = (IDispatch*) pMimeType;
if( SUCCEEDED(hr) )
hr = ::SafeArrayPutElement(pArrMimeMap, &lHigh, &varMimeObj);
if( SUCCEEDED(hr) )
hr = pContainer->PutEx( ADS_PROPERTY_UPDATE, nameMimeMap, varMimeMap );
if( SUCCEEDED(hr) )
hr = pContainer->SetInfo();
}
}

if( SUCCEEDED(hr) )
strcpy(buf, "Added Mime type for .RDF files to IIS");
else
strcpy(buf, "Failed to add MIME type to IIS");
}
else
{
strcpy(buf, "MIME type already registered in IIS");
}


}
pContainer->Release();

}

CoUninitialize();

WikiCalc and REST architecture

Dan Bricklin the co-inventor of the spreadsheet has started to build a web-based spreadsheet – WikiCalc

As office software moves onto the web, it can become more open and collaborative. Consider a web-based spreadsheet, where every cell is addressable through a URL.

If the spreadsheet is at

http://www.example.com/calc/myStuff

then the first cell of the spreadsheet should be adressable as

http://www.example.com/calc/myStuff/R1C1

Ok -  now consider a spreadsheet somewhere else – the second spreadsheet could reference the results of a calculation in my sheet by reference to the URL of the cell in the spreadsheet. The second spreadsheet could contain a formula like this:

= 2 * http://www.example.com/calc/myStuff/R1C1
This is just a straightforward application of the REST architecture.

This could be a great way for government to expose standard values. Income tax rates, VAT rates and so on – easily referenced and automatically updated.

http//www.example.gov/taxrates/2006/vat/goods returns the VAT on goods in 2006 (25% in Norway).
http//www.example.gov/taxrates/current/vat/goods returns the VAT on goods at the moment.

When the rate is changed next year, the current value is updated – and all applications that reference it get the new, fresh value without a software-update.
Now imagine what happens if we extend this to all XML documents through XPath – i.e pretend that the web server is smart enough to dig into an XML document and pull out a fragment, rather than just sending back the entire document. i.e. URLs that reference bits of a document using XPath, not just entire documents:

http://www.xfront.com/REST-Web-Services.html  – this gives us the entire document.
http://www.xfront.com/REST-Web-Services.html/html/body/H2[0] – would in an ideal world give us the contents of the first second level heading: “What is REST?”

Imagine how easily you could glue together web-applications with this kind addressing…

The text fragment extraction wouldn’t have to be done by the web-server, it could just as well be done by the application. The point is that the URL would make integration with existing, well-formed content much much easier. And while much content out there isn’t well-formed (and so can’t be addressed in this way), the next generation of Office tools will output suitable content by default.

When everything is addressable, then everything becomes intertwingled. A point of potential intergration. Lots of places for leverage.

Of course, all the hard problems of versioning and formatting don’t go away, but they apply to all kinds of solutions, not just this one.

Daily Software Grind

I have too much work at once. Transitions between projects are tricky things, and I have (yet again) managed to get caught in a squeeze between four projects (two major, two minor). Whine whine whine.

Anyway, VS.net 2003 will occasionally not help by locking up. Deleting the .NCB file helps. Argh! Nothing more annoying than my primary tool going bonkers and freezing while I’m trying to get some work done. Two hours wasted uninstalling/installing various helpers and tools.
Visual Assist X is lovely, but I suspect it contributes to the Visual Studio lockup-on-start. We have a metric ton of files in our solution, and Visual Assist likes to scan the header files. It usually doesn’t freak out, but I wonder about it. Does it suffer from corruption in its database of symbols?

Xoreax Incredibuild rocks hard when it works, but the last couple of builds (2.40 and 2.42) have not rocked at all. Corrupt files, broken builds and increased flakiness do not endear themselves. The compiler is the most important tool for the programmer, and it’s considered bad to mess it up. Internal Compiler Error is not a good thing.

I’ve been told good things about Code Historian but I don’t have time to try it out. Too busy finishing and starting projects.

ASP.net 2.0 – Plus ca change, plus c’est la même chose

I’ve been safely wrapped up in my little C++ world for a while now, but I’ve had to tweak a few ASP.net web sites in the past year. The problems we’ve had building and testing web sites internally appear to be fixed in the new ASP.net 2.0 release that Microsoft are shipping this fall. But then I read articles like this and I get worried.

The problems and issues Scott outlines contrasts with the simple life in the PHP/MySQL/SMARTY world. Files stay where they are. Compiling happens automatically, but does not litter the hard-disk with mysterious DLLs. Problems are comprehensible and solutions are discoverable.

Could it be that ASP.net is trying too hard to remake the web in Visual Basic’s image?

Split($site)

I’m going to split the blog into two sections – one with the boring general stuff (pictures of random lions, weather reports from Oslo, etc) and one more focused on usability, programming and software design. Partly this is to force myself to write seriously instead of just filling the blog with useless fluff, and partly it’s because I’m impressed by sites like Coding Horror.

This entails me actually figuring out how WordPress theming works. Luckily the wiki has turned up just what I need — I think. Expect random breakages as I muck around below-decks.