How could I launch sysprep.exe with specific arguments from my c# program ?
public void cmdPrint(string[] strcommmand)
{
Process cmd = new Process();
cmd.StartInfo.FileName = "cmd.exe";
cmd.StartInfo.RedirectStandardInput = true;
cmd.StartInfo.RedirectStandardOutput = true;
cmd.StartInfo.CreateNoWindow = true;
cmd.StartInfo.UseShellExecute = false;
cmd.Start();
cmd.StandardInput.WriteLine("cd c:\\");
foreach (string str in strcommmand)
{
cmd.StandardInput.WriteLine(str);
}
cmd.StandardInput.Flush();
cmd.StandardInput.Close();
writeLine(cmd.StandardOutput.ReadToEnd());
}
and I call it from my Windows Form Application,
string[] cmd = { "cd C:\\Windows\\System32\\Sysprep", "sysprep.exe /audit /reboot"};
consoleBox1.cmdPrint(cmd);
But it doesn't seem to start the sysprep.exe. I pasted the two commands in a .bat and launched it with,
System.Diagnostics.Process.Start(Application.StartupPath + "\\awesome.bat");
but it doesn't work either (opens a black window and closes immediately)
Running the bat file from explorer works, so i guess I am missing some permission in my c# application.
In my app.manifest,
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
Is it possible to launch sysprep ? My application is made to run on Windows 7,8,8.1 and 10 on the normal desktop and on audit mode.
EDIT:
I tried the code without fulshing and closing the cmd but the program went to not responding
var procInfo = new
ProcessStartInfo("C:\\Windows\\System32\\Sysprep\\sysprep.exe");
procInfo.Arguments = "/audit /reboot";
var proc = new Process();
proc.StartInfo = procInfo;
proc.Start(); //Actually executes the process
proc.WaitForExit();
Gives error :
The system cannot find the file
specified/nSystem.ComponentModel.Win32Exception (0x80004005): The
system cannot find the file specified at
System.Diagnostics.Process.StartWithShellExecuteEx(ProcessStartInfo
startInfo) at System.Diagnostics.Process.Start() at
Windows_SSD_Optimizer_Method_1.Method1.btn_all_Click(Object sender,
EventArgs e) in :line 182/n/nThe system cannot find the
file specified/nSystem.ComponentModel.Win32Exception (0x80004005): The
system cannot find the file specified at
System.Diagnostics.Process.StartWithShellExecuteEx(ProcessStartInfo
startInfo) at System.Diagnostics.Process.Start() at
Windows_SSD_Optimizer_Method_1.Method1.btn_all_Click(Object sender,
EventArgs e) in :line 182/n/n
http://i.stack.imgur.com/0Em8O.png
In Windows 8 x64 you should be aware of File System Redirection.
When a 32bit application wants to access the System32 folder on a
64bit OS, Windows 8 will default any paths to syswow64 on the idea
that a 32bit program would really be looking for the 32bit files.
Try this path instead:
#"c:\windows\sysnative\sysprep\sysprep.exe"
var procInfo = new ProcessStartInfo(#"c:\windows\sysnative\sysprep\sysprep.exe");
procInfo.Arguments = "/audit /reboot";
var proc = new Process();
proc.StartInfo = procInfo;
proc.Start(); //Actually executes the process
proc.WaitForExit();
Found a solution for Windows Versions older than 8:
You need to compile your programm as x64 binary. If you compile it as x86 binary the system will redirect you to SysWOW64 instead of System32.
If you need to be compatible with x64 and x86 you could also disable folder redirection:
// Disables folder redirection
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);
// Enables folder redirection
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);
Related
I am trying to open the restore point dialog from C# like
I'm using the following code:
Process.Start("SystemPropertiesProtection");
and from cmd:
public static string ExecuteCMD(IEnumerable<string> commands,
bool inBackground,
bool runAsAdministrator ,
bool WaitProcessForExit)
{
try
{
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
if (commands.Any())
{
p.StartInfo.Arguments = #" /C " + string.Join("&&", commands);
}
if (runAsAdministrator)
{
p.StartInfo.Verb = "runas";
}
if (inBackground)
{
p.StartInfo.CreateNoWindow = true;
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
}
else
{
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.UseShellExecute = false;
}
p.OutputDataReceived += (sender, e) => { MessageBox.Show(e.Data); };
p.ErrorDataReceived += (sender, e) => { MessageBox.Show(e.Data); };
p.Start();
if (WaitProcessForExit)
{
p.WaitForExit();
}
return "";// p.StandardOutput.ReadToEnd();
}
catch (Exception ex)
{
FRM_MSG f = new FRM_MSG();
f.ShowDLG(" ",
ex.Message + "\n" + ex.StackTrace.ToString(),
FRM_MSG.MSGIcon.Error,
FRM_MSG.BTNS.One,
new string[] { "Ok" });
throw ex;
}
}
Executor.ExecuteCMD(new string[] { "SystemPropertiesProtection" }, true, false, false);
and even create shortcut to create restore point like this:
and open this shortcut with:
Process.Start(RestorePointShortcutFilePath);
but they always open three tabs and don't open the restore point tab
How do I open restore point dialog like shown on first image which has 5 tabs and not 3 tabs, my OS is Windows 7 64 bit? Thanks.
The issue that you're seeing is because of the File System Redirector which is occurring because you're running your program as 32-bit on your 64-bit OS. Therefore, you're executing %windir%\SysWOW64\SystemPropertiesProtection.exe (ex: C:\Windows\SysWOW64\SystemPropertiesProtection.exe).
There are a few ways to avoid this issue. Uncheck "Prefer 32-bit" (Project => <project name> Properties => Build => uncheck 'Prefer 32-bit'). Compile as x64, or check if your application is running as 32-bit on a 64-bit OS. If so, set the appropriate fully-qualified filename.
The documentation states:
32-bit applications can access the native system directory by
substituting %windir%\Sysnative for %windir%\System32. WOW64
recognizes Sysnative as a special alias used to indicate that the file
system should not redirect the access. This mechanism is flexible and
easy to use, therefore, it is the recommended mechanism to bypass file
system redirection. Note that 64-bit applications cannot use the
Sysnative alias as it is a virtual directory not a real one.
Try the following:
Create a new Windows Forms App (.NET Framework)
Add an Application Manifest to your project
Note: This is used to prompt the user to execute the program as Administrator.
In VS menu, click Project
Select Add New Item...
Select Application Manifest File (Windows only)
Click Add
In app.manifest, replace
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
with
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
Add the following using directives:
using System.IO;
using System.Diagnostics;
private void OpenSystemPropertiesProtection()
{
string filename = System.IO.Path.Combine(Environment.GetEnvironmentVariable("windir"), "System32", "SystemPropertiesProtection.exe");
//environment variable windir has the same value as SystemRoot
//use 'Sysnative' to access 64-bit files (in System32) if program is running as 32-bit process
//use 'SysWow64' to access 32-bit files on 64-bit OS
if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess)
filename = System.IO.Path.Combine(Environment.GetEnvironmentVariable("windir"), "SysNative", "SystemPropertiesProtection.exe");
Debug.WriteLine($"filename: {filename}");
ProcessStartInfo startInfo = new ProcessStartInfo(filename);
startInfo.UseShellExecute = true;
startInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(filename);
Process.Start(startInfo);
}
Resources:
File System Redirector
Running 32-bit Applications
Use ShellExecute to execute the command.
ProcessStartInfo info = new ProcessStartInfo();
info.FileName = "SystemPropertiesProtection";
info.UseShellExecute = true;
Process.Start(info);
I have tested this on Windows 11, but it will probably also work on Windows 7. Be aware that Windows 7 has reached end-of-life back in 2020. It shouldn't be used anymore.
I need to spawn processes from my C# program, but in some cases full path to an executable can be more then 256 characters.
I have studied several related topics on this site, as well as this article #MSDN. According to that information this should be possible by using \\?\ prefix, but I still couldn't make it work. It looks like system tries to start the process, but fails. I am getting "SmartScreen has stopped working" message instead.
Am I missing something? Here is my code:
private void button2_Click(object sender, EventArgs e)
{
ProcessStartInfo start = new ProcessStartInfo();
start.Arguments = "";
start.FileName = #"\\?\c:\11111111111111111111111111111111111111111111\222222222222222222222222222222222222222222222\3333333333333333333333333333333333333333333333\444444444444444444444444444444444444444444444\5555555555555555555555555555555555555555555555\6666666666666666666666666666666666666666666666\test.exe";
start.WindowStyle = ProcessWindowStyle.Normal;
start.CreateNoWindow = true;
int exitCode;
using (Process proc = Process.Start(start))
{
proc.WaitForExit();
exitCode = proc.ExitCode;
MessageBox.Show(String.Format("Exit code: {0}", exitCode));
}
}
I am running this on Windows 10, version 1703 (OS Build 15063.1387).
I am trying to open different files with their associated applications like this:
ProcessPath = #"C:\Users\Public\Pictures\Sample Pictures\Tulips.jpg";
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.FileName = ProcessPath;
processStartInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(ProcessPath);
process = new Process();
process.StartInfo = processStartInfo;
process.EnableRaisingEvents = true;
process.Exited += Process_Exited;
process.Start();
Please can you help me get hold of the Process object that represents the application opened because after the call to process.Start(); most of the fields inside process have threw exceptions.
Thanks.
I have managed to find a solution:
using the Windows API function
[DllImport("shell32.dll")]
static extern int FindExecutable(string file, string directory, [Out] StringBuilder lpResult);
to return the associated application path for a given file. I can then use the original code i posted to execute that associated application with the original file passed through as an argument!
I want to launch a program from inside my program, now I can do this relatively easy, and it works using:
protected void butVNC_ItemClick(object sender, EventArgs e)
{
string str = #"C:\Program Files\RealVNC\VNC4\vncviewer.exe";
Process process = new Process();
process.StartInfo.FileName = str;
process.Start();
}
But my problem is, if my program is installed on a 64-bit operating system, that file path is not right, as it is Program Files(x86) so is there a way to detect and run different code or anything.
From .NET 4.0, you can use Environment.Is64BitProcess.
Example:
if (Environment.Is64BitProcess)
{
// Do 64 bit thing
}
else
{
// Do 32 bit thing
}
You can use the %ProgramFiles% enviroment variable to point to the correct Program Files directory. It should point properly to the correct path.
An example : C# - How to get Program Files (x86) on Windows 64 bit
I ended up using this, and works well, and is really simple:
if (IntPtr.Size == 8)
{
string str = #"C:\Program Files(x86)\RealVNC\VNC4\vncviewer.exe";
Process process = new Process();
process.StartInfo.FileName = str;
process.Start();
}
else if (IntPtr.Size == 4)
{
string str = #"C:\Program Files\RealVNC\VNC4\vncviewer.exe";
Process process = new Process();
process.StartInfo.FileName = str;
process.Start();
}
Thank you for your help though :)
I'm trying to run a shell command with elevated permisions in C#. However the following code returns:
The system cannot find the file specified.
string command = System.IO.Path.Combine(Environment.SystemDirectory, "wdsutil.exe");
string args = ""; //Appropriate arguments
ProcessStartInfo psInfo = new ProcessStartInfo(command);
psInfo.Arguments = args;
psInfo.Verb = "runas";
try
{
Process p = Process.Start(psInfo);
p.WaitForExit();
return "Try Done";
}
catch(Exception e)
{
return e.Message;
}
The error exists without the SystemDriectory prefixed as well.
However, the command does not return the error if I execute the command C:\wdsutil (or any other command in C:).
How do I get Process.Start to run these commands in System32
system32 is on newer systems (esp. 64 Bit windows 7 or 2008) not "real"... it is synthezied from some internal directories and when it is accessed it shows different apps (32 vs. 64) different content...
I test ran the code, changing the executable to one that I located in C:\Windows\System32 directory. It runs ok. (I am running Win 7 64 Bit)
Suggestion: Make sure that the exe is present in the
C:\Windows\System32, or wherever you are trying to run it from. Also, make sure it is unblocked if you'd downloaded it from the internet (Right click the exe > Properties > Unblock).
string command = System.IO.Path.Combine(Environment.SystemDirectory, "wscript.exe");
string args1 = ""; //Appropriate arguments
ProcessStartInfo psInfo = new ProcessStartInfo(command);
psInfo.Arguments = args1;
psInfo.Verb = "runas";
try
{
Process p = Process.Start(psInfo);
p.WaitForExit();
//return "Try Done";
}
catch (Exception e)
{
//return e.Message;
}