Question:
Error getting email from bundle: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. at ClsImap.SetMailFlag(ClsImap , ClsEmail , XString , Int32 , ProgressEvent ) at Chilkat.Imap.SetMailFlag(Email email, String flagName, Int32 value)
Calling with SetMailFlag(email, "Deleted", 1) Runtime Version v4.0.30319 Version 9.4.1.0 Net 4.5 x64
Thanks! I'll have a look right now.
I'm not able to reproduce the error. I'm posting the C# code I used for testing below. I'm confused about what .NET Framework you are using -- is it 4.0 or 4.5?
Your post indicate 4.0 by this: "Runtime Version v4.0.3031", but you seem to be using the Chilkat assembly for the 4.5 Framework?
private void setMailFlagToolStripMenuItem_Click(object sender, EventArgs e) { Chilkat.Imap imap = new Chilkat.Imap(); bool success = imapConnectAndLogin("fausey@chilkatsoft.com", imap); if (!success) return; success = imap.SelectMailbox("Inbox"); if (!success) { textBox2.Text = imap.LastErrorText; return; } // Download the 1st email and set the delete flag. Chilkat.Email email = imap.FetchSingle(1, false); if (email == null) { textBox2.Text = imap.LastErrorText; return; } success = imap.SetMailFlag(email, "Deleted", 1); if (!success) { textBox2.Text = imap.LastErrorText; return; } if (success) { textBox2.Text = "Success."; } return; }
good question. the version of system.dll, for example, is 4.0.30319.18044 the version of mscoreei.dll is 4.0.30319.17929 I think those mean .net 4.5. Sorry I wasn't more specific, I'm just learning that the 4.0.3031 part did not change between 4 and 4.5
Anyway, the exception is sporadic. I just catch, sleep and try from scratch with a new mail instance.
It started with 9.4.1.0.
9.3.2.0 4.5 did not exhibit this.
9.3.1.0 4.0 (i think) use to give me the same sporadic exception but in Imap.FetchBundle
(which a saw in a related question that you fixed.)
my code goes something like:
while (true)
{
try
{
if (_mail == null)
{
_mail = new Imap();
_mail.UnlockComponent("");
_mail.KeepSessionLog = false;
_mail.Ssl = true;
_mail.Port = 993;
_mail.Connect("blah");
_mail.Login("me+blah.com", "passwork")
_mail.SelectMailbox("INBOX")
_bounce = new Bounce();
_bounce.UnlockComponent("xxxxx");
}
// Get the message IDs of all the emails in the mailbox
var messageSet = _mail.Search("ALL", true);
var bundle = _mail.FetchBundle(messageSet);
for (var i = 0; i < bundle.MessageCount; i++)
{
var email = bundle.GetEmail(i);
if (_bounce.ExamineEmail(email) && _bounce.BounceType > 0)
{
//....
}
else
{
//look at email
}
_mail.SetMailFlag(email, "Deleted", 1);
}
//todo: why doing this way?
//It is ok to call Expunge when nothing was deleted.
_mail.Expunge();
}
catch (AccessViolationException)
{
if (_mail != null)
{
_mail.Disconnect();
_mail = null;
}
}
catch (Exception)
{
if (_mail != null)
{
_mail.Disconnect();
_mail = null;
}
}
Thread.Sleep(3000);
}
The DebugLogFilePath property, which is now common to all Chilkat classes, is designed to help with these difficult situations. If you set it to the path of a log file that is to be created, then every Chilkat method call on the object will log to the file each line that goes into the LastErrorText. Each line is logged by opening the log file, writing the line, and closing the file so as to avoid file I/O buffering issues.
Do this: On the line before the call to SetMailFlag, set the DebugLogFilePath property to the path of a log file you want created (for example: C:/temp/chilkatLog.txt) Also, add a line of code to delete the log file. This way, each time SetMailFlag is called, no log file exists, it is created, and if the crash occurs, you'll be left with a log of what happened up until the crash. Make sure to turn on verbose logging by setting the VerboseLogging property = true. This will provide more detailed information in the log file. After the call to SetMailFlag, set the DebugLogFilePath to the empty string so that nothing more is logged -- you only need it for the call to SetMailFlag. Then run to get the next crash and send me the log file (or post it here).
In pseudo-code, the changes would look like this:
_mail.DebugLogFilePath = "c:/temp/chilkatLog.txt" _mail.VerboseLogging = true; If the file c:/temp/chilkatLog.txt exist, then delete it. _mail.SetMailFlag(email, "Deleted", 1); _mail.DebugLogFilePath = ""; _mail.VerboseLogging = false;
The trap has been set!
Caught one! The trap:
Dim chilkatLog = "C:\chilkatLog.txt";
try
{
_mail.DebugLogFilePath = chilkatLog;
_mail.VerboseLogging = true;
_mail.SetMailFlag(email, "Deleted", 1)
}
catch (AccessViolationException e)
{
if (File.Exists(chilkatLog))
{
File.Copy(chilkatLog,
chilkatLog.Replace(".txt", Guid.NewGuid() + ".txt"), true);
}
}
finally
{
_mail.DebugLogFilePath = "";
_mail.VerboseLogging = false;
if (File.Exists(chilkatLog))
{
File.Delete(chilkatLog);
}
}
The Log:
SetMailFlag:
DllDate: Jul 9 2013
ChilkatVersion: 9.4.1.26
UnlockPrefix: KEN**********LQ
Username: YOUCOULD:Ken
Architecture: Little Endian; 64-bit
Language: .NET 4.5 / x64
VerboseLogging: 1
Flag: Deleted
Value: 1
bUid: 1
UidOrSeqNum: 48226
ImapCmdSent: aitq UID STORE 48226 +FLAGS.SILENT (\Deleted)
getCompleteResponse:
rcvUntilMatchStringQP:
dbReceived0:
tlsRecvAppData:
readIncomingTls_appData:
readTlsRecord:
TLS 1.0, Application, sz=48
paddingLen: 1
macLen: 20
decryptedMsg: [aitq OK Store completed.
]
(leaveContext)
processTlsRecord:
processApplicationData:
(leaveContext)
(leaveContext)
(leaveContext)
rcvAppData: success, nReceived = 26
(leaveContext)
startIdx: 0
dbReceived: aitq OK Store completed.
Found match string.
ImapCmdResp: aitq OK Store completed.
(leaveContext)
The Exception:
System.AccessViolationException: Attempted to read or write protected memory.
This is often an indication that other memory is corrupt.
at ClsImap.SetMailFlag(ClsImap* , ClsEmail* , XString* , Int32 , ProgressEvent* )
at Chilkat.Imap.SetMailFlag(Email email, String flagName, Int32 value)
at SCS.Import.EmailPoller.Start() in c:\SCS\Code\Import\EmailPoller.cs:line 88
Thanks. Please do exactly the same with this new build:
http://www.chilkatsoft.com/preRelease/ChilkatDotNet45-9.4.1-x64.zip
If you get the exception again, post the log file. There is additional information that should help isolate the source of the problem.
Here is what the new dll logs before the AccessViolationException:
SetMailFlag:
DllDate: Aug 5 2013
ChilkatVersion: 9.4.1.34
UnlockPrefix: KEN**********LQ
Username: YOUCOULD:Ken
Architecture: Little Endian; 64-bit
Language: .NET 4.5 / x64
VerboseLogging: 1
setFlag:
Flag: Deleted
Value: 1
bUid: 1
UidOrSeqNum: 48657
ImapCmdSent: afjk UID STORE 48657 +FLAGS.SILENT (\Deleted)
getCompleteResponse:
rcvUntilMatchStringQP:
dbReceived0:
tlsRecvAppData:
readIncomingTls_appData:
readTlsRecord:
TLS 1.0, Application, sz=48
paddingLen: 1
macLen: 20
decryptedMsg: [afjk OK Store completed.
]
(leaveContext)
processTlsRecord:
processApplicationData:
(leaveContext)
(leaveContext)
(leaveContext)
rcvAppData: success, nReceived = 26
(leaveContext)
startIdx: 0
dbReceived: afjk OK Store completed.
Found match string.
ImapCmdResp: afjk OK Store completed.
(leaveContext)
(leaveContext)
addingMimeHeader: ckx-imap-deleted
Checking for the ckx-imap-flags header..
and the exception:
System.AccessViolationException: Attempted to read or write protected memory.
This is often an indication that other memory is corrupt.
at ClsImap.SetMailFlag(ClsImap* , ClsEmail* , XString* , Int32 , ProgressEvent* )
at Chilkat.Imap.SetMailFlag(Email email, String flagName, Int32 value)
at SCS.Import.EmailPoller.Start() in c:\SCS\Code\Import\EmailPoller.cs:line 92
Thanks! I think this new build will likely fix the problem:
http://www.chilkatsoft.com/preRelease/ChilkatDotNet45-9.4.1-x64.zip
You have fixed it. Thank you. -Ken