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.
So, I'm fairly certain this is a relatively remedial question with a likely simple solution, but I just can't seem to find it. I've currently got a program that writes the variables it sets to the console on execution, as well as writing them to the logfile when called through Autosys.
Console.WriteLine(DateTime.Now.ToString("hh:mm:ss.fff") + " Output Variable: " + variable1);
Console.WriteLine(DateTime.Now.ToString("hh:mm:ss.fff") + " Output Variable: " + variable2);
Console.WriteLine(DateTime.Now.ToString("hh:mm:ss.fff") + " Output Variable: " + variable3);
Simple stuff. But for some reason, when I call this...
Console.WriteLine(DateTime.Now.ToString("hh:mm:ss.fff") + " Endpoint: " + endpointAddress);
after previously setting
endpointAddress = "https://endpointaddress.com";
for debug
or
string endpointAddress = Environment.GetEnvironmentVariable("ENDPOINT");
for the Autosys call, with ENDPOINT set in the jobvars file to
JV_ENDPOINT https://endpointaddress.com
and JV_ENDPOINT set in the cmd file to
SET ENDPOINT=%JV_ENDPOINT%
with the end result of it pretty much being exactly the same as it is when the program is run through Visual Studio or the executable itself,
Console.WriteLine(DateTime.Now.ToString("hh:mm:ss.fff") + " Endpoint: " + endpointAddress);
is just skipped entirely in the log. The other ten or so WriteLines that are called all work fine, but nothing at all is written in that line's place.
A few lines up in the log file, I get
D:\server_apps\PROCESS_FOLDER>SET ENDPOINT=https://endpointaddress.com
showing that the endpoint is properly set, but not calling it later.
And...this just in...the most recent time I have run it, the endpoint line just WAS put into the log file. Huh. Well, let's adjust this question a bit. Would anyone happen to have any idea why this particular line might be so uniquely temperamental? I haven't changed anything significant in more than an hour, so I can't fathom why it would suddenly work. But any insight into why it may have happened (and why it might not again) could go a long way toward working any bugs or kinks out of this. Hopefully.
As always, thanks for your time!
I'm trying to run a remote batch file - already located on the remote machine - using PsExec, called via Process in C#. I've confirmed that all required files already exist, but believe I may have a problem with my syntax, as the redirected output indicates that it can't find the file specified.
The machine against which PsExec runs is dynamic, which is the myArray[0].MachineName value (this pulls in without issue).
wsStopProcess.StartInfo.FileName = #"C:\Windows\system32\PsExec.exe";
wsStopProcess.StartInfo.Arguments = #" \\" + myArray[0].MachineName + #"D:\stopprofile.bat";
wsStopProcess.StartInfo.UseShellExecute = false;
wsStopProcess.StartInfo.CreateNoWindow = true;
wsStopProcess.StartInfo.RedirectStandardOutput = true;
wsStopProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
wsStopProcess.Start();
Any ideas on what appears to be formatted incorrectly? I'm guessing it's too many backslashes (or not enough!) somewhere.
I think the main problem is you do not have a space between the two arguments.
Try this:
wsStopProcess.StartInfo.Arguments = #"\\" + myArray[0].MachineName + #" D:\stopprofile.bat";
I would also warn you that I could not get psexec to work 100%, despite trying many different things.
Try this:
wsStopProcess.StartInfo.Arguments = #"\\" + myArray[0].MachineName + #" D$\stopprofile.bat";
So instead of using : try $ sign. Also setting breakpoint on the above line while debugging will help you to see the exact path.
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/
How can I make my C# app erase itself (self-destruct)? Here's two ways that I think might work:
Supply another program that deletes the main program. How is this deleter program deleted then, though?
Create a process to CMD that waits a few seconds then deletes your file. During those few seconds, you close your application.
Both of those methods seem inefficient. I have a feeling that there's some built-in flag or something in Windows that allows for such stuff. How should I do it? Also, can you provide some sample code?
UPDATE: Thanks for all your answers! I'm going to try them, and see where that gets me.
First of all, some people have asked why I'd want my app to do this. Here's the answer: a few days ago, I read the Project Aardvark spec that Joel Spolsky posted on his blog, and it mentioned that the client app would delete itself after the remote session. I'm wondering how this works, and how, if I ever need to do this, I can accomplish such a feat.
Here's a little overview of what's been suggested:
Create a registry entry that tells Windows to delete the file on reboot
Launch CMD with a ping command to wait a few seconds and then delete the file
Both of those, of course, have their disadvantages, as outlined in the comments.
However, would such a method as outlined below work?
There are two executables: Program.exe and Cleaner.exe. The former is the program itself, the latter is the app that deletes Program.exe and itself (if it's loaded into memory, as I'm about to explain). Is it possible for Program.exe (which has dependencies) to load all of Cleaner.exe, which doesn't have any dependencies, into memory and run it?
If this is possible, could Cleaner.exe be packaged inside Program.exe, loaded into memory, and run?
There's a MoveFileEx API, which, when given a MOVEFILE_DELAY_UNTIL_REBOOT flag, will delete specified file on next system startup.
There's a great CodeProject Article about this topic.
Edit: Basically it's a simple cmd-call which will delete the specified files after some seconds.
Process.Start("cmd.exe", "/C ping 1.1.1.1 -n 1 -w 3000 > Nul & Del " + Application.ExecutablePath);
Application.Exit();
You will never be able to guarantee that this will work, as long as you require a physical presence on the machine. For example:
What if the app fails to release a resource in a timely fashion while you're trying to delete it? An error occurs, and the app remains.
The behavior of one app starting another which then deletes the first app is very suspicious from an AV perspective. You are likely to trigger defenses on a user's machine which may kill the process that's trying to kill your original app.
If you do something like delete a file at reboot, what if the user moves your file in between or makes a copy? It's not in the original spot anymore, and the app remains.
If your application requires this level of security, consider hosting it on a machine you control (e.g., by providing a web service and letting a stub client access it that way).
On a somewhat related note, one is also tempted to speculate about the motives of someone who (1) requires a physical presence on someone's machine and (2) wants to delete the evidence that the app existed.
A correction to #Bobby answer, in case people will find it useful - executable path needs to be quoted. Additionally, below is setting cmd.exe window to be hidden (otherwise it flashes as a black console window) and converted to run without relying on System.Windows.Forms assembly (the Application class).
var exepath = Assembly.GetEntryAssembly().Location;
var info = new ProcessStartInfo("cmd.exe", "/C ping 1.1.1.1 -n 1 -w 3000 > Nul & Del \"" + exepath + "\"");
info.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(info).Dispose();
Environment.Exit(0);
There is also FileOptions.DeleteOnClose, but that requires the file to be open for writing. You might be able to do it with a sequence like this (untested):
Program launches as Original.exe, and detects (from its own name) that it needs to trigger the self-destruct function.
Original.exe creates a new file Temp.exe with FileOptions.DeleteOnClose and copies its own content into it, but does not close it yet
Original.exe opens a second, read-only handle to Temp.exe and closes the first write handle. The read-only handle can co-exist with an execute handle, whilst keeping the file open to delay auto-deletion.
Original.exe launches Temp.exe. Temp.exe detects that it has been launched from the temp directory and bypasses the self-destruct sequence and continues normal operation.
Original.exe exits (taking its read-only handle to Temp.exe with it.)
Temp.exe continues running. When it exits, the file Temp.exe will no longer be in use so it will be deleted automatically.
Edit #2: Actually I don't think this is possible, because it relies on the kernel opening the file with the FILE_SHARE_DELETE flag, which is unlikely.
sorted by NJ
c#
the other codes does not work so its simple
if u create bath file that loops to del application and
the batch file itself
u can use takkill command to kill the process if u dont want to use
application.close method
`string delname = "test.cmd";
string fileurl = Application.ExecutablePath;
System.IO.StreamWriter file = new System.IO.StreamWriter(delname);
file.WriteLine(":Repeat");
file.WriteLine("del \"" + fileurl + "\"");
file.WriteLine("if exist \"" + fileurl + "\" goto Repeat");
file.WriteLine("del \"" + delname + "\"");
file.Close();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.FileName = delname;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(startInfo);`
`
Th3 3e3 one is not 3d parts ov one
I5
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Think CMD
int sectosleep = 5000;
string exename = "yourexe.exe";
string location = #"c:\yourexe.exe"
Process.Start("cmd.exe", "/C taskkill /f /im " + exename + " & ping 1.1.1.1 -n 1 -w " + sectosleep + " > Nul & Del /F /Q \"" + location + "\"");
;>
I know reflector deletes itself if you use an old version and choose not to update. You might try to figure out what it does. I would start with FileMon and see if it spawns any processes to achieve this.
Since my application (a Windows Service) is installed via the Windows Installer, I self-delete using this:
Dim uninstall_params As String = "/x {MY-PRODUCTS-GUID} /qn /norestart REBOOT=ReallySuppress"
proc.StartInfo = New ProcessStartInfo("msiexec.exe", uninstall_params)
proc.Start()
Environment.Exit(-1)
Sorry--it's in VB, but it should be easily convertible to C#.
Works in Windows 7 & 8, **ENSURE you run your application with admin privileges or you will get an error.
This code exists elsewhere so I can't take full credit I found I made it work for me by adding "Application.Exit();"
static void autodelete()
{
string batchCommands = string.Empty;
string exeFileName = Assembly.GetExecutingAssembly().CodeBase.Replace("file:///", string.Empty).Replace("/", "\\");
batchCommands += "#ECHO OFF\n"; // Do not show any output
batchCommands += "ping 127.0.0.1 > nul\n"; // Wait approximately 4 seconds (so that the process is already terminated)
batchCommands += "echo j | del /F "; // Delete the executeable
batchCommands += exeFileName + "\n";
batchCommands += "echo j | del deleteMyProgram.bat"; // Delete this bat file
File.WriteAllText("deleteMyProgram.bat", batchCommands);
Process.Start("deleteMyProgram.bat");
Application.Exit();
}
This is the Uninstall.exe:
Shutdown.
Wait for 3 sec.
Try to kill that task if it is still running.
Wait for 3 sec.
Delete the app directory with the Uninstall.exe in it.
public void Uninstall()
{
var delPath = AppDomain.CurrentDomain.BaseDirectory;
var procId = Process.GetCurrentProcess().Id;
var psi = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = $"/C timeout 3 & Taskkill /F /PID {procId} & timeout 3 & rd /s /q \"{delPath}\"",
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
};
Process.Start(psi);
Application.Current.Shutdown();
}