Exemple #1
0
        private string ExtractCab(string file)
        {
            m_generatedPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());

            while (Directory.Exists(m_generatedPath))
                m_generatedPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());

            Directory.CreateDirectory(m_generatedPath);

            CommandOptions options = new CommandOptions();
            options.NoThrow = true;
            options.NoWindow = true;
            Command cmd = Command.Run(string.Format("expand -F:*dmp {0} {1}", file, m_generatedPath), options);

            bool error = false;
            if (cmd.ExitCode != 0)
            {
                error = true;
            }
            else
            {
                file = null;
                foreach (var item in Directory.GetFiles(m_generatedPath))
                {
                    string ext = Path.GetExtension(item).ToLower();
                    if (ext == ".dll" || ext == ".pdb" || ext == ".exe")
                        continue;

                    file = item;
                    break;
                }


                error |= file == null;
            }

            if (error)
            {
                Dispose();
                throw new IOException("Failed to extract a crash dump from " + file);
            }

            return file;
        }
Exemple #2
0
 /// <summary>
 /// Run 'commandLine', sending the output to the console, and wait for the command to complete.
 /// This simulates what batch filedo when executing their commands.  It is a bit more verbose
 /// by default, however
 /// </summary>
 /// <param variable="commandLine">The command lineNumber to run as a subprocess</param>
 /// <param variable="options">Additional qualifiers that control how the process is run</param>
 /// <returns>A Command structure that can be queried to determine ExitCode, Output, etc.</returns>
 public static Command RunToConsole(string commandLine, CommandOptions options)
 {
     return(Run(commandLine, options.Clone().AddOutputStream(Console.Out)));
 }
