Not able to delete emails from Outlook at first shot - c#

I built a console application in Visual Studio with C#. I have a configuration file (app.config) with a lot of keys in order to identify the email I want to delete.
My issue is that even if the delete works if I have 10 unread emails to Delete, I need to run the application a few times in order to be able to do that. I am not getting any error.
It looks like there is a kind of timeout, so the application deletes the first 3 emails, leaving untouched the rest, then I run the application again and it removes the next 3 or 4 emails and then over and over until I get everything deleted.
Am I doing something wrong? Following my code, it connects to Outlook and our mail server is Microsoft Exchange.
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using Microsoft.Office.Interop.Outlook;
using Exception = System.Exception;
namespace OutlookReader
{
class Program
{
static void Main()
{
try
{
var outlookApplication = new ApplicationClass();
var mapiNameSpace = outlookApplication.GetNamespace("MAPI");
//Inbox
var inbox = mapiNameSpace.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
//Unread emails
var unreadItems = inbox.Items.Restrict("[Unread]=true");
var splitter = char.Parse(ConfigurationManager.AppSettings["splitter"]);
var excludeBySenderName = ConfigurationManager.AppSettings["ExcludeBySenderName"].Split(splitter).ToList();
var excludeByEmail = ConfigurationManager.AppSettings["ExcludeByEmail"].Split(splitter).ToList();
var excludeByDomain = ConfigurationManager.AppSettings["ExcludeByDomain"].Split(splitter).ToList();
var excludeByTo = ConfigurationManager.AppSettings["ExcludeByTo"].Split(splitter).ToList();
var excludeBySubject = ConfigurationManager.AppSettings["ExcludeBySubject"].Split(splitter).ToList();
foreach (MailItem item in unreadItems)
{
Console.WriteLine("Sender: " + item.SenderName + " - To: " + item.To + " - Subject: " + item.Subject);
if (stringExists(item.SenderName, excludeBySenderName)
|| stringExists(item.SenderEmailAddress, excludeByEmail)
|| stringExists(item.SenderEmailAddress, excludeByDomain)
|| stringExists(item.To, excludeByTo)
|| stringExistsFullSearch(item.Body, excludeByDomain)
|| stringExistsFullSearch(item.HTMLBody, excludeByDomain)
|| stringExistsFullSearch(item.Subject, excludeBySubject))
{
//item.UnRead = false;
item.Delete();
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadKey();
}
private static bool stringExists(string pattern, List<string> list)
{
var result = list.Find(item => item.ToLower().Contains(pattern.ToLower()));
if (string.IsNullOrWhiteSpace(result))
{
return false;
}
return true;
}
private static bool stringExistsFullSearch(string pattern, List<string> list)
{
var result = false;
foreach (var item in list)
{
if (pattern.ToLower().Contains(item.ToLower()))
{
result = true;
}
}
return result;
}
}
}

You are modifying the collection while you are iterating through its elements. Loop through the restricted items colelction and store the entry ids (MailItem.EntryID) in a list. You can then loop through the stings in that list, open each item using Namespace.GetItemFromID, then delete the message using MailItem.Delete.

Related

how to get all the Users along with Team Iteration of a project of TFS WIQL?

i want to get all the users with there Iteration in a project.
Lets say Project 'Precient' has 9 distinct users with 20 iteration so i want distinct users with all the Iteration in the project WIQL C#.it's related to the Question.
WIQL query to get all the team and the users in a Project?
but does not help me fully
You may get that through REST API or Net API. This is sample for Net API.
You may get all users from group "Project Valid Users"
You may get all Iterations from Project root Iterations.
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Microsoft.TeamFoundation.Server;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using System;
using System.Collections.Generic;
namespace GetUserÑ–AndItearions
{
class Program
{
public class Iteration
{
public string Path;
public DateTime DateFrom;
public DateTime DateTo;
}
static void Main(string[] args)
{
string _teamProject = "Your_Project_Name";
try
{
TfsTeamProjectCollection _tpc = new TfsTeamProjectCollection(new Uri("http://your_server:8080/tfs/DefaultCollection"));
GetAllUsers(_tpc, _teamProject);
GetAllIterations(_tpc, _teamProject);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
Console.WriteLine(ex.StackTrace);
}
}
private static void GetAllIterations(TfsTeamProjectCollection pTpc, string pProjectName)
{
List<Iteration> _its = new List<Iteration>();
WorkItemStore _wistore = pTpc.GetService<WorkItemStore>();
var _css = pTpc.GetService<ICommonStructureService4>();
foreach (Node _node in _wistore.Projects[pProjectName].IterationRootNodes)
FillIterations(_css, _node, _its);
Console.WriteLine("Iterations:");
foreach (Iteration _it in _its) Console.WriteLine("{0}:{1}-{2}", _it.Path,
(_it.DateFrom == DateTime.MinValue) ? "0" : _it.DateFrom.ToShortDateString(), (_it.DateTo== DateTime.MinValue) ? "0" : _it.DateTo.ToShortDateString());
}
private static void FillIterations(ICommonStructureService4 pCss, Node pNode, List<Iteration> pIts)
{
var _nodeInfo = pCss.GetNode(pNode.Uri.AbsoluteUri);
pIts.Add(new Iteration { Path = _nodeInfo.Path,
DateFrom = (_nodeInfo.StartDate == null) ? DateTime.MinValue : (DateTime)_nodeInfo.StartDate,
DateTo = (_nodeInfo.FinishDate == null) ? DateTime.MinValue : (DateTime)_nodeInfo.FinishDate });
if (pNode.HasChildNodes)
foreach (Node _node in pNode.ChildNodes)
FillIterations(pCss, _node, pIts);
}
private static void GetAllUsers(TfsTeamProjectCollection pTpc, string pProjectName)
{
List<string> listUsers = new List<string>();
WorkItemStore _wistore = pTpc.GetService<WorkItemStore>();
var _gss = pTpc.GetService<IIdentityManagementService>();
var _teamProject = _wistore.Projects[pProjectName];
string _validGroupName = "[" + pProjectName + "]\\Project Valid Users";
TeamFoundationIdentity _group = _gss.ReadIdentity(IdentitySearchFactor.DisplayName, _validGroupName, MembershipQuery.Expanded, ReadIdentityOptions.ExtendedProperties);
List<string> _memebersIds = new List<string>();
foreach (var _member in _group.Members) _memebersIds.Add(_member.Identifier);
var _members = _gss.ReadIdentities(IdentitySearchFactor.Identifier, _memebersIds.ToArray(), MembershipQuery.Expanded, ReadIdentityOptions.ExtendedProperties);
foreach (var _member in _members) if (!_member[0].IsContainer) listUsers.Add(_member[0].DisplayName);
Console.WriteLine("Users:");
foreach (var _user in listUsers) Console.WriteLine("{0}", _user);
}
}
}
It's not able to get users from Team via WIQL. WIQL is a work item query language which used to query for bugs, tasks, other types of work items. The return value should be work item.
You need use api as #Shamray provided to retrieve the users. The following blog also provided an example:
http://blogs.microsoft.co.il/shair/2012/05/20/tfs-api-part-44-vs11-teams-and-team-members/

WIQL query to get all the team and the users in a Project?

let's say i have a project name ="Scrum" and that has some users the project and got sprints so **i want dstinct users of the Project that the Sprints in Scrum **. image attached.
You can use also this code for teams:
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Microsoft.TeamFoundation.ProcessConfiguration.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using System;
using System.Collections.Generic;
using System.Linq;
namespace QueryLinkedWIQL
{
class Program
{
static List<TeamFoundationTeam> ListTeams(TfsTeamProjectCollection pTpc, Project pProject)
{
TfsTeamService _teamService = pTpc.GetService<TfsTeamService>();
var _teams = _teamService.QueryTeams(pProject.Uri.ToString());
return (from t in _teams select t).ToList();
}
static bool GetTeamsSettings(TfsTeamProjectCollection pTpc, TeamFoundationTeam pTeam)
{
try
{
var _teamConfig = pTpc.GetService<TeamSettingsConfigurationService>();
var _configs = _teamConfig.GetTeamConfigurations(new Guid[] { pTeam.Identity.TeamFoundationId });
Console.WriteLine("============={0}==================", pTeam.Name);
Console.WriteLine("Team Members: ");
foreach (var _member in pTeam.GetMembers(pTpc, MembershipQuery.Expanded))
Console.WriteLine("Display Name: " + _member.DisplayName + " || Is active: " + _member.IsActive);
foreach( var _config in _configs)
{
Console.WriteLine("Team current iteration: " + _config.TeamSettings.CurrentIterationPath);
Console.WriteLine("Team selected iterations:");
foreach (var _iteration in _config.TeamSettings.IterationPaths)
Console.WriteLine(_iteration);
Console.WriteLine("Team selected areas:");
foreach (var _area in _config.TeamSettings.TeamFieldValues)
Console.WriteLine("Area path: " + _area.Value + " || Include children: " + _area.IncludeChildren.ToString());
}
Console.WriteLine("===============================");
}
catch (Exception)
{
return false;
}
return true;
}
static void Main(string[] args)
{
string _teamProject = "YourProjectName";
try
{
TfsTeamProjectCollection _tpc = new TfsTeamProjectCollection(new Uri("http://yourserver/DefaultCollection"));
WorkItemStore _wistore = _tpc.GetService<WorkItemStore>();
var _teams = ListTeams(_tpc, _wistore.Projects[_teamProject]);
foreach (var _team in _teams) GetTeamsSettings(_tpc, _team);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
Console.WriteLine(ex.StackTrace);
}
}
}
}
According to your description, seems you want to get all teams (include all users in the team) and corresponding sprint for each team.
It's not able to do this through WIQL. WIQL is a work item query language which used to query for bugs, tasks, other types of work items. The return value should be work item.
Instead, you could use Rest API to achieve your requirement.
1.First, Get a list of teams in a project.
GET https://fabrikam-fiber-inc.visualstudio.com/DefaultCollection/_apis/projects/eb6e4656-77fc-42a1-9181-4c6d8e9da5d1/teams?api-version=2.2
2.Get a team's members
GET https://fabrikam-fiber-inc.visualstudio.com/DefaultCollection/_apis/projects/eb6e4656-77fc-42a1-9181-4c6d8e9da5d1/teams/564e8204-a90b-4432-883b-d4363c6125ca/members/?api-version=2.2
3.Get a team's iterations
GET https://{instance}/DefaultCollection/{project}/{team}/_apis/work/TeamSettings/Iterations?[$timeframe=current&]api-version={version}
Combine with the above Rest APIs, you could be able to achieve this get teams name with there Sprints in Scrum project and all users of the team.

"RPC Server is unavailable" when exporting Outlook contacts to CSV

I am exporting Outlook contacts with a custom form to CSV from a specific Contacts folder. This folder is not the default location. It is a large folder with almost 7,000 contacts. This is a shared mailbox in Office 365, but we can't use the Outlook or Graph APIs because of the custom data.
My code below works fine, except that after iterating through 200-800 contacts, I get this error: "RPC Server is unavailable. (Exception from HRESULT: 0x800706BA)."
I also tried exporting the folder to a .pst and accessing that folder on my local machine. The result is essentially the same. UPDATE: I've been watching Outlook.exe in the task manager, and it steadily increases its memory consumption to around 300MB before crashing. I've tried the same code on a laptop running Office 2010, and I get an "Out of Memory" error.
I get the error whether Outlook is open or closed, but closing Outlook during program operation will immediately trigger this error. Outlook either starts (or restarts) following this error. I've read a number of SO posts and articles related to this error, but I'm not sure exactly what's going on. Any help is appreciated.
UPDATE: Code has been updated to use for loops instead of foreach loops per Dmitry Streblechenko's suggestion.
using System;
using Microsoft.Office.Interop.Outlook;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
namespace OutlookContacts
{
class Program
{
static void Main(string[] args)
{
var encoding = Encoding.UTF8;
string csvPath = #"myCSVPath";
Application outlook = new Application();
NameSpace ns = outlook.GetNamespace("MAPI");
MAPIFolder sharedContacts;
string recipientName = "myEmail#myDomain";
StringBuilder headerRow = new StringBuilder();
Recipient recip = ns.CreateRecipient(recipientName);
StreamWriter writer = new StreamWriter(csvPath, false, encoding);
recip.Resolve();
if (recip.Resolved)
{
try
{
//EntryID and StoreID of my folder
sharedContacts =
ns.GetFolderFromID(
"myEntryID",
"myStoreID"
);
Items contacts = sharedContacts.Items;
//Writing header row
ContactItem first = contacts.GetFirst();
var properties = first.ItemProperties;
for(int i = 0; i < properties.Count; i++)
{
try
{
headerRow.Append(string.Format("\"{0}\",", properties[i].Name));
}
catch (System.Exception ex)
{
headerRow.Append(string.Format("{0},", ex.Message));
}
}
headerRow.AppendLine(Environment.NewLine);
WriteToCSV(writer, headerRow);
Console.WriteLine("Header row written;");
Marshal.ReleaseComObject(properties);
Marshal.ReleaseComObject(first);
//Writing Records
for (int i = 1; i <= contacts.Count; i++)
{
object o = contacts[i];
if (o is ContactItem)
{
ContactItem contact = (ContactItem)o;
if (contact != null)
{
Console.Write(contact.FullName);
StringBuilder dataRow = new StringBuilder();
ItemProperties contactProps = contact.ItemProperties;
for (int j = 0; j < contactProps.Count; j++)
{
ItemProperty property = contactProps[j];
try
{
if (property.Value == null)
{
string value = "null,";
dataRow.Append(value);
}
//else if (property.Name == "Attachments")
//{
// //Attachment file names
// string attachment = "";
// for (int k = 1; k < contact.Attachments.Count; k++)
// {
// attachment = (string.Format("\"{0}\"; ", contact.Attachments[k].FileName));
// dataRow.Append(attachment);
// }
// dataRow.Append(",");
//}
else
{
string value = property.Value.ToString();
value = value.Replace("\r\n\r\n\r\n", "\r\n")
.Replace("\r\n\r\n", "\r\n")
.Replace("\"", "'");
value = (string.Format("\"{0}\",", value));
dataRow.Append(value);
}
}
catch (System.Exception ex)
{
string value = string.Format("{0}: {1},", property.Name, ex.Message);
dataRow.Append(value);
}
Marshal.ReleaseComObject(property);
}
dataRow.Append(Environment.NewLine);
WriteToCSV(writer, dataRow);
Marshal.ReleaseComObject(contactProps);
Marshal.ReleaseComObject(contact);
}
Marshal.ReleaseComObject(o);
counter++;
Console.WriteLine(": Written " + counter);
}
}
}
catch (System.Exception ex)
{
Console.WriteLine(dataRow.ToString(), ex.Message);
Console.ReadKey();
}
}
}
static void WriteToCSV(StreamWriter writer, StringBuilder row)
{
var data = row.ToString();
writer.WriteAsync(data);
}
}
}
Looks like you are running out of RPC channels. You need to avoid using foreach loops (they tend to keep all collection members referenced until the loop exits) and explicitly release all COM objects are soon as you are done with them.
Off the top of my head:
for(int i = 1; i <= contacts.Count; i++)
{
obejct o = contacts[i];
ContactItem contact = o as ContactItem;
if (o != null)
{
ItemProperties properties = contact.ItemProperties;
StringBuilder newLine = new StringBuilder();
for (int j = 1; j <= properties.Count; j++)
{
ItemProperty property = properties[j];
var value = "";
if (property.Value == null)
{
value = "null,";
Console.WriteLine(value);
newLine.Append(value);
}
else
{
value = property.Value.ToString() + ",";
newLine.Append(value);
}
Marshal.ReleaseComObject(property);
}
newLine.Append(Environment.NewLine);
WriteToCSV(writer, newLine);
Marshal.ReleaseComObject(properties);
Marshal.ReleaseComObject(contact);
}
Marshal.ReleaseComObject(o);
}

ClrMD could not attach to process on production server

I am trying to use ClrMD to dump the stacktrace of all threads running within a specific process. The code works fine in my devlopment enviornment but not on the production server.
The server is running: Windows Server 2012 R2 Standard
The error I recieve is:
Could not attach to process. Error 0.
This post asks how to attach ClrMD to another users process, which was what I was trying to do. I terminated the process (which is running as a windows service) and started it as the same user that I am trying to execute ClrMD with. I still get the error.
Tried giving the user debugging privlidges but that didnt help either.
I bet the problem has something to do with how to production server is configured. I have administrator rights.
Any suggestions on what to do next?
Code:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.Diagnostics.Runtime;
namespace ConsoleApplication4
{
class Program
{
static void Main(string[] args)
{
int pid = 0;
var result = new Dictionary<int, string[]>();
var targetProcessName = "Dist.TingbogScraper.Business.TingbogScraperService.vshost";
// Change this to the process you are looking for
var outputPath = "C:\\temp\\ClrMDresult.txt";
var exceptionOutput = "C:\\temp\\ClrMDdump.txt";
var processes = Process.GetProcesses();
foreach (var process in processes)
{
if (process.ProcessName.Contains(targetProcessName))
{
pid = process.Id;
}
}
try
{
using (var dataTarget = DataTarget.AttachToProcess(pid, 5000, AttachFlag.Passive))
{
ClrRuntime runtime = dataTarget.ClrVersions.First().CreateRuntime();
foreach (var t in runtime.Threads)
{
try
{
if (t.StackTrace != null)
{
result.Add(
t.ManagedThreadId,
t.StackTrace.Select(f =>
{
if (f.Method != null)
{
return f.Method.Type.Name + "." + f.Method.Name;
}
return null;
}).ToArray()
);
}
}
catch (Exception ex)
{
}
}
}
foreach (var kvp in result)
{
var value = kvp.Value;
foreach (var stacktrace in value)
{
System.IO.File.AppendAllText(outputPath,
string.Format("{0} {1} {2}", kvp.Key, stacktrace, Environment.NewLine));
}
}
}
catch (ClrDiagnosticsException ex)
{
System.IO.File.AppendAllText(outputPath,
string.Format("{0} {1} {2}", ex.Message, ex.StackTrace, ex.Source));
}
}
}
}
Found out that the name of the process was different on my development environment compared to production.
Correcting the name of the process fixed the error.

RallyDev - Getting Tasks for Stories using Rally.RestAPI.dll and Service V2.0

I'm pulling data off the Rally server at https://rally1.rallydev.com using C# and the Rally.RestAPI.dll. The server was recently upgraded to webservice v2.0 and I'm having some problems getting tasks for a user story. I know the way child collections are presented were changed in the API with the move to 2.0, but what I'm trying isn't working.
v2.0 removed the ability to return child collections in the same
response for performance reasons. Now fetching a collection will return
an object with the count and the url from which to get the collection
data.A separate request is needed to get to the elements of the
collection.
Here is the code that iterates over user story results, accesses "Tasks" collection on stories and issues a separate request to access individual Task attributes:
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using Rally.RestApi;
using Rally.RestApi.Response;
namespace aRestApp_CollectionOfTasks
{
class Program
{
static void Main(string[] args)
{
//Initialize the REST API
RallyRestApi restApi;
restApi = new RallyRestApi("user#co.com", "secret", "https://rally1.rallydev.com", "v2.0");
//Set our Workspace and Project scopings
String workspaceRef = "/workspace/11111"; //please replace this OID with an OID of your workspace
String projectRef = "/project/22222"; //please replace this OID with an OID of your project
bool projectScopingUp = false;
bool projectScopingDown = true;
Request storyRequest = new Request("HierarchicalRequirement");
storyRequest.Workspace = workspaceRef;
storyRequest.Project = projectRef;
storyRequest.ProjectScopeUp = projectScopingUp;
storyRequest.ProjectScopeDown = projectScopingDown;
storyRequest.Fetch = new List<string>()
{
"Name",
"FormattedID",
"Tasks",
"Estimate"
};
storyRequest.Query = new Query("LastUpdateDate", Query.Operator.GreaterThan, "2013-08-01");
QueryResult queryStoryResults = restApi.Query(storyRequest);
foreach (var s in queryStoryResults.Results)
{
Console.WriteLine("----------");
Console.WriteLine("FormattedID: " + s["FormattedID"] + " Name: " + s["Name"]);
//Console.WriteLine("Tasks ref: " + s["Tasks"]._ref);
Request taskRequest = new Request(s["Tasks"]);
QueryResult queryTaskResult = restApi.Query(taskRequest);
if (queryTaskResult.TotalResultCount > 0)
{
foreach (var t in queryTaskResult.Results)
{
var taskEstimate = t["Estimate"];
var taskName = t["Name"];
Console.WriteLine("Task Name: " + taskName + " Estimate: " + taskEstimate);
}
}
else
{
Console.WriteLine("no tasks found");
}
}
}
}
}

Categories

Resources