Open C# Winforms app through associated file clicking - c#

I am developing a small app that accepts two different types of files (*.miz and *.5js). There are two functions that do parse those files, and they already work properly when triggered from button click events (see below). Also, the solution contains this project and a setup project, to create the installer of the app.
public void button1_Click(object sender, EventArgs e)
{
button1.BackColor = Color.Red;
openFileDialog1.InitialDirectory = "";
openFileDialog1.Title = "Load mission file";
openFileDialog1.ShowDialog();
textBox4.Text = openFileDialog1.FileName;
processMizFile(openFileDialog1.FileName);
button1.BackColor = SystemColors.Control;
}
and
private void button6_Click(object sender, EventArgs e)
{
button6.BackColor = Color.Red;
openFileDialog2.InitialDirectory = "";
openFileDialog2.Title = "Load standalone Datacards";
openFileDialog2.ShowDialog();
loadDatacard(openFileDialog2.FileName);
button6.BackColor = SystemColors.Control;
}
I am now trying to call those functions when I start the app by double clicking in one of those file types (associated to my app through Windows properties dialog). For that, I am running the following code:
public Form1()
{
LoadFont();
InitializeComponent();
string version = Assembly.GetExecutingAssembly().GetName().Version.ToString();//to display program version in the form
label29.Text += version;
string[] cmdl = Environment.GetCommandLineArgs();
using (StreamWriter sw = File.CreateText(Application.UserAppDataPath + #"\log.txt"))
{
if (cmdl.Length > 1)
{
sw.WriteLine("Argument 0 - Exe path: " + cmdl[0]);
sw.WriteLine("Argument 1: " + cmdl[1]);
sw.WriteLine("File type: " + Path.GetExtension(cmdl[1]).ToUpper());
}
else
{
sw.WriteLine("Argument 0 - Exe path: " + cmdl[0]);
sw.WriteLine("No further arguments provided");
}
}
if (cmdl.Length > 1)
{
if (Path.GetExtension(cmdl[1]).ToUpper() == ".MIZ")
{
processMizFile(cmdl[1]);
using (StreamWriter sw2 = File.CreateText(Application.UserAppDataPath + #"\log2.txt"))
{
sw2.WriteLine("MIZ file loaded!");
}
}
else if (Path.GetExtension(cmdl[1]).ToUpper() == ".5JS")
{
loadDatacard(cmdl[1]);
using (StreamWriter sw2 = File.CreateText(Application.UserAppDataPath + #"\log2.txt"))
{
sw2.WriteLine("5Js file loaded!");
}
}
}
}
The streamwriter parts are in place to have some traces, as I am not sure how can I debug this, otherwise.
Now, the problem is that it all works properly on the same laptop where I have Visual Studio installed. But, it does not work on a different computer:
Release Build
If I just double click one of the associated files(on the Desktop), the splash screen flashes quickly, and goes away. No log file is written
If I double click an associated file in the same path as the installed executable, it works fine
If I launch the app from command line, passing a path as argument, I get:
log.txt:
Argument 0 - Exe path: DatacardGenerator.exe
Argument 1: C:\Users\Username\OneDrive\Desktop\Datacards.5js
File type: .5JS
log3.txt: writes up to "Created path to extract dir: " and the right Appdata folder to temporary extract
using (StreamWriter sw3 = File.AppendText(Application.UserAppDataPath + #"\log3.txt"))
{
sw3.WriteLine("Created path to extract dir: " + extract5Js);
}
if (Directory.Exists(extract5Js))
{
System.IO.Directory.Delete(extract5Js, true);
}
using (StreamWriter sw3 = File.AppendText(Application.UserAppDataPath + #"\log3.txt"))
{
sw3.WriteLine("Proceeding to unzip...");
}
ZipFile.ExtractToDirectory(path5jscard, extract5Js);
So, how could I know what happens during the startup of my app when launched by an external file? I`ve set command line arguments in debug mode to test, but I am not sure if they come with full path or not, given the different results on the target machine (works if files in same directory as exe, does not work otherwise)
Thanks for the support!! :)
P.S: I do not process the command line arguments directly in Main() because I am using 2 different forms: Form2 is a splash screen, and Form1 is the main program. For that I am using an example I found time ago, in this way:
namespace WindowsFormsApp2{
static class Program{
static private List<PrivateFontCollection> _fontCollections;
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(true);
CultureInfo culture;
culture = CultureInfo.CreateSpecificCulture("en-US");
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
//Dispose all used PrivateFontCollections when exiting
Application.ApplicationExit += delegate {
if (_fontCollections != null)
{
foreach (var fc in _fontCollections) if (fc != null) fc.Dispose();
_fontCollections = null;
}
string appPath = Application.UserAppDataPath;
string parentPath = System.IO.Directory.GetParent(appPath).ToString();
System.IO.Directory.Delete(parentPath, true);
};
//Application.Run(new Form1());
new MyApp().Run(args);
}
}
public class MyApp : WindowsFormsApplicationBase
{
protected override void OnCreateSplashScreen()
{
this.SplashScreen = new Form2();
}
protected override void OnCreateMainForm()
{
// Do your initialization here
//...
// Then create the main form, the splash screen will automatically close
this.MainForm = new Form1();
}
}
}

Solved!
I just had to declare a global var in Main to be accessed from my form, like:
public static string[] cmdlArgs;
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(true);
CultureInfo culture;
culture = CultureInfo.CreateSpecificCulture("en-US");
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
cmdlArgs = Environment.GetCommandLineArgs();
And then it can be accessed using the namespace :
Program.cmdlArgs

Related

Launching application from server creates Open File for lifetime of application

I launch a program located on one of my file servers. After launching the program it shows as an Open file in Computer Management.
Is there a way I can close this open file while my program runs so it doesn't show up in Computer Management?
My code is below. I'd be happy to take suggestions on improving my program, but I'm really just looking for a solution to stop all these Open Files from appearing.
Program.cs -- starts the program, handles logic to launch my application
using System;
using System.Windows.Forms;
using System.Diagnostics;
namespace IT_TaskbarApp
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
string programName = "TEG System Helper";
//Process[] proc = Process.GetProcessesByName(programName);
if (Process.GetProcessesByName(programName).Length == 1)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Primary());
}
else
{
foreach (Process p in Process.GetProcessesByName(programName))
{
if (Process.GetCurrentProcess().Id != p.Id)
{
p.CloseMainWindow();
p.Close();
p.Kill();
p.Dispose();
}
}
Main();
}
}
}
}
Primary.cs -- creates an icon in the system icons which I can use to send notifications and easily access utilities within our organization
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
namespace IT_TaskbarApp
{
public partial class Primary : Form
{
private NotifyIcon notifyIcon;
private ContextMenu contextMenu;
private MenuItem[] menuItem = new MenuItem[8];
private IContainer components;
//private Boolean SendNotices = true;
private DateTime startTime = DateTime.Now;
private DateTime currentTime;
private Icon tegroupIcon = new Icon(Assembly.GetExecutingAssembly().GetManifestResourceStream("IT_TaskbarApp.Src.tegroup.ico"));
private string prevNotification = "";
private bool isRunning = true;
private BackgroundWorker bgNotify = new BackgroundWorker();
private const string programName = "TEG System Helper";
public Primary()
{
this.FormClosing += Primary_FormClosing; //remove ghost icon in taskbar
ForeColor = Color.Blue;
BackColor = Color.Green;
components = new Container();
contextMenu = new ContextMenu();
for (int i = 0; i < menuItem.Length; i++)
{
menuItem[i] = new MenuItem();
menuItem[i].Index = i;
menuItem[i].Click += new EventHandler(LoadProcess);
}
menuItem[0].Text = programName;
menuItem[1].Text = "Knowledge Base";
menuItem[2].Text = "Policies";
menuItem[3].Text = "Feedback";
menuItem[4].Text = "Global Shop Search";
menuItem[5].Text = "-";
menuItem[6].Text = "Submit Ticket";
menuItem[7].Text = "Send Email";
//initialize contextMenu
contextMenu.MenuItems.AddRange(menuItem);
// Create the NotifyIcon.
notifyIcon = new NotifyIcon(components)
{
Icon = tegroupIcon,
BalloonTipIcon = new ToolTipIcon(),
ContextMenu = contextMenu, //the menu when right clicked
Text = programName,
Visible = true,
BalloonTipTitle = programName,
};
notifyIcon.DoubleClick += new EventHandler(Icon_DoubleClick);
InitializeComponent();
bgNotify.WorkerSupportsCancellation = true;
bgNotify.WorkerReportsProgress = true;
bgNotify.DoWork += NotifyUser;
bgNotify.ProgressChanged += SendNotice;
//bgNotify.RunWorkerCompleted += BgNotify_RunWorkerCompleted; //enable this to perform an action when the thread dies
bgNotify.RunWorkerAsync();
//Thread tNotify = new Thread();
}
#region SupportedFunctions
private void NotifyUser(object Sender, EventArgs e)
{
Console.WriteLine("enter");
while (isRunning)
{
currentTime = DateTime.Now;
#region DisplayCurrentTime
if (currentTime.Hour < 10 || currentTime.Minute < 10)
{
if (currentTime.Hour < 10)
{
if (currentTime.Minute < 10)
{
Console.WriteLine("0{0}:0{1}", currentTime.Hour, currentTime.Minute);
}
else
{
Console.WriteLine("0{0}:{1}", currentTime.Hour, currentTime.Minute);
}
}
else
{
if (currentTime.Minute < 10)
{
Console.WriteLine("{0}:0{1}", currentTime.Hour, currentTime.Minute);
}
}
}
else
{
Console.WriteLine("{0}:{1}", currentTime.Hour, currentTime.Minute);
}
#endregion
FileStream fs = new FileStream("\\\\te-admin\\public\\TaskbarNotices.txt", FileMode.Open);
StreamReader sr = new StreamReader(fs);
string noticeText = sr.ReadToEnd();
sr.Close();
fs.Close();
if (noticeText != "" && noticeText != prevNotification)
{
prevNotification = noticeText;
bgNotify.ReportProgress(1);
}
else
{
bgNotify.ReportProgress(2);
}
Console.WriteLine("Inner Text: {0} TOF: {1}", noticeText, noticeText != "");
Thread.Sleep(10000);
}
}
private void SendNotice(object Sender, ProgressChangedEventArgs e)
{
if (e.ProgressPercentage == 1)
{
Console.WriteLine("notification sent");
this.notifyIcon.BalloonTipText = prevNotification;
this.notifyIcon.ShowBalloonTip(1500);
}
}
private void LoadProcess(object Sender, EventArgs e)
{
if (Sender is MenuItem)
{
MenuItem tempMenu = Sender as MenuItem;
string ProgramTag = "http://";
switch (tempMenu.Index)
{
case 0: //home page
ProgramTag += "teg";
break;
case 1: //docviewer
ProgramTag += "teg/docViewer";
break;
case 2: //policies
ProgramTag += "teg/Policies";
break;
case 3: //feedback
ProgramTag += "teg/Feedback";
break;
case 4: //inventory search
ProgramTag = "http://searchglobalshop/inventory/index.aspx";
break;
case 6: //submit ticket
ProgramTag = "https://timberlandgroup.on.spiceworks.com/portal/tickets";
break;
case 7: //send email
string sendto = "admin#tewinch.com";
string emailSubject = "Assistance Request";
string emailBody = "";
string mailto = string.Format("mailto:{0}?Subject={1}&Body={2}", sendto, emailSubject, emailBody);
ProgramTag = Uri.EscapeUriString(mailto);
break;
}
/*
Try to launch the choice the user made with the default processing method.
Should the default method fail we try to control how the process is run.
We open internet explorer and then we show them what to do otherwise.
*/
#region LaunchSelectedProcess
try
{
if (ProgramTag != "" && ProgramTag != "http://")
Process.Start(ProgramTag);
}
catch (System.ComponentModel.Win32Exception)
{
try
{
if (ProgramTag.StartsWith("http://") || ProgramTag.StartsWith("https://"))
Process.Start("iexplore.exe", ProgramTag);
}
catch (System.ComponentModel.Win32Exception)
{
Process.Start("control.exe", "/name Microsoft.DefaultPrograms");
string message = "";
if (tempMenu.Index <= 6)
{
message = "You must have a default browser set\n\tClick [Set Default Program]\n";
if (Environment.OSVersion.ToString().Contains("NT 10.")) //windows 10
{
message += "\tUnder [Web Browser] Edge is currently set as default\n\tClick on Microsoft Edge\n\tSelect the browser you use";
}
else //windows 7 -- "NT 6.1")
{
message += "Select the browser you use\n\tClick [Set this program as default]";
}
}
else
{
if (Environment.OSVersion.ToString().Contains("NT 10.")) //windows 10
{
message += "Please setup a default email application";
}
}
message += "\n\nIf this issue persists please contact your Administrator.\nPhone: 519-537-6262\nEmail: admin#tewinch.com";
MessageBox.Show(message, "Application Warning", MessageBoxButtons.OK, MessageBoxIcon.Information);
//if ( == DialogResult.OK)
}
}
#endregion
}
}
private void Icon_DoubleClick(object Sender, EventArgs e)
{
Process.Start("http://teg");
}
#endregion
#region BuiltFunctions
private void Primary_FormClosing(object sender, FormClosingEventArgs e)
{
notifyIcon.Icon = null;
notifyIcon.Dispose();
isRunning = false;
Dispose(true);
}
private void InitializeComponent()
{
this.SuspendLayout();
//
// Primary
//
this.Icon = tegroupIcon;
this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
this.CausesValidation = false;
this.ClientSize = new System.Drawing.Size(120, 23);
this.ControlBox = false;
this.Enabled = false;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "Primary";
this.Opacity = 0D;
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.WindowState = System.Windows.Forms.FormWindowState.Minimized;
this.ResumeLayout(false);
}
protected override void Dispose(bool disposing)
{
// Clean up any components being used.
if (disposing)
if (components != null)
components.Dispose();
base.Dispose(disposing);
}
#endregion
}
}
Instead of cancelling the program on start up, I kill the other running instances of the program. The idea is that if any issues arise with the program I just launch another instance and resolve the issues. Right now not much can go wrong but we will be developing this program to complete many more tasks in the future.
The only area I can see which would keep a file open is when I pull an Embedded Resource tegroup.ico I was looking to see if I missed something while opening this, but I couldn't see a way to close the ManifestResourceStream after reading it in.
Any tips/suggestions would be wonderful but again, I really just want to know if there's a way I can close these Open Files
Example below
Open File after app launch
I might be trying to solve something which is a known result of using Application.Run() if this is the case then please suggest alternatives I can use. My other ideas would be loading the program into memory and launching it locally, using the .exe on the server as a starting point for this method though.
I believe that Windows doesn't load an entire executable into ram. It isn't just about files from the resource section of a PE file. Portions of the exe are only loaded when referenced and even after loading everything there is to load, Windows will maintain an open file handle until the process closes. Trying to close that handle yourself is a bad idea.
c/c++ allow a "SWAPFILE" flag to be specified that tells windows to put the whole thing into the page file but I don't know how you would do that with c# and I don't know if that would even stop windows from keeping the handle open anyways (I doubt it).
If this is truly important, iffin' I were your exe... I would:
Check a mutex for an existing running instance, exit if exist
Check where I was running from.
If running from temp, set a mutex that I am running and just run.
If not running from temp, copy myself to %temp%, start that copy, and exit.
Good luck.

When I open my compiled file it does nothing

I made a simple compiler to learn about CodeDom. But it does not work, when I try to open my compiled file it does nothing.
When I run the code and slect an dir to save the exe file the exe file is generated, but when I click the exe file it does nothing.
The builder:
using System;
using System.IO;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Windows.Forms;
namespace TestBuilder
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
void build(string output, string title, string msg)
{
CompilerParameters p = new CompilerParameters();
p.GenerateExecutable = true;
p.ReferencedAssemblies.AddRange(new String[] { "System.dll"});
p.OutputAssembly = output;
p.CompilerOptions = "/t:winexe";
string source = File.ReadAllText(#"C:\Users\Gebruiker\Documents\visual studio 2015\Projects\TestCompiler\Test\Program.cs");
string errors = String.Empty;
source = source.Replace("[MESSAGE]", msg);
CompilerResults results = new CSharpCodeProvider().CompileAssemblyFromSource(p, source);
if (results.Errors.Count > 0)
{
foreach (CompilerError err in results.Errors)
{
errors += "Error: " + err.ToString() + "\r\n\r\n";
}
}
else errors = "Successfully built:\n" + output;
MessageBox.Show(errors, "Build", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void button1_Click(object sender, EventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "EXE files (*.exe)|*.exe";
DialogResult result = sfd.ShowDialog();
if (result == DialogResult.OK)
{
build(sfd.FileName, textBox1.Text, textBox1.Text);
}
}
}
}
The program.cs file:
using System;
namespace Test
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("[MESSAGE]");
Console.ReadLine();
}
}
}
How can I fix this problem, so when I compile a file and execute it, it shows the message I put in the textbox?
Change p.CompilerOptions = "/t:winexe"; to p.CompilerOptions = "/t:exe";.
After that the compiled program should output whatever you've put inside your TextBox when you run it.
Source
Use /target:exe to create a console application.

How do I save continuous console output to a text file in c#?

I'm quite a noob at programming and I've been stuck at this for a while now. I'm using the following code to get continuous data output streamed to a command prompt. How can I ensure that the output gets copied to a text file after closing the prompt manually?
public static void Main(string[] args)
{
Connector connector;
Console.WriteLine("HelloEEG!");
// Initialize a new Connector and add event handlers
connector = new Connector();
connector.DeviceConnected += new EventHandler(OnDeviceConnected);
connector.DeviceConnectFail += new EventHandler(OnDeviceFail);
connector.DeviceValidating += new EventHandler(OnDeviceValidating);
// Scan for devices across COM ports
// The COM port named will be the first COM port that is checked.
connector.ConnectScan("COM40");
// Blink detection needs to be manually turned on
connector.setBlinkDetectionEnabled(true);
Thread.Sleep(400000);
System.Console.WriteLine("Goodbye.");
connector.Close();
Environment.Exit(0);
}
// Called when a device is connected
static void OnDeviceConnected(object sender, EventArgs e)
{
Connector.DeviceEventArgs de = (Connector.DeviceEventArgs)e;
Console.WriteLine("Device found on: " + de.Device.PortName);
de.Device.DataReceived += new EventHandler(OnDataReceived);
}
// Called when scanning fails
static void OnDeviceFail(object sender, EventArgs e)
{
Console.WriteLine("No devices found! :(");
}
// Called when each port is being validated
static void OnDeviceValidating(object sender, EventArgs e)
{
Console.WriteLine("Validating: ");
}
// Called when data is received from a device
static void OnDataReceived(object sender, EventArgs e)
{
Device.DataEventArgs de = (Device.DataEventArgs)e;
DataRow[] tempDataRowArray = de.DataRowArray;
TGParser tgParser = new TGParser();
tgParser.Read(de.DataRowArray);
/* Loops through the newly parsed data of the connected headset*/
// The comments below indicate and can be used to print out the different data outputs.
for (int i = 0; i < tgParser.ParsedData.Length; i++)
{
//string temp = tgParser.ParsedData[1].ToString;
//Console.WriteLine(tgParser.ParsedData.Length + " + " + temp);
if (tgParser.ParsedData[i].ContainsKey("Raw"))
{
//Console.WriteLine("Raw Value:" + tgParser.ParsedData[i]["Raw"]);
//Console.WriteLine("Raw Value:" + tgParser.ParsedData[i]["Raw"]);
}
if (tgParser.ParsedData[i].ContainsKey("PoorSignal"))
{
//The following line prints the Time associated with the parsed data
//Console.WriteLine("Time:" + tgParser.ParsedData[i]["Time"]);
Console.WriteLine("Time:" + tgParser.ParsedData[i]["Time"]);
//A Poor Signal value of 0 indicates that your headset is fitting properly
Console.WriteLine("Poor Signal:" + tgParser.ParsedData[i]["PoorSignal"]);
poorSig = (byte)tgParser.ParsedData[i]["PoorSignal"];
}
if (tgParser.ParsedData[i].ContainsKey("Attention"))
{
//Console.WriteLine("Att Value:" + tgParser.ParsedData[i]["Attention"]);
Console.WriteLine("Att Value:" + tgParser.ParsedData[i]["Attention"]);
}
if (tgParser.ParsedData[i].ContainsKey("Meditation"))
{
//Console.WriteLine("Med Value:" + tgParser.ParsedData[i]["Meditation"]);
Console.WriteLine("Med Value:" + tgParser.ParsedData[i]["Meditation"]);
}
if (tgParser.ParsedData[i].ContainsKey("EegPowerDelta"))
{
//Console.WriteLine("Delta: " + tgParser.ParsedData[i]["EegPowerDelta"]);
Console.WriteLine("Delta: " + tgParser.ParsedData[i]["EegPowerDelta"]);
}
if (tgParser.ParsedData[i].ContainsKey("BlinkStrength"))
{
//Console.WriteLine("Eyeblink " + tgParser.ParsedData[i]["BlinkStrength"]);
Console.WriteLine("Eyeblink " + tgParser.ParsedData[i]["BlinkStrength"]);
}
}
}
It will be much better to log every console output to a file as it happens. Instead of waiting to write to file when the app is closed manually. To save yourself a lot of coding, you can use log4net to handle the logging.
There's several different ways of approaching this, and with a bit of research I'm sure you could find a few, however this is the solution I would use for this particular action :
As Jonesy mentioned in the comments, I would firstly tidy up your Main. Create a separate class to perform the console writeline and the text output at the same time.
In this class perhaps use a loop to output the data to a file as and when it happens, therefore you wouldn't have to code in the logic when the console is closed manually, which in turn would cover unexpected errors and loss of logs.
This might work.
public static void WriteToFileAndConsole()
{
string outFile = "ConsoleOut.txt";
using (FileStream fileStream = new FileStream(outFile, FileMode.OpenOrCreate))
{
using (StreamWriter writer = new StreamWriter(fileStream))
{
using (TextWriter originalConsoleOut = Console.Out)
{
Console.SetOut(writer);
Console.WriteLine("Hello To File");
Console.SetOut(originalConsoleOut);
}
}
}
Console.WriteLine("Hello to console only");
}

FileSystemWatcher Access to a FileShare: Possible permission iusse?

I'm written a basic application that watches one network File Share directory and when a new file is created in that directory it then fires an external application that parses that file. I've also tested with a local directory and everything worked. I've tested it with debug code like so and the application will work:
#if DEBUG
Service1 mysService1 = new Service1();
mysService1.OnDebug(); //calls onStart(Null);
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
#else
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
#endif
Then when I switch to release, build and install the service nothing will happen. So since the path worked i figured this was down to permissions?
I went to Task Manager>Services>Services..> right clicked on my service>Properties>Log On> and have given it my credentials.
I've also gone to the root folder of where my application is on the network Right click>Security>Edit. Then I gave my account Modify, Read & Execute, Listing folder contents, and Read permissions and of course those permissions propagated to all of the folders under its hierarchy.
I even tried mapping it to the network drive Z and trying to access it that one.
With everything I tried the service still refuses to do anything. I've added more debugging code where I would check if the file was changed or deleted and write it down in text files. Once again it would work and detect those changes in debug but upon install nothing would happen.
I'm pretty sure this is probably still some kind of permission issue can anyone tell me what else I could do to remedy this issue?
EDIT:
There was a request for more code. Also note that my Utility class was able to produce a stack trace. It lead to an issue with System.IO.FileStream error started from this line of code in the FileWatcher.cs System.IO.File.AppendAllText(PathLocation() + "\logFile.txt", Environment.NewLine + " Started! " + DateTime.Now.ToString());
Service1.cs:
public Service1()
{
InitializeComponent();
}
public void OnDebug()
{
OnStart(null);
}
protected override void OnStart(string[] args)
{
try
{
FileWatcher f = new FileWatcher();
}
catch (Exception e)
{
new ErrorMailer(e, DateTime.Now.ToString());
}
}
FileWatcher.cs:
private FileSystemWatcher _fileWatcher;
static ProcessStartInfo start;
public FileWatcher()
{
System.IO.File.AppendAllText(PathLocation() + "\\logFile.txt", Environment.NewLine + " Started! " + DateTime.Now.ToString());
_fileWatcher = new FileSystemWatcher(PathLocation());
HasMailClerkBeenRun = false;
start = new ProcessStartInfo();
_fileWatcher.Created += new FileSystemEventHandler(_fileWatcher_Created);
_fileWatcher.Deleted += new FileSystemEventHandler(_fileWatcher_Deleted);
_fileWatcher.Changed += new FileSystemEventHandler(_fileWatcher_Changed);
_fileWatcher.EnableRaisingEvents = true;
}
{
string value = String.Empty;
value = #"Z:\MyAppDirectory\DirectoryFileWatcherIsWatching"; //#"\\FileShareName\RootDirectory\MyAppDirectory\DirectoryFileWatcherIsWatching";
return value;
}
void _fileWatcher_Changed(object sender, FileSystemEventArgs e)
{
System.IO.File.AppendAllText(PathLocation() + "\\logFile.txt", Environment.NewLine + "Started from the bottom now we changed! " + DateTime.Now.ToString());
}
void _fileWatcher_Deleted(object sender, FileSystemEventArgs e)
{
System.IO.File.AppendAllText(PathLocation() + "\\logFile.txt", Environment.NewLine + "Started from the bottom now we deleted! " + DateTime.Now.ToString());
}
void _fileWatcher_Created(object sender, FileSystemEventArgs e)
{
System.IO.File.AppendAllText(PathLocation() + "\\logFile.txt", Environment.NewLine + "Started from the bottom now we here! " + DateTime.Now.ToString());
LaunchExternalApp();
}
private void LaunchExternalApp()
{
start.UseShellExecute = false;
start.RedirectStandardError = true;
start.RedirectStandardInput = true;
start.RedirectStandardOutput = true;
start.CreateNoWindow = true;
start.ErrorDialog = false;
start.WindowStyle = ProcessWindowStyle.Hidden;
start.FileName =#"Z:\MyAppDirectory\AppExcutionLocation\MyApp.exe"
Thread thread1 = new Thread(new ThreadStart(A));
thread1.Start();
thread1.Join();
}
static void A()
{
using (Process proc = Process.Start(start))
{
proc.WaitForExit();
//HasMailClerkBeenRun = true;
// Retrieve the app's exit code
/// int exitCode = proc.ExitCode;
}
Thread.Sleep(100);
Console.WriteLine('A');
}
Check that the service is running under the same account as the interactive user account that you are using when checking the share or mapping the drive. If not, try switching it to use this account.
I have no idea why you are calling System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite), but I suspect that removing that line will solve your problem. If it doesn't, please post more code.

Killing Java Process from C# Console App

I hate to post about this again but I answered my own last post thinking I fixed it (which I didn't). Basically when my c# .NET application shuts down, I want to remove the running Java process that it created. The initial problem was that I was trying to save processID to a static class member variable (which obviously didnt work). I found a Global Class example online and used that instead, however it still isn't shutting down the process.
Debugging it isn't working properly. I guess it just creates a new instance of the application rather than running the one that I built, and even setting the working directory to the "Bin" directory doesn't work. So I am just having to run my .exe from the Bin directory at the moment.
namespace MinecraftDaemon
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Starting Minecraft Daemon...");
Arguments CommandLine = new Arguments(args);
// Hook ProcessExit Event
AppDomain.CurrentDomain.ProcessExit += new EventHandler(Current_ProcessExit);
if (CommandLine["file"] != null && CommandLine["memory"] != null)
{
// Launch the Application (Command Line Parameters)
LaunchMinecraft(CommandLine["file"], CommandLine["memory"]);
}
else
{
// Launch the Application (Default Parameters)
LaunchMinecraft("minecraft_server.jar", "1024");
}
}
public static void LaunchMinecraft(String file, String memoryValue)
{
String memParams = "-Xmx" + memoryValue + "M" + " -Xms" + memoryValue + "M ";
String args = memParams + "-jar " + file + " nogui";
ProcessStartInfo processInfo = new ProcessStartInfo("java.exe", args);
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
try
{
using (Process minecraftProcess = Process.Start(processInfo))
{
GlobalClass.ProcessID = minecraftProcess.Id;
Console.WriteLine("Process ID is " + GlobalClass.ProcessID);
minecraftProcess.WaitForExit();
}
}
catch
{
// Log Error
}
}
static void Current_ProcessExit(object sender, EventArgs e)
{
// Loop the Current Windows Processes
foreach (Process winProcess in Process.GetProcesses())
{
Console.WriteLine("WinProcessID is " + winProcess.Id + " GlobalClass.ProcessID is " + GlobalClass.ProcessID);
// If this is our Process, shut it down
if (winProcess.Id == GlobalClass.ProcessID)
{
Process.GetProcessById(GlobalClass.ProcessID).Kill();
}
}
}
}
}
This was resolved by switching from catching the Event AppDomain.CurrentDomain.ProcessExit to using SetConsoleCtrlHandler();

Categories