MS Source Server - при просмотре с помощью srctool, по-видимому, нет исходного потока - PullRequest
2 голосов
/ 29 марта 2009

Я играл с MS Source Server в установке MS Debugging Tools.

В настоящее время я выполняю свой код / ​​pdbs с помощью команды индексации Subversion, которая теперь выполняется должным образом. Он создает поток для данного файла pdb и записывает его в файл pdb.

Однако, когда я использую эту DLL и связанный pdb в Visual Studio 2008, он говорит, что исходный код не может быть получен.

Если я проверяю pdb против srctool, он говорит, что ни один из содержащихся в нем исходных файлов не проиндексирован, что очень странно, так как предыдущий процесс прошел нормально.

Если я проверю поток, сгенерированный из прогона svnindex.cmd для pdb, srctool скажет, что все исходные файлы проиндексированы.

Почему будет разница?

Я открыл файл pdb в текстовом редакторе и вижу исходные ссылки на исходные файлы на моем компьютере (также под именем заголовка srcsrv), а новый «внедренный» источник ссылается на мой репозиторий subversion).

Должны ли обе ссылки существовать в pdb? Я бы ожидал, что один будет удален?

В любом случае, Visual Studio 2008 не получит ссылки на мои источники, поэтому я немного растерялся, что делать дальше. Насколько я могу судить, я сделал все, что должен был.

Кто-нибудь имеет подобный опыт?

Большое спасибо.

Ответы [ 3 ]

2 голосов
/ 01 апреля 2009

Я решил мою проблему - путь к исходному файлу, который был записан в PDB во время сборки, немного отличался от того, который был написан как часть задачи индекса исходного кода Subversion.

Это должно сделать недействительным поиск источника в Visual Studio, поскольку два пути не совпадают.

Также записываю собственный упрощенный поток исходного индекса в мои файлы PDB из пользовательской задачи NAnt, которая подключается к Vault, нашей системе SCM.

1 голос
/ 29 марта 2009

В параметрах \ Отладка \ Символы Visual Studio есть опция для создания журналов исходного сервера.
Также вам нужна последняя версия srcsrv.dll, просто скачайте последнюю WinDBG , скопируйте оттуда DLL и убедитесь, что Visual Studio ее использует.

0 голосов
/ 31 марта 2010

Не был здесь давно, извините. Это довольно специфично для потребностей нашей компании. Должно быть достаточно, чтобы показать, что происходит.

Фрагменты кода ниже:

PdbFile.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Code.Integration.SourceIndex
{
    public class PdbFile
    {
        private FileInfo _pdbFile;

        public FileInfo Pdb
        {
            get { return _pdbFile; }
        }

        public PdbFile(FileInfo pdbFile)
        {
            if (pdbFile == null)
                throw new ArgumentNullException("pdbFile");

            if (!pdbFile.Exists)
                throw new ArgumentException(string.Format("Pdb file specified \"{0}\" does not exist.", pdbFile.FullName), "pdbFile");

            _pdbFile = pdbFile;
        }

        // Read source files
        // Write source stream
    }
}

PdbUtil.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;

namespace Code.Integration.SourceIndex
{
    public static class PdbUtil
    {
        private static readonly string SRCTOOL_PATH_1 = @"C:\Program Files\Debugging Tools for Windows\srcsrv\srctool.exe";
        private static readonly string SRCTOOL_PATH_2 = @"C:\Program Files\Debugging Tools for Windows (x86)\srcsrv\srctool.exe";
        private static readonly string PDBSTR_PATH_1 = @"C:\Program Files\Debugging Tools for Windows\srcsrv\pdbstr.exe";
        private static readonly string PDBSTR_PATH_2 = @"C:\Program Files\Debugging Tools for Windows (x86)\srcsrv\pdbstr.exe";

        private static string SRCTOOL = "";
        private static string PDBSTR = "";

        static PdbUtil()
        {
            if (File.Exists(SRCTOOL_PATH_1))
                SRCTOOL = SRCTOOL_PATH_1;
            else if (File.Exists(SRCTOOL_PATH_2))
                SRCTOOL = SRCTOOL_PATH_2;

            if (File.Exists(PDBSTR_PATH_1))
                PDBSTR = PDBSTR_PATH_1;
            else if (File.Exists(PDBSTR_PATH_2))
                PDBSTR = PDBSTR_PATH_2;
        }

