Process.Start(url)在循环中没有启动每个实例

时间:2011-06-01 22:06:40

标签: c#

我需要连续启动多个浏览器实例/标签但是使用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());
    }

我更愿意让它使用默认的浏览器行为,但需要它是确定性的。

4 个答案:

答案 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);
    }
}

}