/// <summary> /// Connects to the XenCenter named pipe. If the pipe didn't already exist, a new thread is started /// that listens for incoming data on the pipe (from new invocations of XenCenter) and deals /// with the command line arguments of those instances. If the pipe does exist, a Win32Exception is thrown. /// </summary> /// <exception cref="Win32Exception">If creating the pipe failed for any reason.</exception> private static void ConnectPipe() { string pipe_path = string.Format(PIPE_PATH_PATTERN, Process.GetCurrentProcess().SessionId, Environment.UserName, Assembly.GetExecutingAssembly().Location.Replace('\\', '-')); // Pipe path must be limited to 256 characters in length if (pipe_path.Length > 256) { pipe_path = pipe_path.Substring(0, 256); } log.InfoFormat(@"Connecting to pipe '{0}'", pipe_path); // Line below may throw Win32Exception pipe = new NamedPipes.Pipe(pipe_path); log.InfoFormat(@"Successfully created pipe '{0}' - proceeding to launch XenCenter", pipe_path); pipe.Read += new EventHandler <NamedPipes.PipeReadEventArgs>(delegate(object sender, NamedPipes.PipeReadEventArgs e) { MainWindow m = Program.MainWindow; if (m == null || RunInAutomatedTestMode) { return; } Program.Invoke(m, delegate { log.InfoFormat(@"Received data from pipe '{0}': {1}", pipe_path, e.Message); ArgType argType = ArgType.None; string[] other_args; string file_arg = ""; string[] bits = e.Message.Split(new char[] { ' ' }, 3); if (bits.Length == 2) { List <string> args = new List <string>(); args.Add(bits[0]); args.Add(bits[1]); argType = ParseFileArgs(args, out other_args); file_arg = other_args[0]; if (argType == ArgType.Passwords) { log.Error("Refusing to accept passwords request down pipe. Use XenCenterMain.exe directly"); return; } else if (argType == ArgType.Connect) { log.Error("Connect not supported down pipe. Use XenCenterMain.exe directly"); return; } else if (argType == ArgType.None) { return; } } else if (e.Message.Length > 0) { log.Error("Could not process data received from pipe."); return; } m.WindowState = FormWindowState.Normal; // Note slight hack: the C++ splash screen passes its command line as a // literal string. This means we will get an e.Message e.g. // open "C:\Documents and Settings\foo.xva" // INCLUDING double quotes. Thus we trim the quotes below. if (file_arg.Length > 1 && file_arg.StartsWith("\"") && file_arg.EndsWith("\"")) { file_arg = file_arg.Substring(1, file_arg.Length - 2); } m.ProcessCommand(argType, new string[] { file_arg }); }); }); pipe.BeginRead(); // We created the pipe successfully - i.e. nobody was listening, so go ahead and start XenCenter }
/// <summary> /// Connects to the XenCenter named pipe. If the pipe didn't already exist, a new thread is started /// that listens for incoming data on the pipe (from new invocations of XenCenter) and deals /// with the command line arguments of those instances. If the pipe does exist, a Win32Exception is thrown. /// </summary> /// <exception cref="Win32Exception">If creating the pipe failed for any reason.</exception> private static void ConnectPipe() { string pipe_path = string.Format(PIPE_PATH_PATTERN, Process.GetCurrentProcess().SessionId, Environment.UserName, Assembly.GetExecutingAssembly().Location.Replace('\\', '-')); // Pipe path must be limited to 256 characters in length if (pipe_path.Length > 256) { pipe_path = pipe_path.Substring(0, 256); } log.InfoFormat(@"Connecting to pipe '{0}'", pipe_path); // Line below may throw Win32Exception pipe = new NamedPipes.Pipe(pipe_path); log.InfoFormat(@"Successfully created pipe '{0}' - proceeding to launch XenCenter", pipe_path); pipe.Read += delegate(object sender, NamedPipes.PipeReadEventArgs e) { MainWindow m = MainWindow; if (m == null || RunInAutomatedTestMode) { return; } var bits = e.Message.Split(' ').Where(ar => ar != "--wait").ToArray(); var firstArgType = ParseFileArgs(bits, out string[] tailArgs); if (firstArgType == ArgType.Passwords) { log.Error("Refusing to accept passwords request down pipe. Use XenCenterMain.exe directly"); return; } if (firstArgType == ArgType.Connect) { log.Error("Connect not supported down pipe. Use XenCenterMain.exe directly"); return; } if (firstArgType == ArgType.None) { return; } // The C++ splash screen passes its command line as a literal string. // This means we will get an e.Message like // open "C:\Documents and Settings\foo.xva" // INCLUDING the double quotes, thus we need to trim them var argument = tailArgs[0]; if (argument.StartsWith("\"")) { var count = tailArgs.TakeWhile(t => !t.EndsWith("\"")).Count(); if (count < tailArgs.Length) { count++; } argument = string.Join(" ", tailArgs.Take(count).ToArray()); } argument = argument.Trim('"'); Invoke(m, delegate { m.WindowState = FormWindowState.Normal; m.ProcessCommand(firstArgType, argument); }); }; pipe.BeginRead(); // We created the pipe successfully - i.e. nobody was listening, so go ahead and start XenCenter }