Christian,

Sorry it took me so long to track this down, but it's
been a while.  A guy who I believe was named Peter,
sent me the following code.  It's supposed to be like
a <solution> task but for VB6.  I don't have the C#
skills to debug it and such.  Maybe you or one of the
folks talking about vb6 here do.  If so, it could be
very helpful as I'm starting to automate the build of
a vb6 application.

Thanks,
Eric


--- "Crowhurst,Christian"
<[EMAIL PROTECTED]> wrote:

> Hi to everyone on the forum.
> 
> I'm currently building 20-30 vb6 projects using
> FinalBuilder2. I found this tool to be particular
> usefully as it resolves / fixes any broken reference
> to other compiled vb6 projects. So for example where
> project B has an old / broken reference to project A
> it will resolve this broken reference and replace it
> with project A's current type library ID. Great,
> but... I still have to make sure that I build in
> accordance with the dependency tree. So in the above
> (trivial) example I've got to make sure that project
> A is built before project B.
> 
> So my question to the forum is, can I create an NANT
> configuration file (I assume using the VB6 task),
> that specifies the vb6 projects I want to compile,
> and let NANT figure out the dependency order for me?
> 
> Also, same question but this time I want to build a
> number of .Net projects where the projects don't all
> live in the same .Net solution.
> 
> Thanks in advance.
> Christian
>  
>  
>  
>  
>  
> This e-mail, and any attachment, is confidential and
> is intended only for the use of the individual to
> which it is addressed. If you have received it in
> error, please delete it from your system, do not use
> or disclose the information in any way. The contents
> of this message may contain personal views which are
> not the views of the ECA Group, unless specifically
> stated.
>  
> 
>  
> 
> 
>
-------------------------------------------------------
> This SF.net email is sponsored by: IT Product Guide
> on ITManagersJournal
> Use IT products in your business? Tell us what you
> think of them. Give us
> Your Opinions, Get Free ThinkGeek Gift Certificates!
> Click to find out more
>
http://productguide.itmanagersjournal.com/guidepromo.tmpl
> _______________________________________________
> Nant-users mailing list
> [EMAIL PROTECTED]
>
https://lists.sourceforge.net/lists/listinfo/nant-users
> 


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 
using System;
using System.Collections.Specialized; 
using System.Collections;
using System.Globalization;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;

using NAnt.Core;
using NAnt.Core.Attributes;
using NAnt.Core.Tasks;
using NAnt.Core.Types;
using NAnt.Core.Util;

namespace NAnt.Contrib.Tasks {

                public class VBRef 
                {
                        public string _clsid;
                        public int _usageCount = 1;
                        public string ver;
                        public string tmp;
                        public string path;
                        public string name;
                        public System.Collections.Specialized.StringCollection 
_searchResults = null;
                        
                        public void Parse(string p) 
                        {
                                string[] refData = p.Split(new char[] {'#'},5);
                                _clsid = refData[0];
                                ver=refData[1];
                                tmp=refData[2];
                                path=refData[3];
                                name=refData[4];
                        }
                };

                public class VBProj
                {
                        public string filename;
                        public enum STATE { NOTDONE = 0, INPROCESS = 1, DONE=2 };
                        public STATE _done = STATE.NOTDONE;
                        public bool _buildSucceeded = false;
                        public string _shortName;
                        public string _dir;
                        public string _outputFile;
                        public string _title;
                        public ArrayList _references = new ArrayList();
                        public ArrayList _projectDependencies = new ArrayList();
                        public ArrayList _refsWithoutProj = new ArrayList();
                        public ArrayList _refsInPath = new ArrayList();

                        public void Parse(string fname)
                        {
                                filename = fname;

                                FileInfo fdata = new FileInfo(filename);               
                 

                                _dir = fdata.DirectoryName;                     
                                _shortName = fdata.Name;

                                System.IO.FileStream fstr = 
fdata.Open(System.IO.FileMode.Open,FileAccess.Read);
                                System.IO.StreamReader srdr = new StreamReader(fstr);
                                
                                string prop;
                                
                                while(null!=(prop = srdr.ReadLine())) 
                                {                                       
                                        string[] pair = prop.Split(new char[] {'='},2);
                                        switch(pair[0])
                                        {
                                                case "Reference": 
                                                        VBRef vbref = new VBRef();
                                                        vbref.Parse(pair[1]);
                                                    _references.Add(vbref);
                                                        break;
                                                case "Title": 
                                                        _title = pair[1]; 
                                                        break;
                                                case "ExeName32":
                                                        _outputFile = pair[1].Trim(new 
char[] { '\"' }); 
                                                        break;
                                        }
                                }
                                fstr.Close();                           
                        }

