Scheduled Console App Crashes with App.config - c#

I have a C# console application that reads app settings from its app.config. The console application is targeted as the action of a Windows Scheduler Task. It runs once a day.
Since adding the code to read from the configuration file the app crashes only when run by the Task Scheduler. When run manually (from command prompt or by clicking on it in it's folder)), the application runs with no issues and it works exactly as expected.
Here's the code that reads from the app settings section:
int someValue = 1;
try
{
if (ConfigurationManager.AppSettings["someValue"] != null)
someValue = int.Parse(ConfigurationManager.AppSettings["someValue"].ToString());
}
catch(Exception exception)
{
// Write to error log
}
This is the exception I'm getting in my error log:
Exception: The type initializer for '<my application name>' threw an exception.
System.Configuration.ConfigurationErrorsException: An error occurred loading a configuration file: The parameter 'exePath' is invalid.
Parameter name: exePath ---> System.ArgumentException: The parameter 'exePath' is invalid.
Parameter name: exePath
I have tried allowing the task to run with highest privileges. I have tried accessing the configuration file in different ways (Configuration.OpenConfigurationExe(...)), etc... I get the same problem every time. I have tried putting my .exe in various locations on disk. This one is in C:\Program Files. I have looked around on S.O. and this post suggests that it might be a read permissions issue, but if the task runs under my domain's account and has the highest privileges, is that still possible? Note that it runs just fine if I run it manually from a command prompt or by clicking on it.
How can I reliably get a console application to read its app.config if it has been configured to run under Windows Task Scheduler?

Solved it. Turns out I had some legacy bits running code like this:
Configuration config = ConfigurationManager.OpenExeConfiguration("<app exe name>");
This where the exception was being thrown, not in the code in my question. Shame on me. Should have debugged that more thoroughly. I removed it all and replaced the local config object usage above with calls to:
ConfigurationManager.AppSettings["someValue"];

It could definitely be a permission issue, and maybe more than just read permissions. Things to check:
IS the task running under YOUR account, or another account? If this app is stored under a directory in your local profile then even other administrator accounts don't have permissions by default (they have to manually set permissions). Try moving the application to a local folder on the hard drive and set permissions as needed.
Try setting audit settings for the directory your app is stored in. If it is a permission issue then the security log will tell you more about what and why it is getting denied.

Related

System.IO.Copy operation intermittently giving Access Denied Error in .Net 4.0 C# Console Application

I have a console application written in .Net framework 4.0 C#. In the application I am copying a file from one location of the server to another location.
Here is the code:
System.IO.File.Copy("sourceFile","destFile",true);
I have created a Windows scheduler which executes the console app everyday at a particular time.
The code works perfectly fine if I run it manually. However it intermittently gives below access denied error (say once in every 10 times) while running it through scheduler.
Error Message: Access to the path "destFile" is denied. Other information(if any)
Stack Trace: at Syste.IO._Error.WinIOError(Int32 errorCode, String maybeFullPath) at Syste.IO.File.InternalCopy(String sourceFileName, String destFileName,Boolean overwrite,Boolean checkHost) at System.IO.File.Copy(String sourceFileName,String destFileName,Boolean overwrite)
I tried to reproduce the error in other lower environment servers (Dev/Test), but the issue could not be reproduced. Have already deleted the task scheduler and created fresh ones many times, but no luck. The issue gets fixed once I rerun the code as it is totally intermittent in nature. Permission to the source and destination location is already given because of which it works fine 9/10 times.
Pls advise if you see any issue or need additional information for further troubleshooting.
Give a look to the application user permissions, probably the user which you are using to run your application, misses the permissions to write in your desired path.
Noticed that you turned on overwrite option. If one of the dest files(being overwritten) are opened by other applications, you will get some error messages.

File gets "locked" while moving operation and iis give 401 error

I have a windows service run with local system account
What my program does is :
if (File.Exists(outputPath))
{
File.Delete(outputPath);
}
File.Move(archivePath, outputPath);
Relevant folder is application folder of iis where its application pool's identity is ApplicationPoolIdentity located under c:\MyAppFolder.
My windows service does its few times a day, and my clients checks if any new version exists every 5 minutes(0,5,10,15...) and download that file.
Time to time, file is somehow get "locked" on filesystem then
iis gives 401 error
File cannot be deleted
My first question how can I repro this situation?
One patch is done by colleagues is:
var fs = File.GetAccessControl(outputPath);
fs.SetAccessRuleProtection(false, false);
File.SetAccessControl(outputPath, fs);
Although this patch, it seems error occured again,
I may apply, this solution as well.
Are those solutions are enough or necessary?
Again my first question is important "repro issue" and understand why this happens.

Process.Start won't work

I am trying to launch a process from a web page's back-end code/app pool. This process will launch an App that i built myself.
For some reason, the process only works / runs when i start it from VS2013... it never works when i launch it from IIS(7.5) itself.
I am on a Windows 7 machine (both IIS host, and App location), and I've setup my web site to only be accessible via internal network.
Here's the code, followed by the config / attempts to fix the issue:
protected void btn_DoIt_Click(object sender, EventArgs e)
{
string file_text = this.txt_Urls.Text;
if (!String.IsNullOrWhiteSpace(file_text))
File.WriteAllText(ConfigurationManager.AppSettings["filePath"], file_text);
ProcessStartInfo inf = new ProcessStartInfo();
SecureString ss = GetSecureString("SomePassword");
inf.FileName = #"........\bin\Release\SomeExecutable.exe";
inf.Arguments = ConfigurationManager.AppSettings["filePath"];
inf.UserName = "SomeUserName";
inf.Password = ss;
inf.UseShellExecute = false;
//launch desktop app, but don't close it in case we want to see the results!
try
{
Process.Start(inf);
}
catch(Exception ex)
{
this.txt_Urls.Text = ex.Message;
}
this.txt_Urls.Enabled = false;
this.btn_DoIt.Enabled = false;
this.txt_Urls.Text = "Entries received and process started. Check local machine for status update, or use refresh below.";
}
Here are the things I've tried to resolve the issue:
Made sure the executing assembly was built with AnyCPU instead of
x86
Ensured that the AppPool that runs the app, also runs under the same account (SomeUsername) as the ProcessStartInfo specified.
Ensured that the specific user account has full access to the executable's folder.
Ensured that IIS_USR has full access to the executable's folder.
Restarted both the app pool and IIS itself many times over implementing these fixes
I am now at a loss as to why this simply will not launch the app... when i first looked into the event log, i saw that the app would die immediately with code 1000:KERNELBASE.dll, which got me on the AnyCPU config instead of X86 fix... that fixed the event log entries but the app still doesn't start (nothing comes up in task manager), and i get no errors in the event log...
if someone could help me fix this problem i would really appreciate it. This would allow me to perform specific tasks on my main computer from any device on my network (phone, tablet, laptop, etc etc) without having to be in front of my main PC...
UPDATE
The comment to my OP, and ultimate answer from #Bradley Uffner actually nailed the problem on the head: My "app" is actually a desktop application with a UI, and in order to run that application, IIS would need to be able to get access to the desktop and the UI, just like if it were a person sitting down in front of the PC. This of course is not the case since IIS is running only as a service account and it makes sense that it shouldn't be launching UI programs in the background. Also see his answer for one way of getting around this.
Your best bet might be to try writing this as 2 parts. A web site that posts commands to a text file (or database, or some other persistent storage), and a desktop application that periodically polls that file (database, etc) for changes and executes those commands. You could write out the entire command line, including exe path command arguments, and switches.
This is the only way I can really think of to allow a service application like IIS to execute applications that require a desktop context with a logged in user.
You should assign a technical user with enough high priviliges to the running application pool. By default the application pool is running with ApplicationPoolIdentity identy which has a very low priviliges.

Determining Write Permissions to the Application Folder

I have a C# application, and I need to dump some output to a log file during operation. I am wanting to give the user the option of where to locate the log file, but by the client request it needs to default to the current application location, which is normally /Program Files/.
When I deploy my application on a Win7/Vista machine, though, the application does not write the log file unless I run the program as an Administrator. At the same time, it seems to be silently handling the case where it cannot write the file, as I am currently handling all exceptions being thrown during the file creation and writing process.
I am currently trying to detect lack of write permission by both:
A) Creating a DirectorySecurity object by calling "Directory.GetAccessControl()" and
B) Checking security priviledges with the "SecurityManager.IsGranted(permissions)" method,
but A does not throw an exception when I expect it to, and B returns true every time.
I have seen numerous posts related to this topic, but they all give the solution of just writing to Application.UserAppDataFolder or some variation of it. My client has specifically asked to default to the current Application path, so I need to at least find a way to gracefully warn them when writing the log file is going to silently fail.
Note: My current code works find on Windows XP (since there are no UAC, I assume). Basically all I need to know is why all my calls are telling me that writing the file is going fine, when the file is never created at all unless I am running as Admin.
Thanks!
Windows Vista and 7 will write files to the Program Files directory just fine.
Well, not really, but the program thinks it's just fine. In reality, the file is written to the current user's VirtualStore directory; that is, in %userprofile%\AppData\Local\VirtualStore\Program Files
You can include a manifest file to disable this behavior for your application to get the results you expect.
You can force the os to run your app as Admin.
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
There are three ways your app can run - elevated, deliberately not elevated (manifest saying asInvoker), or accidentally not elevated (no manifest). Elevated apps will be able to write to Program Files. Deliberately not elevated apps will get access denied. Accidentally not elevated apps will succeed but the file will be written elsewhere. This last case is what's happening to you. It didn't silently fail. You just don't know where the files are. See http://www.gregcons.com/KateBlog/FindingFilesYoureSureYouWrote.aspx for screenshots.
Therefore if the users insist on the current directory, you should add a manifest requesting asInvoker. You will then get AccessDenied and they will see the error message. I think they are odd for wanting this. Ask them if they are ok with one extra click to find them: if so, keep your app using virtualization (I really disapprove) by having no manifest and then train them to click the Compatibility Files button.
My preference: write elsewhere and manifest to asInvoker. My second choice: stick with current directory, no manifest, train them to find virtualized files. My third choice: stick with current directory, manifest to asInvoker, users see error messages when log files are not written, but logs are lost.
I am experiencing the same problem. I have an xml file that i am writing to...When I install the app(C sharp) and try to run the application am getting an exception due to write permission. When I change the file permission (give read permission to users) it is working ok..
The ultimate test for whether you have the rights to write a file is to open it for writing.
I.e.
try
{
File.Open(path, FileMode.OpenOrCreate);
...
}
catch(SecurityException)
{
... it failed for security reasons
}
catch(Exception)
{
... it failed for other reasons
}
Besides Stefan P.'s suggestion to elevate the app to run as admin, you could also modify the installation folder permission on install to to add the Users group to have write access. Then the application would work as well.
Moving the log file location would be the best option though.

System.Diagnostics.Process.Start() cannot start process when called from Windows service

I am trying to start an external process from a .NET Windows service. In the past I have used the Process.Start() overload that takes the executable path and a command line string. This works. But now I would like to start the process and have it run in the context of a particular user. So I call this version of Start()
public static Process Start(
string fileName,
string userName,
SecureString password,
string domain)
However, when I call the method, the application I am trying to run generates an unhandled exception:
The application failed to initialize properly (0xc0000142). Click on OK to terminate the application.
I have tried to start different applications and they all generate the same exception. I have run the code outside of the Windows service and the application starts correctly.
So is there a way to get this to work in a Windows service?
Maybe the user has to have, "logon as a service" security right. This is done with the "local security policy" application. And/or "logon as a batch job".
This is very similar to this question here. The answer is usually due to security issues with the desktop and window station in which the process is being run. See this article for an explanation and some sample code.
This is just a shot in the dark, but perhaps you can try to run the Windows Service in Interactive mode. If that works, though, this can't be done in Windows Vista (because of Session 0 Isolation).
Use Filemon and see if it is trying to open a config file and not finding it. I once had this error due to a malformed config.

Categories