        private static void EnsureToolsExist()
        {
            if (string.IsNullOrEmpty(SRCTOOL))
                throw new ApplicationException(string.Format("SRCTOOL does not exist. Is it installed?", SRCTOOL));

            if (string.IsNullOrEmpty(PDBSTR))
                throw new ApplicationException(string.Format("PDBSTR does not exist. Is it installed?", PDBSTR));
        }

        public static List<string> ReadSourceFiles(PdbFile pdb)
        {
            EnsureToolsExist();

            ProcessStartInfo info = new ProcessStartInfo(SRCTOOL);

            info.UseShellExecute = false;
            info.RedirectStandardError = true;
            info.RedirectStandardOutput = true;
            info.Arguments = string.Format("-r \"{0}\"", pdb.Pdb.FullName);

            string output;
            string errors;

            using (Process p = Process.Start(info))
            {
                output = p.StandardOutput.ReadToEnd();
                errors = p.StandardError.ReadToEnd();

                p.WaitForExit();
            }

            if (!string.IsNullOrEmpty(errors))
                throw new ApplicationException(string.Format("Error reading pdb source files \"{0}\".", errors));

            List<string> result = new List<string>();

            if (!string.IsNullOrEmpty(output))
            {
                foreach (string item in output.Split('\r', '\n'))
                {
                    string sourceFile = item.Trim();

                    if (string.IsNullOrEmpty(sourceFile))
                        continue;

                    result.Add(sourceFile);
                }
            }

            return result;
        }

        public static void WriteSourceFileStream(PdbFile pdb, FileInfo stream)
        {
            EnsureToolsExist();

            ProcessStartInfo info = new ProcessStartInfo(PDBSTR);

            info.UseShellExecute = false;
            info.RedirectStandardError = true;
            info.RedirectStandardOutput = true;
            info.Arguments = string.Format("-w -s:srcsrv -p:\"{0}\" -i:\"{1}\"", pdb.Pdb.FullName, stream.FullName);

            string output;
            string errors;

            using (Process p = Process.Start(info))
            {
                output = p.StandardOutput.ReadToEnd();
                errors = p.StandardError.ReadToEnd();

                p.WaitForExit();
            }

            if (!string.IsNullOrEmpty(errors))
                throw new ApplicationException(string.Format("Error writing to pdb \"{0}\".", errors));
        }
    }
}

SourceIndexTask.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

using NAnt.Core;
using NAnt.Core.Attributes;
using NAnt.Core.Types;

using Code.Integration.SourceIndex;

namespace Code.Integration.NAnt.Tasks.SourceIndex
{
    [TaskName("codesourceindex")]
    public class SourceIndexTask : Task
    {
        private FileSet _pdbs = new FileSet();
        private string _build = "0.0.0.0";
        private string _repositoryName = "";
        private string _repositoryProjectStart = "";
        private string _user = "";
        private string _password = "";
        private string _server = "";

        #region Properties

        /// <summary>
        /// FileSet of pdbs to process.
        /// </summary>
        [BuildElement("pdbs")]
        public FileSet Pdbs
        {
            get { return _pdbs; }
            set { _pdbs = value; }
        }

        /// <summary>
        /// Build label to extract.
        /// Default is "0.0.0.0".
        /// </summary>
        [TaskAttribute("build", Required = true)]
        [StringValidator(AllowEmpty = false)]
        public string Build
        {
            get { return _build; }
            set { _build = value; }
        }

        /// <summary>
        /// Name of repository we are working on.
        /// </summary>
        [TaskAttribute("reponame", Required = true)]
        [StringValidator(AllowEmpty = false)]
        public string RepositoryName
        {
            get { return _repositoryName; }
            set { _repositoryName = value; }
        }

        /// <summary>
        /// Name of start folder within project we are working on. i.e. if the 
        /// repository was "Code 2-0" then the repository project start could be "/Code/Trunk"
        /// or "/Code/Branches/1.0.0.123/"
        /// </summary>
        [TaskAttribute("repoprojectstart", Required = true)]
        [StringValidator(AllowEmpty = false)]
        public string RepositoryProjectStart
        {
            get { return _repositoryProjectStart; }
            set { _repositoryProjectStart = value; }
        }

        /// <summary>
        /// Vault user with repository access.
        /// </summary>
        [TaskAttribute("user", Required = true)]
        [StringValidator(AllowEmpty = false)]
        public string User
        {
            get { return _user; }
            set { _user = value; }
        }

        /// <summary>
        /// Vault user password.
        /// </summary>
        [TaskAttribute("password", Required = true)]
        [StringValidator(AllowEmpty = false)]
        public string Password
        {
            get { return _password; }
            set { _password = value; }
        }

