2011-06-01 102 views
2

我需要连续启动多个浏览器实例/选项卡,但使用Process.Start(url)我发现并非每个URL都启动。Process.Start(url)不会启动每个实例

for (int i = 0; i < n; i++) 
    { 
     var p = Process.Start("http://localhost/#" + i.ToString()); 
    } 

对于任何值n> 1我发现,只有最后一个URL在浏览器中打开(我用IE测试为默认浏览器)。如果我在Process.Start之后添加一个Thread.Sleep(1000),那么我会看到各种行为:有时所有n都被创建;有时是一个子集。

下不工作不如预期,但假设IE(宁愿使用默认浏览器),并启动ñ浏览器实例,而超过n标签:

for (int i = 0; i < n; i++) 
    { 
     var p = Process.Start("iexplore.exe", "http://localhost/#" + i.ToString()); 
    } 

我更愿意把它与默认的浏览器工作行为,但需要它是确定性的。

+0

是否有可能在同一窗口中不断打开页面(覆盖第一/第二/第三/等)。过程开始)? – FreeSnow 2011-06-01 22:09:15

+1

@DalexL - 可能的,但不知道我会怎么知道。 – alexdej 2011-06-01 22:19:07

回答

0

结束了与以下,依然不理想(启动多个浏览器窗口),结合命令行参数解析溶液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); 
    } 
} 

}

0

似乎是一个Windows资源管理器的错误。您可以尝试查找常见的浏览器可执行文件,并在存在的情况下使用它们,如果找不到匹配项,则可以回退到默认方法。

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传递给打开的实例并退出您的调用进程。

+0

是的,这与我的观察结果一致:在第一个Process.Start之后添加Thread.Sleep(5000),这使得它更加稳定,但我想象会在特别慢/繁忙的机器上发生故障。顺便说一句,你从哪里获得'浏览器'的价值?我正在考虑查找HKCR \ http \ shell \ open \命令并使用它。 – alexdej 2011-06-01 22:22:53

+0

这本身就是另一个蜡球。一般来说,你可以从注册表中获得它,但是一些更新的Win7机器似乎存在一些问题。此刻使用key = Registry.CurrentUser.OpenSubKey(@“Software \ Clients \ StartMenuInternet”,false); – tofutim 2011-06-01 22:27:41

+0

请参阅http://msdn.microsoft.com/en-us/library/dd203067(v=vs.85).aspx - 答案是否适用于您? – tofutim 2011-06-01 22:32:20

0

我完全赞同这一个,但它在这里。来自@ tofutim的回答。基本上,使用锁定并使用定时器监视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();