open restore point dialog c# - c#

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.

Related

How to start windows explorer with taskbar in c#

I need to update my shell dll and to make sure that it is not in use, I am killing current windows explorer process using taskkill /F /IM explorer.exe command.
But when I try to start explorer again it don't bring back taskbar, I search for different solutions that brings taskbar back, but problem with them is that It is working on Windows 8.1, 10 but on Windows 7 64 bit, somehow it is not starting and that also randomly(sometime it do start).
Below are the solutions that I tried:
Solution 1:
Process.Start(Path.GetDirectoryName(Environment.SystemDirectory) + "\\Explorer.exe");
Solution 2:
RegistryKey localMachine = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64);
RegistryKey regKey = localMachine.OpenSubKey(#"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true);
regKey.SetValue("Shell", "explorer.exe", RegistryValueKind.String);
regKey.Close();
Process.Start(Environment.SystemDirectory + "\\..\\explorer.exe");
Solution 3:
var ProcessStartInfo = new ProcessStartInfo();
string anyCommand = "%systemroot%\\sysnative\\cmd.exe /c start /B explorer.exe";
ProcessStartInfo.UseShellExecute = false;
ProcessStartInfo.WorkingDirectory = System.IO.Path.Combine(System.IO.Path.GetPathRoot(Environment.SystemDirectory), "Windows\\System32");
ProcessStartInfo.FileName = System.IO.Path.Combine(System.IO.Path.GetPathRoot(Environment.SystemDirectory), "Windows\\System32\\cmd.exe");
//ProcessStartInfo.Verb = "runas";
ProcessStartInfo.Arguments = "/c " + anyCommand;
ProcessStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
using (var exeProcess = Process.Start(ProcessStartInfo))
{
if (exeProcess != null)
{
exeProcess.WaitForExit();
}
}
If you want to replace a file that is in use, you can always rename the existing file and copy the new version with the original name next to the existing one.
Then there is the Windows API call (name escapes me) that allows you to schedule the deletion of the renamed file on reboot.

Launch Sysprep.exe from C# Program

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);

Any way to programmatically get a value/setting from Bcdedit.exe, using .NET?

When running bcdedit.exe from an elevated command prompt, you can see the values of the current BCD settings. I need to read the setting/value of hypervisorlaunchtype.
Does anyone know a way to do this?
I've tried to write the piped output to a tmp file so that I could parse it, but ran into piped output issues due to the fact that bcdedit.exe needs to be run from an elevated prompt. Maybe there's a better way?
Edit: I forgot to add that I'd like to be able to do this without the end user seeing the Command Prompt at all (i.e. not even a quick flash) is possible.
First, run your Visual Studio as Administrator and try this code in a console application (run the application with debugging):
static void Main(string[] args)
{
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.FileName = #"CMD.EXE";
p.StartInfo.Arguments = #"/C bcdedit";
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
// parse the output
var lines = output.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).Where(l => l.Length > 24);
foreach (var line in lines)
{
var key = line.Substring(0, 24).Replace(" ", string.Empty);
var value = line.Substring(24).Replace(" ", string.Empty);
Console.WriteLine(key + ":" + value);
}
Console.ReadLine();
}
However, there is a problem, If you want this to work when launching the application from outside the elevated Visual Studio, you need to configure your application to ask for elevated rights:
On your project, click add new item and select Application Manifest File.
Open app.manifest file and replace this line:
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
with this one:
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

C# ProcessStartInfo and Process.Start cannot find programs in System32

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;
}

Website runs executable program

My website runs a local .exe file (generates some data), when a user clicks a certain link.
I would like to know how to do the following
what command to use to run the .exe?
where should I store the .exe and still maintain security?
I use .net 4 c#
Not sure if this works in MVC, but give it a shot:
// Process class resides in System.Diagnostics namespace
Process myProcess = Process.Start("...");
myProcess.WaitForExit();
// todo : process your data
Here's something that I use in one of my applications:
var p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.FileName = HttpContext.Current.Server.MapFfmpegPath();
p.StartInfo.Arguments = "arguments go here :)";
p.Start();
p.WaitForExit();
As for the executable itself, I created a directory in my project and put the exe in that directory. The MapFfmpegPath method looks something like this.
public static string MapFfmpegPath(this HttpServerUtility server)
{
return "\"" + server.MapPath("/CoolPathHere/ffmpeg.exe") + "\"";
}

Categories

Resources