Writing to EventLog from Outlook VSTO Plugin - c#

I'm trying to write to the eventlog from a VSTO Outlook Plugin, but I haven't figured out how.
I've tried this a few different ways and I'm still not sure if I'm hitting a security permission issue between the Outlook plugin and the eventlog or something code related.
I tried with 2 different pieces of code. This is my testing piece and even it doesn't write:
EventLog myLog = new EventLog("Application");
myLog.Source = "ReportPhishing";
myLog.WriteEntry("Reporting Email");
This is the code I'm ultimately trying to add in:
string sourceName = "ReportPhishing";
//Defines who was the sender email
string SenderEmail = obj_CurrentItem.SenderEmailAddress;
//Defines who the end receiving email address is
string ReceiverEmail = obj_CurrentItem.ReceivedByName;
//Defines the schema used to pull the header information out of the email
string EmailHeaders = obj_CurrentItem.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x007D001E");
//Defines FileName as from the subject line
string FileName = obj_CurrentItem.Subject;
//Specifies the main event context
string eventSubject = "Reported Phishing Email";
//Creates the payload information for sending to the local eventlog
string eventPayload = eventSubject + "%n%nSenderEmail: " + SenderEmail + "%n%nReceivingEmail: " + ReceiverEmail + "%n%nSubject: " + FileName + "%n%nHeaders: " + EmailHeaders;
//string eventpayload = #"<EventData><Data Name=""SenderEmail"">"+ SenderEmail +"</Data><Data Name=""ReceivingEmail"">" + SenderEmail + "</Data><Data Name=""Subject"">" + FileName + "</Data><Data Name=""Headers"">" + EmailHeaders + "</Data></EventData>";
EventLog.WriteEntry(sourceName, eventPayload, EventLogEntryType.Error);
What I've tried:
I tried to create the event source from the plugin, but that never worked as it wouldn't execute without admin permissions.
I manually created the source via the registry, but that didn't seem to work either.
I removed the registry entry and created the source via an elevated command line using eventcreate. By creating it via commandline, I confirmed that a non-elevated command line could still write to the event source
Verified permissions from the Registry (I added a lot more permissions as a just in case)
Read through a number of other StackOverflow posts around the EventLog. None really discussed the plugin aspect. Most focused on permission issues or incorrect implementation of MS code examples.
Created a basic form application that created a log event. This appears to work with my above sample code:
There appears to be something within the VSTO Plugin functionality that prevents logging to the EventLog. I'm unsure where to go from here.

Related

C# & Selenium WebDriver 4.0+ - Microsoft Edge Profile Selection Window Prevents Tests from Running

