I have figured it out, thisApp being null really was the problem, the ExternalApplication class was never invoke, and Revit throw the exception at the ExternalCommand level. I just need to make a new ExternalApplication class instance ,call the ShowWindow method and the program does what I expected:
public virtual Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { try { new ThisApplication().ShowWindow(commandData.Application); return Result.Succeeded; } catch (Exception ex) { message = ex.Message; return Result.Failed; } }
However, this is exactly how the example in SDK modeless dialog. I wonder why it work there?