I have a console application,whose target version is .Net Framework 3.5. When I try to trigger the complied exe manually, the program executes and does its job perfectly. But the exe is not at all getting triggered when using a Task Scheduler.
The error details in Task Sceduler is as follows:
last run result 0xE0434F4D
Edits:
The event log is as follows,
Fault bucket , type 0
Event Name: CLR20r3
Response: Not available
Cab Id: 0
Problem signature:
P1: flvtomp4converter.exe
P2: 1.0.0.0
P3: 4ffa8abc
P4: mscorlib
P5: 2.0.0.0
P6: 4e1539fa
P7: 349e
P8: 119
P9: System.IO.DirectoryNotFound
P10:
What is happening here?
Welcome to wonderful world of Windows 2008 family.
This is about under what user your application scheduled to run in Task Scheduler and what permission that specific user have to all(!!!) folders involved in processing by your application.
Also you must make sure that this user authorized to run batch processes in security settings.
Just been member of administrators group no longer is enough!
In my case, it's because my console app trying to create an log.txt file inside C:\Windows\System32 and the task scheduler has no permission to create a new file inside that folder.
This is happen because i don't specify an absolute filename where to put the log file.
Let me explain this with an example of my code :
I have a program inside this directory D:\somefolder\ and the .exe directory is D:\somefolder\program.exe
This is a snapshot of my code (visual basic)
Wrong :
Dim logFileName As String = "log.txt"
/*
Create file based on logFileName directory
*/
If I execute .exe via windows explorer -> it'll create a log file with directory D:\somefolder\log.txt (no problem)
If I execute .exe via task scheduler -> it'll create a log file with directory C:\Windows\System32\log.txt (This will leave last run result 0xE0434F4D)
Correct :
Dim logFileName As String = AppDomain.CurrentDomain.BaseDirectory + "/log.txt"
/*
Create file based on logFileName directory
*/
If I execute .exe via windows explorer -> it'll create a log file with directory D:\somefolder\log.txt (no problem)
If I execute .exe via task scheduler -> it'll create a log file with directory D:\somefolder\log.txt (no problem)
So you need to specify an absolute filename where to put the log file. In my example I use AppDomain.CurrentDomain.BaseDirectory
Related
I'm trying to run a .bat file in my application. This .bat calls a JTAG application to load a firmware in microcontroller. However, I don't know why this fail in to execute the software.
If I run the .bat outside of Visual Studio it works perfectly.
I have the GUI and a Button which I will click to execute the firmware loading
To generate the command files I used a software Uniflash. This software generates a folder with all necessary files to execute the JTAG access and load the firmware.
My code is below:
private void Button_Relay_Click(object sender, EventArgs e)
{
Process MSP = new Process();
MSP.StartInfo.WorkingDirectory = #"D:\\Projects\\Test_Fixture\\Test_Fixture_Visual_Studio\uniflash_windows_64";
MSP.StartInfo.FileName = "dslite.bat ";
MSP.Start();
Thread.Sleep(500);
MSP.WaitForExit();
}
However when I executed this code the compilation is ok, but when I run this code appear this error:
Questions:
I will always generate specific bat files for each application and include the .bat folder inside the folder of VS C#, how I set up the directory path to check automatically in my software folder?
Why the VS can't find the files if the path is right?
After my .bat run I would like to read the status of the programming ( Success or fail ) How I do it?
Success
Fail:
Ad 2)
About the error:
That's because you may have specified the path wrong:
Instead of
MSP.StartInfo.WorkingDirectory = #"D:\\Projects\\Test_Fixture\\Test_Fixture_Visual_Studio\uniflash_windows_64";
either use \\ everywhere (there is only one \ between Test_Fixture_Visual_Studio and uniflash_windows_64) and skip the # OR use the # and just use one \ instead of two. So replace your line with this one:
MSP.StartInfo.WorkingDirectory = #"D:\Projects\Test_Fixture\Test_Fixture_Visual_Studio\uniflash_windows_64";
Ad 3)
About the result of your prcess:
In my opinion it is easier to not call a batch file but to call the process itself directly. In this way you can retrieve the Process.ExitCode property to retrieve the exit code of the executable (if it returns it's state via the exit code).
You can check this by calling the executable in the command shell and check the error level of the last execution by calling
echo %ERRORLEVEL%
Usually 0 indicates success, everything else indicates a failure of some kind.
I'm running msbuild in a build script and I get this error:
MSBUILD : error MSB4166: Child node "2" exited prematurely. Shutting down. Diagnostic information may be found in files in the temporary files directory named MSBuild_*.failure.txt.
I cannot find the file MSBuild_*.failure.txt on my machine. Is it something that needs to be configured? If not, what would the default location for that file be?
You can run
msbuild /v:diag > c:\log.txt
to force your log file to go to c:\log.txt.
Alternative, you may use /flp:filename=c:\log.txt, more information here.
TL;DR
Why
System.Reflection.Assembly.GetExecutingAssembly().Location
returns "<Unknown>"?
The whole story:
When I run my console application manually, everything goes well. When I set Task Scheduler to run my app, there is a problem: my app can't find some dependent files.
These files are written in the .config file like this:
<add key="SomeFile" value="SomeFolder\SomeFile.xml"/>, I need only relative pathes.
When I run my app manually, 'current folder' = 'application folder', but when I run with Task Scheduler, 'current folder' = C:\Windows\system32, because with Task Scheduler my app runs under taskeng.exe which lies in system32.
So to find assembly path I want to use this code:
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
from this answer https://stackoverflow.com/a/16102640/6184866.
But it doesn't work.
After native compilation, the assembly no longer exists on the file system.
A more recent way to pull the current directory is:
AppContext.BaseDirectory
This works in .net6
I had this same issue also with a console application.
I only received this error when:
The assembly is built as release with optimisations on
The program is run outside of Visual Studio and then the process is attached to
The command Assembly.GetExecutingAssembly().Location is executed via the Immediate Window.
It can be replicated with the following code. The sleep in a loop is just to give me time to attach the debugger.
static void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine(10 - i);
Thread.Sleep(1000);
}
Console.WriteLine(Assembly.GetExecutingAssembly().Location);
Console.WriteLine(Directory.GetCurrentDirectory());
Console.ReadLine();
}
Breakpointing this code (when the above constraints are true) and from the Immediate Window executing the command Assembly.GetExecutingAssembly().Location returns <Unknown>. Executing Directory.GetCurrentDirectory() returns Cannot evaluate expression because the code of the current method is optimized.
However, both commands execute and print the expected correct values to the console.
I have a visual studio installer project which installs a C# app, I have a custom action and code to run the process after install is complete.
Let's say the logged in user on windows machine is "john". Now when john runs the msi installer, I check the process in the taskmanager and it shows that msiexec.exe is the process name for installer and it is running as user "john"
The installer completes and runs the install app's process myapp.exe now when I check this process in taskmanager of windows it shows that myapp.exe is running as SYSTEM (which I do know what account is that and why its not running as john)
Problem
When myapp.exe runs as SYSTEM user it can not create com component instance of a component (iTunes in my case) which was already running as user john. If the component was not running then creating isntance of the iTunes is sucessful, otherwise it fails.
Question
So is it possible to make sure when installer runs as john, when it finishes it starts process myapp.exe as john and not as SYSTEM user ? Note that I do not asks user for password during installer.
Code that I run when installer completes
// Event handler for 'Committed' event.
private void MyInstaller_Committed(object sender, InstallEventArgs e)
{
try
{
Directory.SetCurrentDirectory(Path.GetDirectoryName
(Assembly.GetExecutingAssembly().Location));
Process.Start(Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location) + "\\MyApp.exe");
}
catch
{
// Do nothing...
}
}
This most likely happens because you are running your custom action as deferred. i.e. it is running by default under the SYSTEM user account.
A solution is to make sure you launch it immediate, for example you can launch it using a published event on the "Finish" button from the last dialog of the installation. I don't know exactly how to add a published event in VS setup projects, or if it is possible, but you can easily add one in packages built with specialized setup authoring tools.
In the Form_Load event write like this:
string lUserName=Environment.GetEnvironmentVariable("USERNAME");
Then instead of getting system user account you will get windows login user name at the time of installing MSI.
Personally I did manage to resolve this by running explorer.exe parameterized with the path to my app's executable:
Process.Start(
new ProcessStartInfo
{
FileName = "explorer.exe",
Arguments = Context.Parameters["target"],
UseShellExecute = true
});
(See end for solution)
I didn't think this was going to be hard. I have a commmand file, d:\a.cmd which contains:
copy /b d:\7zS.sfx + d:\config.txt + d:\files.7z d:\setup.exe
But these lines of C# won't execute it:
Process.Start("d:\\a.cmd");
Process.Start("cmd", "/c d:\\a.cmd");
Throws Win32Exception: "%1 is not a valid Win32 application."
Process.Start opens .pdf files...why not execute command files?
This works if I type it in a cmd window:
cmd /c d:\a.cmd
Windows XP, MS Visual Studio 2008.
Thanks in advance,
Jim
SOLUTION
I'm only SLIGHTLY embarrassed :( There was a file named cmd.exe, size zero in my app's dir. I have no idea how it got there but it is now toast and both of the above C# statements now work. I'm off to find a Harry Potter book so I can get some self-punishment ideas from Dobby...
I've got four things for you that you can try out:
(1) Try providing the full path for cmd.exe (e.g. on my machine: C:\WINDOWS\SYSTEM32\CMD.EXE).
(2) Try adding call to the command to be executed:
Process.Start(#"C:\WINDOWS\SYSTEM32\CMD.EXE", #"/c call D:\a.cmd");
(3) Besides that, I can only guess where the %1 in the Win32Exception is coming from. Maybe your file associations are set-up incorrectly.
If you type the following on the command-line:
> assoc .cmd
You will likely get a mention of cmdfile. If you then look up this token with:
> ftype cmdfile
You might get an answer along the lines of:
cmdfile="%1" %*
Those settings are stored in the registry, and this is how the command-line interpreter knows how to execute files with custom extensions. (You can find out how a PDF document is started by executing the above two statements for the .pdf extension.)
(4) If you start to suspect that your machine might be mis-configured, start regedit (the registry editor) and locate the key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor.
On my Windows XP machine (and your Process.Start example works on my machine, with different filenames though), I've got the following values stored in there:
// Name Type Value
// -----------------------------------------------
// (standard) REG_SZ (not set)
// AutoRun REG_SZ
// CompletionChar REG_DWORD 0x00000040 (64)
// DefaultColor REG_DWORD 0x00000000 (0)
// EnableExtensions REG_DWORD 0x00000001 (1)
// PathCompletionChar REG_DWORD 0x00000040 (64)
Of those, the AutoRun value might be of some interest. I think it corresponds to the /d command-line switch of cmd.exe, which controls whether cmd.exe attempts to start files with custom extensions. Usually, this is enabled. Maybe, on your machine, it isn't?
Or you can do a .bat file, then call this file through System.Diagnostics.Process.Start(). It won't redirect output to Console Application, but it would certainly execute the commands inside.
You need to specify the process full name (cmd.exe).
You should try
Environment.GetFolderPath(Environment.SpecialFolder.System) + "cmd.exe"
So you can be sure to execute the right file even if a cmd.exe is in your applications directory.
It looks like something wrong with your computer. Try running this on another machine. This should work. Process.Start(string) uses ShellExecuteEx to launch the file, so it's pretty much the same thing as double-clicking the file in Explorer, as you supposed.
A simple test worked for me.
B:\foo.cmd:
#echo Hello from foo.cmd!
#pause
Program.cs:
class Program{
static void Main(){
System.Diagnostics.Process.Start("B:\\foo.cmd");
}
}
This works as expected.
Your error message is suspicious, "%1 is not a valid Win32 application." The value in my registry at HKCR\cmdfile\shell\open\command is
"%1" %*
The %1 gets replaced by the file name, and the %* can be ignored here (it indicates that any further command-line arguments should be passed along, but we're not concerned with that right now).
The fact that the file itself is launched to handle this type of file indicates that Windows itself knows how to launch this type of file. On a normal installation of Windows, the following extensions should be set up similarly:
.exe Windows and DOS executable files
.com DOS "command" files
.bat Windows and DOS batch files
.cmd Windows NT batch files
.pif Windows shortcuts to DOS executable files
If you go to HKCR\.xxx (where xxx is any of the above), the "(Default)" value should be xxxfile. If you then go to HKCR\xxxfile\shell\open\command, the "(Default)" value should be "%1" %*. Also the "(Default)" value of HKCR\xxxfile\shell should be either not set or open.
If you have anything else in any of these values, then some program has attempted to insert itself into the execution process. Viruses sometimes do this (Sircam, for example).
Have you tried executing cmd.exe, and passing the .cmd file to it as an argument?
hmm try:
System.Diagnostics.Process myproc = new System.Diagnostics.Process();
myproc.EnableRaisingEvents=false;
myproc.StartInfo.FileName="d:\\a.cmd";
myproc.Start();
MessageBox.Show("did the command");
Have you tested your batch file in the directory, context it's going to run? The error message with %1 looks like the problem may be in there?