        /// <summary>
        /// Location of Vault server.
        /// </summary>
        [TaskAttribute("server", Required = true)]
        [StringValidator(AllowEmpty = false)]
        public string Server
        {
            get { return _server; }
            set { _server = value; }
        }

        #endregion

        protected override void ExecuteTask()
        {
            try
            {
                WriteFiles();
            }
            catch (Exception exception)
            {
                throw new BuildException("Source indexing could not be completed.", Location, exception);
            }
        }

        private void WriteFiles()
        {
            foreach (string fileName in Pdbs.FileNames)
            {
                Log(Level.Info, string.Format("Processing '{0}'.", fileName));

                PdbFile pdb = new PdbFile(new FileInfo(fileName));
                List<string> sourceFiles = PdbUtil.ReadSourceFiles(pdb);
                string tmpFile = Path.GetFullPath(Path.GetTempFileName());

                try
                {
                    using (StreamWriter sw = new StreamWriter(tmpFile))
                    {
                        sw.WriteLine("SRCSRV: ini ------------------------------------------------");
                        sw.WriteLine("VERSION=1");
                        sw.WriteLine("VERCTRL=VAULT");
                        sw.WriteLine("DATETIME=" + DateTime.Now.ToUniversalTime().ToString("u"));
                        sw.WriteLine("SRCSRV: variables ------------------------------------------");
                        sw.WriteLine("VAULT_USER=" + User);
                        sw.WriteLine("VAULT_PASS=" + Password);
                        sw.WriteLine("VAULT_SRV=" + Server);
                        sw.WriteLine("VAULT_EXTRACT_TARGET=%targ%%fnbksl%(%var3%)\\%var4%\\%fnfile%(%var1%)");
                        sw.WriteLine("VAULT_EXTRACT_FOLDER=%targ%%fnbksl%(%var3%)\\%var4%");
                        sw.WriteLine("VAULT_EXTRACT_CMD=\"C:\\Program Files\\SourceGear\\Vault Client\\vault.exe\" getlabel -host %vault_srv% -user %vault_user% -password %vault_pass% -repository \"%var2%\" \"$%var3%\" %var4% -nonworkingfolder \"%vault_extract_folder%\" > \"%vault_extract_target%.log\"");
                        sw.WriteLine("SRCSRVTRG=%vault_extract_target%");
                        sw.WriteLine("SRCSRVCMD=%vault_extract_cmd%");
                        sw.WriteLine("SRCSRV: source files ---------------------------------------");

                        foreach (string sourceFile in sourceFiles)
                        {
                            // Will build against something like:
                            // D:\CruiseControl.NET.Working\Solutions 2.0\Code\Code\Trunk\Working\Solution\..
                            // Don't want "Working" folder name in there either.
                            // Need to generate Vault repo path to asset:
                            // /Code/Trunk/Solution/..

                            // 1. Pass in repo start - /Code/Trunk
                            // 2. Redirect slashes and search for \Code\Trunk
                            // 3. Find first index and split at index to get - \Code\Trunk\Working\Solution\..
                            // 4. Remove "Working\"
                            // 5. Flip slashes again to get - /Code/Trunk/Solution/..

                            // Problems:
                            // 1. Passing in "Trunk" - would need to work that out dynamically over time

                            string repositoryPath = sourceFile;

                            int index = sourceFile.IndexOf(RepositoryProjectStart.Replace("/", @"\"));
                            if (index != -1)
                                repositoryPath = sourceFile.Substring(index);

                            repositoryPath = repositoryPath.Replace(@"Working\", "");
                            repositoryPath = repositoryPath.Replace(@"\", "/");

                            sw.Write(sourceFile);
                            sw.Write("*");
                            sw.Write(RepositoryName);
                            sw.Write("*");
                            sw.Write(repositoryPath);
                            sw.Write("*");
                            sw.Write(Build);
                            sw.WriteLine();
                        }

                        sw.WriteLine("SRCSRV: end ------------------------------------------------");
                    }

                    Log(Level.Debug, string.Format("Generated stream '{0}'.", File.ReadAllText(tmpFile)));

                    // Write the stream to the pdb file
                    PdbUtil.WriteSourceFileStream(pdb, new FileInfo(tmpFile));

                    Log(Level.Info, "Written stream to pdb.");
                }
                finally
                {
                    if (File.Exists(tmpFile))
                        File.Delete(tmpFile);
                }
            }
        }
    }
}
...