This is possible using SendMessage with WM_CLOSE parameter. There are two tricks here: first, DLLImport the method from user32.dll, second get Revit windows handle.
For the first, there is a good source of those methods at PInvike.NET website. For this case, we need the SendMessage header. For the second, there is a good post at The Builder Coder blog.
Finally, the code will look like:
[Transaction(TransactionMode.Manual)]
public class AdskCommand : IExternalCommand
{
public Result Execute(
ExternalCommandData commandData,
ref string message,
ElementSet elements)
{
// send the message to close
SendMessage(RevitWndHandle,
WM_CLOSE,
IntPtr.Zero, IntPtr.Zero);
return Result.Succeeded;
}
// the value for close
static uint WM_CLOSE = 0x10;
// Use P/Invoke to DLLImport
[DllImport("user32.dll",
CharSet = CharSet.Auto,
SetLastError = false)]
static extern IntPtr SendMessage(
IntPtr hWnd, UInt32 Msg,
IntPtr wParam, IntPtr lParam);
// singleton to store Revit handle
static IntPtr _hWndRevit = IntPtr.Zero;
// get Revit handle
private static IntPtr RevitWndHandle
{
get
{
if (_hWndRevit == IntPtr.Zero)
{
System.Diagnostics.Process[] processes
= System.Diagnostics.Process.
GetCurrentProcess();
if (0 < processes.Length)
{
_hWndRevit = processes[0].MainWindowHandle;
}
}
return _hWndRevit;
}
}
}