我需要连续启动多个浏览器实例/标签但是使用Process.Start(url)我发现不是每个URL都启动了。
for (int i = 0; i < n; i++)
{
var p = Process.Start("http://localhost/#" + i.ToString());
}
对于任何值n&gt; 1我发现浏览器中只打开了最后一个URL(我正在使用IE作为默认浏览器进行测试)。如果我在Process.Start之后添加一个Thread.Sleep(1000),那么我会看到各种行为:有时会创建所有n;有时是一个子集。
以下确实按预期工作,但假设IE(宁愿使用默认浏览器)并启动n个浏览器实例而不是n个标签:
for (int i = 0; i < n; i++)
{
var p = Process.Start("iexplore.exe", "http://localhost/#" + i.ToString());
}
我更愿意让它使用默认的浏览器行为,但需要它是确定性的。
答案 0 :(得分:0)
似乎是一个Windows资源管理器错误。您可以尝试查找常见的浏览器可执行文件并使用它们(如果存在),如果未找到匹配项,则可以回退到默认方法。
答案 1 :(得分:0)
另见Open multiple-tabs in IE9 using Process(可能重复)
我们正在为IE9准备这个问题。这似乎有效。
bool isLaunched = false;
foreach (string url in urls)
{
try
{
if (!isLaunched)
{
Process p = new Process();
p.StartInfo.FileName = browser;
p.StartInfo.Arguments = url;
p.Start();
Thread.Sleep(1000);
isLaunched = true;
}
else
{
Process.Start(url);
}
}
catch (Exception ex)
{
// something
}
}
根据我的经验,p.WaitForIdle不起作用。此外,如果浏览器实例已在计算机上打开,则行为也会有所不同。调用iexplore实际上会将url传递给打开的实例并退出被调用的进程。
答案 2 :(得分:0)
我完全支持这一个,但它就在这里。源于@ tofutim的答案。基本上,使用锁定并使用Timer监视Process状态。这当然在很大程度上取决于能否确定流程是否已成功启动,正在使用
进行测试if (p.HasExited == false && p.Id != 0){ }
完整的解决方案:
bool isLaunching = false;
object launchingLock = new object();
Process p = null;
Timer timer = new Timer(new TimerCallback((state) =>
{
lock (launchingLock)
{
if (isLaunching)
{
if (p != null && p.HasExited == false && p.Id != 0)
{
// Success!
isLaunching = false;
Monitor.PulseAll(launchingLock);
}
else if(p != null && p.HasExited)
{
// Some sort of failure code/notification?
// We still want to pulse though, otherwise thread will be forever kept waiting
isLaunching = false;
Monitor.PulseAll(launchingLock);
}
}
}
}));
timer.Change(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1));
foreach (string url in urls)
{
try
{
lock (launchingLock)
{
isLaunching = true;
p = new Process();
p.StartInfo.FileName = browser;
p.StartInfo.Arguments = url;
p.Start();
// Wait until the process has finished starting before moving on
Monitor.Wait(launchingLock);
}
}
catch (Exception ex)
{
// something
}
}
timer.Dispose();
答案 3 :(得分:0)
结束以下,仍然不理想(启动多个浏览器窗口),合并命令行arg解析解决方案Split string containing command-line parameters into string[] in C#
const int n = 3;
static void Main(string[] args)
{
for (int i = 0; i < n; i++)
{
var start = GetDefaultBrowserStartInfo("http");
start.Arguments += string.Format(" http://localhost/#{0}", i);
var p = Process.Start(start);
}
}
static ProcessStartInfo GetDefaultBrowserStartInfo(string scheme)
{
string command = null;
using (var key = Registry.ClassesRoot.OpenSubKey(string.Format(@"{0}\shell\open\command", scheme)))
{
command = (string)key.GetValue("");
}
string[] parsed = CommandLineToArgs(command);
return new ProcessStartInfo
{
FileName = parsed[0],
Arguments = string.Join(" ", parsed.Skip(1).ToArray()),
};
}
[DllImport("shell32.dll", SetLastError = true)]
static extern IntPtr CommandLineToArgvW(
[MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine, out int pNumArgs);
static string[] CommandLineToArgs(string commandLine)
{
int argc;
var argv = CommandLineToArgvW(commandLine, out argc);
if (argv == IntPtr.Zero)
throw new System.ComponentModel.Win32Exception();
try
{
var args = new string[argc];
for (var i = 0; i < args.Length; i++)
{
var p = Marshal.ReadIntPtr(argv, i * IntPtr.Size);
args[i] = Marshal.PtrToStringUni(p);
}
return args;
}
finally
{
Marshal.FreeHGlobal(argv);
}
}
}