            public string FileContents 
            {
                get 
                { 
                    StreamReader prjFileReader = null;
                    FileStream prjFileStream = null;
                    try 
                    {
                        prjFileReader = new StreamReader(prjFileStream = 
File.Open(filename,FileMode.Open));    
                        return prjFileReader.ReadToEnd();
                    }
                    finally
                    {
                        if(null != prjFileStream)
                        {
                            prjFileStream.Close();
                        }
                        if(null != prjFileReader)
                        {
                            prjFileReader.Close();
                        }
                    }
                }
            }
                };

    /// <summary>
    /// Compiles multiple dependent Microsoft Visual Basic 6 projects.
    /// </summary>
    /// <remarks>
    ///     <para>Uses the <see cref="Vb6Task">VB6 Task</see> to perform the actual 
compile.</para>
    /// </remarks>
    /// <example>
    ///   <para>Build all projects found under the <c>vbproject</c> directory.</para>
    ///   <code>
    ///     <![CDATA[
    /// <vb6tree>
    ///    <source basedir="vbproject">
    ///        <includes name="**.vbp"></includes>
    ///    </source>
    ///    <references>
    ///         <includes name="c:\Program Files\Microsoft Office\Office10\**.dll" />
    ///    </references>
    /// </vb6tree>
    ///     ]]>
    ///   </code>
    /// </example>
    [TaskName("vb6tree")]
    public class Vb6TreeBuilder : NAnt.Core.Task {
        
        private FileSet     _source = new FileSet();
        private bool        _traceOnly = false;
        private Hashtable   _refsWithoutProj = new Hashtable();
        private FileSet     _references = new FileSet();
        private FileInfo     _errorFile = null;

        /// <summary>
        /// Set of vb base.Project / group files to use as input
        /// </summary>
        [BuildElement("source")]
        public FileSet Source
        {
            get { return _source; }
            set { _source = value; }
        }

        /// <summary>
        /// Set of files that can be considered references
        /// </summary>
        [BuildElement("references")]
        public FileSet References 
        {
            get { return _references; }
            set { _references = value; }
        }

        /// <summary>
        /// The file to which the Visual Basic compiler should log errors.
        /// Forwarded on to the VB6 compiler
        /// </summary>
        [TaskAttribute("errorfile")]
        public FileInfo ErrorFile 
        {
            get { return _errorFile; }
            set { _errorFile = value; }
        } 

        [TaskAttribute("traceOnly")]
        [BooleanValidator()]
        public bool TraceOnly 
        {
            get { return _traceOnly; }
            set { _traceOnly = value; }
        }         

        ///<summary>
        ///Initializes task and ensures the supplied attributes are valid.
        ///</summary>
        ///<param name="taskNode">Xml node used to define this task instance.</param>
        protected override void InitializeTask(System.Xml.XmlNode taskNode) 
        {
            if (_source.FileNames.Count == 0) 
            {
                throw new BuildException("base.Projects fileset cannot be empty!", 
Location);
            }
        }

        #region Logger Helper Methods (LogInfo,LogError,LogWarning,LogVerbose,LogDebug)
        private void LogInfo(string msg, params Object[] objs)
        {
            base.Project.Log(Level.Info,msg,objs);
        }
        private void LogError(string msg, params Object[] objs)
        {
            base.Project.Log(Level.Error,msg,objs);
        }
        private void LogWarning(string msg, params Object[] objs)
        {
            base.Project.Log(Level.Warning,msg,objs);
        }
        private void LogDebug(string msg, params Object[] objs)
        {
            base.Project.Log(Level.Debug,msg,objs);
        }
        private void LogVerbose(string msg, params Object[] objs)
        {
            base.Project.Log(Level.Verbose,msg,objs);
        }
        #endregion Logger Helper Methods 
(LogInfo,LogError,LogWarning,LogVerbose,LogDebug)

