I need to run a command "control bthprops.cpl" in a C# program. This command brings up Bluetooth Settings control panel window. I tried running it using Process.Start() but the bluetooth window doesn't show up. I also tried writing a BAT file to the disk and executing it though my program, but still has the same problem. Is there any way to accomplish this?
//Dump BAT File and execute it
string path = System.IO.Directory.GetCurrentDirectory()+"startBT.bat";
string[] content = {"control bthprops.cpl"};
System.IO.File.WriteAllLines(path, content);
//Execute BAT file
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = path;
p.Start();
No need to go with a BAT file, this single line ought to open the specified control panel;
System.Diagnostics.Process.Start("control", "bthprops.cpl");
Since I don't have aforementioned bthprops.cpl; at least this works on W7 (open desktop settings)
System.Diagnostics.Process.Start("control", "desk.cpl");
If your control panel has tabs, you can even select what tab to open;
System.Diagnostics.Process.Start("control", "bthprops.cpl,,2");
Supply the full path and start it, for example:
var path = Path.Combine(Environment.SystemDirectory, "bthprops.cpl");
if (File.Exists(path))
{
Process.Start(path);
}
Related
I'm trying to solve a problem i got. My job is to make little app, that will show text which is inside of .txt file in the app window, but for some reason they told me that i have to use # ShellExecute(use Process.Start).
Is there even a way to do it? Because when i use ShellExecute, that file opens in notepad after button press, which is, I guess, point of using Shell.
There is little code of what i tried to do, but without success.
Thanks in advice!
string filePath = #"C:\Folder\file.txt";
ProcessStartInfo psi = new ProcessStartInfo(filePath);
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
psi.CreateNoWindow = true;
var proc = Process.Start(psi);
string s = proc.StandardOutput.ReadToEnd();
textBox1.Text = s;
Instead of using ProcessStartInfo, try StreamReader like this :
string filePath = #"C:\Folder\file.txt";
StreamReader sr = new StreamReader(filePath);
string s = sr.ReadToEndAsync().GetAwaiter().GetResult();
Console.WriteLine(s);
Use Async method to read all text without blocking.
If you absolutely need to do that, you can create a second application TxtToTextBox, which you can run from your first application using Process.Start (initialize ProcessStartInfo with the path to that application instead of the txt file).
Then you can give that process an argument pointing to the file using psi.Arguments = $"\"{filePath}\"; (this also adds quotation marks around your path, so spaces are escaped).
Then in your second application you can do the sane thing, and simply read the file with File.ReadAllLines(args[0]) and print that into your text box.
If possible, I would recommend talking to whoever told you to use Process.Start and asking them for more reasons as to why you should use is, as this is one of the most roundabout ways to do this I could think of.
I created this simple .bat File:
mstsc C:\Temp\example.rdp
DEL C:\Temp\example.rdp
The normal behaviour of the .bat file is to open the rdp dialog and wait til I close the RDP connection. After that the .rdp file will be deleted.
This works perfect for me.
Now I want to open the .bat file from my C# WPF project with a click on a button.
Process p = new Process();
p.StartInfo.FileName = #"cmd.exe";
p.StartInfo.WorkingDirectory = #"C:\Temp";
p.StartInfo.Arguments = "/k " + "example.bat";
p.Start();
I tried all different arguments but the result is always the same the .bat file won't wait for the mstsc command to finish.
Do you have an idea to get this work?
Edit:
I want the .bat file because i want to delete the .rdp file although my program isn't running and i don't want to close all rdp connections when i close the program.
Why are you not directly running mstsc?
Process.Start("mstsc", "dir-to-blah.rdp").WaitForExit();
File.Delete("dir-to-blah.rdp");
try using the "start" command.
start is documented here: https://ss64.com/nt/start.html
you should be able to do something like
Process p = new Process();
p.StartInfo.FileName = #"cmd.exe";
p.StartInfo.WorkingDirectory = #"C:\Temp";
p.StartInfo.Arguments = "start /w" + "/k " + "example.bat";
p.Start();
(as usual, my code is completely untested - leaving the final solution up to the OP)
I have a winforms application in C# where I have to open a certain Folder.
I use
System.Diagnostics.Process.Start(pathToFolder);
This results in the following exception:
System.ComponentModel.Win32Exception (0x80004005): Access is denied
at System.Diagnostics.Process.StartWithShellExecuteEx(ProcessStartInfo
startInfo)
at System.Diagnostics.Process.Start()
at System.Diagnostics.Process.Start(ProcessStartInfo startInfo)
at MyApp.openLogFolderToolStripMenuItem_Click(Object sender, EventArgs e)
I have already checked the following things:
The folder exists
The user has rights to the folder (can open it in Explorer)
Another thing is that if I use Process.Start() to open a file inside this folder, it works.
Can anyone give me a hint?Cheers
Edit
My goal is to open the folder in Explorer.
The pathToFolder is something like H:\Something\App.Name\Log
According to Microsoft Doc's the System.Diagnostics.Process.Start(string) runs the file or process (and therefore does not open the folder). For opening a folder, this doc page sugests that you might do this with System.Diagnostics.Process.Start(string, string) where first should be a way to explorer, Total commander or something similar, and second should be a argument telling the used explorer what to do (open the folder pathToFolder).
I suppose that some system variable stores the value for "default folder viewer" but I do not know where. I will try to go for it and return later with the answer.
Hope that it helps.
EDIT: I did some quick digging around and to open the folder the following should do the trick:
System.Diagnostics.Process.Start(Environment.GetEnvironmentVariable("WINDIR") +
#"\explorer.exe", pathToFolder);
Where first argument is a path to classical windows explorer and second is the actual path to the folder itself.
It seem that widows does not by itself hold path to other "folder viewer" (such as Total Commander etc.), so this way is probably off the table.
Try this:
var psi = new System.Diagnostics.ProcessStartInfo() { FileName = pathToFolder, UseShellExecute = true };
System.Diagnostics.Process.Start(psi);
I usually use this to open file/directory:
public static void OpenFile(string path, bool isDirectory = false)
{
if (string.IsNullOrEmpty(path)) return;
if ((isDirectory && Directory.Exists(path)) || (!isDirectory && File.Exists(path)))
{
ProcessStartInfo pi = new ProcessStartInfo(path);
pi.Arguments = Path.GetFileName(path);
pi.UseShellExecute = true;
pi.WindowStyle = ProcessWindowStyle.Normal;
pi.Verb = "OPEN";
Process proc = new Process();
proc.StartInfo = pi;
proc.Start();
}
}
or
Process.Start("explorer.exe",path);
If this doesn't work it may be a permission issue after all.
You can set the working directory like this but you can't run the directory itself only files or exe
var startInfo = new ProcessStartInfo();
startInfo.WorkingDirectory = //working directory
Process proc = Process.Start(startInfo);
This error actually happens when there is a difference between the default behaviour of opening the file and the relative behaviour of opening the file.
For example, if you have selected the default application to open .pdf files as Internet Explorer, and you are trying to open the same file using Process.Start() method. You will receive an exception because as per the default operations it should open that file in Internet Explorer and your application is trying to open it using Adobe reader.
To rectify this set the default application for the .pdf file as Adobe Reader and you won't receive this error any more.
You can do this by, right-clicking on the file and then select, Default program or App. Further, select the default Program or App from the list of available programs and then select the Always use the selected program/App to open files of this type.
I am creating a File copy program which will copy large number of files(~100,000) with size ~50 KB using ROBOCOPY command.
For each file, I am creating a new process and passing the ROBOCOPY command and arguments as follow:
using (Process p = new Process)
{
p.StartInfo.Arguments = string.Format("/C ROBOCOPY {0} {1} {2}",
sourceDir, destinationDir, fileName);
p.StartInfo.FileName = "CMD.EXE";
p.StartInfo.CreateNoWindow = true;
p.StartInfo.UseShellExecute = false;
p.Start();
p.WaitForExit();
}
Instead of creating a process for each file, I am looking for a better approach, which will be good in terms of performance and design. Can someone suggest a better method?
This question is a bit old but I thought I would answer to help anyone who still land on it. I wrote a library called RoboSharp (https://github.com/tjscience/RoboSharp) that brings all of the goodness in Robocopy to c#. Take a look if you require the power of Robocopy in c#.
Process p = new Process();
p.StartInfo.Arguments = string.Format("/C Robocopy /S {0} {1}", "C:\\source", "C:\\destination");
p.StartInfo.FileName = "CMD.EXE";
p.StartInfo.CreateNoWindow = true;
p.StartInfo.UseShellExecute = false;
p.Start();
p.WaitForExit();
/C Robocopy -> this is a command to run robocopy
/S -> This will help to copy sub folders as well as Files
I would just use System.IO. Should be plenty fast enough, and your filename could be a wildcard.
using System.IO;
// snip your code... providing fileName, sourceDir, destinationDir
DirectoryInfo dirInfo = new DirectoryInfo(sourceDir);
FileInfo[] fileInfos = dirInfo.GetFiles(fileName);
foreach (FileInfo file in fileInfos)
{
File.Copy(file.FullName, Path.Combine(destinationDir, file.Name), true); // overwrites existing
}
You should call File.Copy in a loop.
Robocopy can use up to 128 thread by itself. It makes a huge difference. By default it uses 8.
See https://pureinfotech.com/robocopy-multithreaded-file-copy-windows-10/
.cmd has following lines
Start ROBOCOY src dest a* b* c* /z /w:1 r:1
Start ROBOCOY src dest d* e* f* g* /z /w:1 r:1
Start ROBOCOY src dest h* K* P* Y* /z /w:1 r:1
Start ROBOCOY src dest xry* srp* /z /w:1 r:1
When I run > Robocopy sample.cmd
I starts with 4 multiple windows copying files simultaneously as per above commands, it waits
for another file, as it has wait time, if file is being used by another process. Is is more
faster as it do job simultaneously.
Now I am developing GUI using C# windows to run the process instead going to command console and
start
main()
{
process.start( "path of sample.cmd" )
process.waitforexit()
label.text=" sucessful copy"
}
However, if it takes control of one process, i.e. cmd.exe and and there are 4 robocopy processes in
taskmanager. when cmd.exe process completes, it returns the cursor to label.text "Sucesssfully
completed". While there are robocopy processes still running. you can see the robocopy windows
doing the copying process.
Here is the question: I want to take control of all the processes (cmd.exe and robocopy.exe)
programatically in C#, so that when the label.text should display "successfully completed" only
when all commands are successfully completed", if one fails, then there is no point in the GUI.
option 2 (similar to Biju has written above): is it better to remove robocopy command scripts from
sample.cmd(batch file) file and write code to run the 4 robocopy lines in C#, but how to run the
robocooy script line written .cmd file, as they have arguments as well. I code runs each robocopy
process then each will return to the next line of code and if it fails, we can catch the error and
display in the message box.
Hope this will help... However, I am looking for more better way, if somebody can improve on the same.
So anyways, I've been working on a batch IDE, and I was wondering if there was a good way to effectively embed the file into the form.
It would function sort of like a debug mode, where at any time, the user can click a button, and the batch file would load into the actual form.
Like the black cmd window would be embedded into the form...
Is there any way to do that?
ProcessStartInfo psi = new ProcessStartInfo();
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
psi.FileName = "C:\\echo.cmd";
var p = Process.Start(psi);
Console.WriteLine(p.StandardOutput.ReadToEnd());
And in C:\echo.cmd I have just basic echo hello!. When this code is executed - you'll see hello! received from batch's output stream.
Note that if executed command will wait for some input - ReadToEnd() can't return. In this case you should use Process.OutputDataReceived event.
Look at the process object and the StandardInput, StandardOutput and StandardError streams.
That is essentially all the command window is showing with some special handling of control characters.