2011-06-01 103 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();