ProcessEvent not called in TFS plugin - c#

Recently i have decided to create a plugin for the TFS for tracking work item changes based on ISubscriber interface.
So the workflow would be the following:
1) Work item state changes
2) Plugin catches the WorkItemChangedEvent
3) Send an email to the person specified in the Requester
As the base for my project, i used the following project from CodePlex - The Mail Alert
After i adopted it to my needs and saved compiled binaries in %TFS-DIR%\Microsoft Team Foundation Server 14.0\Application Tier\Web Services\bin\Plugins the TFS restarted the tier and... that's it. On work item change the ProcessEvent method is not called, but it should be.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Common;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Microsoft.TeamFoundation.Framework.Server;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Server;
using System.Diagnostics;
using System.Xml.Linq;
using System.Xml;
using System.DirectoryServices;
using System.Net.Mail;
using System.Xml.Xsl;
using System.Configuration;
using System.Reflection;
namespace MailAlert
{
public class WorkItemChangedEventHandler : ISubscriber
{
static string serverPath = "";
static string ExternalURL = "";
static string MailAddressFrom = "";
static string SMTPHost = "";
static string Password = "";
static int Port = 25;
static int index = 0;
static string projectCollectionFolder;
static Uri projectCollectionUri;
static WorkItemStore wiStore;
static WorkItem wItem;
static WorkItemChangedEvent workItemChangedEvent;
static string teamProjectPath = "";
static VersionControlServer versionControlServer;
static TfsTeamProjectCollection projectCollection;
static Dictionary<IdentityDescriptor, TeamFoundationIdentity> m_identities = new Dictionary<IdentityDescriptor, TeamFoundationIdentity>(IdentityDescriptorComparer.Instance);
public Type[] SubscribedTypes()
{
return new Type[1] { typeof(WorkItemChangedEvent) };
}
public WorkItemChangedEventHandler()
{
TeamFoundationApplicationCore.Log("WorkItemChangedEvent Started", index++, EventLogEntryType.Information);
}
public EventNotificationStatus ProcessEvent(TeamFoundationRequestContext requestContext, NotificationType notificationType,
object notificationEventArgs, out int statusCode, out string statusMessage, out ExceptionPropertyCollection properties)
{
TeamFoundationApplicationCore.Log("WorkItemChangedEventHandler: ProcessEvent entered", index++, EventLogEntryType.Information);
statusCode = 0;
properties = null;
statusMessage = String.Empty;
GetTfsServerName();
projectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(TfsTeamProjectCollection.GetFullyQualifiedUriForName(serverPath));
try
{
if (notificationType == NotificationType.Notification && notificationEventArgs is WorkItemChangedEvent)
{
workItemChangedEvent = notificationEventArgs as WorkItemChangedEvent;
TeamFoundationApplicationCore.Log("WorkItemChangedEventHandler: WorkItem " + workItemChangedEvent.WorkItemTitle + " was modified", index++, EventLogEntryType.Information);
TeamFoundationApplicationCore.Log("WorkItemChangedEventHandler: serverPath - " + serverPath, index++, EventLogEntryType.Information);
projectCollectionFolder = requestContext.ServiceHost.VirtualDirectory.ToString();
projectCollectionUri = new Uri(serverPath + projectCollectionFolder);
projectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(projectCollectionUri);
wiStore = projectCollection.GetService<WorkItemStore>();
versionControlServer = projectCollection.GetService<VersionControlServer>();
TeamFoundationApplicationCore.Log("WorkItemChangedEventHandler: Before process workitem", index++, EventLogEntryType.Information);
ProcessWorkItem();
TeamFoundationApplicationCore.Log("WorkItemChangedEventHandler: After process workitem", index++, EventLogEntryType.Information);
}
}
catch (Exception ex)
{
TeamFoundationApplicationCore.Log("WorkItemChangedEventHandler: FUCKING EXCEPTION! =>\n" + ex.Message, index++, EventLogEntryType.Error);
}
return EventNotificationStatus.ActionPermitted;
}
private static void GetTfsServerName()
{
try
{
string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);
XmlDocument XmlDoc = new XmlDocument();
XmlDoc.Load(assemblyFolder + #"\Settings.xml");
// Declare the xpath for finding objects inside the XML file
XmlNodeList XmlDocNodes = XmlDoc.SelectNodes("/configuration/tfssettings");
XmlNodeList XmlDocExt = XmlDoc.SelectNodes("/configuration/Externaltfssettings");
// Define a new List, to store the objects we pull out of the XML
serverPath = XmlDocNodes[0].InnerText;
ExternalURL = XmlDocExt[0].InnerText;
XmlNodeList XmlDocNodes2 = XmlDoc.SelectNodes("/configuration/appSettings");
foreach (XmlNode mailNode in XmlDocNodes2)
{
foreach (XmlNode varElement in mailNode.ChildNodes)
{
switch (varElement.Attributes["key"].Value)
{
case "MailAddressFrom":
MailAddressFrom = varElement.Attributes["value"].Value;
break;
case "SMTPHost":
SMTPHost = varElement.Attributes["value"].Value;
break;
case "Password":
Password = varElement.Attributes["value"].Value;
break;
case "Port":
Port = Convert.ToInt32(varElement.Attributes["value"].Value);
break;
}
}
}
}
catch (Exception ex)
{
EventLog.WriteEntry("WorkItemChangedEventHandler", ex.Message);
}
}
public string Name
{
get { return "WorkItemChangedEventHandler"; }
}
public SubscriberPriority Priority
{
get { return SubscriberPriority.High; }
}
private static void ProcessWorkItem()
{
var teamProjects = versionControlServer.GetAllTeamProjects(false);
for (int i = 0; i < teamProjects.Length; i++)
{
string teamProjectName = teamProjects[i].Name;
var teamProject = teamProjects[i];
Project teamProjectWI = wiStore.Projects[i];
teamProjectPath = projectCollectionUri + teamProject.Name;
if (workItemChangedEvent.PortfolioProject == teamProjectName)
{
//get the workitem by ID ( CoreFields.IntegerFields[0] == ID ?!)
//check if any of String changed fields
foreach(StringField sf in workItemChangedEvent.ChangedFields.StringFields)
{
//is the State field
if (sf.Name.Equals("State"))
{
//then notify Reuqester
wItem = wiStore.GetWorkItem(workItemChangedEvent.CoreFields.IntegerFields[0].NewValue);
string CollGuid = projectCollection.InstanceId.ToString();
string Requester = wItem.Fields["Requester"].Value.ToString();
string WorkItemId = wItem.Id.ToString();
string mail = GetEmailAddress(Requester);
SendMail(CollGuid, WorkItemId, mail);
}
}
}
}
}
private static string GetEmailAddress(string userDisplayName)
{
DirectorySearcher ds = new DirectorySearcher();
ds.PropertiesToLoad.Add("mail");
ds.Filter = String.Format("(&(displayName={0})(objectCategory=person)((objectClass=user)))", userDisplayName);
SearchResultCollection results = ds.FindAll();
if (results.Count == 0)
{
return string.Empty;
}
ResultPropertyValueCollection values = results[0].Properties["mail"];
if (values.Count == 0)
{
return string.Empty;
}
return values[0].ToString();
}
private static void SendMail(string collID,string workItemId,string tomailAddrees)
{
MailMessage objeto_mail = new MailMessage();
SmtpClient client = new SmtpClient();
client.Port = Port;
client.Host = SMTPHost;
client.Timeout = 200000;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = true;
client.EnableSsl = true;
client.Credentials = new System.Net.NetworkCredential(MailAddressFrom, Password);
objeto_mail.From = new MailAddress(MailAddressFrom);
objeto_mail.To.Add(new MailAddress(tomailAddrees));
//objeto_mail.CC.Add(new MailAddress("nagarajb#hotmail.com"));
objeto_mail.Subject = "Work Item Changed:"+workItemId;
string mailbody = serverPath+"/tfs/web/wi.aspx?pcguid=" + collID + "&id=" + workItemId;
string mailbody2 = "";
if (ExternalURL.Length > 0)
{
mailbody2 = ExternalURL + "/tfs/web/wi.aspx?pcguid=" + collID + "&id=" + workItemId;
}
string tables = "<table border=1><tr><td>Work Item ID</td><td>" + wItem.Id.ToString() + "</td></tr><tr><td>Title</td><td>" + wItem.Title + "</td></tr><tr><td>State</td><td>" + wItem.State + "</td></tr><tr><td>Assigned To</td><td>" + wItem.Fields["Assigned to"].Value.ToString() + "</td></tr><tr><td>Internal URL</td><td>" + mailbody + "</td></tr><tr><td>External URL</td><td>" + mailbody2 + "</td></tr></table>";
objeto_mail.IsBodyHtml = true;
objeto_mail.Body = "<i>Hi " + wItem.Fields["Requester"].Value.ToString() + ","+"</i></br></br></br>" + tables + " </br></br> Best regards; </br></br>Configuration Management Team</br></br></br>";
client.Send(objeto_mail);
EventLog.WriteEntry("WorkItemChangedEventHandler", "Email Sent");
}
}
}
No errors or exceptions are thrown in the Event Log either. Tracing TFS (trace=true property in web.config) also was of no help.
Maybe someone could help or shed light on this mysterious case?
UPDATE:
Thanks for a reply Giulio Vian!
Here how it goes:
1) I haven't seen the dependencies broken, plus the constructor WorkItemChangedEventHandler is successfully called. That is seen in the Windows Event Log - WorkItemChangedEvent Started message is written.
2) I am not sure how to register the event handler.... i'll look that up
3) I am not sure how this works. I thought just copy-pasting dlls in the appropriate folder will do the trick, and there is no need for an account for the plugin. Mind giving a bit more info on this?
4) yes. Web.config in the main Web config in Application Tier\Web Services
5) Yes. Using an account with Administer rights. if i set a break point in the constructor, it is reached. Any other place in the code is not reached.

