I have a C# console application that runs as a scheduled task within Windows Task Scheduler. This console app writes to a log file that when runs within debug mode creates and writes to the file within the application folder itself. However, when it runs in the task scheduler it throws an error saying that access is denied because it is trying to write to the same log file, but for some reason it is trying to write to it within the windows\system32 folder. Why would this be happening? And how would I correct this?
Here is the code snippet that assigns a StreamWriter to the log file:
static void Main(string[] args)
{
using (_swrtr = File.AppendText("gapi_gen_log.txt"))
{
_swrtr.Write("\r\n");
_swrtr.Write("\r\nGOOGLE CALENDAR:");
_swrtr.Write("\r\n\tDate Time - " + DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString());
start();
}
}
I also tried but this didn't work:
string dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
using (_swrtr = File.AppendText(dir + "gapi_gen_log.txt"))
{
_swrtr.Write("\r\n");
_swrtr.Write("\r\nGOOGLE CALENDAR:");
_swrtr.Write("\r\n\tDate Time - " + DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString());
start();
}
This is happening because you are not specifying a directory for your log file, so it's assuming the directory where the parent executable resides which, while you're debugging, is your debug output folder and when you're running it from the task scheduler, is the "c:\windows\system32" folder.
You could provide a path to the directory like this:
File.AppendText(#"c:\MyLogFiles\gapi_gen_log.txt")
Related
So I have a .NET Core 2.2 app running on an Azure VM with Windows Server 2019 which has the following disk configuration:
The disk on the red box is where the App files are located. Now, when Directory.GetCurrentDirectory() is called by the app, it returns the root directory of the project and not the current directory where the app is running. When I tried to run it locally, it works.
To illustrate it:
When run locally, the directory ~/MyApp/bin/Debug/netcoreapp2.2/ is returned by the call. When run in the VM, ~/MyApp/ is returned instead.
Here's the relevant code where the issue happens. What I do here is when the app is closed, it copies the current configuration file from ~/MyApp/bin/Debug/netcoreapp2.2/ to the ~/MyApp/ directory. This code works when run on a local machine, but it is not when running on the VM. How to make sure that calling Directory.GetCurrentDirectory() does indeed point to the directory of the running app?
private void ProcessExit(object sender, EventArgs e)
{
try
{
string rawConfigLocation = _config.GetSection("configurationSettings")["ConfigurationDirectory"];
File.Delete($"{Path.Combine(rawConfigLocation, "Config.json.inc")}");
using (var writer = File.CreateText($"{Path.Combine(Directory.GetCurrentDirectory(), "Config.json.inc")}"))
{
using (var reader = new StreamReader(Path.Combine(Directory.GetCurrentDirectory(), "Config.json")))
{
while (!reader.EndOfStream) writer.WriteLine(reader.ReadLine());
writer.Close();
}
Console.WriteLine(rawConfigLocation);
File.Move($"{Path.Combine(Directory.GetCurrentDirectory(), "Config.json.inc")}", $"{Path.Combine(rawConfigLocation, "Config.json.inc")}");
File.Delete($"{Path.Combine(rawConfigLocation, "Config.json")}");
File.Move($"{Path.Combine(rawConfigLocation, "Config.json.inc")}", $"{Path.Combine(rawConfigLocation, "Config.json")}");
Debug.WriteLine($"New file saved as {Path.Combine(rawConfigLocation, "Config.json")}");
#region [WINDOWS ONLY] Lines for debugging. Will be removed if the issue of incorrect config saving is fixed.
using (EventLog eventLog = new EventLog("MyApp"))
{
eventLog.Source = "MyApp";
eventLog.WriteEntry(
$"Raw Config Location: {_config.GetSection("configurationSettings")["ConfigurationDirectory"]}{Environment.NewLine}" +
$"File that was deleted: {Path.Combine(rawConfigLocation, "Config.json.inc")}{Environment.NewLine}" +
$"Temporary file created: {Path.Combine(Directory.GetCurrentDirectory(), "Config.json.inc")}{Environment.NewLine}" +
$"Current Directory: {Directory.GetCurrentDirectory()}{Environment.NewLine}" +
$"New file saved as {Path.Combine(rawConfigLocation, "Config.json")}",
EventLogEntryType.Information,
101,
1);
}
#endregion
}
}
I wish I could put a grenade to my computer at this point. I'm so frustrated because I don't understand why my application won't install using installUtil.
I've just looked through this link now: Windows Service Install Ends in Rollback and unfortunately the kind suggestions on there don't help in my situation, the following error was generated after taking into consideration all of the answers posted by the good people of SO on that link and others.
I have looked for best practices on the web for task parallel processing patterns but there's nothing helpful so far. The latest error I get when attempting to install is as follows:
.exe assembly's progress. The file is located at
E:\xxx\MyService\Service_V2.InstallLog. Installing assembly
'E:\xxx\MyService\Service_V2.exe'. Affected parameters are:
logtoconsole = logfile = E:\xxx\MyService\Service_V2.InstallLog
assemblypath = E:\xxx\MyService\Service_V2.exe Installing service
Service V2... Service Service V2 has been successfully installed.
Creating EventLog source Service V2 in log Application... Installing
service Service V2... Creating EventLog source Service V2 in log
Application...
An exception occurred during the Install phase.
System.ComponentModel.Win32Exception: The specified service already
exists
The Rollback phase of the installation is beginning. See the contents
of the log file for the E:\xxx\MyService\Service_V2 .exe assembly's
progress. The file is located at
E:\xxx\MyService\Service_V2.InstallLog. Rolling back assembly
'E:\xxx\MyService\Service_V2.exe'. Affected parameters are:
logtoconsole = logfile = E:\xxx\MyService\Service_V2.InstallLog
assemblypath = E:\xxx\MyService\Service_V2.exe Restoring event log to
previous state for source Service V2. Restoring event log to previous
state for source Service V2. Service Service V2 is being removed from
the system... Service Service V2 was successfully removed from the
system.
The Rollback phase completed successfully.
The transacted install has completed. The installation failed, and the
rollback has been performed.
There was nothing written to the event log either.
Here is my OnStart() method:
protected override void OnStart(string[] args)
{
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
ErrorLogFileName = "Service_V2Errors" + DateTime.Now.ToString("yyyy-MM-dd") + ".txt";
Service_V2LogFile = "Service_V2Log" + DateTime.Now.ToString("yyyy-MM-dd") + ".log";
ErrorLogPath = ConfigurationManager.AppSettings["Errorpath"].ToString();
CheckBatchRecord = Convert.ToInt32(ConfigurationManager.AppSettings["CheckBatchTime"].ToString());
if (!Directory.Exists(ErrorLogPath))
{
Directory.CreateDirectory(ErrorLogPath);
}
LogMessage("Starting Service " + DateTime.Now.ToString());
_ErrorLog = new StreamWriter(ErrorLogPath + "//" + ErrorLogFileName, true);
_ErrorLog.WriteLine("Error, Location, AdditionalInformation", true);
_ErrorLog.Close();
var t = Task.Run(() => Service_V2Start(), token);
try
{
t.Wait();
}
catch (AggregateException e)
{
LogMessage("Exception messages:");
foreach (var ie in e.InnerExceptions)
LogMessage(ie.GetType().Name + " : " + ie.Message);
LogMessage("\nTask status: " + t.Status);
}
finally
{
tokenSource.Dispose();
}
}
I have also set the compile mode to release for the final install files compiled.
I have done an "sc delete Servie V2" and I also checked the services console and there is no such service listed there.
I have also tried the InstallUtil.exe -u command to uninstall, but I still get this nitwit error. What should I do now?
Make sure your Program.cs file looks something like this:
static class Program
{
static void Main()
{
var service = new YourServiceName();
ServiceBase.Run(service);
}
}
Inside the InitializeComponent() method make sure that the ServiceName property value is the same as the ServiceName in the ProjectInstaller.cs
this.ServiceName = "MyServiceName";//in the YourServiceName partial class
this.myServiceInstaller.ServiceName = "MyServiceName";//in the installer
Make sure you have only one installer.
In the batch files that you created to install and uninstall your service make sure that you are pointing to the correct InstallUtil.exe.
For 64 bit architectures you can use - C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe
For 32 bit architectures you can use - C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe
Sample InstallService.bat file:
"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe" "PathToTheExecutables\MyServiceName.exe"
pause
Sample UninstallService.bat file:
"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe" /u "PathToTheExecutables\MyServiceName.exe"
pause
Make sure you run cmd as Administrator :)
I have a Login application that will disable after 3 times of wrong attempts..I just wanted to know how to make that application still running after i restart my computer..my application is already in .exe ...thanks in advance :)
Going on the assumption that you're talking about Windows here, a simple google search for "windows run application at startup" would yield a plethora of simple ways to make an application run when the OS starts.
Here is one of those results...
http://windows.microsoft.com/en-us/windows/run-program-automatically-windows-starts#1TC=windows-7
I guess you can add application executable in windows startup. Following method help to create app shortcut.
public static void CreateStartupShortcut(string applicationName)
{
string _startupFolder = Environment.GetFolderPath(Environment.SpecialFolder.Startup);
WshShell _shell = new WshShell();
//
string _shortcutAddress = _startupFolder + #"\" + applicationName + ".lnk";
IWshShortcut _shortcut = (IWshShortcut)_shell.CreateShortcut(_shortcutAddress);
_shell.RegDelete(_shortcutAddress);
//
_shortcut.Description = "Start up shortcut link for application " + applicationName + ". Delete shortcut to if you dont want to run application on stat up";
_shortcut.WorkingDirectory = Application.StartupPath;
_shortcut.TargetPath = Application.ExecutablePath;
_shortcut.Save();
}
Simply pass your application exe path to the method and it will add shortcut in windows startup.
I have created following C# console app:
var userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
var path = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
var path2 = Environment.ExpandEnvironmentVariables("%userprofile%");
File.AppendAllText(#"D:\logs\info.txt", userName + " -- " + path + " -- " + path2);
When I create a scheduled task using Windows Task Scheduler and set the user account to run the task to my account (ht-laptop\huseyin), I am getting the following output in info.txt file:
ht-laptop\huseyin -- C:\Users\Default\Documents -- C:\Users\Default
This seems to be random though, I had seen cases where the printed text was as follows:
ht-laptop\huseyin -- C:\Users\huseyin\Documents -- C:\Users\huseyin
Any idea why this happens?
Are you running this on Windows 8+ (or similar)? If so, this is a known issue with user profile loading. The technote (kb2968540) has a workaround (which is kind of kludgy IMO).
I'm all out of ideas on fixing an "Access Denied" issue on Windows 8.1...
I'm building a console app in Visual Studio under Administrative mode and my app is simply trying to do the following:
using System.IO;
namespace CommandCenterScriptLauncher
{
class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine("The argument passed was " + args[0] + ".");
Console.ReadLine();
File.WriteAllText(#"C:\Users\Matt\Music\target", "TEXT FILE BODY WITH ARG: " + args[0]);
}
catch
{
Console.WriteLine("No arguments were passed.");
Console.ReadLine();
File.WriteAllText("C:\\Users\\Matt\\Music\\target", "TEXT FILE BODY WITH NO ARGS");
}
}
}
}
Not only am I running in Admin mode which isn't helping, but the folder itself is NOT read only, and ALL USERS on the Security tab for the target folder have been granted FULL CONTROL.
What else am I missing here?!
You need to pass in a filename to File.WriteAllText. Right now, it looks like you are trying to write to a directory. That won't work.
Can you write in another location?. Windows for some reason prevent for writing on system folders. Try something like 'c:/Test/yourFile.txt'.
Check also UAC is disabled.