Exemple #3
0
        /// <summary>
        /// Launch a new command and returns the Command object that can be used to monitor
        /// the restult.  It does not wait for the command to complete, however you
        /// can call 'Wait' to do that, or use the 'Run' or 'RunToConsole' methods. */
        /// </summary>
        /// <param variable="commandLine">The command lineNumber to run as a subprocess</param>
        /// <param variable="options">Additional qualifiers that control how the process is run</param>
        /// <returns>A Command structure that can be queried to determine ExitCode, Output, etc.</returns>
        public Command(string commandLine, CommandOptions options)
        {
            _options     = options;
            _commandLine = commandLine;

            // See if the command is quoted and match it in that case
            Match m = Regex.Match(commandLine, "^\\s*\"(.*?)\"\\s*(.*)");

            if (!m.Success)
            {
                m = Regex.Match(commandLine, @"\s*(\S*)\s*(.*)");    // thing before first space is command
            }
            ProcessStartInfo startInfo = new ProcessStartInfo(m.Groups[1].Value, m.Groups[2].Value)
            {
                UseShellExecute        = false,
                RedirectStandardError  = true,
                RedirectStandardOutput = true,
                ErrorDialog            = false,
                CreateNoWindow         = true,
                RedirectStandardInput  = options.Input != null
            };

            _process = new Process()
            {
                StartInfo = startInfo
            };
            _process.StartInfo = startInfo;
            _output            = new StringBuilder();
            if (options.elevate)
            {
                options.useShellExecute = true;
                startInfo.Verb          = "runas";
                if (options.currentDirectory == null)
                {
                    options.currentDirectory = Environment.CurrentDirectory;
                }
            }
            _process.OutputDataReceived += new DataReceivedEventHandler(OnProcessOutput);
            _process.ErrorDataReceived  += new DataReceivedEventHandler(OnProcessOutput);

            if (options.environmentVariables != null)
            {
                // copy over the environment variables to the process startInfo options.
                foreach (string key in options.environmentVariables.Keys)
                {
                    // look for %VAR% strings in the value and subtitute the appropriate environment variable.
                    string value = options.environmentVariables[key];
                    if (value != null)
                    {
                        int startAt = 0;
                        for (; ;)
                        {
                            m = new Regex(@"%(\w+)%").Match(value, startAt);
                            if (!m.Success)
                            {
                                break;
                            }
                            string varName = m.Groups[1].Value;
                            string varValue;
                            if (startInfo.EnvironmentVariables.ContainsKey(varName))
                            {
                                varValue = startInfo.EnvironmentVariables[varName];
                            }
                            else
                            {
                                varValue = Environment.GetEnvironmentVariable(varName);
                                if (varValue == null)
                                {
                                    varValue = "";
                                }
                            }
                            // replace this instance of the variable with its definition.
                            int varStart = m.Groups[1].Index - 1;             // -1 becasue % chars are not in the group
                            int varEnd   = varStart + m.Groups[1].Length + 2; // +2 because % chars are not in the group
                            value   = value.Substring(0, varStart) + varValue + value.Substring(varEnd, value.Length - varEnd);
                            startAt = varStart + varValue.Length;
                        }
                    }
                    startInfo.EnvironmentVariables[key] = value;
                }
            }
            startInfo.WorkingDirectory = options.currentDirectory;

            _outputStream = options.outputStream;
            if (options.outputFile != null)
            {
                _outputStream = File.CreateText(options.outputFile);
            }

#if false
            if (options.showCommand && outputStream != null)
            {
                // TODO why only for output streams?
                outputStream.WriteLine("RUN CMD: " + commandLine);
            }
#endif
#if false
            // Make sure we kill this task when Ctrl C or appdomain unloads
            if (!options.noWait)
            {
                AddCommandToCleanupList(this);
            }
#endif
            try
            {
                _process.Start();
            }
            catch (Exception e)
            {
                string msg = "Failure starting Process\r\n" +
                             "    Exception: " + e.Message + "\r\n" +
                             "    Cmd: " + commandLine + "\r\n";

                if (Regex.IsMatch(startInfo.FileName, @"^(copy|dir|del|color|set|cd|cdir|md|mkdir|prompt|pushd|popd|start|assoc|ftype)", RegexOptions.IgnoreCase))
                {
                    msg += "    Cmd " + startInfo.FileName + " implemented by Cmd.exe, fix by prefixing with 'cmd /c'.";
                }
                throw new Exception(msg, e);
            }

            if (!startInfo.UseShellExecute)
            {
                // startInfo asyncronously collecting output
                _process.BeginOutputReadLine();
                _process.BeginErrorReadLine();
            }

            // Send any input to the command
            if (options.input != null)
            {
                _process.StandardInput.Write(options.input);
                _process.StandardInput.Dispose();
            }
        }
