I have this very simple program
Process process = new Process();
process.StartInfo.FileName = #"psexec";
process.Start();
But when I run it the debug says "The system cannot find the file specified"
If I have the same program and change "psexec" by "Notepad", it works and opens notepad.
Process process = new Process();
process.StartInfo.FileName = #"notepad";
process.Start();
This is weird because I have my psexec in the System32 and if run "psexec" using Windows-Run, it works.
Thank you in advance for any help.
Update: I specify the full path #="C:\Windows\System32\PSexec.exe" and It doesnt work. But If I move Psexec to, as example #"D:\psexec.exe" it works!!
Why coud this happen?
Running programs from c:\windows\system32 is troublesome on a 64-bit operating system. The workaround is Project + Properties, Build tab, change Platform target to AnyCPU. Or to copy the file also to c:\windows\syswow64.
Or to just not put it in the Windows directory, it is not an operating system specific file that belongs there. The appropriate place is the same directory as your EXE.
You can learn more about the File System Redirector in this MSDN article.
try specify the full path of 'psexec'
there is any property 'WorkingDirectory', which might help.
Related
I have the following issue:
I have a C# app that runs as a 32-bit Application on my 64-Bit Machine. This application opens a process and starts wbadmin to make a backup of the C drive.
Now: when I call enter "wbadmin" in the command line wbadmin works and shows lists all its commands.
In my c# app when i do
ProcessStartInfo info = new ProcessStartInfo("wbadmin", $"start backup -backupTarget:{destinationDrive} -include:C: -quiet -vssCopy")
{
UseShellExecute = false
};
Process p = new Process()
{
StartInfo = info,
EnableRaisingEvents = true
};
p.Start();
it tells me that the file specified cannot be found.
I did some research and I think my app is looking for the wbadmin in the WOW64 folder, where it cant find it because it is inside the System32 Folder.
How do I tell my program to use the correct wbadmin.exe in the correct location?
Do I HAVE to run the app as a 64-bit application for it to work?
If so how would i support 32-bit architecture?
Thanks
Thanks to #PavelAnikhouski for providing me with the correct answer.
I had to specify the path to sysnative.
I am running a VBS file that needs to be executed on the 64-bit version of cscript. On the command line, when I call cscript, it opens the 64-bit version located at C:\Windows\System32\cscript.exe and the VBS file works fine.
However, I'd like to call this VBS file through C# as a Process. Starting the process with the FileName as cscript does open cscript, but only opens the 32-bit version, located at C:\Windows\SysWoW64\cscript.exe.
Even when I set the FileName to specifically point to the 64-bit version of cscript, it only loads the 32-bit version.
How can I force the process to open the 64-bit version of cscript?
Here is my code, including the 64-bit version file path explained above:
string location = #"C:\location";
Process process = new Process();
process.StartInfo.FileName = #"C:\Windows\System32\cscript.exe";
process.StartInfo.WorkingDirectory = location+#"\VBS\";
process.StartInfo.Arguments = "scriptName.vbs";
process.Start();
Depending on your requirements there is another solution.
Some background: When you run a 64-Bit application and try to start cscript.exe then you call C:\Windows\System32\cscript.exe (or more general %windir%\System32\cscript.exe)
However, when you run a 32-Bit application then each call to %windir%\System32\ is automatically redirected to %windir%\SysWOW64\. In this directory you will find all your 32-Bit DLL's. This redirection is done by Windows internally and your application does not recognize any difference.
In order to access %windir%\System32\ from a 32-Bit application you can use %windir%\Sysnative\, i.e. process.StartInfo.FileName = #"C:\Windows\Sysnative\cscript.exe"; should work even if you compile your application as 32-Bit.
Note, folder %windir%\Sysnative\ does not exist in 64-Bit environment, thus you may check your run-environment by Environment.Is64BitProcess, so
if Environment.Is64BitProcess {
process.StartInfo.FileName = #"C:\Windows\System32\cscript.exe";
} else {
process.StartInfo.FileName = #"C:\Windows\Sysnative\cscript.exe";
}
See also File System Redirector
Note, a similar mechanism exists also for the Registry, see Registry Redirector
A simple answer has arose:
In my C# application I am creating, in Visual Studio (2017) had selected my Platform target to Prefer 32-bit, which should perhaps better be called as "force 32-bit".
By unselecting this option, my process ran as 64-bit, both by specifying the 64-bit path as the code above, but also by just running the cscript by name.
process.StartInfo.FileName = "cscript";
Toggle this option inside Properties > Build > Prefer 32-bit
I'm trying to compile an IL Code to an Assembly. The ilasm.exe should get called by my C# Application. I'm invoking the ilasm.exe through an ProcessStartInfo Instance. The generation of the PE works fine and my Assembly is working.
My problem is that the files that were created by my application, afterwards need administrator privileges to be executed.
If I call ilasm.exe manually from command line, no admin rights are needed.
Used ilasm.exe command:
ilasm.exe /qui /output="c:\test\newFile.exe" <path to il file>
My Application calling the ilasm.exe:
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = #"C:\Windows\Microsoft.NET\Framework\v4.0.30319\ilasm.exe";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = ilFilePath + " /qui /output=" + outputPath + "testFile.exe";
try
{
using (Process exeProcess = Process.Start(startInfo))
{
exeProcess.WaitForExit();
}
}
catch
{
// Log error.
}
Am I doing anything wrong? Do I need to specify anything else when calling another Process from C#?
I'm running my Application and the commandline without admin rights.
It's requiring UAC because you're not supplying a path to a writable location in output, so it's trying to write to the same folder ilasm is in (or the current folder for your app).
A non-admin user doesn't have write access to anything under %WINDIR% (the Windows folder) or %ProgramFiles%, so it's asking for elevation to a user that does have write access to the folder.
What is patchFile?
This comment by #Chris is relevant to this puzzle, I don't see it in the question. You are probably dealing with a difficult problem that Microsoft needed to solve with UAC. Supporting old programs that need UAC privileges but don't ask for it because they were written before Vista. Like installers. And patch programs.
My crystal ball says that your actual program name is not newFile.exe like your question says but has a name like "update.exe" or "patch.exe". And furthermore, it isn't obvious either, that you don't include a manifest in the program you generated. A manifest that says that the program is Vista aware with the <requestedExecutionLevel> element. And furthermore, also not obvious, that when you run this from the command line by hand that you use another name for the .exe.
That's a lot of guesses, but put them together and it makes sense: Windows goes "aha! Old program, sounds like it is going to want to write to .exe files in a restricted directory. Better display the UAC prompt".
public void runBatchfile(String batchfilename)
{
try
{
ProcessStartInfo processInfo = new ProcessStartInfo(batchfilename);
processInfo.UseShellExecute = false;
Process batchProcess = new Process();
batchProcess.StartInfo = processInfo;
batchProcess.StartInfo.CreateNoWindow = true;
batchProcess.Start();
batchProcess.WaitForExit();
}
catch (Exception r) { }
}
runBatchfile(#"c:\lol.bat");
lol.bat contains these 2 lines
dir c:\ /s /b > c:\filelist.txt
exit
and when I run my code all it does is creating a filelist.txt file, but doesn't actually perform the rest of the command, which does work if I manually insert it into CMD.
Btw I've tried making the extension .cmd and I also tried without the exit command, without any other results.
please help me :)
On my Windows 7 64-bit machine with Visual Studio 2010, running this code straight from the IDE doesn't do anything whatsoever.
On a hunch that it might have something to do with permission to write to the root directory of drive C:, I tried running the .exe directly from an Explorer window with admin rights (right-click, Run as Administrator) and that worked.
I'd say it's a permission problem.
Maybe you could redirect the output to a file located elsewhere?
update:
I changed the batch file so that the dir command gets redirected to my desktop and it runs just fine.
I've had issues with this as well when calling from C#. The workaround that I usually use is to physically allow it to show the window when running the command. Not sure why this makes a difference but it has worked for me in the past.
I'm launching the path C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools\IIS Manager.lnk via Process.Start, but it fails with The system cannot find the file specified.
The link shows up on a dir, so it exists.
Can it be permissions?
Notes:
The path is auto-discovered by iterating over the Start Menu directory.
I can launch it via explorer and command line.
Clarifications:
Code is as follows:
public void Execute() { Process.Start(_shortcut.FullName);}
_shortcut is of type FileInfo
_shortcut.Exists is true, so the file can be found
replacing _shortcut.FullName with the explicit path #"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools\IIS Manager.lnk" has the same effect.
This is a WPF app using Caliburn and MEF.
Running as Administrator has the same effect.
This here on the other hand seems to work:
[Fact]
public void TestIisManager()
{
var path = new FileInfo(#"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools\IIS Manager.lnk");
Process.Start(path.FullName);
}
It does seem to be a bit "environment" based.
Second clarification:
It seems to work in a Windows 7 x86 but not in a Windows 7 x64.
I ran into this recently. Windows Forms based solution, VS2013, x64 machine. Process.Start() could not launch applications via .lnk file. Using process explorer, it seemed that the target specified in the .lnk file was resolving incorrectly to c:\program files (x86)... instead of c:\program files... I followed Bruno's excellent advice, but then again my Target was already marked as "AnyCPU".
After some head scratching, it turned out there's a new compiler flag in VS11+ called "Prefer 32-bit" that was checked by default. This was forcing the EXE output to be 32-bit even though my OS was 64-bit and platform was set to AnyCPU. After I unchecked and recompiled, the problem was fixed.
More reading at: http://blogs.microsoft.co.il/sasha/2012/04/04/what-anycpu-really-means-as-of-net-45-and-visual-studio-11/
Found the issue.
The WPF application was compiled as x86 (all other dlls were compiled as AnyCPU), and when launching some executables or links in a 64 bit machine it failed.
Changing the "Platform Target" to AnyCPU fixes this.
This may not actually relate to your situation, but you can launch the IIS Manager by using
Process.Start("inetmgr.exe")
If you want to continue to use the shortcut, it will probably work if you start the process using a ProcessStartInfo and set ProcessStartInfo.UseShellExecute to true
Can you make sure that you are trying this from an STA thread? You can see whether the apartment state is a problem if the following sample succeeds:
using System;
using System.Diagnostics;
public class Program
{
// make sure to call Process.Start from an STA thread
[STAThread]
static void Main(string[] args)
{
Process.Start(#"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools\IIS Manager.lnk");
}
}
Process.Start calls ShellExecute under the hood to run the file passed. As described by Raymond Chen, shell functions require an STA thread:
One possible reason why ShellExecute returns SE_ERR_ACCESSDENIED and ShellExecuteEx returns ERROR_ACCESS_DENIED
As stated already, you will see the "The system cannot find the file specified" error because Windows is looking for inetmgr.exe in ...\SysWOW64\intsrv\ (caused by file system redirection), but it only exists in ...\System32\intsrv\.
This is caused by your 32-bit executable attempting to launch a 64-bit executable. As suggested, not using a 32-bit executable will solve this, but for anyone who must build for 32-bit (a WiX installer bundle in my case), try the following.
Using the start menu LNK/shortcut to inetmgr.exe instead of the executable is a good start, but an extra level of distance is required. This can be provided by using explorer.exe, which can be launched from a 32-bit executable:
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = "explorer.exe";
startInfo.Arguments = "/seperate /root,\"C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Administrative Tools\\IIS Manager.lnk\"";
System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo = startInfo;
process.Start();
It's a bit of a hack, but try launching it like this:
string path = #"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools\IIS Manager.lnk";
Process.Start("cmd.exe", String.Format("/k \"\"{0}\"\"",path));
Note the double quotes needed to save the spaces in the path.
That way, you might see a more precise error message and/or walk around in the command environment afterwards to see what is wrong with the path.