MS源服务器 - 使用srctool查看时,源流显然不存在

时间:2009-03-29 14:07:06

标签: .net debugging srcsrv

我一直在使用MS调试工具安装中的MS Source Server。

目前,我正在通过Subversion索引命令运行我的代码/ pdbs,该命令现在正在按预期运行。它为给定的pdb文件创建流并将其写入pdb文件。

然而,当我在visual studio 2008中使用该DLL和相关的pdb时,它说无法检索源代码。

如果我检查pdb对srctool说没有包含所有源文件的索引,这很奇怪,因为之前的进程运行正常。

如果我检查从pv的svnindex.cmd运行生成的流,则srctool表示所有源文件都已编入索引。

为什么会有差异?

我已经在文本编辑器中打开了pdb文件,我可以看到我机器上的源文件的原始引用(也在srcsrv头名称下),新的“注入”源服务器链接到我的subversion存储库)。

两个引用是否仍然存在于pdb中?我本以为要删除一个?

无论哪种方式,visual studio 2008都不会拿起我的源代码引用,所以我对于接下来要尝试什么感到有点迷茫。据我所知,我已经做了我应该做的一切。

有没有类似的经历?

非常感谢。

3 个答案:

答案 0 :(得分:2)

我已经解决了我的问题 - 在构建期间写入PDB的源文件路径与作为Subversion源索引任务的一部分写入的路径略有不同。

这必须使Visual Studio中的源搜索无效,因为两条路径不匹配。

还将我自己的简化源索引流从自定义的NAnt任务写入我的PDB文件,该任务连接到我们的SCM系统Vault。

答案 1 :(得分:1)

Visual Studio的Options \ Debugging \ Symbols中有一个选项可以发出源服务器的日志 您还需要最新版本的srcsrv.dll,只需从该处下载最新的WinDBG复制DLL,并确保Visual Studio使用它。

答案 2 :(得分:0)

很久没多久了,抱歉。这完全符合我们公司的需求。应该足以显示正在发生的事情。

以下代码段:

<强> 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);
                }
            }
        }
    }
}