When attempting to build tests using Selenium WebDriver 4.10 and C# (.NET Framework 4.5.2) using the following code I receive a pop-up asking to select a profile. From what I understand the code below already is specifying the profile to use:
string strEdgeProfilePath = #"C:\\Users\\" + Environment.UserName + #"\\AppData\\Local\\Microsoft\\Edge\\User Data";
string strDefautProfilePath = strEdgeProfilePath + #"\\Default";
string strSeleniumProfilePath = strEdgeProfilePath + #"\\Selenium"; // <---- I have deleted this folder and copied the contents of the "Default" folder to no avail.
using (var service = EdgeDriverService.CreateDefaultService(#"C:\Temp\Selenium\Edge")) {
service.UseVerboseLogging = true;
EdgeOptions edgeOptions = new EdgeOptions();
edgeOptions.AddArgument("--user-data-dir=" + strSeleniumProfilePath);
edgeOptions.AddArgument("--profile-directory=Selenium");
driver = new EdgeDriver(#"C:\Temp\Selenium\Edge", edgeOptions); // <----- msedgeserve.exe located here
}
Even when I select the profile Microsoft Edge does not continue and the test times out.
What can I do to prevent the profile selection and get the test to run?
There're some problems in your code:
You don't need to use double backslash, backslash is enough.
The value for --user-data-dir is not right. Using strEdgeProfilePath for it is enough.
So the right code should be like this:
string strEdgeProfilePath = #"C:\Users\" + Environment.UserName + #"\AppData\Local\Microsoft\Edge\User Data";
...
\\Here you set the path of the profile ending with User Data not the profile folder
edgeOptions.AddArgument("--user-data-dir=" + strEdgeProfilePath);
\\Here you specify the actual profile folder
\\If it is Default profile, no need to use this line of code
edgeOptions.AddArgument("--profile-directory=Selenium");
Besides, to avoid running Edge processes errors, you need to follow the back up steps in this answer. Please use the backup folder instead of the original folder in the code.

Debugging a live ASP.net website

I have a C# ASP.net website. Locally I can run it in debug and step through the code to see why things arent working but when its hosted on my live site I cannot do this.
What is the best way to debug what is going on with my website?
Should I add debut/output/trace statements?
If so, which and how do I view the output of these? Can I view them in Chrome-->Developer Tools somehow?
For example, right now I can register a user on my site so I know the database connection is good, but I cannot login a registered user and want to figure out why.
Thanks
You may add trace and debug logs on your app. For ease, you may use logging frameworks like
http://nlog-project.org/
https://serilog.net/
You can actually write your own logging mechanism in which you can create a log class and some functions in it eg
public class Log
{
internal static bool RecordLog(string strSource, string strMethodName, string strStatement)//additional params you think appropriate for your logs
{
List<string> lstInfo = new List<string>();
string strProductName = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location.ToString()).ProductName.ToString();
string strProductVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location.ToString()).ProductVersion.ToString();
try
{
strProductName = FileVersionInfo.GetVersionInfo(Assembly.GetCallingAssembly().Location.ToString()).ProductName.ToString();
strProductVersion = FileVersionInfo.GetVersionInfo(Assembly.GetCallingAssembly().Location.ToString()).ProductVersion.ToString();
}
catch
{
}
try
{
lstInfo.Add("** Date=" + DateTime.Now.ToString("d MMM yy, H:mm:ss") + ", " + strProductName + " v" + strProductVersion);
lstInfo.Add("Source=" + strSource + ", Server=" + strServerIP + ""); //add more info in list as per rquirement
bool flag = blnWriteLog("LogFilename", lstInfo);
}
catch (Exception objEx)
{
//exception handling
}
return true;
}
private static bool blnWriteLog(string strProductName, List<string> lstInfo)
{
string strPath = strGetLogFileName(strProductName);
using StreamReader write in the log file received
return true;
}
private static string strGetLogFileName(string strFilePrefix)
{
//logic to check your file name, if it exists return name else create one
return strFile;
}
}
and then you can use the same from your file
Log.RecordLog()// Values as per your code and requirement
Note : Above is just a suggested way to do it, there can be many other and efficient ways also
You can use the built-in Microsoft Intellitrace feature to step through code from the generated intellitrace logs. This link https://msdn.microsoft.com/en-us/library/dn449058.aspx gives instructions on how to achieve the following;
"If you are using Microsoft Monitoring Agent to control IntelliTrace,
you also need to set up set up application performance monitoring on
your web server. This records diagnostic events while your app runs
and saves the events to an IntelliTrace log file. You can then look at
the events in Visual Studio Enterprise (but not Professional or
Community editions), go to the code where an event happened, look at
the recorded values at that point in time, and move forwards or
backwards through the code that ran. After you find and fix the
problem, repeat the cycle to build, release, and monitor your release
so you can resolve future potential problems earlier and faster."

How can I supply a password to a console application?

As I come across issues when testing my current application, I often have to tweak the database the app uses. After losing important changes several times, I wrote a program that will back up my database to a file and then check the file into SubVersion. I have found that that backup application is not good enough.
The database is a PostgreSQL database, and my backup application invokes pg_dump to create the backup file. pg_dump is executed in a console window. When the database was on my own machine, it worked well. But when I moved the database to our test server, pg_dump asked for a password. While it's not that big a deal, I'd like to be able to supply the password automatically, since it is available in the backup application.
I've tried to follow advice I've found here, but pg_dump still stops and asks for a password. Here's the code that I thought should have supplied the password:
Process backupProcess = new Process();
backupProcess.StartInfo.UseShellExecute = false;
backupProcess.StartInfo.RedirectStandardInput = true;
backupProcess.StartInfo.FileName = dumpPath + "pg_dump.exe";
backupProcess.StartInfo.Arguments = " --host " + host +
" --port " + port +
" --username " + userName +
" --format custom --blobs --verbose --file " +
"\"" + txtBackupFile.Text + "\" " + dbName;
backupProcess.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
backupProcess.Start();
StreamWriter standardInput = backupProcess.StandardInput;
standardInput.WriteLine("mypassword");
backupProcess.WaitForExit();// Waits here for the process to exit.
Thank you for your help.
RobR
I have solved this by using
backupProcess.EnvironmentVariables["PGPASSWORD"] = "password";
This way, I avoid the password will be stored on the computer
Maybe it's cheating a little bit (in the sense that it doesn't really help you answer the question of how to feed input to pg_dump), but you could refer to this answer which suggests the use of a .pgpass file. It would certainly be possible to write to this file dynamically rather than try to interact with the program once it prompts.
Info on .pgpass here.

Prevent application from opening

