Wanted to know if there is a reason that Powershell needs a special library (in System.Management.Automation NS) to be invoked from C# code? I have this code:
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
string trackerPath = "C:\\Users\\bernam\\Downloads\\test_scripts\\test_scripts\\Mindaugas_Scripts\\test.ps1";
p.StartInfo.FileName = "Powershell.exe";
p.StartInfo.Arguments = " -file " + trackerPath;
Console.WriteLine(p.StartInfo.FileName + p.StartInfo.Arguments);
p.Start();
string output = p.StandardOutput.ReadToEnd();
And it does not seem to be working - output is not returned back. However all these scenarios work fine (produce desired output):
p.StartInfo.FileName = "Powershell.exe"; p.StartInfo.Arguments = "get-service"; - works fine.
Invoking the PS script from the command line works fine as well (invocation from CMD):
>Powershell.exe -file "C:\Users\<shortened>\test.ps1"
1
2
The powershell code inside the script:
1..10 | % { Write-Host $_ ; sleep -m 500}
I know that there is a recommendation to use PowerShell class in System.Management.Automation namespace. What is interesting to me - is why? And is it possible to use PS without that Class? Maybe my code is simply wrong?
Yes this is certainly possible.
Try replacing Write-Host with Write-Output in the script you are calling.
Write-Host does not write to the standard streams, it writes to a console host. If you are not running a console host (cmd/powershell console), the output will just disappear. In general it is best to avoid using Write-Host all together.
The reason most people recommend using the System.Management.Automation method, is it simplifies many interactions that you may wish to use with powershell, rather than trying to parse the returns from powershell.exe, there are however valid reasons for calling the exe directly, for example if you are using .net core, which doesn't currently fully support System.Management.Automation.
You should invoke PS scripts from System.Management.Automation NS, because then you can work with results and exceptions having type-safe environment.
EDIT also, you can use asynchronous execution or you can execute PS scripts on a Remote server. Generally, you have much more possibilities using that library.
You can take a look at my example below.
string script = ""; // PS script content
List<ScriptParameter> ExecParamList; // parameters
var result = new ExecPSResult(); // Class with list of outputs and errors
using (var powerShellInstance = PowerShell.Create())
{
powerShellInstance.AddScript(script);
foreach (var execParamModel in ExecParamList)
{
powerShellInstance.AddParameter(execParamModel.ParamName,
execParamModel.ParamValue ?? "$null");
}
var psOutput = powerShellInstance.Invoke();
result.Errors =
powerShellInstance.Streams.Error.Select(e =>
ExecException.MakeFromException(e.Exception) // just make models for exeptions
).ToList();
result.OutputItems =
psOutput.Where(
outputItem =>
outputItem != null &&
outputItem.TypeNames[0] != "System.ServiceProcess.ServiceController")
.Select(e => new ExecOutput
{
ObjectTypeFullName = e.BaseObject.GetType().FullName,
ObjectValue = e.BaseObject //This is typeof(Object)
}).ToList();
}
return result;
I'm attempting to build a java process to execute the docusign retrieve product via the command line. I've written the process to execute based on a given property file.
buildRoot = isWindowsOs() ? "C:" + "\\Program Files (x86)\\DocuSign, Inc\\Retrieve 3.2" : "\\Program Files (x86)\\DocuSign, Inc\\Retrieve 3.2" ;
String[] command = new String [2];
command[0] = "\""+buildRoot+ "\\" + docuSignAppName+"\"";
logger.info(command[0].toString());
//ADDED FOR EXPLANATION - "C:\Program Files (x86)\DocuSign, Inc\Retrieve 3.2\DocuSignRetrieve.exe"
command[1] = arguments;
logger.info(command[1].toString());
ProcessBuilder processBuilder = new ProcessBuilder(command);
logger.info("ProcessBuilder starting directory" +processBuilder.directory());
processBuilder.redirectErrorStream(true);
p = processBuilder.start();
InputStream is = p.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
stdout = new BufferedReader(isr);
Once I pass in the built out string of parameters the executed code looks like the sample provided but always results in the error back to the screen "Missing "accountid" parameter".
The parameter list looks like the following.
/endpoint "Demo"
/userid "REMOVED"
/password "REMOVED"
/accountid "REMOVED"
/span "-1"
/spanfilter "Completed"
/statusfilter "Completed"
/fieldlog "LIST OF FIELDS"
/nstyle "EnvelopeID"
/save "MergedPdfWithoutCert"
/dir "D:\DocuSignStore"
/includeheaders "true"
Any help or assistance would be appreciated.
The solution was found in a StackOverflow discussion regarding common issues with the ProcessBuilder.
My problem was that I expected by changing the putting in the full path, that I could run the executable. For the reason I'm not sure right now, that wasn't working as expected. The solution was to run the CMD command which exists on the %PATH% on any windows OS.
String[] command = new String [2];
command[0] = "\""+buildRoot+ "\\" + docuSignAppName+"\"";
logger.info(command[0].toString());
//ADDED FOR EXPLANATION - "C:\Program Files (x86)\DocuSign, Inc\Retrieve 3.2\DocuSignRetrieve.exe"
command[1] = arguments;
logger.info(command[1].toString());
//This starts a new command prompt
ProcessBuilder processBuilder = new ProcessBuilder("cmd","/c","DocusignRetreive.exe);
//This sets the directory to run the command prompt from
File newLoc = new File("C:/Program Files (x86)/DocuSign, Inc/Retrieve 3.2");
processBuilder.directory(newLoc);
logger.info("ProcessBuilder starting directory" +processBuilder.directory());
processBuilder.redirectErrorStream(true);
/*When the process builder starts the prompt looks like
*C:\Program Files (x86)\DocuSign, Inc\Retrieve 3.2
*Now DocusignRetrieve.exe is an executable in the directory to be run
*/
p = processBuilder.start();
I am developing an application that spawns child processes using the Process API, with UseShellExecute set to false. The problem with this is that I don't want to go looking for the processes I'm spawning, since they are available in my system PATH. For example, I want to run Python scripts by just typing SCRIPT_NAME.py ARGUMENTS. However, when I set Process.FileName to be SCRIPT_NAME.py, I get an error telling me it couldn't find SCRIPT_NAME.py. I want the working directory to be where SCRIPT_NAME.py is, otherwise I'll have to specify the absolute path to SCRIPT_NAME.py and to its arguments, which is ridiculous and excessive.
I can avoid this by using cmd.exe /C SCRIPT_NAME.py ARGUMENTS but there are problems with force halting command prompt that are pushing me in this direction instead.
To fix this you just need to search the set of available paths looking for the one that has python.exe. Once you find that just fully qualify the python executable for launching in process
var path = Environment.GetEnvironmentVariable("PATH");
string pythonPath = null;
foreach (var p in path.Split(new char[] { ';' })) {
var fullPath = Path.Combine(p, "python.exe");
if (File.Exists(fullPath)) {
pythonPath = fullPath;
break;
}
}
if (pythonPath != null) {
// Launch Process
} else {
throw new Exception("Couldn't find python on %PATH%");
}
I am designing a small C# application and there is a web browser in it. I currently have all of my defaults on my computer say google chrome is my default browser, yet when I click a link in my application to open in a new window, it opens internet explorer. Is there any way to make these links open in the default browser instead? Or is there something wrong on my computer?
My problem is that I have a webbrowser in the application, so say you go to google and type in "stack overflow" and right click the first link and click "Open in new window" it opens in IE instead of Chrome. Is this something I have coded improperly, or is there a setting not correct on my computer
===EDIT===
This is really annoying. I am already aware that the browser is IE, but I had it working fine before. When I clicked a link it opened in chrome. I was using sharp develop to make the application at that time because I could not get c# express to start up. I did a fresh windows install and since I wasn't too far along in my application, I decided to start over, and now I am having this problem. That is why I am not sure if it is my computer or not. Why would IE start up the whole browser when a link is clicked rather than simply opening the new link in the default browser?
You can just write
System.Diagnostics.Process.Start("http://google.com");
EDIT: The WebBrowser control is an embedded copy of IE.
Therefore, any links inside of it will open in IE.
To change this behavior, you can handle the Navigating event.
For those finding this question in dotnet core. I found a solution here
Code:
private void OpenUrl(string url)
{
try
{
Process.Start(url);
}
catch
{
// hack because of this: https://github.com/dotnet/corefx/issues/10361
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
url = url.Replace("&", "^&");
Process.Start(new ProcessStartInfo(url) { UseShellExecute = true });
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Process.Start("xdg-open", url);
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
Process.Start("open", url);
}
else
{
throw;
}
}
}
After researching a lot I feel most of the given answer will not work with dotnet core.
1.System.Diagnostics.Process.Start("http://google.com"); -- Will not work with dotnet core
2.It will work but it will block the new window opening in case default browser is chrome
myProcess.StartInfo.UseShellExecute = true;
myProcess.StartInfo.FileName = "http://some.domain.tld/bla";
myProcess.Start();
Below is the simplest and will work in all the scenarios.
Process.Start("explorer", url);
public static void GoToSite(string url)
{
System.Diagnostics.Process.Start(url);
}
that should solve your problem
Did you try Processas mentioned here: http://msdn.microsoft.com/de-de/library/system.diagnostics.process.aspx?
You could use
Process myProcess = new Process();
try
{
// true is the default, but it is important not to set it to false
myProcess.StartInfo.UseShellExecute = true;
myProcess.StartInfo.FileName = "http://some.domain.tld/bla";
myProcess.Start();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
My default browser is Google Chrome and the accepted answer is giving the following error:
The system cannot find the file specified.
I solved the problem and managed to open an URL with the default browser by using this code:
System.Diagnostics.Process.Start("explorer.exe", "http://google.com");
I'm using this in .NET 5, on Windows, with Windows Forms. It works even with other default browsers (such as Firefox):
Process.Start(new ProcessStartInfo { FileName = url, UseShellExecute = true });
Based on this and this.
Try this , old school way ;)
public static void openit(string x)
{
System.Diagnostics.Process.Start("cmd", "/C start" + " " + x);
}
using : openit("www.google.com");
Am I the only one too scared to call System.Diagnostics.Process.Start() on a string I just read off the internet?
public bool OnBeforeBrowse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool userGesture, bool isRedirect)
{
Request = request;
string url = Request.Url;
if (Request.TransitionType != TransitionType.LinkClicked)
{ // We are only changing the behavoir when someone clicks on a link.
// Let the embedded browser handle this request itself.
return false;
}
else
{ // The user clicked on a link. Something like a filter icon, which links to the help for that filter.
// We open a new window for that request. This window cannot change. It is running a JavaScript
// application that is talking with the C# main program.
Uri uri = new Uri(url);
try
{
switch (uri.Scheme)
{
case "http":
case "https":
{ // Stack overflow says that this next line is *the* way to open a URL in the
// default browser. I don't trust it. Seems like a potential security
// flaw to read a string from the network then run it from the shell. This
// way I'm at least verifying that it is an http request and will start a
// browser. The Uri object will also verify and sanitize the URL.
System.Diagnostics.Process.Start(uri.ToString());
break;
}
case "showdevtools":
{
WebBrowser.ShowDevTools();
break;
}
}
}
catch { }
// Tell the browser to cancel the navigation.
return true;
}
}
This code was designed to work with CefSharp, but should be easy to adapt.
Take a look at the GeckoFX control.
GeckoFX is an open-source component
which makes it easy to embed Mozilla
Gecko (Firefox) into any .NET Windows
Forms application. Written in clean,
fully commented C#, GeckoFX is the
perfect replacement for the default
Internet Explorer-based WebBrowser
control.
dotnet core throws an error if we use Process.Start(URL). The following code will work in dotnet core. You can add any browser instead of Chrome.
var processes = Process.GetProcessesByName("Chrome");
var path = processes.FirstOrDefault()?.MainModule?.FileName;
Process.Start(path, url);
This opened the default for me:
System.Diagnostics.Process.Start(e.LinkText.ToString());
I tried
System.Diagnostics.Process.Start("https://google.com");
which works for most of the cases but I run into an issue having a url which points to a file:
The system cannot find the file specified.
So, I tried this solution, which is working with a little modification:
System.Diagnostics.Process.Start("explorer.exe", $"\"{uri}\"");
Without wrapping the url with "", the explorer opens your document folder.
In UWP:
await Launcher.LaunchUriAsync(new Uri("http://google.com"));
Open dynamically
string addres= "Print/" + Id + ".htm";
System.Diagnostics.Process.Start(Path.Combine(Environment.CurrentDirectory, addres));
update the registry with current version of explorer
#"Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION"
public enum BrowserEmulationVersion
{
Default = 0,
Version7 = 7000,
Version8 = 8000,
Version8Standards = 8888,
Version9 = 9000,
Version9Standards = 9999,
Version10 = 10000,
Version10Standards = 10001,
Version11 = 11000,
Version11Edge = 11001
}
key.SetValue(programName, (int)browserEmulationVersion, RegistryValueKind.DWord);
This works nicely for .NET 5 (Windows):
ProcessStartInfo psi = new ProcessStartInfo {
FileName = "cmd.exe",
Arguments = $ "/C start https://stackoverflow.com/",
WindowStyle = ProcessWindowStyle.Hidden,
CreateNoWindow = true
};
Process.Start(psi);
to fix problem with Net 6
i used this code from ChromeLauncher
,default browser will be like it
internal static class ChromeLauncher
{
private const string ChromeAppKey = #"\Software\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe";
private static string ChromeAppFileName
{
get
{
return (string) (Registry.GetValue("HKEY_LOCAL_MACHINE" + ChromeAppKey, "", null) ??
Registry.GetValue("HKEY_CURRENT_USER" + ChromeAppKey, "", null));
}
}
public static void OpenLink(string url)
{
string chromeAppFileName = ChromeAppFileName;
if (string.IsNullOrEmpty(chromeAppFileName))
{
throw new Exception("Could not find chrome.exe!");
}
Process.Start(chromeAppFileName, url);
}
}
I'd comment on one of the above answers, but I don't yet have the rep.
System.Diagnostics.Process.Start("explorer", "stackoverflow.com");
nearly works, unless the url has a query-string, in which case this code just opens a file explorer window. The key does seem to be the UseShellExecute flag, as given in Alex Vang's answer above (modulo other comments about launching random strings in web browsers).
You can open a link in default browser using cmd command start <link>, this method works for every language that has a function to execute a system command on cmd.exe.
This is the method I use for .NET 6 to execute a system command with redirecting the output & input, also pretty sure it will work on .NET 5 with some modifications.
using System.Diagnostics.Process cmd = new();
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("start https://google.com");
cmd.StandardInput.Flush();
cmd.StandardInput.Close();
cmd.WaitForExit();
I have ASP.NET web pages for which I want to build automated tests (using WatiN & MBUnit). How do I start the ASP.Net Development Server from my code? I do not want to use IIS.
This is what I used that worked:
using System;
using System.Diagnostics;
using System.Web;
...
// settings
string PortNumber = "1162"; // arbitrary unused port #
string LocalHostUrl = string.Format("http://localhost:{0}", PortNumber);
string PhysicalPath = Environment.CurrentDirectory // the path of compiled web app
string VirtualPath = "";
string RootUrl = LocalHostUrl + VirtualPath;
// create a new process to start the ASP.NET Development Server
Process process = new Process();
/// configure the web server
process.StartInfo.FileName = HttpRuntime.ClrInstallDirectory + "WebDev.WebServer.exe";
process.StartInfo.Arguments = string.Format("/port:{0} /path:\"{1}\" /virtual:\"{2}\"", PortNumber, PhysicalPath, VirtualPath);
process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false;
// start the web server
process.Start();
// rest of code...
From what I know, you can fire up the dev server from the command prompt with the following path/syntax:
C:\Windows\Microsoft.NET\Framework\v2.0.50727\Webdev.WebServer.exe /port:[PORT NUMBER] /path: [PATH TO ROOT]
...so I could imagine you could easily use Process.Start() to launch the particulars you need through some code.
Naturally you'll want to adjust that version number to whatever is most recent/desired for you.
Building upon #Ray Vega's useful answer, and #James McLachlan's important update for VS2010, here is my implementation to cover VS2012 and fallback to VS2010 if necessary. I also chose not to select only on Environment.Is64BitOperatingSystem because it went awry on my system. That is, I have a 64-bit system but the web server was in the 32-bit folder. My code therefore looks first for the 64-bit folder and falls back to the 32-bit one if necessary.
public void LaunchWebServer(string appWebDir)
{
var PortNumber = "1162"; // arbitrary unused port #
var LocalHostUrl = string.Format("http://localhost:{0}", PortNumber);
var VirtualPath = "/";
var exePath = FindLatestWebServer();
var process = new Process
{
StartInfo =
{
FileName = exePath,
Arguments = string.Format(
"/port:{0} /nodirlist /path:\"{1}\" /virtual:\"{2}\"",
PortNumber, appWebDir, VirtualPath),
CreateNoWindow = true,
UseShellExecute = false
}
};
process.Start();
}
private string FindLatestWebServer()
{
var exeCandidates = new List<string>
{
BuildCandidatePaths(11, true), // vs2012
BuildCandidatePaths(11, false),
BuildCandidatePaths(10, true), // vs2010
BuildCandidatePaths(10, false)
};
return exeCandidates.Where(f => File.Exists(f)).FirstOrDefault();
}
private string BuildCandidatePaths(int versionNumber, bool isX64)
{
return Path.Combine(
Environment.GetFolderPath(isX64
? Environment.SpecialFolder.CommonProgramFiles
: Environment.SpecialFolder.CommonProgramFilesX86),
string.Format(
#"microsoft shared\DevServer\{0}.0\WebDev.WebServer40.EXE",
versionNumber));
}
I am hoping that an informed reader might be able to supply the appropriate incantation for VS2013, as it apparently uses yet a different scheme...
You can easily use Process Explorer to find complete command line options needed for manually start it.
Start Process Explorer while debugging your website. For VS2012, expand 'devenv.exe' node. Right-click on 'WebDev.WebServer20.exe' and from there you can see Path and Command Line values.