        /// <summary>
        /// Builds a map of projects to possible outputs before traversing them.
        /// </summary>
        protected override void ExecuteTask() 
        {                                    
            
//Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\WINNT\System32\stdole2.tlb#OLE
 Automation
            //Title="Adapter"
            //ExeName32="Adapter.dll"

            Hashtable outputToProject = new Hashtable();
            Hashtable vbpsInMemory = new Hashtable();

            foreach(string filename in _source.FileNames)
            {
                VBProj proj = new VBProj();
                proj.Parse(filename);

                outputToProject[proj._shortName] = proj;

                string temp = 
proj._outputFile.Substring(0,proj._outputFile.LastIndexOf("."));
                                
                outputToProject[temp+".tlb"] = proj;
                outputToProject[temp+".vbp"] = proj;
                outputToProject[temp] = proj;
                                
            }

            LogInfo("{0} base.Projects loaded into memory", _source.FileNames.Count);

            foreach(VBProj prj in outputToProject.Values)
            {
                if(prj._done == VBProj.STATE.NOTDONE)RecurseOver("[vb6r] ", prj, 
outputToProject);
            }

            if(_refsWithoutProj.Values.Count > 0)
            {
                LogWarning("References problems:");
            }
            foreach(VBRef vbref in _refsWithoutProj.Values)
            {
                string searchpath = 
vbref.path.Substring(vbref.path.LastIndexOf("\\")+1);
                                
                System.Collections.Specialized.StringCollection pc = 
vbref._searchResults;
                        
                if(pc.Count == 0)
                {                                       
                    string cleared = vbref.path.Replace("..\\","");
                    LogError("   * {0}, used by {1} base.Projects", cleared, 
vbref._usageCount);
                }
                else
                {                                       
                    LogVerbose("   . {0} => ", searchpath);
                }
                                
                foreach(string s in pc)
                {
                    LogVerbose("   ... {0}", s);
                }
                                
            }

        }