Many things can be wrong.
If any dependency is broken, you should see an error in the Event log
If you do not register the "WorkItemChangedEventHandler" event source, no message is written
Can the user account running the plugin access TFS?
How did you enabled the tracing (you pasted a bunch of code, but no configuration)?
Have you attached the debugger to the TFS process and set a breakpoint (do not this on a production TFS)?
We have collected similar suggestions in the documentation for our plugin at
https://github.com/tfsaggregator/tfsaggregator/wiki.

Related

How to list of ports and Mac addresses to connected switch (Cisco) C#

Hello everyone I want to ask about how can list ports and mac addresses of devices connected to switch using C#.
I have found code which works for Dell switch. I need it for Cisco switch
using SnmpSharpNet;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace PortMapper
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
List<KeyValuePair<string, string>> portList = new List<KeyValuePair<string, string>>();
List<Portmap> portMaps = new List<Portmap>();
public class Portmap
{
public string Hostname { get; set; }
public string Port { get; set; }
public string IP { get; set; }
public string MAC { get; set; }
}
private void Button_Click(object sender, RoutedEventArgs e)
{
IPAddress ip = IPAddress.Parse("192.168.0.2");
IPAddress ip2 = IPAddress.Parse("192.168.0.3");
SnmpWalk(ip, "community", "1.3.6.1.2.1.17.7.1.2.2.1.2.1", "1");
SnmpWalk(ip2, "community","1.3.6.1.2.1.17.7.1.2.2.1.2.1", "2");
DhcpQuery("netsh", "dhcp server \\\\servername scope 192.168.0.0 show clients", "192");
List<Portmap> gridResults = new List<Portmap>();
//Example of filtering uplink ports from other switches
foreach(Portmap portMap in portMaps)
{
if (portMap.Port != "1/2/48" && portMap.Port != "2/1/48")
{
gridResults.Add(portMap);
}
}
PortMapGrid.ItemsSource = gridResults;
}
//Use NETSH to retrieve a list of DHCP MAC and IP addresses
private void DhcpQuery(string cmd, string args, string subnet)
{
ProcessStartInfo procStartInfo = new ProcessStartInfo();
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.FileName = cmd;
procStartInfo.Arguments = args;
procStartInfo.CreateNoWindow = true;
string output;
using (Process proc = Process.Start(procStartInfo))
{
output = proc.StandardOutput.ReadToEnd();
proc.WaitForExit();
}
//Find valid leases in command output
string[] lines = output.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
List<string> leases = new List<string>();
foreach (string line in lines)
{
if (line.StartsWith(subnet))
{
leases.Add(line);
}
}
//Create threads
Thread[] threadArray = new Thread[leases.Count];
int threadcount = 0;
//Loop each Dhcp Lease
foreach (string line in leases)
{
string[] pieces = line.Split('-');
string ipAddress = pieces[0].Trim();
string mac = "";
string hostname = "";
foreach (string piece in pieces)
{
if (piece.Trim().Length == 2)
{
mac += piece;
}
}
ThreadStart start = delegate
{
hostname = GetHost(ipAddress);
foreach (KeyValuePair<string, string> port in portList)
{
if (port.Key.ToUpper().Trim() == mac.ToUpper().Trim())
{
Portmap portMap = new Portmap();
portMap.IP = ipAddress;
portMap.MAC = mac.ToUpper();
portMap.Port = port.Value;
portMap.Hostname = hostname;
portMaps.Add(portMap);
}
}
};
threadArray[threadcount] = new Thread(start);
threadArray[threadcount].Start();
threadcount = threadcount + 1;
}
//Join all threads in the array to wait for results
for (int i = 0; i < threadcount; i++)
{
threadArray[i].Join();
}
}
//SNMPWALK the ports on a switch or stack of switches. Ports will be labeled SwitchNum/Stack Number/Port Numbers.
private void SnmpWalk(IPAddress ip, string snmpCommunity, string oid, string switchNum)
{
UdpTarget target = new UdpTarget(ip);
// SNMP community name
OctetString community = new OctetString(snmpCommunity);
// Define agent parameters class
AgentParameters param = new AgentParameters(community);
// Set SNMP version to 1
param.Version = SnmpVersion.Ver1;
// Define Oid that is the root of the MIB tree you wish to retrieve
Oid rootOid = new Oid(oid);
// This Oid represents last Oid returned by the SNMP agent
Oid lastOid = (Oid)rootOid.Clone();
// Pdu class used for all requests
Pdu pdu = new Pdu(PduType.GetNext);
// Loop through results
while (lastOid != null)
{
// When Pdu class is first constructed, RequestId is set to a random value
// that needs to be incremented on subsequent requests made using the
// same instance of the Pdu class.
if (pdu.RequestId != 0)
{
pdu.RequestId += 1;
}
// Clear Oids from the Pdu class.
pdu.VbList.Clear();
// Initialize request PDU with the last retrieved Oid
pdu.VbList.Add(lastOid);
// Make SNMP request
SnmpV1Packet result = (SnmpV1Packet)target.Request(pdu, param);
// You should catch exceptions in the Request if using in real application.
// If result is null then agent didn't reply or we couldn't parse the reply.
if (result != null)
{
// ErrorStatus other then 0 is an error returned by
// the Agent - see SnmpConstants for error definitions
if (result.Pdu.ErrorStatus != 0)
{
// agent reported an error with the request
Console.WriteLine("Error in SNMP reply. Error {0} index {1}",
result.Pdu.ErrorStatus,
result.Pdu.ErrorIndex);
lastOid = null;
break;
}
else
{
// Walk through returned variable bindings
foreach (Vb v in result.Pdu.VbList)
{
// Check that retrieved Oid is "child" of the root OID
if (rootOid.IsRootOf(v.Oid))
{
//Convert OID to MAC
string[] macs = v.Oid.ToString().Split('.');
string mac = "";
int counter = 0;
foreach (string chunk in macs)
{
if (counter >= macs.Length - 6)
{
mac += string.Format("{0:X2}", int.Parse(chunk));
}
counter += 1;
}
//Assumes a 48 port switch (52 actual). You need to know these values to correctly iterate through a stack of switches.
int dellSwitch = 1 + int.Parse(v.Value.ToString()) / 52;
int port = int.Parse(v.Value.ToString()) - (52 * (dellSwitch - 1));
KeyValuePair<string, string> Port = new KeyValuePair<string, string>(mac, switchNum + "/" + dellSwitch.ToString() + "/" + port.ToString());
portList.Add(Port);
//Exit Loop
lastOid = v.Oid;
}
else
{
//End of the requested MIB tree. Set lastOid to null and exit loop
lastOid = null;
}
}
}
}
else
{
Console.WriteLine("No response received from SNMP agent.");
}
}
target.Close();
}
private string GetHost(string ipAddress)
{
try
{
IPHostEntry entry = Dns.GetHostEntry(ipAddress);
return entry.HostName;
}
catch
{
return "";
}
}
}
}
Can Anyone is going to help me out for finding the code or give me a way that how can I convert this code to work for Cisco. what Oid it can be?