Exemple #4
0
        /// <summary>
        /// Launch a new command and returns the Command object that can be used to monitor
        /// the restult.  It does not wait for the command to complete, however you
        /// can call 'Wait' to do that, or use the 'Run' or 'RunToConsole' methods. */
        /// </summary>
        /// <param variable="commandLine">The command lineNumber to run as a subprocess</param>
        /// <param variable="options">Additional qualifiers that control how the process is run</param>
        /// <returns>A Command structure that can be queried to determine ExitCode, Output, etc.</returns>
        public Command(string commandLine, CommandOptions options)
        {
            Options      = options;
            _commandLine = commandLine;

            // See if the command is quoted and match it in that case
            Match m = Regex.Match(commandLine, "^\\s*\"(.*?)\"\\s*(.*)");

            if (!m.Success)
            {
                m = Regex.Match(commandLine, @"\s*(\S*)\s*(.*)"); // thing before first space is command
            }
            ProcessStartInfo startInfo = new ProcessStartInfo(m.Groups[1].Value, m.Groups[2].Value)
            {
                UseShellExecute        = false,
                RedirectStandardError  = true,
                RedirectStandardOutput = true,
                ErrorDialog            = false,
                CreateNoWindow         = true,
                RedirectStandardInput  = options.Input != null
            };

            Process = new Process {
                StartInfo = startInfo
            };
            Process.StartInfo = startInfo;
            _output           = new StringBuilder();
            if (options.elevate)
            {
                options.useShellExecute = true;
                startInfo.Verb          = "runas";
                options.currentDirectory ??= Environment.CurrentDirectory;
            }

            Process.OutputDataReceived += OnProcessOutput;
            Process.ErrorDataReceived  += OnProcessOutput;

            if (options.environmentVariables != null)
            {
                // copy over the environment variables to the process startInfo options.
                foreach (KeyValuePair <string, string> pair in options.environmentVariables)
                {
                    // look for %VAR% strings in the value and subtitute the appropriate environment variable.
                    string value = pair.Value;
                    if (value != null)
                    {
                        value = Environment.ExpandEnvironmentVariables(value);
                    }

                    startInfo.EnvironmentVariables[pair.Key] = value;
                }
            }

            startInfo.WorkingDirectory = options.currentDirectory;

            _outputStream = options.outputStream;
            if (options.outputFile != null)
            {
                _outputStream = File.CreateText(options.outputFile);
            }

            try
            {
                Process.Start();
            }
            catch (Exception e)
            {
                string msg = "Failure starting Process\r\n" +
                             "    Exception: " + e.Message + "\r\n" +
                             "    Cmd: " + commandLine + "\r\n";

                if (Regex.IsMatch(startInfo.FileName, @"^(copy|dir|del|color|set|cd|cdir|md|mkdir|prompt|pushd|popd|start|assoc|ftype)", RegexOptions.IgnoreCase))
                {
                    msg += "    Cmd " + startInfo.FileName + " implemented by Cmd.exe, fix by prefixing with 'cmd /c'.";
                }
                throw new Exception(msg, e);
            }

            if (!startInfo.UseShellExecute)
            {
                // startInfo asyncronously collecting output
                Process.BeginOutputReadLine();
                Process.BeginErrorReadLine();
            }

            // Send any input to the command
            if (options.input != null)
            {
                Process.StandardInput.Write(options.input);
                Process.StandardInput.Dispose();
            }
        }
