예제 #1
0
        public StackHashScriptResult RunScript(StackHashProduct product, StackHashFile file, StackHashEvent theEvent, StackHashCab cab,
                                               String dumpFileName, String scriptName, bool extractCab, StackHashClientData clientData, bool forceRun)
        {
            if (product == null)
            {
                throw new ArgumentNullException("product");
            }
            if (file == null)
            {
                throw new ArgumentNullException("file");
            }
            if (theEvent == null)
            {
                throw new ArgumentNullException("theEvent");
            }
            if (cab == null)
            {
                throw new ArgumentNullException("cab");
            }
            if (scriptName == null)
            {
                throw new ArgumentNullException("scriptName");
            }


            String machineArchitecture = "x86"; // Default to 32 bit.

            if ((cab.DumpAnalysis != null) && !String.IsNullOrEmpty(cab.DumpAnalysis.MachineArchitecture))
            {
                machineArchitecture = cab.DumpAnalysis.MachineArchitecture;
            }


            StackHashScriptResult result = null;
            bool use32BitDebugger        = true;

            if (machineArchitecture != null)
            {
                if ((String.Compare(machineArchitecture, "x64", StringComparison.OrdinalIgnoreCase) == 0) ||
                    (String.Compare(machineArchitecture, "X64", StringComparison.OrdinalIgnoreCase) == 0))
                {
                    use32BitDebugger = false;
                }
            }


            // Unwrap the cab if necessary.
            String cabFileName   = m_ErrorIndex.GetCabFileName(product, file, theEvent, cab);
            String cabFileFolder = Path.GetDirectoryName(cabFileName);

            if (!File.Exists(cabFileName))
            {
                throw new StackHashException("Cab file does not exist: " + cabFileName, StackHashServiceErrorCode.CabDoesNotExist);
            }

            if (extractCab)
            {
                try
                {
                    Cabs.ExtractCab(cabFileName, cabFileFolder);
                }
                catch (System.Exception ex)
                {
                    if (ex.Message.Contains("The file is not a cabinet") || ex.Message.Contains("corrupt") || ex.Message.Contains("Corrupt"))
                    {
                        // Set the downloaded flag appropriately if different.
                        StackHashCab loadedCab = m_ErrorIndex.GetCab(product, file, theEvent, cab.Id);

                        if (loadedCab != null)
                        {
                            if (loadedCab.CabDownloaded)
                            {
                                loadedCab.CabDownloaded = false;
                                m_ErrorIndex.AddCab(product, file, theEvent, loadedCab, false);
                            }
                        }
                    }

                    throw new StackHashException("Cab file cannot be unpackaged. Try downloading the file from again.", ex, StackHashServiceErrorCode.CabIsCorrupt);
                }
            }

            // Now get the dump filename - mdmp and dmp files should be returned.
            String[] allDumpFiles = Directory.GetFiles(cabFileFolder, "*.*dmp");

            if (allDumpFiles.Length == 0)
            {
                return(null);
            }

            // Choose the largest dump file to process.
            String fullDumpFilePath = null;

            long largestFileSize = 0;

            foreach (String fileName in allDumpFiles)
            {
                FileInfo fileInfo = new FileInfo(fileName);
                if (fileInfo.Length > largestFileSize)
                {
                    largestFileSize  = fileInfo.Length;
                    fullDumpFilePath = fileName;
                }
            }

            if (!String.IsNullOrEmpty(dumpFileName))
            {
                fullDumpFilePath = cabFileFolder + "\\" + dumpFileName;
            }

            // Find the script that the user wants to run.
            StackHashScriptSettings scriptSettings = m_ScriptManager.LoadScript(scriptName);

            // Auto generate the script file.
            String dumpAnalysisFolder = cabFileFolder + "\\Analysis";

            if (!Directory.Exists(dumpAnalysisFolder))
            {
                Directory.CreateDirectory(dumpAnalysisFolder);
            }

            // Check if the file has already been run.
            bool   runScript       = true;
            String resultsFileName = String.Format(CultureInfo.InvariantCulture, "{0}\\{1}.log", dumpAnalysisFolder, scriptSettings.Name);

            if (File.Exists(resultsFileName))
            {
                DateTime lastWriteTime = File.GetLastWriteTimeUtc(resultsFileName);

                if (scriptSettings.LastModifiedDate <= lastWriteTime)
                {
                    runScript = false;
                }
            }

            String installFolder = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

            if (runScript || forceRun)
            {
                String overrideSymbolPath = null;
                String overrideBinaryPath = null;
                String overrideSourcePath = null;

                if (m_Debugger.Use32BitDebugger(use32BitDebugger, m_DebuggerSettings))
                {
                    overrideSymbolPath = m_DebuggerSettings.SymbolPath.FullPath;
                    overrideBinaryPath = m_DebuggerSettings.BinaryPath.FullPath;
                    overrideSourcePath = null;

                    // Check the script for PSSCOR loading.
                    String clrVersion = String.Empty;
                    if ((cab.DumpAnalysis != null) && (!String.IsNullOrEmpty(cab.DumpAnalysis.DotNetVersion)))
                    {
                        clrVersion = cab.DumpAnalysis.DotNetVersion;
                    }
                    scriptSettings.FixUp(StackHashScriptDumpArchitecture.X86, clrVersion, installFolder);
                }
                else
                {
                    overrideSymbolPath = m_DebuggerSettings.SymbolPath64Bit.FullPath;
                    overrideBinaryPath = m_DebuggerSettings.BinaryPath64Bit.FullPath;
                    overrideSourcePath = null;

                    // Check the script for PSSCOR loading.
                    String clrVersion = String.Empty;
                    if ((cab.DumpAnalysis != null) && (!String.IsNullOrEmpty(cab.DumpAnalysis.DotNetVersion)))
                    {
                        clrVersion = cab.DumpAnalysis.DotNetVersion;
                    }
                    scriptSettings.FixUp(StackHashScriptDumpArchitecture.Amd64, clrVersion, installFolder);
                }

                String scriptFileName = Path.GetTempFileName();
                scriptSettings.GenerateScriptFile(scriptFileName, resultsFileName, ref overrideSymbolPath, ref overrideBinaryPath, ref overrideSourcePath);

                DateTime timeOfRun = DateTime.Now.ToUniversalTime();
                try
                {
                    m_Debugger.RunScript(m_DebuggerSettings, use32BitDebugger, scriptFileName, fullDumpFilePath, resultsFileName, overrideSymbolPath, overrideBinaryPath, overrideSourcePath);

                    // Check if the results were generated. If not there must be a command line error so get the output from the
                    // debugger and throw an exception.
                    if (!File.Exists(resultsFileName))
                    {
                        throw new StackHashException("Debugger Error: " + m_Debugger.StandardError, StackHashServiceErrorCode.DebuggerError);
                    }


                    // Load in the results.
                    result = StackHashScriptResult.MergeAnalysisDumpFiles(resultsFileName);

                    // Add a script run note to the error index.
                    StackHashNoteEntry note = new StackHashNoteEntry();

                    // MUST KEEP THIS TEXT THE SAME - because it is used as a search string by the BugTrackerTask.
                    note.Note = String.Format(CultureInfo.CurrentCulture, "Script {0} executed", scriptName);
                    if ((clientData == null) || (clientData.ClientName == null))
                    {
                        note.Source = "Service";
                        note.User   = "******";
                    }
                    else
                    {
                        note.Source = "StackHash Client";
                        note.User   = clientData.ClientName;
                    }

                    note.TimeOfEntry = timeOfRun;
                    int cabNoteId = m_ErrorIndex.AddCabNote(product, file, theEvent, cab, note);

                    // Report the event to bug tracking plug-ins.
                    m_ErrorIndex.AddUpdate(new StackHashBugTrackerUpdate(
                                               StackHashDataChanged.DebugScript, StackHashChangeType.NewEntry, product.Id, file.Id, theEvent.Id, theEvent.EventTypeName, cab.Id, cabNoteId));
                }
                catch (System.Exception ex)
                {
                    // Add a script run note to the error index.
                    StackHashNoteEntry note = new StackHashNoteEntry();
                    note.Note   = String.Format(CultureInfo.CurrentCulture, "Script {0} execution failed: {1}", scriptName, ex.Message);
                    note.Source = "Service";
                    if ((clientData == null) || (clientData.ClientName == null))
                    {
                        note.User = "******";
                    }
                    else
                    {
                        note.User = clientData.ClientName;
                    }
                    note.TimeOfEntry = timeOfRun;
                    m_ErrorIndex.AddCabNote(product, file, theEvent, cab, note);
                    throw;
                }
                finally
                {
                    if (File.Exists(scriptFileName))
                    {
                        File.Delete(scriptFileName);
                    }
                }
            }

            return(result);
        }