|
Hi,
This is my second post, I hope to do better that the first one..
I wrote a small addin in C# to Outlook 2007.
It connects to a local DB and should remove mail addresses which are either "Bounced" (not vaild) or asked to un-subscribe from the mailing list.
The addin was written using Visual Studio 2008 VSTO tools.
It does what it should, when I debug, yet when I step out of my managed code, the Outlook hangs, CPU is 100% and the message I see at the system tray is "Outlook is synchronizing folders".
When I remove my logic and use a "hard coded" address - it works.
I would also like to attach my code, since it's very long, I will only put some part of it here,
I can send the complete file (300 lines totally) by mail.
I will appreciate if someone is familiar with this
TIA,
Amit.
<code>
void App_ItemSend(object Item, ref bool Cancel)
{
Outlook.MailItem Mail = (Outlook.MailItem)Item;
//Get the addresses from the "To" field
string[] toArray =
Mail.To == null ? new string[] { } : Mail.To.Split(new char[] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries);
//Internal Data Structures to hold the "To"recipients
Dictionary<string, Recipient> toDic = new Dictionary<string, Recipient>();
List<string> emailToCheck = new List<string>();
List<string> invalidEmails = null;
//Remove spaces from the "To" list (originally recieved as "tuktuk@blabla.com; oved@sabih.com")
for (int i = 0; i < toArray.Length; i++)
{
toArray[i] = toArray[i].Replace(" ", "");
}
try
{
while (Mail.Recipients.Count > 0)
{
//Get the first recipient object in the recipient list
Recipient rec = Mail.Recipients[1];
//Remove the first object from the recipient list
Mail.Recipients.Remove(1);
List<Recipient> recList = new List<Recipient>();
ICollection<string> emailList = GetEmailsList(rec.AddressEntry);
foreach (string email in emailList)
{
//Create a new recipient
Recipient newRec = Mail.Session.CreateRecipient(email);
if (!newRec.Resolve())
{
//if eMail address can't be verified against the Outlook address book - skip it
continue;
}
//if eMail address is valid against the address book, add it to the current recipient list
recList.Add(newRec);
//Add the new recipient to the list of emails to check "Bounced"/"Un-Subscribed"
if (!emailToCheck.Contains(newRec.Address))
{
emailToCheck.Add(newRec.Address);
}
}
//If the current recipient is contained in the original "To" list, then go over the recipient list
//For each such recipient under that recipient name, add it the the "To" group
if (Array.IndexOf(toArray, rec.Name) >= 0)
{
foreach (Recipient r in recList)
{
toDic[r.Address.ToLower()] = r;
}
}
}
// Get the list of invalid email lists
invalidEmails = GetInvalidEmails(emailToCheck);
}
catch (System.Exception e)
{
Cancel = true;
MessageBox.Show(e.Message + "\nMailing Canceled", "Error Validating Emails");
return;
}
//Create the final data structure for the email lists
StringBuilder toList = new StringBuilder();
//Go over each entry in the "To" dictionary. In case the current entry is valid, add it to the "To" final list
foreach (KeyValuePair<string, Recipient> kvp in toDic)
{
if (invalidEmails == null || !invalidEmails.Contains(kvp.Key.Replace("'", "")))
{
toList.AppendFormat("{0};", kvp.Key);
}
}
if (toList.Length == 0 && ccList.Length == 0 && bccList.Length == 0)
{
MessageBox.Show("All recipients addresses are invalid or unsubscribed.\nSend operation aborted.");
Cancel = true;
return;
}
Mail.To = null;
//Add the address lists back to the original "To" list of the Outlook 2007 object
if (toList.Length > 0)
{
Mail.To = toList.ToString().Substring(0, toList.Length - 1);
}
}
</code>
|
|
|
|
|
Perhaps it's been mentioned before, but I'm looking at a switch (with sixteen cases, a little bit large) and it has occurred to me that because it's controlled by an enumerated value (zero to fifteen) that I might get better performance (or maybe worse), and perhaps better readability from an array of delegates (perhaps anonymous methods).
The value has already been validated so I know that it won't be out of range. I would also know that none of the values is null.
Maintainability might be hindered somewhat, depending on how I implement it.
Any experiences? Discuss...
|
|
|
|
|
I do not know the answer, but I would put it to the test. And forcing it to run through the loop many times. Lets say 1000 times. and add a measuring system. And see what results you get
|
|
|
|
|
If possible, a better object model.
Enums are often the sign of a missing inheritance hierarchy, I many times before using them. The other thing they lead to is switces, which are almost the work of the devil. This follows Martin Fowler's work on re-factoring:
http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html[^]Dalek Dave: There are many words that some find offensive, Homosexuality, Alcoholism, Religion, Visual Basic, Manchester United, Butter.
Pete o'Hanlon: If it wasn't insulting tools, I'd say you were dumber than a bag of spanners.
|
|
|
|
|
|
An array of delegates is approximately 4 times as slow, if the switch is non-sparse and compiled down to a switch instruction in MSIL
|
|
|
|
|
And a V-table for a class hierarchy might be as well?
|
|
|
|
|
So, I benchmarked it.
Switch: 150
Array of delegates: 676
Abstract methods, sealed: 2868
Abstract methods, not sealed: 2866
(the number is the tick count / 10 million, for a loop of 500 million iterations)
I'm surprised to see that sealed vs unsealed made absolutely no difference..
All tests were done in 64bit mode, on release, with no debugger attached, using the Stopwatch class. The methods did nothing, the switch had some integer additions in it to keep it from being optimized away (not sure whether it would even do that, but an addition is nearly free anyway and it's safer that way)
|
|
|
|
|
Yowch! I had a feeling that calling methods would outweigh the switch, but that's surprising. Thanks.
Article?
|
|
|
|
|
You're welcome
But a whole article about this? I'd have to dig up the "real disassembly" (without debugger attached) to make it article-worthy..
|
|
|
|
|
I'm familiar with that dilemma as I regularly write CPU simulators for all kinds of processors. When an instruction gets decoded and needs being dispatched, the choice boils down to:
- create a small method for each of the instructions, and make all CPU state global or pass it back and forth; this would use an array of delegates/function pointers;
- create one huge method with one huge switch and perform everything that is reasonably possible inside that one method, keeping all state local.
As simulation is all about performance, I go for the huge and ugly switch. That is about the only time I create a method exceeding 1000 lines of code.
BTW: it is often impossible to take advantage of known invariants; e.g. switching on a byte and presenting cases for all possible values [0..255] isn't sufficient to keep most compilers from generating out-of-bounds testing code. Yes, I know, the expression type gets promoted to int in most C-like languages, but that is not really relevant, the compiler could easily infer the possible range.
|
|
|
|
|
Luc Pattyn wrote: as I regularly write CPU simulators for all kinds of processors.
Sooooooo...where are the articles to go along with these?!
|
|
|
|
|
Won't happen as:
1. None of that is public.
2. It is a vast topic.
3. I expect most potential readers would find the subject very dull, as it presumes good knowledge about the processor at hand.
4. Coding for performance, when taken to the extreme, goes against all normal coding guidelines; I'm not inclined to show the ugly beasts I sometimes create!
|
|
|
|
|
Luc Pattyn wrote: I'm not inclined to show the ugly beasts I sometimes create!
That's gotta be worth a 5!
I'm creating a bit of a 'beast' at the moment - I hope I have some time to refactor it before anyone reviews the code! Unlikely as it's going live tomorrow (if I can complete this evening) and so long as it works then no one will be interested Dave
Binging is like googling, it just feels dirtier. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn) Why are you using VB6? Do you hate yourself? (Christian Graus)
|
|
|
|
|
DaveyM69 wrote: refactor it before anyone reviews the code
Right, that's basically what I'm doing -- revisiting my code before I publish it. I find this to be a good exercise.
|
|
|
|
|
Luc Pattyn wrote: goes against all normal coding guidelines; I'm not inclined to show the ugly beasts I sometimes create!
Chicken sh!^.
|
|
|
|
|
Luc Pattyn wrote: 4. Coding for performance, when taken to the extreme, goes against all normal coding guidelines
I would actually be interested to see what conditions are "acceptable" for breaking normal rules and different methods for acheiving said perfomance. Is that a bad thing?
DybsThe shout of progress is not "Eureka!" it's "Strange... that's not what i expected". - peterchen
|
|
|
|
|
There is nothing wrong as long as you are fully aware of the consequences. The first thing you probably loose is good readability and hence easy debugging and maintainability.
When in search of maximum performance, quite often object orientation is bad when the objects are very small and very many (too much overhead). Method calls are bad (they don't compute anything), conditionals are bad (they disturb normal program flow). Combine that and you may end up with large pieces of straight, hardly structured, code; and then there is a whole collection of hacks to choose from.
Whether all this is acceptable is matter of discussion.
|
|
|
|
|
Luc Pattyn wrote: CPU simulators
Yeah, this is kinda that -- a script language interpreter.
|
|
|
|
|
I need to make client-server project with separated access. It should be 3 groups of users with different access level. Access level defines the appearance of form witch user would see. Can somebody advise how to realize this separated access.
|
|
|
|
|
I would do it like this: (As long as I presume, that client doesn't access Database directly)
1. step: Client logs in with authentic username and password
2. step: Server sends to client current access level and the server holds its data per session. (Doesn't clean memory, till logout or Time out)
3. step: Client gets access level and then prepares GUI.
When client sends command, witch exceeds user privileges wont get them info. This design prevents users modifying client, to get higher access. This works as long you do not connect directly to database only to service that sits on Server side between client and database.
and bad design: If you want to directly connect to database (Witch I do not recommend) use for each privileges, use own build client for each access level.
C++ have compiler directive: (I do not know if exists in C#)
#define, #ifdef, #ifndef and #endif.
|
|
|
|
|
Hi,
1. I configured the Outlook to work with Windows Live Hotmail(my hotmail account)
2. Now i want to read all the inbox from my hotmail account using C#.
3. The outlook create for hotmail a file with .ost extension(not with .pst)
4. My procedure is like this:
TextWriter tw = new StreamWriter(@"C:\pstfile_html.txt");
// Create the Outlook application.
// in-line initialization
Outlook.Application oApp = new Outlook.Application();
// Get the MAPI namespace.
Outlook.NameSpace oNS = oApp.GetNamespace("MAPI");
// Log on by using the default profile or existing session (no dialog box).
oNS.Logon(Missing.Value,Missing.Value,false,true);
//Get the Inbox folder.
Outlook.MAPIFolder oInbox = oNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
//Get the Items collection in the Inbox folder.
Outlook.Items oItems = oInbox.Items;
Outlook.MailItem oMsg = (Outlook.MailItem)oItems.GetFirst();
for (int i = 0; i < oItems.Count; i++)
{
//Output some common properties.
tw.WriteLine(oMsg.Subject);
tw.WriteLine(oMsg.SenderName);
tw.WriteLine(oMsg.ReceivedTime);
tw.WriteLine(oMsg.Body);
tw.WriteLine(oMsg.HTMLBody);
tw.WriteLine("Next Message-----------------------");
oMsg = (Outlook.MailItem)oItems.GetNext();
//System.Diagnostics.Debug.WriteLine(objMail.Body.ToString());
}
//Log off.
oNS.Logoff();
//Explicitly release objects.
oMsg = null;
oItems = null;
oInbox = null;
oNS = null;
oApp = null;
tw.Close();
}
//Error handler.
catch (Exception e)
{
Console.WriteLine("{0} Exception caught: ", e);
}
// Return value.
return 0;
}
6. I don't know how to take hotmail folder.
Thanks,
Anca
|
|
|
|
|
Hello,
I can't get the challenge and player respond working, it currently responds no player time, score only name, But the names are to little strange.
public string Challenge(string servIP, int servPORT)
{
byte[] buffer = new byte[100 * 1024];
byte[] PlayerQuery = { 0xff, 0xff, 0xff, 0xff, 0x55, 0x65 };
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint ipEP = new IPEndPoint(IPAddress.Parse(servIP), servPORT);
EndPoint EP = (EndPoint)ipEP;
socket.ReceiveTimeout = 1000;
socket.SendTo(PlayerQuery, PlayerQuery.Length, SocketFlags.None, EP);
int recvBytes = socket.ReceiveFrom(buffer, ref EP);
return ParseChallenge(buffer);
}
private string ParseChallenge(byte[] resp)
{
_CHALLANGE = System.Text.Encoding.ASCII.GetString(resp, 5, 4);
return _CHALLANGE;
}
private SourceQuery ParsePlayers(byte[] resp)
{
SourceQuery ret = new SourceQuery();
int i = 0;
ret.PPlayers = Encoding.ASCII.GetString(resp);
return ret;
}
public SourceQuery Players(string servIP, int servPORT)
{
byte[] buffer = new byte[4096];
string challenge = Challenge(servIP, servPORT);
byte[] PlayerQuery = { 0xff, 0xff, 0xff, 0xff, 0x55 };
string pQuery = Encoding.ASCII.GetString(PlayerQuery);
byte[] Query = Encoding.ASCII.GetBytes(pQuery + challenge);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint ipEP = new IPEndPoint(IPAddress.Parse(servIP), servPORT);
EndPoint EP = (EndPoint)ipEP;
socket.ReceiveTimeout = 1500;
socket.SendTo(PlayerQuery, PlayerQuery.Length, SocketFlags.None, EP);
int recvBytes = socket.ReceiveFrom(buffer, ref EP);
return ParsePlayers(buffer);
}
|
|
|
|
|
Hi,
i've got a Graphics Object and have drawn a rectangle (graphics.DrawRectangle) on it. Now I want to rotate it using the mouse. and the rotation matrix. But I don't see the rotation while moving the mouse, I just see it after realeasing the button...
Can anybody help me?
|
|
|
|
|
Without seeing any code it is difficult to tell you much - but are you calling Invalidate in the MouseMove Event? You should never use standby on an elephant. It always crashes when you lift the ears. - Mark Wallace
C/C++ (I dont see a huge difference between them, and the 'benefits' of C++ are questionable, who needs inheritance when you have copy and paste) - fat_boy
|
|
|
|
|