Exemple #5
0
        /// <summary>
        /// Launch a new command and returns the Command object that can be used to monitor
        /// the restult.  It does not wait for the command to complete, however you 
        /// can call 'Wait' to do that, or use the 'Run' or 'RunToConsole' methods. */
        /// </summary>
        /// <param variable="commandLine">The command lineNumber to run as a subprocess</param>
        /// <param variable="options">Additional qualifiers that control how the process is run</param>
        /// <returns>A Command structure that can be queried to determine ExitCode, Output, etc.</returns>
        public Command(string commandLine, CommandOptions options)
        {
            _options = options;
            _commandLine = commandLine;

            // See if the command is quoted and match it in that case
            Match m = Regex.Match(commandLine, "^\\s*\"(.*?)\"\\s*(.*)");
            if (!m.Success)
                m = Regex.Match(commandLine, @"\s*(\S*)\s*(.*)");    // thing before first space is command

            ProcessStartInfo startInfo = new ProcessStartInfo(m.Groups[1].Value, m.Groups[2].Value);
            _process = new Process();
            _process.StartInfo = startInfo;
            _output = new StringBuilder();
            if (options.elevate)
            {
                options.useShellExecute = true;
                startInfo.Verb = "runas";
                if (options.currentDirectory == null)
                    options.currentDirectory = Environment.CurrentDirectory;
            }
            startInfo.CreateNoWindow = options.noWindow;
            if (options.useShellExecute)
            {
                startInfo.UseShellExecute = true;
                if (options.noWindow)
                    startInfo.WindowStyle = ProcessWindowStyle.Hidden;
            }
            else
            {
                if (options.input != null)
                    startInfo.RedirectStandardInput = true;
                startInfo.UseShellExecute = false;
                startInfo.RedirectStandardError = true;
                startInfo.RedirectStandardOutput = true;
                startInfo.ErrorDialog = false;
                startInfo.WindowStyle = ProcessWindowStyle.Hidden;
                startInfo.CreateNoWindow = true;

                _process.OutputDataReceived += new DataReceivedEventHandler(OnProcessOutput);
                _process.ErrorDataReceived += new DataReceivedEventHandler(OnProcessOutput);
            }

            if (options.environmentVariables != null)
            {
                // copy over the environment variables to the process startInfo options. 
                foreach (string key in options.environmentVariables.Keys)
                {
                    // look for %VAR% strings in the value and subtitute the appropriate environment variable. 
                    string value = options.environmentVariables[key];
                    if (value != null)
                    {
                        int startAt = 0;
                        for (;;)
                        {
                            m = new Regex(@"%(\w+)%").Match(value, startAt);
                            if (!m.Success) break;
                            string varName = m.Groups[1].Value;
                            string varValue;
                            if (startInfo.EnvironmentVariables.ContainsKey(varName))
                                varValue = startInfo.EnvironmentVariables[varName];
                            else
                            {
                                varValue = Environment.GetEnvironmentVariable(varName);
                                if (varValue == null)
                                    varValue = "";
                            }
                            // replace this instance of the variable with its definition.  
                            int varStart = m.Groups[1].Index - 1;     // -1 becasue % chars are not in the group
                            int varEnd = varStart + m.Groups[1].Length + 2; // +2 because % chars are not in the group
                            value = value.Substring(0, varStart) + varValue + value.Substring(varEnd, value.Length - varEnd);
                            startAt = varStart + varValue.Length;
                        }
                    }
                    startInfo.EnvironmentVariables[key] = value;
                }
            }
            startInfo.WorkingDirectory = options.currentDirectory;

            _outputStream = options.outputStream;
            if (options.outputFile != null)
            {
                _outputStream = File.CreateText(options.outputFile);
            }

#if false
            if (options.showCommand && outputStream != null)
            {
                // TODO why only for output streams?
                outputStream.WriteLine("RUN CMD: " + commandLine);
            }
#endif
#if false
            // Make sure we kill this task when Ctrl C or appdomain unloads
            if (!options.noWait)
                AddCommandToCleanupList(this);
#endif
            try
            {
                _process.Start();
            }
            catch (Exception e)
            {
                string msg = "Failure starting Process\r\n" +
                    "    Exception: " + e.Message + "\r\n" +
                    "    Cmd: " + commandLine + "\r\n";

                if (Regex.IsMatch(startInfo.FileName, @"^(copy|dir|del|color|set|cd|cdir|md|mkdir|prompt|pushd|popd|start|assoc|ftype)", RegexOptions.IgnoreCase))
                    msg += "    Cmd " + startInfo.FileName + " implemented by Cmd.exe, fix by prefixing with 'cmd /c'.";
                throw new ApplicationException(msg, e);
            }

            if (!startInfo.UseShellExecute)
            {
                // startInfo asyncronously collecting output
                _process.BeginOutputReadLine();
                _process.BeginErrorReadLine();
            }

            // Send any input to the command 
            if (options.input != null)
            {
                _process.StandardInput.Write(options.input);
                _process.StandardInput.Close();
            }
        }
Exemple #6
0
 /// <summary>
 /// Run 'commandLine' as a subprocess and waits for the command to complete.
 /// Output is captured and placed in the 'Output' property of the returned Command 
 /// structure. 
 /// </summary>
 /// <param variable="commandLine">The command lineNumber to run as a subprocess</param>
 /// <param variable="options">Additional qualifiers that control how the process is run</param>
 /// <returns>A Command structure that can be queried to determine ExitCode, Output, etc.</returns>
 public static Command Run(string commandLine, CommandOptions options)
 {
     Command run = new Command(commandLine, options);
     run.Wait();
     return run;
 }
Exemple #7
0
 /// <summary>
 /// Run 'commandLine', sending the output to the console, and wait for the command to complete.
 /// This simulates what batch filedo when executing their commands.  It is a bit more verbose
 /// by default, however 
 /// </summary>
 /// <param variable="commandLine">The command lineNumber to run as a subprocess</param>
 /// <param variable="options">Additional qualifiers that control how the process is run</param>
 /// <returns>A Command structure that can be queried to determine ExitCode, Output, etc.</returns>
 public static Command RunToConsole(string commandLine, CommandOptions options)
 {
     return Run(commandLine, options.Clone().AddOutputStream(Console.Out));
 }
