Workarounds for mailing/lockup problems with Outlook

delphi package - automated exception handling
Post Reply
markk
Posts: 15
Joined: Fri Mar 04, 2016 12:07 am

Workarounds for mailing/lockup problems with Outlook

Post by markk »

Hi

I'm new to madExcept and have just the first project replacement of excMagic with it.
We're wanting to e-mail a bug report and screenshot back to us whenever an unexpected exception occurs and had this setup and ready to deploy when I discovered a problem.

1) If using MailViaMapi and Outlook and the faulting application is closed before the bug report e-mail is sent we see Outlook complain with something along the lines of "Cannot display the folder. '<appName> exited without properly closing your Outlook data file 'C:\...\Outlook\outlook.ost;. 'Microsoft Office Outlook must be restarted...'
After exiting outlook I often have to kill task outlook.exe before Outlook will work again.
From a web search I suspect this effects versions of Outlook 2007 onwards (I use 2007)
Does anyone know of a solution to stop this error occurring as we don't want to lock up our customers e-mail systems.

2) As a work around I thought I'd use MailViaMailTo as it doesn't exhibit the same lockup problem but discovered it only seems to support sending the basic bug report in the message contents. No problem I thought, I'll just MIME encode the bug report and screenshot but haven't been able to get this to work. Does anyone know if this is possible with madExcept's mailing system?

Thanks
Mark
markk
Posts: 15
Joined: Fri Mar 04, 2016 12:07 am

Re: Workarounds for mailing/lockup problems with Outlook

Post by markk »

A third option would be to get the application to wait until the mapi mail has been sent/closed. I've tried setting the threads to suspend but as soon as

Code: Select all

          b2 := ResumeMainThread;
          mapiResult := sendProc(0, parentWindow, mail, flags, 0);
is called within madExcept.SendMapiMailEx normal app message processing begins

If I set sendInBackground to false MAPI sendProc fails returning 2

Following is an example of the handler code I've been trialling.

Code: Select all

procedure CExceptionHandler.CheckAndSaveException(
  const exceptIntf : IMEException;
  var handled      : boolean);
const
  MAIL_TO_LINE_BREAK = #13#10; // don't change this from 13 10!!!  See rfc2368 for details
var
  appInfo            : IVersionInfo;
  logFileName        : string;
  screenShotFilename : string;
  dir                : string;
  logPathWithoutExtn : string;
  rawLogData         : RawByteString;
  screenshot         : INVBitmap;
  compressor         : TLZRW1;
  fileStream         : TFileStream;
  memStream          : TMemoryStream;
  mailCreated        : boolean;
