Detect 32-bit or 64-bit - c#

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

Related

open restore point dialog 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.

Why doesn't dfrgui exe work in x86 target platform

static void Main(string[] args)
{
string fileName = #"C:\windows\SysWOW64\dfrgui.exe";
ExecuteAsAdmin(fileName);
}
public static void ExecuteAsAdmin(string fileName)
{
Process proc = new Process();
proc.StartInfo.FileName = fileName;
proc.StartInfo.UseShellExecute = true;
proc.StartInfo.Verb = "runas";
try
{
proc.Start();
}
catch (Exception e)
{
}
}
I am trying to run dfrgui.exe from process.start(). I am using Visual Studio 2008 as my source code is compatible only with this. When I run this code nothing happens and dfrgUI doesn't show up. My target platform is x86 and I should work on it. Is there way I can call this dfrgui.exe from my code using x86 as target platform? I don't want to change this to either anycpu or x64 because my application is 32bit.

Is there a way to run a program if its path exceeds MAX_PATH?

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

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

C#.Net: Why is my Process.Start() hanging?

I'm trying to run a batch file, as another user, from my web app. For some reason, the batch file hangs! I can see "cmd.exe" running in the task manager, but it just sits there forever, unable to be killed, and the batch file is not running. Here's my code:
SecureString password = new SecureString();
foreach (char c in "mypassword".ToCharArray())
password.AppendChar(c);
ProcessStartInfo psi = new ProcessStartInfo();
psi.WorkingDirectory = #"c:\build";
psi.FileName = Environment.SystemDirectory + #"\cmd.exe";
psi.Arguments = "/q /c build.cmd";
psi.UseShellExecute = false;
psi.UserName = "builder";
psi.Password = password;
Process.Start(psi);
If you didn't guess, this batch file builds my application (a different application than the one that is executing this command).
The Process.Start(psi); line returns immediately, as it should, but the batch file just seems to hang, without executing. Any ideas?
EDIT: See my answer below for the contents of the batch file.
The output.txt never gets created.
I added these lines:
psi.RedirectStandardOutput = true;
Process p = Process.Start(psi);
String outp = p.StandardOutput.ReadLine();
and stepped through them in debug mode. The code hangs on the ReadLine(). I'm stumped!
I believe I've found the answer. It seems that Microsoft, in all their infinite wisdom, has blocked batch files from being executed by IIS in Windows Server 2003. Brenden Tompkins has a work-around here:
http://codebetter.com/blogs/brendan.tompkins/archive/2004/05/13/13484.aspx
That won't work for me, because my batch file uses IF and GOTO, but it would definitely work for simple batch files.
Why not just do all the work in C# instead of using batch files?
I was bored so i wrote this real quick, it's just an outline of how I would do it since I don't know what the command line switches do or the file paths.
using System;
using System.IO;
using System.Text;
using System.Security;
using System.Diagnostics;
namespace asdf
{
class StackoverflowQuestion
{
private const string MSBUILD = #"path\to\msbuild.exe";
private const string BMAIL = #"path\to\bmail.exe";
private const string WORKING_DIR = #"path\to\working_directory";
private string stdout;
private Process p;
public void DoWork()
{
// build project
StartProcess(MSBUILD, "myproject.csproj /t:Build", true);
}
public void StartProcess(string file, string args, bool redirectStdout)
{
SecureString password = new SecureString();
foreach (char c in "mypassword".ToCharArray())
password.AppendChar(c);
ProcessStartInfo psi = new ProcessStartInfo();
p = new Process();
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.WorkingDirectory = WORKING_DIR;
psi.FileName = file;
psi.UseShellExecute = false;
psi.RedirectStandardOutput = redirectStdout;
psi.UserName = "builder";
psi.Password = password;
p.StartInfo = psi;
p.EnableRaisingEvents = true;
p.Exited += new EventHandler(p_Exited);
p.Start();
if (redirectStdout)
{
stdout = p.StandardOutput.ReadToEnd();
}
}
void p_Exited(object sender, EventArgs e)
{
if (p.ExitCode != 0)
{
// failed
StringBuilder args = new StringBuilder();
args.Append("-s k2smtpout.secureserver.net ");
args.Append("-f build#example.com ");
args.Append("-t josh#example.com ");
args.Append("-a \"Build failed.\" ");
args.AppendFormat("-m {0} -h", stdout);
// send email
StartProcess(BMAIL, args.ToString(), false);
}
}
}
}
Without seeing the build.cmd it's hard to tell what is going on, however, you should build the path using Path.Combine(arg1, arg2); It's the correct way to build a path.
Path.Combine( Environment.SystemDirectory, "cmd.exe" );
I don't remember now but don't you have to set UseShellExecute = true ?
Another possibility to "debug" it is to use standardoutput and then read from it:
psi.RedirectStandardOutput = True;
Process proc = Process.Start(psi);
String whatever = proc.StandardOutput.ReadLine();
In order to "see" what's going on, I'd suggest you transform the process into something more interactive (turn off Echo off) and put some "prints" to see if anything is actually happening. What is in the output.txt file after you run this?
Does the bmail actually executes?
Put some prints after/before to see what's going on.
Also add "#" to the arguments, just in case:
psi.Arguments = #"/q /c build.cmd";
It has to be something very simple :)
My guess would be that the build.cmd is waiting for some sort of user-interaction/reply. If you log the output of the command with the "> logfile.txt" operator at the end, it might help you find the problem.
Here's the contents of build.cmd:
#echo off
set path=C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727;%path%
msbuild myproject.csproj /t:Build > output.txt
IF NOT ERRORLEVEL 1 goto :end
:error
bmail -s k2smtpout.secureserver.net -f build#example.com -t josh#example.com -a "Build failed." -m output.txt -h
:end
del output.txt
As you can see, I'm careful not to output anything. It all goes to a file that gets emailed to me if the build happens to fail. I've actually been running this file as a scheduled task nightly for quite a while now. I'm trying to build a web app that allows me to run it on demand.
Thanks for everyone's help so far! The Path.Combine tip was particularly useful.
I think cmd.exe hangs if the parameters are incorrect.
If the batch executes correctly then I would just shell execute it like this instead.
ProcessStartInfo psi = new ProcessStartInfo();
Process p = new Process();
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.WorkingDirectory = #"c:\build";
psi.FileName = #"C:\build\build.cmd";
psi.UseShellExecute = true;
psi.UserName = "builder";
psi.Password = password;
p.StartInfo = psi;
p.Start();
Also it could be that cmd.exe just can't find build.cmd so why not give the full path to the file?
What are the endlines of you batch? If the code hangs on ReadLine, then the problem might be that it's unable to read the batch fileā€¦

Categories

Resources