hope this is a valid questions.
This is legacy code I maintain.
A Windows Services (logon as SYSTEM or A "dedicated service user") will execute a portable python exe, the python.exe run code (.pyc) with additional parameters.
The question:
No exception is thrown from Process.Start() and it return false, is there a way to investigate why ? Please dont paste MSDN documentation i have read it enough times.
I try to execute the python with UseShellExecute true/false, does not matter, does not work.
The C# Windows Service code:
var processInfo = new ProcessStartInfo(_pythonExePath/*path to python.exe*/, exeParams/*path to pyc, and additionl params*/)
{
WorkingDirectory = workingDirectory
};
var process = new Process
{
StartInfo = processStartInfo,
EnableRaisingEvents = true
};
process.Start();
When I executed python.exe with arguments from command line (as the "dedicated service user" and also with psexec as SYSTEM), it worked.
Call GetLastError() or Marshal.GetLastWin32Error() returned 0.
There was nothing in Event Viewer (Application, System, Security)
I have captured with process monitor the 2 executions, the one that worked, the one that did not. both executions shows python.exe started, and there are ofcourse thousands of calls afterwards.. what am i suppose to investigate ? how can i see if a security policy has blocked my exe ?
Thanks.
Check the docs for the return value of Process.Start
true if a process resource is started; false if no new process resource is started (for example, if an existing process is reused).
So false does not necessarily indicate an error occurs in Process.Start; if there was an error, it should have thrown an exception, and it won't just set an error code and silently go to the next line.
As suggested by Harry in the comment, using Process Monitor to monitor python.exe is a good start.
Related
I have an app that runs DirectX 11 that plays a scene and generates an mp4.
I am trying to launch it through Process.Start so that I can manage the process and force it to timeout if it crashed or doesn't close correctly.
When I test the function on my local Win10 machine it works perfectly, and when I run it through CL or a .BAT file on the WinServ2012R2 machine it works perfectly too.
However when I try to run it through the Process.Start function on the server machine it fails to open DirectX
var startInfo = new System.Diagnostics.ProcessStartInfo($"{AppLocation}", $"{Parameters}")
{
WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal,
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = false,
WorkingDirectory = $"{DirectoryName}",
Verb = "runas"
};
var loop = 0;
while (!System.IO.File.Exists($"{FileLocation}"))
{
loop++;
using (var p = System.Diagnostics.Process.Start(startInfo))
{
Logger.Info("Process Running....");
if (!p.WaitForExit(300000))
{
p.Kill();
}
if (loop >= 5)
break;
}
}
Edit: The DirectX error is: DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
0x887A0022
It’s probably something about the environment.
If the parent process is a normal Win32 console or GUI app running inside a desktop of that server, put something like Sleep( 60000 ); in the first line of your main() or WinMain function, and use Process Explorer to find differences between manual launch which works, and programmatic launch which fails. Check the “Image”, “Security” and “Environment” tabs of the processes.
If the parent process is a system service, it’s more complicated. Services generally run under another user account and you gonna need some setup to allow the service, or a child process launched by the service, to access GPU.
Another possible reason is anti-virus or anti-malware breaking things.
P.S. Note you have minor bugs in your code.
One thing, when you detect timeouts, Process.Kill is asynchronous, you need to wait afterwards.
Another one, you specifying RedirectStandardOutput = true but you don't consume that stream. If the child process prints a lot of text it will eventually stall waiting for the parent process to consume the data buffered in that pipe. If you don’t care about output, don’t redirect these streams. If you do care, redirect and consume the data as soon as it printed, either on a separate thread or with async/await.
I am getting an exception on my server side code, which is serving up a silverlight app,
Win32Exception - No such interface supported
Our server side C# code starts up a separate process for a short task because of a third party dll not being thread safe. So the error above occurs in part of the code like this,
Process process = new Process();
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.CreateNoWindow = true;
processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
processStartInfo.FileName =
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", "PreviewGenerator.exe");
process.StartInfo = processStartInfo;
process.Start(); // THIS IS WHERE THE EXCEPTION OCCURS
process.WaitForExit();
The PreviewGenerator.exe process does not start when it is not working, the exception occurs where the comment is above.
UPDATE:
I have run process monitor on the IIS server when the issue occurs. This shows that the w3wp process does this,
Thread Create
Access the file PreviewGenerator.exe
Hive unloaded (this is the registry)
Thread Exit
And it does this before calling the other process. If I compare this with a the process monitor log when it is working it does this,
Thread Create
Access the file PreviewGenerator.exe
Process Start
Does heaps of stuff with PreviewGenerator.exe including reading / writing / registry, etc.
Process Exit
Hive unloaded
Thread Exit
But process monitor does not show any information as to why the first case doesn't work.
Is there a way I can see why the thread exits prematurely?
Also I think this problem relates to when my server is being loaded up more, and much more memory is being used. How can I prove this?
I had a similar issue, I used
processStartInfo.UseShellExecute = false;
and that fixed it for me.
http://www.progtown.com/topic31343-process-start-processstartinfo-startinfo.html
I found the best thing to do was to create a separate app pool for my application in IIS and set an upper limit for the amount of RAM it could use. Also I found it useful to turn on the 'Generate Recycle Event Log Entry' items under the app pool settings.
You can then go to the system event log and filter out the items with a source of 'WAS' to understand what is going on in the app pools, when they are restarting and when they stop from being idle etc.
I think the main problem in our case is that the IIS box was running out of memory. Tuning the app pools and adding some extra RAM seems to have solved it.
Why this code runs perfectly on my development computer (win7 32bit) and on target server(2008r2 64bit) as console app. But when I try to run it as a web service on the target server it does nothing. No error, nothing.
If I remove
exitMsg = proc.StandardOutput.ReadToEnd();
then it fail with error:
System.InvalidOperationException:
Process must exit before requested
information can be determined.
[WebMethod]
public string GetRunningProcesses()
{
ProcessStartInfo pInfo = new ProcessStartInfo();
pInfo.FileName = #"E:\bin\PsList.exe";
pInfo.WindowStyle = ProcessWindowStyle.Hidden;
pInfo.CreateNoWindow = true;
pInfo.UseShellExecute = false;
pInfo.RedirectStandardOutput = true;
string exitMsg = "";
int exitCode = 1;
using (Process proc = Process.Start(pInfo))
{
exitMsg = proc.StandardOutput.ReadToEnd();
proc.WaitForExit(1000);
exitCode = proc.ExitCode;
}
return exitMsg;
}
I think there must be something about user under which code runs. As web service this code runs under asp.net user and this might couses the problems.
Please advice me how to fix this. Thank you very much.
RESOLVED
The problem was with EULA dialog, which poped up but it was invisble due to ProcessStartInfo settings.
When I run PsList.exe via CMD under account which is also used for Application pool for this web service, I get prompted for an EULA agreement and after that everthing works fine.
The strange thing is that I have "pInfo.Arguments = "/accepteula";" in my real code. This should prevent my probem, but it didn't and I don't know why.
If any of you knows why, please tell me.
Thank you very much for all the help. You are trully good peoples here.
I think your only problem is with:
proc.WaitForExit(1000);
Which instructs the program to wait for a second for the process to finish. On your machine, the process finishes fine. On another machine, though, it may take longer. Try changing to:
proc.WaitForExit();
Which will wait indefinitely for the program to exit.
You may also want to redirect the output of the Process to see if the programming is hanging or waiting for something else from you (or, in this case, your code).
In addition, the process may be hitting an error and writing a message to StandardError rather than StandardOutput. Try setting pInfo.RedirectStandardError = true; and reading that as well to see if there's anything you're missing.
The problem was with EULA dialog, which poped up but it was invisble due to ProcessStartInfo settings.
When I run PsList.exe via CMD under account which is also used for Application pool for this web service, I get prompted for an EULA agreement and after that everthing works fine.
The strange thing is that I have "pInfo.Arguments = "/accepteula";" in my real code. This should prevent my probem, but it didn't and I don't know why.
If any of you knows why, please tell me.
Thank you very much for all the help. You are trully good peoples here.
Try wrapping your business logic in a try / catch block that catches any exception and either writes it to the output or to a log file.
In my local network ,I have more than 10 pc.I need to take care all of the pc.I want to know all pc’s hardware informations.I also want to control those pc,Suppose ,at this moment I want to restart one of my client pc.Is it possible in C#.if have any question plz ask.Thanks in advance
I use bellow syntax to execute command.
try
{
// create the ProcessStartInfo using "cmd" as the program to be run,
// and "/c " as the parameters.
// Incidentally, /c tells cmd that we want it to execute the command that follows,
// and then exit.
System.Diagnostics.ProcessStartInfo procStartInfo =
new System.Diagnostics.ProcessStartInfo("cmd", "/c " + "shutdown /r /m \\172.16.1.3 /t 1 /");
// The following commands are needed to redirect the standard output.
// This means that it will be redirected to the Process.StandardOutput StreamReader.
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
// Do not create the black window.
procStartInfo.CreateNoWindow = true;
// Now we create a process, assign its ProcessStartInfo and start it
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
// Get the output into a string
string result = proc.StandardOutput.ReadToEnd();
// Display the command output.
Console.WriteLine(result);
}
catch (Exception objException)
{
// Log the exception
}
Using the above code I get the message "The network path was not found."
Pls check the url.
http://support.microsoft.com/kb/317371
If you want to make a program which u can able to get the remote system information. You have to use Microsoft's Remoting.Here we can able to create an object in the remote system and we can able to control it.
It is possible to get System's information by executing the System.Diagnostics.ProcessStartInfo.
It is possible to get system information using "systeminfo" .It is possible to take the output using C#
Pls chk the this.
I hope this will be useful for you.
I don't think this is a C# question, cause this can be done much more elegant with things like Group Policy Editor, System Management Server, System Center Operations Manager, etc.
To do some simple tasks on a remote machine you can take a look into the PsTools.
With those requirements my first stop would be WMI. There's for example the Win32_OperatingSystem class with its Reboot and Shutdown methods and the Win32_Processor with all kinds of information about the CPU.
This MSDN section shows you how to use it from .Net: Getting Started Accessing WMI Data
This MSDN section has quite a lot of short VBScript samples for doing various things using WMI, and even if the code is different, at least you can see which WMI classes/methods/properties you should be looking at: WMI Tasks for Scripts and Applications
Please note RB's comment though, you'll need to have the correct permissions for it to work.
Edit: Forgot that since you'll want to connect to other computers, this sample will be useful: How To: Connect to a Remote Computer
Processes launched via Process.Start seems to have around a 26-second delay when the spawned process (the "child") launches more new processes (the "grandchildren") - I'm trying to find a way to solve this issue. Specifically, this is occurring when the original process (the "parent") is an ASP.Net website or a Windows Service (tried both).
We're attempting to run a server-side command-line tool to gather information, make modifications in the file system, and continue with other processes when the "child" is finished. When creating the "child" directly via command-line, there is no delay, and with certain command-line parameters, the "child" does not spawn new processes, and there is no delay. However, with other parameters, the "child" spawns "grandchildren" (the same executable as itself, but we can't modify its code) and seems to have a 25-30 second (usually 26 seconds) delay before the first process is started, and then runs normally.
I've tried modifying the UseShellExecute property, the CreateNoWindow property, and the WindowStyle property, to no effect. ErrorDialog and the RedirectStandard* properties are false.
The code I'm using is as follows:
using (Process p = new Process())
{
p.StartInfo = new ProcessStartInfo(exePath, args)
{
WorkingDirectory = workingDirectory,
UseShellExecute = true,
CreateNoWindow = true,
};
p.Start();
p.WaitForExit();
}
Oh, I don't think it matters as I've seen the issue referenced elsewhere (but no solutions), but the exePath I'm using points to msysgit's git.exe.
I had this same exact problem executing a .bat file which in turn made a call to git.cmd using Process.Start from a windows service. The git command would execute immediately if the .bat file was ran directly from the command line, but would delay exactly 50 seconds any time it was called from the windows service.
It came down to a permissions issue. After configuring my windows service to run as a user (administrator in my case), the git process ran immediately. You can probably modify your service installer to run the service as "User", but you can just modify the service properties after it's installed to the same effect.
There may be ways to enable "Local Service" to get around the delay, but I wouldn't know how.
Hard to tell a reason why this might happen, you need to do further troubleshooting.
I would suggest that you use Process Explorer and Process Monitor to look for potential problems.
I would guess that the problem is not directly in your code but more related to the environment of the user. For example, the w3wp.exe process runs in a non-GUI session (session 0) and the user might not be configured to have web access (proxy configuration) so that you might see a timeout issue here.