I'm writing an app in C# to prevent some executable file from opening. My app will detect opening selected executable file and show message box to let user choose to run it or not.
REGEDIT4
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\notepad.exe]
"Debugger"="calc.exe"
I have use above method from This topic but it will block all executable file with that name from any path. Which I want is to block only executable file in flashdrive or specifed path.
Example. I selected that my program will show message box when "a.exe" in Drive F:/ is opening. If I use a method in reference topic, it will block all "a.exe" in any path like "C:/a.exe", "D:/a.exe" or "F:/a.exe" but I want it to block only a.exe in F:/ not in other path or drive.
Any idea for this?
Thanks a lot.
Additional information:
Easy understanding with this question is...
I want my program to block some exe in specified path. When user try to open specified exe, my app will block it and have a message box to alert user. If user click "No", specify exe will not run but If user click "Yes", specify exe will run normally.
this will work like a anti virus software when user accidentally run virus file, Anti virus will block it and have some message to ask user that he still wanted to run it or not.
I have a similar point in a blog article where I try to detect the creation and destruction of a process instance. For this I use ManagementEventWatcher and this class uses queries like
internal ManagementEventWatcher WatchForProcessStart(string ProcessName)
{
string Query = "SELECT TargetInstance" +
" FROM __InstanceCreationEvent " + "WITHIN 2 " +
" WHERE TargetInstance ISA 'Win32_Process' " +
" AND TargetInstance.Name = '" + ProcessName + "'";
string Scope = "\\\\.\\root\\CIMV2";
ManagementEventWatcher Watcher = new ManagementEventWatcher(Scope, Query);
Watcher.Start();
return Watcher;
}
The scope is a ManagementScope instance which can be manipulated for your purposes as seen at MSDN
ManagementScope scope =
new ManagementScope(
"\\\\FullComputerName\\root\\cimv2");
scope.Connect();
I hope this helps you a bit. More information
http://msdn.microsoft.com/en-us/library/system.management.managementscope.aspx
http://www.idipous.net/how-to-monitor-proccess-creation-with-c/

Can't Access a xml file at random by C# console application

I have a C# console application which creates, parses and deletes multiple xml files at runtime. The application used to run fine in Windows 2003 server with .Net 2.0.
Recently, the Application framework was upgraded to >net 4.0 and the Windows Server OS to Windows 2008 64-bit.
Since then, the application encounters the following exception at random:
Access to the path 'D:\Content\iSDC\GDCOasis\GATE_DATA\LOG\635125008068192773\635125008074911566\SOD\AllRespId.xml' is denied.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.File.Delete(String path)
at ProcessGateFile.SOD.saveFile(String psFile, String psXMLString, Boolean isNonAscii)
The code for the creation, parsing and deletion is as follows:
saveFile(tmpPath + "\\SOD\\AllRespId.xml", "<?xml version= \"1.0\" ?><XML>" + sbldDistinctResp.ToString() + "</XML>", isChinese);
//Save list of Distinct responsibilities for User
sbldDistinctResp.Remove(0, sbldDistinctResp.Length);
xmlCase.Load(tmpPath + "\\SOD\\AllRespId.xml");
arrResps.Clear();
//Start preparing Responsibility selection criteria
RespNodes = xmlCase.SelectNodes("//row");
sRespCriteria = "";
if (RespNodes.Count > 0)
{
foreach (XmlNode RespNode in RespNodes)
{
string RespName = RespNode.Attributes.GetNamedItem("RespId").Value.ToString();
if (!arrResps.Contains(RespName))
{
arrResps.Add(RespName);
}
}
for (int i = 0; i < arrResps.Count; i++)
{
sbldDistinctResp.Append("(#RespId = '" + arrResps[i].ToString() + "') or ");
}
sbldDistinctResp.Remove(sbldDistinctResp.Length - 4, 4);
sRespCriteria = sbldDistinctResp.ToString();
if (!sRespCriteria.Equals(""))
{
sRespCriteria = "(" + sRespCriteria + ")";
}
}
File.Delete(tmpPath + "\\SOD\\AllRespId.xml");
I repeat, the error is happening at random, i.e. it works at times and does not at other times during the same process.
Any idea what might be causing this and how to resolve?
Just a couple of observations:
Why are you saving and then immediately loading the file again? In fact, why do you even need to save this file - you already have all the information you need in the sbldDistinctResp variable to generate the XML you need to work with (as evidenced by the saveFile call at the start of the code) - couldn't you just make a copy of it, surround it with the same XML as you did during saveFile, and work with that?
"It happens randomly" is a very subjective observation :). You should profile this (run it 10,000 times in a loop for example) and record the pattern of errors. You may well be surprised that what seems random at first actually shows a clear pattern over a large number of runs. This may help you to make a connection between the problem and some other apparently unrelated event on the server; or it may confirm that it truly is random and therefore outside of your control.
If you really can't find the problem and you go with the idea of anti-virus, etc, then you could wrap the loading code in a try/catch and re-try a couple of times if you get the error. It's hacky but it would work, assuming you have accepted that the initial error is beyond your control.

Categories