begin
  handled := false;
  try
    handled := m_promptToLogError and (not PromptToLogError(exceptIntf.ExceptMessage));

    if not handled then
    begin
      // get application info
      appInfo := CVersionInfo.Create;

      dir := m_LogFolder;
      if not DirectoryExists(dir) then
      begin
        ForceDirectories(m_LogFolder);
      end;
      logPathWithoutExtn := dir + 'ErrorLog' + FormatDateTime('yyyymmdd-hhnnsszzz', Now);
      if m_CompressLog then
      begin
        logFileName := logPathWithoutExtn + '.merz';
      end
      else
      begin
        logFileName := logPathWithoutExtn + '.mer';
      end;
      screenShotFilename := ChangeFileExt(logFilename, '.png');

      m_LastMessage := exceptIntf.ExceptMessage;


  //    exceptIntf.CreateScreenShot;
  //    exceptIntf.AppendScreenShot;
      exceptIntf.ShowAssistant;
      exceptIntf.ShowSetting := ssSimpleBox;
      exceptIntf.AutoSave;
      exceptIntf.BugReportFile := logFileName;

      exceptIntf.BugReportHeader.Add('Screenshot', screenShotFilename);
      exceptIntf.BugReportHeader.Add('[PRODUCT]', '');
      exceptIntf.BugReportHeader.Add('Product', appInfo.ProductName);
      exceptIntf.BugReportHeader.Add('ProductVersion', appInfo.ProductVersionStr);
      exceptIntf.BugReportHeader.Add('Company', appInfo.CompanyName);
      exceptIntf.BugReportHeader.Add('Copyright', appInfo.LegalCopyright);
      exceptIntf.BugReportHeader.Add('Trademarks', appInfo.LegalTrademarks);
      exceptIntf.BugReportHeader.Add('FileVersion', appInfo.FileVersionStr);
      exceptIntf.BugReportHeader.Add('FileFlags', appInfo.FileFlagsStr);
      exceptIntf.BugReportHeader.Add('OriginalFilename', appInfo.OriginalFilename);
      exceptIntf.BugReportHeader.Add('FileDescription', appInfo.FileDescription);
      exceptIntf.BugReportHeader.Add('InternalName', appInfo.InternalName);
      exceptIntf.BugReportHeader.Add('Language', appInfo.LanguageName);
      exceptIntf.BugReportHeader.Add('Comments', appInfo.Comments);

      screenshot := exceptIntf.ScreenShot;

      rawLogData := RawByteString(exceptIntf.BugReport);
      madCrypt.Encrypt(AnsiString(rawLogData), PASS_BASE, INIT_VECTOR);
      rawLogData := RawByteString(Format('%s:%d',[BUG_REPORT_VERSION_FIELD_NAME, MERZ_VERSION])+sLineBreak)+rawLogData;

      // get input and output streams
      fileStream := TFileStream.Create(logFileName, fmCreate or fmShareExclusive);
      memStream := TMemoryStream.Create;
      memStream.Write(PAnsiChar(rawLogData)^, Length(rawLogData));
      memStream.Position := 0;

      try
        // now save to file
        if m_CompressLog then
        begin
          compressor := TLZRW1.Create(nil);
          Compressor.UseStream := true;
          Compressor.InputStream := memStream;
          Compressor.OutputStream := fileStream;
          Compressor.Compress;
        end
        else
        begin
          fileStream.CopyFrom(memStream, 0);
        end;

        // store file name
        m_LastSavedLogfile := logFileName;

      finally
        memStream.Free;
        fileStream.Free;
      end;

      if assigned(screenShot) then
      begin
        screenshot.SavePng(screenShotFilename, pf256Colors);
      end;

      if not m_silent and m_emailBugReport then
      begin
        try
          { setting sendInBackground to false results in MailViaMailTo being
            used so no attachments and partial clear text bug report

            At the moment using MailViaMapi can result in Outlook locking up if
            the user exits Primecut before they send the mail message.
            MailViaMailTo does not allow for attachments etc and is not send an
            email large enough to contain the full bug report
            Using AutoSendBugReport also causes the MAPI lockup.

            Attempting to sent MIME encoded data is not working for MailViaMailTo
          }
          exceptIntf.sendInBackground := true;
          exceptIntf.MailViaMapi := true;
      //    exceptIntf.MailViaMapi := false;
          exceptIntf.MailViaMailTo := false;
      //    exceptIntf.MailViaMailTo := true;
          exceptIntf.MailAddr := BUG_REPORTS_EMAIL_ADDRESS;

          exceptIntf.ScreenShotSendAs := screenShotFilename;
          exceptIntf.BugReportSendAs := logFilename;
          exceptIntf.attachBugReport := true;
          exceptIntf.attachBugReportFile := false;

          exceptIntf.MailSubject := appInfo.FileDescription + ' bug report';
          exceptIntf.MailBody := 'Please find the bug report attached' + MAIL_TO_LINE_BREAK + MAIL_TO_LINE_BREAK;
          exceptIntf.MailBody := exceptIntf.MailBody + format('Product: %s' + MAIL_TO_LINE_BREAK, [appInfo.ProductName]);
          exceptIntf.MailBody := exceptIntf.MailBody + format('ProductVersion: %s' + MAIL_TO_LINE_BREAK, [appInfo.ProductVersionStr]);
          exceptIntf.MailBody := exceptIntf.MailBody + format('FileVersion: %s' + MAIL_TO_LINE_BREAK, [appInfo.FileVersionStr]);
          exceptIntf.MailBody := exceptIntf.MailBody + format('FileDescription: %s' + MAIL_TO_LINE_BREAK, [appInfo.FileDescription]);
          if appInfo.Comments <> '' then
          begin
            exceptIntf.MailBody := exceptIntf.MailBody + format('FileComments: %s'+sLineBreak, [appInfo.Comments]);
          end;

          exceptIntf.SendBugReport();
{
          mailCreated := madExcept.SendBugReport(exceptIntf.BugReport, screenShot, 0, exceptIntf) = madTypes.yes;

          mailCreated := madExcept.AutoSendBugReport(exceptIntf.BugReport, screenShot, exceptIntf) = madTypes.yes;
          if not mailCreated then
          begin
            ShowMessage('Email creation failed');
          end;
}
        except
          on e : Exception do
            begin
              OutputDebugString( PChar('CExceptionHandler.CheckAndSaveException raised exception: ' +
                     e.Message + ' while handling exception: ' + m_LastMessage) );
            end;
        end;
      end;
      handled := true;
    end

  except
    on e : Exception do
      begin
        OutputDebugString( PChar('CExceptionHandler.CheckAndSaveException raised exception: ' +
               e.Message + ' while handling exception: ' + m_LastMessage) );
      end;
  end;
end;

madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Re: Workarounds for mailing/lockup problems with Outlook

Post by madshi »

Try unchecking the "send bug report in background" option. Does that help?

Another option would be to use HTTP uploading instead of MAPI sending. MAPI sending is a comfortable option, but it depends on a local mail client being installed and properly configured on your end users' PCs, which may not be the case in these days of gmail etc, where mailing is often done through the browser interface, only.

mailto unfortunately doesn't support attachments. It's a very simple API, only meant to send short text messages.
markk
Posts: 15
Joined: Fri Mar 04, 2016 12:07 am

Re: Workarounds for mailing/lockup problems with Outlook

Post by markk »

I ended up going with the http upload, using a php script (running on our webserver) based on your supplied one to convert the upload into an e-mail
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Re: Workarounds for mailing/lockup problems with Outlook

Post by madshi »

I think that's probably the best choice.
Post Reply