        ///<summary>
        ///Builds the given project. If the project has dependencies, it builds those 
first.
        ///</summary>
        ///<param name="pfx">A log prefix used to indent log output.</param>
        ///<param name="prj">The VB project to be built.</param>
        ///<param name="outputToProject">A mapping of output files (reference targets) 
to projects previously built.</param>
        private bool RecurseOver(string pfx, VBProj prj, System.Collections.Hashtable 
outputToProject)
        {
            string logRefsInPath="";
            string logRefsNotFound = "";
                        
            // Check the state of the project we have been asked to build:

            switch(prj._done)
            {
                case VBProj.STATE.INPROCESS:
                    // This project is a dependency of itself :(
                    LogError(pfx + "{0} CIRCULAR REFERENCE!", prj._shortName);
                    return false;
                case VBProj.STATE.DONE:
                    // This project has already been built
                    LogVerbose(pfx + "{0} {1}", prj._shortName,prj._buildSucceeded ? 
"DONE" : "PREVIOUSLY FAILED" );
                    return true;
            }

            // Mark project in process being built
            prj._done = VBProj.STATE.INPROCESS;
                        
            int countOfValidRefs = 0;

            // Build dependencies first by mapping references 
            // to the projects that create them
            LogInfo(pfx + "{0} checking...", prj._shortName);
            foreach(VBRef vbref in prj._references)
            {
                string relative = vbref.path;

                relative = relative.Replace(".dll","");
                relative = relative.Replace(".tlb","");
                relative = relative.Replace(".exe","");

                string _shortName = relative.Substring(relative.LastIndexOf("\\")+1);
                                
                switch(outputToProject.ContainsKey(_shortName))
                {
                    case true: 
                        // This reference has a matching project

                        LogDebug(pfx + "| Ref ({0})", 
((VBProj)outputToProject[_shortName])._outputFile);
                        
prj._projectDependencies.Add(((VBProj)outputToProject[_shortName]));
                                                
                        if(RecurseOver(pfx+"| ", 
((VBProj)outputToProject[_shortName]), outputToProject))
                        {
                            ++countOfValidRefs;
                        }
                                                
                        break;
                    case false: 
                        // This reference is not part of the project collection
                        // So we search for it:

                        VBRef prevRef = (VBRef)_refsWithoutProj[vbref._clsid];
                        System.Collections.Specialized.StringCollection searchResults 
= null;
                                                             
                        if(prevRef != null)
                        {
                            // Reference has previously been searched for
                            searchResults = prevRef._searchResults;
                        }
                        else prevRef = vbref;
                                                
                        string searchpath = 
prevRef.path.Substring(prevRef.path.LastIndexOf("\\")+1);
                                                
                        // Perform search, if necessary
                        if(searchResults == null)
                        {
                            NAnt.Core.PathScanner p = new NAnt.Core.PathScanner();
                            p.Add(searchpath);
                                                    
                            searchResults = p.Scan();
                            prevRef._searchResults = searchResults;
                        }                                        
                        
                        // Analyze results
                        if(searchResults.Count == 0)
                        {
                            // Mark not found in project
                            prj._refsWithoutProj.Add(vbref);
                        }
                        else 
                        {
                            // Mark found via search in project
                            prj._refsInPath.Add(vbref);
                        }
                                                
                        // Similarly mark in the global list of lost projects
                        if(!_refsWithoutProj.ContainsKey(vbref._clsid))
                        {
                            _refsWithoutProj.Add(vbref._clsid,vbref);
                        }
                        else
                        {
                            // Increment # of projects using for kicks
                            ++prevRef._usageCount;
                        }


                        // We're done now, but build a log message for information only
                        string cleared = prevRef.path.Replace("..\\","");
                        string _shortName2 = 
searchpath.Substring(searchpath.LastIndexOf("\\")+1);
                                                   
                        if(searchResults.Count == 0)
                        {                       
                            logRefsNotFound += _shortName2 + ", ";
                        }
                        else
                        {                                       
                            logRefsInPath += _shortName2 + "(";
                        }
                                                
                        foreach(string s in searchResults)
                        {
                            LogDebug(pfx+"| {2} alt: {0} for {1}", s,searchpath, 
prj._shortName);
                            logRefsInPath += s;
                            logRefsInPath += ", ";
                        }
                                                
                        if(searchResults.Count != 0)
                        {                                       
                            logRefsInPath += ")";
                        }

                        break;
                }
            }
            
            // Log results
            if(prj._refsInPath.Count > 0) LogVerbose(pfx + "| {0} IN PATH {1}", 
prj._shortName, logRefsInPath);
            if(prj._refsWithoutProj.Count > 0) LogVerbose(pfx + "| {0} MISSING {1}", 
prj._shortName, logRefsNotFound);
                        
            if(prj._refsWithoutProj.Count == 0 && prj._refsInPath.Count + 
countOfValidRefs == prj._references.Count ) 
            {
                // Finally, invoke the Vb6 task to build this project.

                try 
                {
                    BuildProject(prj);

                    LogInfo(pfx + "{0} OK!",prj._shortName);
                    
                    return prj._buildSucceeded=true;
                }
                finally 
                {
                    // Project has been built
                    prj._done = VBProj.STATE.DONE;                    
                }                
            }
            else 
            {                   
                LogError(pfx + "{0} MISSING REFERENCES {1}/{2}/{3}!",prj._shortName, 
countOfValidRefs, prj._references.Count-prj._refsWithoutProj.Count, 
prj._references.Count);
                
                // Project cannot be built
                prj._done = VBProj.STATE.DONE;

                return prj._buildSucceeded=false; 
            }
        }
/// <summary>
/// Rewrites a project file for a project and then compiles it. 
/// This rewritten version includes modifying references to point 
/// to their resolved locations.
/// </summary>
/// <param name="prj">The Visual Basic project to compile</param>
        protected void BuildProject(VBProj prj)
        {
            FileInfo projectFileInfo = new FileInfo(prj.filename);
            FileInfo tempProjectFileInfo = new FileInfo(projectFileInfo.DirectoryName 
+ "\tmp_" + prj._shortName + ".vbp");
            FileInfo outputFileInfo = new FileInfo(prj._outputFile);

            //-------------------------------------------------

            FileStream tempProjStream = 
tempProjectFileInfo.Open(FileMode.CreateNew,FileAccess.Write,FileShare.Read);

            try 
            {
                string prjData = prj.FileContents;

                if(base.Verbose)
                {
                    LogVerbose(prjData);
                }
            
                System.IO.StreamWriter prjWriter = new 
System.IO.StreamWriter(tempProjStream);

                prjWriter.WriteLine(prjData);
            }
            finally
            {
                tempProjStream.Close();
            }

            //-------------------------------------------------

            try 
            {
                Vb6Task compileTask = new Vb6Task();
                compileTask.Initialize(null);
                compileTask.CheckReferences=true;
                compileTask.ErrorFile = ErrorFile;
                compileTask.OutDir = outputFileInfo.Directory;
                compileTask.Project = base.Project;
                compileTask.ProjectFile = tempProjectFileInfo;            

                if(!TraceOnly)
                {
                    compileTask.Execute();
                }
            }
            finally
            {
                tempProjectFileInfo.Delete();
            }

            //-------------------------------------------------            
        }
    }
}

Reply via email to