Exemple #8
0
        /// <summary>
        /// Given a full filename path to an NGEN image, insure that there is an NGEN image for it
        /// in the symbol cache.  If one already exists, this method simply returns that.   If not
        /// it is generated and placed in the symbol cache.  When generating the PDB this routine
        /// attempt to resolve line numbers, which DOES require looking up the PDB for the IL image. 
        /// Thus routine may do network accesses (to download IL PDBs).  
        /// 
        /// Note that FindSymbolFilePathForModule calls this, so normally you don't need to call 
        /// this method directly.  
        /// </summary>
        public string GenerateNGenPdbForModule(string ngenImageFullPath)
        {
            SymbolReader symReader = this;

            var log = symReader.m_log;
            if (!File.Exists(ngenImageFullPath))
            {
                log.WriteLine("Warning, NGEN image does not exist: {0}", ngenImageFullPath);
                return null;
            }

            // When V4.5 shipped, NGEN CreatePdb did not support looking up the IL pdb using symbol servers.  
            // We work around by explicitly fetching the IL PDB and pointing NGEN CreatePdb at that.  
            string ilPdbName = null;
            Guid ilPdbGuid = Guid.Empty;
            int ilPdbAge = 0;

            string pdbName;
            Guid pdbGuid;
            int pdbAge;
            using (var peFile = new PEFile(ngenImageFullPath))
            {
                if (!peFile.GetPdbSignature(out pdbName, out pdbGuid, out pdbAge, true))
                {
                    log.WriteLine("Could not get PDB signature for {0}", ngenImageFullPath);
                    return null;
                }

                // Also get the IL pdb information
                peFile.GetPdbSignature(out ilPdbName, out ilPdbGuid, out ilPdbAge, false);
            }

            // Fast path, the file already exists.
            pdbName = Path.GetFileName(pdbName);
            var relPath = pdbName + "\\" + pdbGuid.ToString("N") + pdbAge.ToString() + "\\" + pdbName;
            var pdbPath = Path.Combine(symReader.SymbolCacheDirectory, relPath);
            if (File.Exists(pdbPath))
                return pdbPath;

            var clrDir = GetClrDirectoryForNGenImage(ngenImageFullPath, log);
            if (clrDir == null)
                return null;

            // See if this is a V4.5 CLR, if so we can do line numbers too.l  
            var lineNumberArg = "";
            var ngenexe = Path.Combine(clrDir, "ngen.exe");
            log.WriteLine("Checking for V4.5 for NGEN image {0}", ngenexe);
            if (!File.Exists(ngenexe))
                return null;
            var isV4_5Runtime = false;

            Match m;
            using (var peFile = new PEFile(ngenexe))
            {
                var fileVersionInfo = peFile.GetFileVersionInfo();
                if (fileVersionInfo != null)
                {
                    var clrFileVersion = fileVersionInfo.FileVersion;
                    m = Regex.Match(clrFileVersion, @"^[\d.]+\.(\d+) ");       // Fetch the build number (last number)
                    if (m.Success)
                    {
                        // Is this a V4.5 runtime?
                        var buildNumber = int.Parse(m.Groups[1].Value);
                        log.WriteLine("Got NGEN.exe Build number: {0}", buildNumber);
                        if (buildNumber > 16000)
                        {
                            if (ilPdbName != null)
                            {
                                var ilPdbPath = symReader.FindSymbolFilePath(ilPdbName, ilPdbGuid, ilPdbAge);
                                if (ilPdbPath != null)
                                    lineNumberArg = "/lines " + Command.Quote(Path.GetDirectoryName(ilPdbPath));
                                else
                                    log.WriteLine("Could not find IL PDB {0} Guid {1} Age {2}.", ilPdbName, ilPdbGuid, ilPdbAge);
                            }
                            else
                                log.WriteLine("NGEN image did not have IL PDB information, giving up on line number info.");
                            isV4_5Runtime = true;
                        }
                    }
                }
            }

            var options = new CommandOptions();
            options.AddEnvironmentVariable("COMPLUS_NGenEnableCreatePdb", "1");

            // NGenLocalWorker is needed for V4.0 runtims but interferes on V4.5 runtimes.  
            if (!isV4_5Runtime)
                options.AddEnvironmentVariable("COMPLUS_NGenLocalWorker", "1");
            options.AddEnvironmentVariable("_NT_SYMBOL_PATH", symReader.SymbolPath.ToString());
            var newPath = "%PATH%;" + clrDir;
            options.AddEnvironmentVariable("PATH", newPath);
            options.AddOutputStream(log);
            options.AddNoThrow();

            // For Metro Auto-NGEN images we need to use a location where the app can write the PDB file
            var outputDirectory = symReader.SymbolCacheDirectory;
            var outputPdbPath = pdbPath;

            // Find the tempDir where we can write.  
            string tempDir = null;
            m = Regex.Match(ngenImageFullPath, @"(.*)\\Microsoft\\CLR_v(\d+)\.\d+(_(\d\d))?\\NativeImages", RegexOptions.IgnoreCase);
            if (m.Success)
            {
                tempDir = Path.Combine(m.Groups[1].Value, @"Temp\NGenPdb");
                DirectoryUtilities.Clean(tempDir);
                Directory.CreateDirectory(tempDir);
                outputDirectory = tempDir;
                outputPdbPath = Path.Combine(tempDir, relPath);
                log.WriteLine("Updating NGEN createPdb output file to {0}", outputPdbPath); // TODO FIX NOW REMOVE (for debugging)
            }
            try
            {

                for (; ; ) // Loop for retrying without /lines 
                {
                    // TODO FIX NOW: there is a and ugly problem with persistance of suboptimial PDB files
                    // This is made pretty bad because the not finding the IL pdbs is enough to make it fail.  

                    // TODO we need to figure out a convention show we know that we have fallen back to no-lines
                    // and we should regenerate it if we ultimately get the PDB information 
                    var cmdLine = string.Format(@"{0}\ngen.exe createpdb {1} {2} {3}",
                        clrDir, Command.Quote(ngenImageFullPath), Command.Quote(outputDirectory), lineNumberArg);
                    // TODO FIX NOW REMOVE after V4.5 is out a while
                    log.WriteLine("set COMPLUS_NGenEnableCreatePdb=1");
                    if (!isV4_5Runtime)
                        log.WriteLine("set COMPLUS_NGenLocalWorker=1");
                    log.WriteLine("set PATH=" + newPath);
                    log.WriteLine("set _NT_SYMBOL_PATH={0}", symReader.SymbolPath);
                    log.WriteLine("*** NGEN  CREATEPDB cmdline: {0}\r\n", cmdLine);
                    options.AddOutputStream(log);
                    var cmd = Command.Run(cmdLine, options);
                    log.WriteLine("*** NGEN CREATEPDB returns: {0}", cmd.ExitCode);

                    if (cmd.ExitCode != 0)
                    {
                        // ngen might make a bad PDB, so if it returns failure delete it.  
                        if (File.Exists(outputPdbPath))
                            File.Delete(outputPdbPath);

                        // We may have failed because we could not get the PDB.  
                        if (lineNumberArg.Length != 0)
                        {
                            log.WriteLine("Ngen failed to generate pdb for {0}, trying again without /lines", ngenImageFullPath);
                            lineNumberArg = "";
                            continue;
                        }
                    }

                    if (cmd.ExitCode != 0 || !File.Exists(outputPdbPath))
                    {
                        log.WriteLine("ngen failed to generate pdb for {0} at expected location {1}", ngenImageFullPath, outputPdbPath);
                        return null;
                    }

                    // Copy the file to where we want the PDB to live.  
                    if (outputPdbPath != pdbPath)
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(pdbPath));        // Make sure the destination directory exists.
                        File.Copy(outputPdbPath, pdbPath);
                    }
                    return pdbPath;
                }
            }
            finally
            {
                // Insure we have cleaned up any temporary files.  
                if (tempDir != null)
                    DirectoryUtilities.Clean(tempDir);
            }
        }