I get error 1053 at end of my C# service. How do I stop it?

I'm trying to make a service on a server that runs every 24 hours to get information from Blancco reports, then input it into a Filemaker database.
The service works completely as it should but every time it ends, I get the meesage box error:
Error 1053: the service did not respond to the start or control request in a timely fashion
I tried to run service on my pc and I don't get any errors there. So I guess there might be something wrong with the server, but I don't know what.
Hopefully one of you guys know
code:
using System;
using System.ServiceProcess;
namespace Blancco_Report_Service
{
class Program
{
static void Main(string[] args)
{
Service service = new Service();
if (Environment.UserInteractive)
{
service.RunAsConsole(args);
}
else
{
ServiceBase[] services;
services = new ServiceBase[] { service };
ServiceBase.Run(services);
}
}
}
}
I know it looks weird I made it create a batch file to get the reports, but I could not get Blancco's API to work with RestSharp so this was the next best option. This is not important anyways
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RestSharp;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Xml;
using Formatting = Newtonsoft.Json.Formatting;
namespace Blancco_Report_Service
{
class Service : ServiceBase
{
private string fmToken = "placeholder";
Thread work;
public void RunAsConsole(string[] args)
{
OnStart(args);
Console.ReadLine();
OnStop();
}
protected override void OnStart(string[] args)
{
work = new Thread(new ThreadStart(Work));
work.Start();
}
protected override void OnStop()
{
Console.WriteLine("Stopping");
try
{
work.Abort();
}
catch (Exception)
{
}
}
private void Work()
{
List<Report> reports = GetReports();
foreach (var report in reports)
{
UpdateField(report);
}
}
private List<Report> GetReports()
{
List<Report> reports = new List<Report>();
StringBuilder output = new StringBuilder();
XmlDocument doc = new XmlDocument();
Process process = new Process();
Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory + "export.bat");
ProcessStartInfo startInfo = new ProcessStartInfo("cmd.exe", "/C \"" + AppDomain.CurrentDomain.BaseDirectory + "export.bat\"");
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
process.StartInfo = startInfo;
process.OutputDataReceived += (sender, args) => output.Append(args.Data);
process.Start();
process.BeginOutputReadLine();
process.WaitForExit();
string[] outputSplit = output.ToString().Split("web-service-request.xml\" ");
try
{
doc.LoadXml(outputSplit[1]);
}
catch (Exception)
{
Console.WriteLine("No reports");
return reports;
}
string json = JsonConvert.SerializeXmlNode(doc, Formatting.None, true);
json = json.Substring(45);
dynamic result = JObject.Parse(json);
foreach (var report in result.report)
{
Report reportClass = new Report();
try
{
dynamic blancco_data = report.blancco_data;
dynamic blancco_hardware_report = blancco_data.blancco_hardware_report;
dynamic hardware_entries = blancco_hardware_report.entries;
foreach (var hardwere_entry in hardware_entries)
{
if (hardwere_entry["#name"] == "system")
{
dynamic system_entry = hardwere_entry.entry;
foreach (var systemInfo in system_entry)
{
if (systemInfo["#name"] == "serial")
{
reportClass.Serial = systemInfo["#text"];
}
}
}
}
dynamic description = blancco_data.description;
dynamic document_log = description.document_log;
dynamic log_entry = document_log.log_entry[0];
string date = log_entry.date;
DateTime oDate = DateTime.ParseExact(date, "MM/dd/yyyy HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture);
date = oDate.ToString();
reportClass.Date = date;
reports.Add(reportClass);
}
catch (Exception e)
{
}
}
return reports;
}
private void UpdateField(Report report)
{
var client = new RestClient(FMAPI.Url + "_find");
var request = new RestRequest(Method.POST);
request.AddHeader("cache-control", "no-cache");
request.AddHeader("authorization", "Bearer " + fmToken);
request.AddHeader("content-type", "application/json");
request.AddParameter("application/json", "{ \"query\": [{ \"service::ser_serial no\": \"=" + report.Serial + "\"}] }", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
dynamic result = JObject.Parse(response.Content);
string code = result.messages[0].code;
switch (code)
{
case "952":
fmToken = FMAPI.GetToken("service_000_DK");
UpdateField(report);
return;
case "401": return;
default: break;
}
string recordID = result.response.data[0].recordId;
client = new RestClient(FMAPI.Url + "records/" + recordID);
request = new RestRequest(Method.PATCH);
request.AddHeader("cache-control", "no-cache");
request.AddHeader("content-type", "application/json");
request.AddHeader("authorization", "Bearer " + fmToken);
request.AddParameter("application/json", "{ \"fieldData\": { \"service::ser_dataerased\": \"" + report.Date + "\" } }", ParameterType.RequestBody);
response = client.Execute(request);
result = JObject.Parse(response.Content);
code = result.messages[0].code;
if (code == "0")
{
Console.WriteLine("Uploaded");
}
else
{
Console.WriteLine("Failed to Upload");
}
}
}
}

"404 - File or directory not found" error when logging in to DocuSign API

I am using the code listed below for a c# visual studio project to interface with the DocuSign API. As soon as the code gets to
LoginInformation loginInfo = authApi.Login();
I am getting error message:
404 - File or directory not found.
The resource you are looking for might have been removed, had its name changed, or is temporarily unavailable
Does anyone know why?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using Newtonsoft.Json;
using DocuSign.eSign.Api;
using DocuSign.eSign.Model;
using DocuSign.eSign.Client;
namespace CoreRecipes
{
class Program
{
private string INTEGRATOR_KEY = "[key]";
static void Main(string[] args)
{
Program recipes = new Program();
recipes.listDocumentsAndDownloadTest();
Console.Read();
}
public void listDocumentsAndDownloadTest()
{
string username = "[username]";
string password = "[password]";
string envelopeId = "envelopid";
//configureApiClient("www.docusign.net/restapi");
//http"s://demo.docusign.net/restapi"
configureApiClient("https://demo.docusign.net/restpi");
string accountId = loginApi(username, password);
EnvelopesApi envelopesApi = new EnvelopesApi();
EnvelopeDocumentsResult docsList = envelopesApi.ListDocuments(accountId, envelopeId);
Console.WriteLine("EnvelopeDocumentsResult:\n{0}", JsonConvert.SerializeObject(docsList));
int docCount = docsList.EnvelopeDocuments.Count;
string filePath = null;
FileStream fs = null;
for (int i = 0; i < docCount; i++)
{
MemoryStream docStream = (MemoryStream)envelopesApi.GetDocument(accountId, envelopeId, docsList.EnvelopeDocuments[i].DocumentId);
filePath = Path.GetTempPath() + Path.GetRandomFileName() + ".pdf";
fs = new FileStream(filePath, FileMode.Create);
docStream.Seek(0, SeekOrigin.Begin);
docStream.CopyTo(fs);
fs.Close();
Console.WriteLine("Envelope Document {0} has been downloaded to: {1}", i, filePath);
}
}
public void configureApiClient(string basePath)
{
ApiClient apiClient = new ApiClient(basePath);
Configuration.Default.ApiClient = apiClient;
}
public string loginApi(string usr, string pwd)
{
ApiClient apiClient = Configuration.Default.ApiClient;
string authHeader = "{\"Username\":\"" + usr + "\", \"Password\":\"" + pwd + "\", \"IntegratorKey\":\"" + INTEGRATOR_KEY + "\"}";
Configuration.Default.AddDefaultHeader("X-DocuSign-Authentication", authHeader);
string accountId = null;
AuthenticationApi authApi = new AuthenticationApi();
LoginInformation loginInfo = authApi.Login();
foreach (LoginAccount loginAcct in loginInfo.LoginAccounts)
{
if (loginAcct.IsDefault == "true")
{
accountId = loginAcct.AccountId;
break;
}
}
if (accountId == null)
{
accountId = loginInfo.LoginAccounts[0].AccountId;
}
return accountId;
}
}
}
The issue is with this list:
configureApiClient("https://demo.docusign.net/restpi")
There is a typo in it - as identified by going to https://demo.docusign.net/restpi and seeing that it returned a 404.
I suggest changing it to:
configureApiClient("https://demo.docusign.net/restapi")

C# - Visual Studio - 'object' does not contain a definition for 'ExecuteQuery'

I am trying to add code to an existing project that will check for existence of a device in SCCM and delete it if it does exist. I seem to be missing something, in that particular block of code. I get an error - 'object' does not contain a definition for 'ExecuteQuery' and no extension method 'ExecuteQuery' accepting a first argument of type 'object' could be found.
Here is the C# code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Net.NetworkInformation;
using SupportToolkit.Models;
using SupportToolkit.WindowsAutomationServices;
using NLog;
using System.Text;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
using System.Management;
namespace SupportToolkit.Controllers
{
public class TPOSRecordDeletionController : Controller
{
private static Logger recordDeletionLogger = LogManager.GetCurrentClassLogger();
[Authorize(Roles = #"nor\NST_RIT_Users,nor\NST_STM_Users,nor\NST_Admin_Users,nor\NST_CORP_Users")]
// GET: TPOSRecordDeletion
public ActionResult Index(TPOSRecordDeletionModel model)
{
if (model.ComputerName != null)
{
}
if (ModelState.IsValid)
{
if (!(string.IsNullOrEmpty(model.btnDeleteRecord)))
{
InvokeRecordDeletion(model);
}
}
return View(model);
}
[Authorize(Roles = #"nor\NST_RIT_Users,nor\NST_STM_Users,nor\NST_Admin_Users,nor\NST_CORP_Users")]
public string InvokeRecordDeletion(TPOSRecordDeletionModel model)
{
model.Status = "Running Service";
var windowsAutomationService = new WindowsAutomationServicesClient();
string shortServiceOutput;
var serviceAction = "Remove-TPOSRecords";
var SCCMServer = "server.nor.net";
var siteCode = "PO60";
string[] recordDeletionArguments = new string[1];
recordDeletionArguments[0] = model.ComputerName;
model.Status = "Processing" + model.ComputerName;
Ping pingSender = new Ping();
PingOptions options = new PingOptions();
// Use the default Ttl value which is 128,
// but change the fragmentation behavior.
options.DontFragment = true;
// Create a buffer of 32 bytes of data to be transmitted.
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 120;
PingReply reply = pingSender.Send(model.ComputerName, timeout, buffer, options);
if (reply.Status == IPStatus.Success)
{
model.Status = model.ComputerName + "is currently online and will not be removed!";
}
else
{
// set up domain context
using (var ctx = new System.DirectoryServices.AccountManagement.PrincipalContext(System.DirectoryServices.AccountManagement.ContextType.Domain))
{
// find a computer
ComputerPrincipal computer = ComputerPrincipal.FindByIdentity(ctx, model.ComputerName);
if (computer == null)
{
model.Status = model.ComputerName + "does not exist in Active Directory.";
}
else
{
computer.Delete();
model.Status = model.ComputerName + "successfully removed from Active Directory!";
}
//insert code here for checking for existence of computer in SCCM and removing from SCCM if exists
SmsNamedValuesDictionary namedValues = new SmsNamedValuesDictionary();
WqlConnectionManager connection = new WqlConnectionManager(namedValues);
connection.Connect("s0319p60.nordstrom.net");
foreach (IResultObject computerobject in connection.QueryProcessor.ExecuteQuery("Select ResourceID From SMS_R_System Where Name ='" + model.ComputerName + "'"))
{
if (computerobject == null)
{
model.Status = model.ComputerName + "does not exist in SCCM.";
}
else
{
computerobject.Delete();
model.Status = model.ComputerName + "successfully removed from SCCM!";
}
}
}
var userName = User.Identity.Name;
var serviceOutput = windowsAutomationService.RunAutomationService(serviceAction, userName, recordDeletionArguments);
recordDeletionLogger.Info(userName + " is attempting to remove the record " + model.ComputerName);
if (serviceOutput.Length >= 7)
{
shortServiceOutput = serviceOutput.Substring(0, 7);
shortServiceOutput = shortServiceOutput.ToLower();
}
else
{
shortServiceOutput = serviceOutput;
shortServiceOutput = shortServiceOutput.ToLower();
}
if (shortServiceOutput == "success")
{
model.Status = "Successfully removed " + model.ComputerName + " from SCCM and Active Directory";
recordDeletionLogger.Info(userName + " successfully removed " + model.ComputerName + " from SCCM and Active Directory");
return "Success";
}
else
{
model.Status = "Failure removing " + model.ComputerName + " from SCCM and Active Directory. Unknown Error";
recordDeletionLogger.Info(userName + " failed to remove " + model.ComputerName + " from SCCM and Active Directory");
return "Failure";
}
}
}
}
internal interface IResultObject
{
//void Delete();
void Delete();
}
internal class WqlConnectionManager
{
private SmsNamedValuesDictionary namedValues;
public WqlConnectionManager(SmsNamedValuesDictionary namedValues)
{
this.namedValues = namedValues;
}
public object QueryProcessor { get; internal set; }
internal void Connect(string v)
{
throw new NotImplementedException();
}
public object ExecuteQuery { get; internal set; }
}
internal class SmsNamedValuesDictionary
{
public SmsNamedValuesDictionary()
{
}
}
Well - after a few days of searching, I FINALLY figured out the issue.
The entire block of code at the end, was not necessary. The issue was that there were missing assembly references and using statements in the code. Specifically:
using Microsoft.ConfigurationManagement.ManagementProvider;
using Microsoft.ConfigurationManagement.ManagementProvider.WqlQueryEngine;
The corresponding DLLs also needed to be added to the project as references.
I hope this helps someone who runs into similar issues and is not versed in C# coding. I myself am only versed in PowerShell, so figuring this out took a lot of work for me. Thanks.
You create a custom "connection" object:
WqlConnectionManager connection = new WqlConnectionManager(namedValues);
Then call a method on one of its properties:
connection.QueryProcessor.ExecuteQuery("...")
But what is that QueryProcessor property?...
public object QueryProcessor { get; internal set; }
It's an object. As the error states, object doesn't have a method called ExecuteQuery. (It doesn't have very many methods or properties at all, really.)
I can't really tell from this code (maybe I'm missing something?) what specific type you're expecting QueryProcessor to be, but it should definitely be something more specific than object. Something analogous to a SQLCommand object, perhaps? Essentially, whatever type would have that ExecuteQuery method.
If there's a compelling reason in the existing codebase for this to be of type object, you'd need to determine what that reason is. There seems to be a lot of use of object here, which smells of some bad design choices from before you got there.

Detecting if internet connection is busy

We are developing an application that will install on PC and it will perform some background upload and download to/from our server. One of the requirement is to detect if the internet connection is currently busy (say above 50% utilization) and if it is, it needs to back-off and try another time. The main reason is to ensure the app does not interfere with user experience if they are in the middle of gaming, watching online movie or aggressively downloading files
After much thinking and research on google and of course SO, I still haven't found a good way on how to implement this, so decided to throw this out here. The application is implemented in C#, .NET 4.0 and I am looking for all forms of responses - either implementation in C# or other languages, pseudo-logic or approach on how to achieve - measuring of internet traffic utilization on local PC with good enough accuracy.
To avoid duplication of effort, so far I have tried these (and why they aren't suitable)
Use WMI to get network statistic. Most SO posts and solutions out there since to refer to this as the approach but it doesn't meet our requirement as measuring of bytes sent/received against network interface capacity (e.g. 1GB Ethernet Card) for utilisation will yield a good measure for LAN traffic but not for internet traffic (where the actual internet bandwidth might only be say 8Mbps)
Use of .NET Network Information Statistics or performance counter - yield similar readings to the above hence have the same shortcomings
Use ICMP (Ping) and measure RTT. It was suggested that 400ms RTT is considered as slow and good indication for busy network, however I was told that user with modem (yes we have to support that), use of reverse proxy or microwave link often get ping above that hence not a good measure
Start downloading a known file and measure the speed - this itself generate traffic which we are trying to avoid, also if this check is done often enough, our application will end up creating a lot of internet traffic - which again not ideal
MOD: Using BITS - this service can be disabled on user pc, requires group policy changes and assume server to be IIS (with custom configuration) and in our case our server is not IIS
So here it is, I'm all confuse and looking for some advice. I highlighted the question text so that you guys don't get lost reading this and wondering what the question is. Thanks.
You could use UPnP to query the router, and retrive the number of bytes sent and received over the network. You could keep checking this value on the router to determine what the activity is. Unfortunately this functionality doesn't seem to be well-documented, but it is possible to implement UPnP communication functionality within a C# application. You will need to use UDP to query for the router (UPnP discover), and once you have found the device, query its functionality, and then query the number of packets sent and received for the Internet Gateway Device using a WebClient (TCP).
Code for a UPnP library:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Xml;
using System.IO;
namespace UPNPLib
{
public class RouterElement
{
public RouterElement()
{
}
public override string ToString()
{
return Name;
}
public List children = new List();
public RouterElement parent;
public string Name;
public string Value;
public RouterElement this[string name] {
get
{
foreach (RouterElement et in children)
{
if (et.Name.ToLower().Contains(name.ToLower()))
{
return et;
}
}
foreach (RouterElement et in children)
{
Console.WriteLine(et.Name);
}
throw new KeyNotFoundException("Unable to find the specified entry");
}
}
public RouterElement(XmlNode node, RouterElement _parent)
{
Name = node.Name;
if (node.ChildNodes.Count
/// Gets the root URL of the device
///
///
public static string GetRootUrl()
{
StringBuilder mbuilder = new StringBuilder();
mbuilder.Append("M-SEARCH * HTTP/1.1\r\n");
mbuilder.Append("HOST: 239.255.255.250:1900\r\n");
mbuilder.Append("ST:upnp:rootdevice\r\n");
mbuilder.Append("MAN:\"ssdp:discover\"\r\n");
mbuilder.Append("MX:3\r\n\r\n");
UdpClient mclient = new UdpClient();
byte[] dgram = Encoding.ASCII.GetBytes(mbuilder.ToString());
mclient.Send(dgram,dgram.Length,new IPEndPoint(IPAddress.Broadcast,1900));
IPEndPoint mpoint = new IPEndPoint(IPAddress.Any, 0);
rootsearch:
dgram = mclient.Receive(ref mpoint);
string mret = Encoding.ASCII.GetString(dgram);
string orig = mret;
mret = mret.ToLower();
string url = orig.Substring(mret.IndexOf("location:") + "location:".Length, mret.IndexOf("\r", mret.IndexOf("location:")) - (mret.IndexOf("location:") + "location:".Length));
WebClient wclient = new WebClient();
try
{
Console.WriteLine("POLL:" + url);
string reply = wclient.DownloadString(url);
if (!reply.ToLower().Contains("router"))
{
goto rootsearch;
}
}
catch (Exception)
{
goto rootsearch;
}
return url;
}
public static RouterElement enumRouterFunctions(string url)
{
XmlReader mreader = XmlReader.Create(url);
XmlDocument md = new XmlDocument();
md.Load(mreader);
XmlNodeList rootnodes = md.GetElementsByTagName("serviceList");
RouterElement elem = new RouterElement();
foreach (XmlNode et in rootnodes)
{
RouterElement el = new RouterElement(et, null);
elem.children.Add(el);
}
return elem;
}
public static RouterElement getRouterInformation(string url)
{
XmlReader mreader = XmlReader.Create(url);
XmlDocument md = new XmlDocument();
md.Load(mreader);
XmlNodeList rootnodes = md.GetElementsByTagName("device");
return new RouterElement(rootnodes[0], null);
}
}
public class RouterMethod
{
string url;
public string MethodName;
string parentname;
string MakeRequest(string URL, byte[] data, string[] headers)
{
Uri mri = new Uri(URL);
TcpClient mclient = new TcpClient();
mclient.Connect(mri.Host, mri.Port);
Stream mstream = mclient.GetStream();
StreamWriter textwriter = new StreamWriter(mstream);
textwriter.Write("POST "+mri.PathAndQuery+" HTTP/1.1\r\n");
textwriter.Write("Connection: Close\r\n");
textwriter.Write("Content-Type: text/xml; charset=\"utf-8\"\r\n");
foreach (string et in headers)
{
textwriter.Write(et + "\r\n");
}
textwriter.Write("Content-Length: " + (data.Length).ToString()+"\r\n");
textwriter.Write("Host: " + mri.Host+":"+mri.Port+"\r\n");
textwriter.Write("\r\n");
textwriter.Flush();
Stream reqstream = mstream;
reqstream.Write(data, 0, data.Length);
reqstream.Flush();
StreamReader reader = new StreamReader(mstream);
while (reader.ReadLine().Length > 2)
{
}
return reader.ReadToEnd();
}
public RouterElement Invoke(string[] args)
{
MemoryStream mstream = new MemoryStream();
StreamWriter mwriter = new StreamWriter(mstream);
//TODO: Implement argument list
string arglist = "";
mwriter.Write("" + "" + "");
mwriter.Write("");//" + arglist + "");
mwriter.Write("");
mwriter.Flush();
List headers = new List();
headers.Add("SOAPAction: \"" + parentschema + "#" + MethodName + "\"");
mstream.Position = 0;
byte[] dgram = new byte[mstream.Length];
mstream.Read(dgram, 0, dgram.Length);
XmlDocument mdoc = new XmlDocument();
string txt = MakeRequest(url, dgram, headers.ToArray());
mdoc.LoadXml(txt);
try
{
RouterElement elem = new RouterElement(mdoc.ChildNodes[0], null);
return elem["Body"].children[0];
}
catch (Exception er)
{
RouterElement elem = new RouterElement(mdoc.ChildNodes[1], null);
return elem["Body"].children[0];
}
}
public List parameters = new List();
string baseurl;
string parentschema;
public RouterMethod(string svcurl, RouterElement element,string pname, string baseURL, string svcpdsc)
{
parentschema = svcpdsc;
baseurl = baseURL;
parentname = pname;
url = svcurl;
MethodName = element["name"].Value;
try
{
foreach (RouterElement et in element["argumentList"].children)
{
parameters.Add(et.children[0].Value);
}
}
catch (KeyNotFoundException)
{
}
}
}
public class RouterService
{
string url;
public string ServiceName;
public List methods = new List();
public RouterMethod GetMethodByNonCaseSensitiveName(string name)
{
foreach (RouterMethod et in methods)
{
if (et.MethodName.ToLower() == name.ToLower())
{
return et;
}
}
throw new KeyNotFoundException();
}
public RouterService(RouterElement element, string baseurl)
{
ServiceName = element["serviceId"].Value;
url = element["controlURL"].Value;
WebClient mclient = new WebClient();
string turtle = element["SCPDURL"].Value;
if (!turtle.ToLower().Contains("http"))
{
turtle = baseurl + turtle;
}
Console.WriteLine("service URL " + turtle);
string axml = mclient.DownloadString(turtle);
XmlDocument mdoc = new XmlDocument();
if (!url.ToLower().Contains("http"))
{
url = baseurl + url;
}
mdoc.LoadXml(axml);
XmlNode mainnode = mdoc.GetElementsByTagName("actionList")[0];
RouterElement actions = new RouterElement(mainnode, null);
foreach (RouterElement et in actions.children)
{
RouterMethod method = new RouterMethod(url, et,ServiceName,baseurl,element["serviceType"].Value);
methods.Add(method);
}
}
}
}
Code for a bandwidth meter:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using UPNPLib;
using System.IO;
namespace bandwidthmeter
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
BinaryReader mreader = new BinaryReader(File.Open("bandwidthlog.txt", FileMode.OpenOrCreate));
if (mreader.BaseStream.Length > 0)
{
prevsent = mreader.ReadInt64();
prevrecv = mreader.ReadInt64();
}
mreader.Close();
List services = new List();
string fullurl = UPNP.GetRootUrl();
RouterElement router = UPNP.enumRouterFunctions(fullurl);
Console.WriteLine("Router feature enumeration complete");
foreach (RouterElement et in router.children)
{
services.Add(new RouterService(et.children[0], fullurl.Substring(0, fullurl.IndexOf("/", "http://".Length+1))));
}
getReceiveDelegate = services[1].GetMethodByNonCaseSensitiveName("GetTotalBytesReceived");
getSentDelegate = services[1].GetMethodByNonCaseSensitiveName("GetTotalBytesSent");
Console.WriteLine("Invoking " + getReceiveDelegate.MethodName);
//Console.WriteLine(services[1].GetMethodByNonCaseSensitiveName("GetTotalPacketsSent").Invoke(null));
Timer mymer = new Timer();
mymer.Tick += new EventHandler(mymer_Tick);
mymer.Interval = 1000;
mymer.Start();
FormClosed += new FormClosedEventHandler(Form1_FormClosed);
}
long prevsent = 0;
long prevrecv = 0;
void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
BinaryWriter mwriter = new BinaryWriter(File.Open("bandwidthlog.txt", FileMode.OpenOrCreate));
mwriter.Write(getsent());
mwriter.Write(getreceived());
mwriter.Flush();
mwriter.Close();
}
long getsent()
{
long retval = Convert.ToInt64(getSentDelegate.Invoke(null).children[0].Value);
if (prevsent > retval)
{
retval = prevsent + retval;
}
return retval;
}
long getreceived()
{
long retval = Convert.ToInt64(getReceiveDelegate.Invoke(null).children[0].Value);
if (prevrecv > retval)
{
retval = prevrecv + retval;
}
return retval;
}
void mymer_Tick(object sender, EventArgs e)
{
label1.Text = "Sent: "+(getsent()/1024/1024).ToString()+"MB\nReceived: "+(getreceived()/1024/1024).ToString()+"MB";
}
RouterMethod getSentDelegate;
RouterMethod getReceiveDelegate;
}
}
Have you considered using Background Intelligent Transfer Service (BITS). It's designed to do this job already:
Background Intelligent Transfer Service (BITS) transfers files (downloads or uploads) between a client and server and provides progress information related to the transfers. You can also download files from a peer.
and,
Preserve the responsiveness of other network applications.
I'm not sure if there's a managed interface to it (I can see reference to Powershell Cmdlets), so you might have to use COM interop to use it.
Making the assumption that you are targetting Windows PC's (as you said you were developing in C#), have you looked at BITS, the Background Intelligent Transfer Service?
There's examples of how to hook into it using C# on MSDN and elsewhere, e.g. http://msdn.microsoft.com/en-us/magazine/cc188766.aspx

Categories