I'm running the code below and I was under the impression that it did what it was supposed to. However, it seems that Outlook never deletes the address book folder. It just sets .ShowAsOutlookABto false. It means that when I check if the folder exists at the next start-up of Outlook, the folder is there (although I didn't realize it since it didn't show in the UI).
Outlook.MAPIFolder defaultContactsFolder =
this.Application.GetNamespace("MAPI").GetDefaultFolder(
Outlook.OlDefaultFolders.olFolderContacts);
defaultContactsFolder.Folders["My AB"].Delete();
I also tried the following code to make sure it's not something with my choice of library.
Outlook.Folder defaultContactsFolder =
this.Application.Session.GetDefaultFolder(
Outlook.OlDefaultFolders.olFolderContacts) as Outlook.Folder;
Outlook.Folders contactFolders = defaultContactsFolder.Folders;
if (contactFolders.Cast<Outlook.Folder>().Where(
element => element.Name == _CrmkAddressBookName).Count() > 0)
contactFolders["My AB"].Delete();
In each case, the Delete is executed but results in merely hiding the address book from the user interface. I want the stupid thing gone for good!
How can I really remove a folder with an address book?
I've done a mistake like that but with a different entity, although still in Outlook. The recommendation I've got was simply to ignore the issue. The Deleted directory was full of items with the same name and the user was chacked when they discovered it.
My solution, mostly to calm down the customer, was to rename the fields I knew that the end-user usually checked and add the text "Safely stored by Outlook maintnance". Then the user was happy.
As far my knowledge streches, though, the short answer to your question is "sorry, you can't".
The long answer brings us to the option of removing the account and creating a new one but it wouldn't surprise me if all the stuff then re-appeared all over again. :)
Related
I have a situation wherein a List object is built off of values pulled from a MSSQL database. However, this particular table is mysteriously getting an errant record or two tossed in. Removing the records cause trouble even though they have no referential links to any other tables, and will still get recreated without any known user actions taken. This causes some trouble as it puts unwanted values on display that add a little bit of confusion. The specific issue is that this is a platform that allows users to run a search for quotes, and the filtering allows for sales rep selection. The select/dropdown field is showing these errant values, and they need to be removed.
Given that deleting the offending table rows does not provide a desirable result, I was thinking that maybe the best course of action was to modify the code where the List object is created and either filter the values out or remove them after the object is populated. I'd like to do this in a clean, scalible fashion by providing some kind of appendable data object where I could just add in a new string value if something else cropped up as opposed to doing something clunky that adds new code to find the value and remove it each time.
My thought was to create a string array, and somehow loop through that to remove bad List values, but I wasn't entirely certain that was the best way to approach this, and I could not for the life of me think of a clean approach for this. I would think that the best way would be to add a filter within the Find arguments, but I don't know how to add in an array or list that way. Otherwise I figured to loop through the values either before or after the sorting of the List and remove any matches that way, but I wasn't sure that was the best choice of actions.
I have attached the current code, and would appreciate any suggestions.
int licenseeID = Helper.GetLicenseeIdByLicenseeShortName(Membership.ApplicationName);
List<User> listUsers;
if (Roles.IsUserInRole("Admin"))
{
//get all users
listUsers = User.Find(x => x.LicenseeID == licenseeID).ToList();
}
else
{
//get only the current user
listUsers = User.Find(x => (x.LicenseeID == licenseeID && x.EmailAddress == Membership.GetUser().Email)).ToList();
}
listUsers.Sort((x, y) => string.Compare(x.FirstName, y.FirstName));
-- EDIT --
I neglected to mention that I did not develop this, I merely inherited its maintenance after the original developer(s) disappeared, and my coworker who was assigned to it left the company. I'm not really really skilled at handling ASP.NET sites. Many object sources are hidden and unavailable for edit, I assume due to them being defined in a DLL somewhere. So, for any of these objects that are sourced from database tables, altering the tables will not help, since I would not be able to get the new data anyway.
However, I did try to do the following to filter out the undersirable data:
List<String> exclude = new List<String>(new String[] { "value1" , "value2" });
listUsers = User.Find(x => x.LicenseeID == licenseeID && !exclude.Contains(x.FirstName)).ToList();
Unfortunately it only resulted in an error being displayed to the page.
-- EDIT #2 --
I got the server setup to accept a new event viewer source so I could write info to the Application log to see what was happening. Looks like this installation of ASP.NET does not accept "Contains" as an action on a List object. An error gets kicked out stating that the method is not available.
I will probably add a bit to the table and flag Errant rows and then skip them when I query the table, something like
&& !ErrantData
Other way, that requires a bit more upkeep but doesn't require db change, would be to keep a text file that gets periodically updated and you read it and remove users from list based on it.
The bigger issue is unknown rows creeping in your database. Changing user credentials and adding creation timestamps may help you narrow down the search scope.
I'm executing my query and it works fine when I'm using the following ColumnSet.
...
ColumnSet = new ColumnSet(
"name",
"address1_postalcode",
"beep_cin",
"telephone1",
//"address1_street1",
"address1_city"),
...
However, when I uncomment the street reference, I get an error telling me that such an attribute doesn't exist. I'm guessing it's got to do with the control being composite.
How can I access in CRM 2013 the equivalent of address1_street1 in CRM 2011?
Why can I access the other address_... fields like I'm used to but not street1?
Edit
I discovered also that even on the client, using JavaScript, there seems to be something weird. Let's try to run the following two lines (frames[0] is there because that's how it works in IE console window, F12).
frames[0].Xrm.Page.getAttribute("address1_street1").getValue()
frames[0].Xrm.Page.getAttribute("address1_city").getValue()
While the first one gives me Stockholm, the seconds yields an error because the returned attribute is null, despite the fact that I've entered the street as supposed to. Furthermore, I notice that the following line:
frames[0].Xrm.Page.getAttribute("address1_composite").getValue()
returns the whole composite address text - street, city, country etc. In that attribute, there's an object called controls but I didn't find anything useful in it. This is weird and unexpected. I don't like the combination of weirdness and unexpectedness.
Please note that it's the CRM13 version that the weirdification occurs in.
Of course, I could use this atrocity below but is that really what we want to see on the screen of every CRM developer?! It makes my eyes bleed and my will to live withers.
Xrm.Page.getControl("address1_composite_compositionLinkControl_address1_line1")
Besides, I still don't get the value and I still can't see how to use it in C#!
I don't know which entity you want to retrieve, but normally the logical name for Address 1: Street1 field is address1_line1
Here the Attribute Metadata for Account entity:
http://msdn.microsoft.com/en-us/library/gg328057(v=crm.5).aspx#bkmk_attributes
I recently posted a question about saving an email once it's sent - I have just about everything working, except for one small detail. Basically, I am able to catch an email right before it sends, and do whatever I want with it - in my case, save it. However, if you try to access that email's CreationTime attribute, it returns January 1st 4501 at 12AM. This is most likely because it hasn't actually been 'created' yet, in that it will be created in the Sent items folder as soon as my code finishes executing and it actually sends.
I'd like to leave this MailItem, which is about to be sent, untouched. I would like to duplicate it, change the CreationTime attribute of the duplicate to DateTime.Now, then save the duplicate, then allow Outlook to continue sending the original. However, when I attempt to modify the CreationTime, I get an error that that attribute is read-only. Is there any way to 'break into' it? Or any way to force a write or something?
A better approach is attaching to the sent items Folder.ItemAdd so you can save messages after they have been sent instead of before - that way your MailItem.CreationTime should be accurate. This may or may not be an option for you but could alleviate the issue.
Outlook.Folder sentItems = ThisAddIn.Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderSentMail) as Outlook.Folder;
sentItems.Items.ItemAdd += new Outlook.ItemsEvents_ItemAddEventHandler(sentItems_ItemAdd);
// ...
void sentItems_ItemAdd(object Item)
{
var msg = Item as Outlook.MailItem;
msg.SaveAs(yourPath, Outlook.OlSaveAsType.olMSG);
}
Note: You need to handle proper COM resource disposal and error handling.
Okay, this is a little hard to explain, as the title might suggest.
I have an event receiver on ItemUpdated and ItemCheckedIn, which both writes custom SPAuditEntries. When CheckedIn occurs though - it comes with two update entries as well (one for added file, and one for a simple update to the list item I suspect).
I'd love to get rid of these entries. At first I thought it would be really simple, just put an if in the itemUpdated event receiver, and stop everything
if(SPListItem.CheckedOut = false) { //... do nothing }
However I couldn't find any way to ascertain the checkout-status of the listitem.
My next thinking was, they hit almost at exactly the same time, so I could just crawl into the auditCollection, filter down to the specific listitem, user, and time (minus a second) and delete the two entries. But, sadly I found out I couldn't delete auditentries.
Anyone got any ideas?
Checked out status is determined via:
if (item.Level == SPFileLevel.Checkout) {
where item is an SPListItem
-Oisin
I have a Nsf file in which in one of folder there are some mail and notes items.
I am differentiating each item with "form" property.
In case of mails form type is "memo" but in above scenario Notes "form" type is again "memo"
How can i differentiate these two items?
thanx
Using the "form" item is not a safe way to distinguish emails from other "documents". In fact, a Notes data store does not really distinguish where a document came from - whether from a delivered email or a created document. However, you can use the fields RouteTimes and RouteServers to take a pretty good guess as to whether a given document was initiated from an email message. (The existence of either field will generally mean the document was delivered by the mail router).
If you want to compare the fields, I think the best way is to compare $ fields because they are usually reserved for internal use and should not be updated without a good reason. Therefore they are the most accurate fields of a form.
Check $MessageID, $MIMETrack or $UpdatedBy. This last one should be used with care but it should contains the mail server(s) if it is a mail.
In LN you can mock a the mail template in a note. So there is no sure way to distinguish a note from a mail UNLESS you know how the notes were created and use that info to build a test based on specific conditions. If you can control the note creation, I suggest to use a specific form to be able to distinguish each record type.
Of course you can check the properties (fields and values) of your notes and build a test "heuristically" (meaning rule-of-thumb)