protected override void WriteProject(SolutionNode solution, ProjectNode project)
        {
            if (!m_Tools.ContainsKey(project.Language))
                throw new Exception("Unknown .NET language: " + project.Language);

            ToolInfo toolInfo = (ToolInfo)m_Tools[project.Language];
            string projectFile = Helper.MakeFilePath(project.FullPath, project.Name, toolInfo.FileExtension);
            StreamWriter ps = new StreamWriter(projectFile);

            m_Kernel.CWDStack.Push();
            Helper.SetCurrentDir(Path.GetDirectoryName(projectFile));

            using (ps) {
                ps.WriteLine("<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">");
                // ps.WriteLine("\t<{0}", toolInfo.XMLTag);
                ps.WriteLine("\t<PropertyGroup>");
                ps.WriteLine("\t\t<ProjectType>Local</ProjectType>");
                ps.WriteLine("\t\t<ProductVersion>{0}</ProductVersion>", m_ProductVersion);
                ps.WriteLine("\t\t<SchemaVersion>{0}</SchemaVersion>", m_SchemaVersion);
                ps.WriteLine("\t\t<ProjectGuid>{{{0}}}</ProjectGuid>", project.Guid.ToString().ToUpper());

                ps.WriteLine("\t\t<Configuration Condition = \" '$(Configuration)' == '' \">Debug</Configuration>");
                ps.WriteLine("\t\t<Platform Condition = \" '$(Platform)' == '' \">AnyCPU</Platform>");
                // ps.WriteLine("\t\t<Build>");

                // ps.WriteLine("\t\t\t<Settings");
                ps.WriteLine("\t\t<ApplicationIcon></ApplicationIcon>");
                ps.WriteLine("\t\t<AssemblyKeyContainerName></AssemblyKeyContainerName>");
                ps.WriteLine("\t\t<AssemblyName>{0}</AssemblyName>", project.AssemblyName);
                ps.WriteLine("\t\t<AssemblyOriginatorKeyFile></AssemblyOriginatorKeyFile>");
                ps.WriteLine("\t\t<DefaultClientScript>JScript</DefaultClientScript>");
                ps.WriteLine("\t\t<DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>");
                ps.WriteLine("\t\t<DefaultTargetSchema>IE50</DefaultTargetSchema>");
                ps.WriteLine("\t\t<DelaySign>false</DelaySign>");

                // if(m_Version == VSVersion.VS70)
                //     ps.WriteLine("\t\t\t\tNoStandardLibraries = \"false\"");

                ps.WriteLine("\t\t<OutputType>{0}</OutputType>", project.Type.ToString());
                ps.WriteLine("\t\t<RootNamespace>{0}</RootNamespace>", project.RootNamespace);
                ps.WriteLine("\t\t<StartupObject>{0}</StartupObject>", project.StartupObject);
                // ps.WriteLine("\t\t\t>");
                ps.WriteLine("\t\t<FileUpgradeFlags></FileUpgradeFlags>");

                ps.WriteLine("\t</PropertyGroup>");

                foreach (ConfigurationNode conf in project.Configurations) {
                    ps.Write("\t<PropertyGroup ");
                    ps.WriteLine("Condition=\" '$(Configuration)|$(Platform)' == '{0}|AnyCPU' \">", conf.Name);
                    ps.WriteLine("\t\t<AllowUnsafeBlocks>{0}</AllowUnsafeBlocks>", conf.Options["AllowUnsafe"]);
                    ps.WriteLine("\t\t<BaseAddress>{0}</BaseAddress>", conf.Options["BaseAddress"]);
                    ps.WriteLine("\t\t<CheckForOverflowUnderflow>{0}</CheckForOverflowUnderflow>", conf.Options["CheckUnderflowOverflow"]);
                    ps.WriteLine("\t\t<ConfigurationOverrideFile></ConfigurationOverrideFile>");
                    ps.WriteLine("\t\t<DefineConstants>{0}</DefineConstants>", conf.Options["CompilerDefines"]);
                    ps.WriteLine("\t\t<DocumentationFile>{0}</DocumentationFile>", conf.Options["XmlDocFile"]);
                    ps.WriteLine("\t\t<DebugSymbols>{0}</DebugSymbols>", conf.Options["DebugInformation"]);
                    ps.WriteLine("\t\t<FileAlignment>{0}</FileAlignment>", conf.Options["FileAlignment"]);
                    // ps.WriteLine("\t\t<IncrementalBuild = \"{0}\"", conf.Options["IncrementalBuild"]);

                    // if(m_Version == VSVersion.VS71)
                    // {
                    //     ps.WriteLine("\t\t\t\t\tNoStdLib = \"{0}\"", conf.Options["NoStdLib"]);
                    //     ps.WriteLine("\t\t\t\t\tNoWarn = \"{0}\"", conf.Options["SupressWarnings"]);
                    // }

                    ps.WriteLine("\t\t<Optimize>{0}</Optimize>", conf.Options["OptimizeCode"]);
                    ps.WriteLine("\t\t<OutputPath>{0}</OutputPath>",
                        Helper.EndPath(Helper.NormalizePath(conf.Options["OutputPath"].ToString())));
                    ps.WriteLine("\t\t<RegisterForComInterop>{0}</RegisterForComInterop>", conf.Options["RegisterCOMInterop"]);
                    ps.WriteLine("\t\t<RemoveIntegerChecks>{0}</RemoveIntegerChecks>", conf.Options["RemoveIntegerChecks"]);
                    ps.WriteLine("\t\t<TreatWarningsAsErrors>{0}</TreatWarningsAsErrors>", conf.Options["WarningsAsErrors"]);
                    ps.WriteLine("\t\t<WarningLevel>{0}</WarningLevel>", conf.Options["WarningLevel"]);
                    ps.WriteLine("\t</PropertyGroup>");
                }

                // ps.WriteLine("\t\t\t</Settings>");

                ps.WriteLine("\t<ItemGroup>");
                foreach (ReferenceNode refr in project.References) {
                    if (solution.ProjectsTable.ContainsKey(refr.Name)) {
                        ProjectNode refProject = (ProjectNode)solution.ProjectsTable[refr.Name];
                        ps.Write("\t\t<ProjectReference");
                        ps.WriteLine(" Include=\"{0}\">", refProject.Path);
                        ps.WriteLine("\t\t\t<Project>{{{0}}}</Project>", refProject.Guid.ToString().ToUpper());
                        ps.WriteLine("\t\t\t<Package>{0}</Package>", toolInfo.Guid.ToString().ToUpper());
                        ps.WriteLine("\t\t\t<Name>{0}</Name>", refr.Name);
                        if (refr.LocalCopy)
                            ps.WriteLine("\t\t\t<Private>{0}</Private>", refr.LocalCopy);
                        ps.WriteLine("\t\t</ProjectReference>");
                    } else {
                        ps.Write("\t\t<Reference");
                        ps.WriteLine(" Include=\"{0}\">", refr.Name);
                        ps.WriteLine("\t\t\t<Name>{0}</Name>", refr.Name);
                        if (refr.Path != null)
                            ps.WriteLine("\t\t\t<HintPath>{0}</HintPath>", Helper.MakeFilePath(refr.Path, refr.Name, "dll"));
                        if (refr.LocalCopy)
                            ps.WriteLine("\t\t\t<Private>{0}</Private>", refr.LocalCopy);
                        ps.WriteLine("\t\t</Reference>");
                    }
                    // ps.WriteLine("\t\t\t\t/>");
                }
                ps.WriteLine("\t</ItemGroup>");

                // ps.WriteLine("\t\t</Build>");
                ps.WriteLine("\t<ItemGroup>");

                // ps.WriteLine("\t\t\t<Include>");
                foreach (string file in project.Files) {
                    ps.Write("\t\t<{0} ", project.Files.GetBuildAction(file));
                    ps.WriteLine(" Include =\"{0}\">", file.Replace(".\\", ""));
                    ps.WriteLine("\t\t\t<SubType>Code</SubType>");
                    ps.WriteLine("\t\t</{0}>", project.Files.GetBuildAction(file));

                    // ps.WriteLine("\t\t\t\t<File");
                    // ps.WriteLine("\t\t\t\t\tRelPath = \"{0}\"", file.Replace(".\\", ""));
                    // ps.WriteLine("\t\t\t\t\tSubType = \"Code\"");
                    // ps.WriteLine("\t\t\t\t\tBuildAction = \"{0}\"", project.Files.GetBuildAction(file));
                    // ps.WriteLine("\t\t\t\t/>");
                }
                // ps.WriteLine("\t\t\t</Include>");

                ps.WriteLine("\t</ItemGroup>");
                ps.WriteLine("\t<Import Project=\"$(MSBuildBinPath)\\Microsoft.CSHARP.Targets\" />");
                ps.WriteLine("\t<PropertyGroup>");
                ps.WriteLine("\t\t<PreBuildEvent>");
                ps.WriteLine("\t\t</PreBuildEvent>");
                ps.WriteLine("\t\t<PostBuildEvent>");
                ps.WriteLine("\t\t</PostBuildEvent>");
                ps.WriteLine("\t</PropertyGroup>");
                // ps.WriteLine("\t</{0}>", toolInfo.XMLTag);
                ps.WriteLine("</Project>");
            }

            ps = new StreamWriter(projectFile + ".user");
            using (ps) {
                ps.WriteLine("<Project xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">");
                // ps.WriteLine( "<VisualStudioProject>" );
                // ps.WriteLine("\t<{0}>", toolInfo.XMLTag);
                // ps.WriteLine("\t\t<Build>");
                ps.WriteLine("\t<PropertyGroup>");
                // ps.WriteLine("\t\t\t<Settings ReferencePath=\"{0}\">", MakeRefPath(project));
                ps.WriteLine("\t\t<Configuration Condition=\" '$(Configuration)' == '' \">Debug</Configuration>");
                ps.WriteLine("\t\t<Platform Condition=\" '$(Platform)' == '' \">AnyCPU</Platform>");
                ps.WriteLine("\t\t<ReferencePath>{0}</ReferencePath>", MakeRefPath(project));
                ps.WriteLine("\t\t<LastOpenVersion>{0}</LastOpenVersion>", m_ProductVersion);
                ps.WriteLine("\t\t<ProjectView>ProjectFiles</ProjectView>");
                ps.WriteLine("\t\t<ProjectTrust>0</ProjectTrust>");
                ps.WriteLine("\t</PropertyGroup>");
                foreach (ConfigurationNode conf in project.Configurations) {
                    ps.Write("\t<PropertyGroup");
                    ps.Write(" Condition = \" '$(Configuration)|$(Platform)' == '{0}|AnyCPU' \"", conf.Name);
                    ps.WriteLine(" />");
                }
                // ps.WriteLine("\t\t\t</Settings>");

                // ps.WriteLine("\t\t</Build>");
                // ps.WriteLine("\t</{0}>", toolInfo.XMLTag);
                // ps.WriteLine("</VisualStudioProject>");
                ps.WriteLine("</Project>");
            }

            m_Kernel.CWDStack.Pop();
        }
        protected override void WriteSolution(SolutionNode solution)
        {
            m_Kernel.Log.Write("Creating Visual Studio {0} solution and project files", m_VersionName);

            foreach(ProjectNode project in solution.Projects)
            {
                m_Kernel.Log.Write("...Creating project: {0}", project.Name);
                WriteProject(solution, project);
            }

            m_Kernel.Log.Write("");
            string solutionFile = Helper.MakeFilePath(solution.FullPath, solution.Name, "sln");
            StreamWriter ss = new StreamWriter(solutionFile);

            m_Kernel.CWDStack.Push();
            Helper.SetCurrentDir(Path.GetDirectoryName(solutionFile));

            using(ss)
            {
                ss.WriteLine("Microsoft Visual Studio Solution File, Format Version {0}", m_SolutionVersion);
                foreach(ProjectNode project in solution.Projects)
                {
                    if(!m_Tools.ContainsKey(project.Language))
                        throw new Exception("Unknown .NET language: " + project.Language);

                    ToolInfo toolInfo = (ToolInfo)m_Tools[project.Language];

                    string path = Helper.MakePathRelativeTo(solution.FullPath, project.FullPath);
                    ss.WriteLine("Project(\"{0}\") = \"{1}\", \"{2}\", \"{{{3}}}\"",
                        toolInfo.Guid, project.Name, Helper.MakeFilePath(path, project.Name,
                        toolInfo.FileExtension), project.Guid.ToString().ToUpper());

                    // ss.WriteLine("\tProjectSection(ProjectDependencies) = postProject");
                    // ss.WriteLine("\tEndProjectSection");

                    ss.WriteLine("EndProject");
                }

                ss.WriteLine("Global");

                // VS2005 uses SolutionConfigurationPlatforms instead of SolutionConfiguration
                // This also means that the config name includes the "|Any CPU" part.
                ss.WriteLine("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution");
                foreach (ConfigurationNode conf in solution.Configurations)
                    ss.WriteLine("\t\t{0}|Any CPU = {0}|Any CPU", conf.Name);
                ss.WriteLine("\tEndGlobalSection");

                // VS2005 doesn't want this line if there are no projects
                if (solution.Projects.Count > 1) {
                    ss.WriteLine("\tGlobalSection(ProjectDependencies) = postSolution");
                }
                foreach (ProjectNode project in solution.Projects) {
                    for (int i = 0; i < project.References.Count; i++) {
                        ReferenceNode refr = (ReferenceNode)project.References[i];
                        if (solution.ProjectsTable.ContainsKey(refr.Name)) {
                            ProjectNode refProject = (ProjectNode)solution.ProjectsTable[refr.Name];
                            ss.WriteLine("\t\t({{{0}}}).{1} = ({{{2}}})",
                                project.Guid.ToString().ToUpper()
                                , i,
                                refProject.Guid.ToString().ToUpper()
                            );
                        }
                    }
                }
                // VS2005 doesn't want this line if there are no projects
                if (solution.Projects.Count > 1) {
                    ss.WriteLine("\tEndGlobalSection");
                }

                // Again VS2005 wants to include the platform, so we use
                // ProjectConfigurationPlatforms instead of ProjectConfiguration and
                // we add the "|Any CPU" to the config lines.
                ss.WriteLine("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution");
                foreach (ProjectNode project in solution.Projects) {
                    foreach (ConfigurationNode conf in solution.Configurations) {
                        ss.WriteLine("\t\t{{{0}}}.{1}|Any CPU.ActiveCfg = {1}|Any CPU",
                            project.Guid.ToString().ToUpper(),
                            conf.Name);

                        ss.WriteLine("\t\t{{{0}}}.{1}|Any CPU.Build.0 = {1}|Any CPU",
                            project.Guid.ToString().ToUpper(),
                            conf.Name);
                    }
                }
                ss.WriteLine("\tEndGlobalSection");

                // VS2005 has SolutionProperties
                ss.WriteLine("\tGlobalSection(SolutionProperties) = preSolution");
                ss.WriteLine("\t\tHideSolutionNode = FALSE");
                ss.WriteLine("\tEndGlobalSection");

                // VS2005 does not have SolutionItems
                // if(solution.Files != null)
                // {
                //     ss.WriteLine("\tGlobalSection(SolutionItems) = postSolution");
                //     foreach(string file in solution.Files)
                //         ss.WriteLine("\t\t{0} = {0}", file);
                //     ss.WriteLine("\tEndGlobalSection");
                // }

                ss.WriteLine("EndGlobal");
            }

            m_Kernel.CWDStack.Pop();
        }
        private void WriteCombine(SolutionNode solution)
        {
            m_Kernel.Log.Write("Creating SharpDevelop combine and project files");
            foreach(ProjectNode project in solution.Projects)
            {
                m_Kernel.Log.Write("...Creating project: {0}", project.Name);
                WriteProject(solution, project);
            }

            m_Kernel.Log.Write("");
            string combFile = Helper.MakeFilePath(solution.FullPath, solution.Name, "cmbx");
            StreamWriter ss = new StreamWriter(combFile);

            m_Kernel.CWDStack.Push();
            Helper.SetCurrentDir(Path.GetDirectoryName(combFile));

            using(ss)
            {
                ss.WriteLine("<Combine fileversion=\"1.0\" name=\"{0}\" description=\"\">", solution.Name);

                int count = 0;
                foreach(ProjectNode project in solution.Projects)
                {
                    if(count == 0)
                        ss.WriteLine("\t<StartMode startupentry=\"{0}\" single=\"True\">", project.Name);

                    ss.WriteLine("\t\t<Execute entry=\"{0}\" type=\"None\" />", project.Name);
                    count++;
                }
                ss.WriteLine("\t</StartMode>");

                ss.WriteLine("\t<Entries>");
                foreach(ProjectNode project in solution.Projects)
                {
                    string path = Helper.MakePathRelativeTo(solution.FullPath, project.FullPath);
                    ss.WriteLine("\t\t<Entry filename=\"{0}\" />",
                        Helper.MakeFilePath(path, project.Name, "prjx"));
                }
                ss.WriteLine("\t</Entries>");

                count = 0;
                foreach(ConfigurationNode conf in solution.Configurations)
                {
                    if(count == 0)
                        ss.WriteLine("\t<Configurations active=\"{0}\">", conf.Name);

                    ss.WriteLine("\t\t<Configuration name=\"{0}\">", conf.Name);
                    foreach(ProjectNode project in solution.Projects)
                        ss.WriteLine("\t\t\t<Entry name=\"{0}\" configurationname=\"{1}\" build=\"True\"/>", project.Name, conf.Name);
                    ss.WriteLine("\t\t</Configuration>");

                    count++;
                }
                ss.WriteLine("\t</Configurations>");
                ss.WriteLine("</Combine>");
            }

            m_Kernel.CWDStack.Pop();
        }
        private void WriteProject(SolutionNode solution, ProjectNode project)
        {
            string csComp = "Csc";
            string netRuntime = "MsNet";
            if(project.Runtime == Runtime.Mono)
            {
                csComp = "Mcs";
                netRuntime = "Mono";
            }

            string projFile = Helper.MakeFilePath(project.FullPath, project.Name, "prjx");
            StreamWriter ss = new StreamWriter(projFile);

            m_Kernel.CWDStack.Push();
            Helper.SetCurrentDir(Path.GetDirectoryName(projFile));

            using(ss)
            {
                ss.WriteLine(
                    "<Project name=\"{0}\" description=\"\" standardNamespace=\"{1}\" newfilesearch=\"None\" enableviewstate=\"True\" version=\"1.1\" projecttype=\"C#\">",
                    project.Name,
                    project.RootNamespace
                    );

                ss.WriteLine("\t<Contents>");
                foreach(string file in project.Files)
                {
                    string buildAction = "Compile";
                    switch(project.Files.GetBuildAction(file))
                    {
                        case BuildAction.None:
                            buildAction = "Nothing";
                            break;

                        case BuildAction.Content:
                            buildAction = "Exclude";
                            break;

                        case BuildAction.EmbeddedResource:
                            buildAction = "EmbedAsResource";
                            break;

                        default:
                            buildAction = "Compile";
                            break;
                    }

                    // Sort of a hack, we try and resolve the path and make it relative, if we can.
                    string filePath = PrependPath(file);
                    ss.WriteLine("\t\t<File name=\"{0}\" subtype=\"Code\" buildaction=\"{1}\" dependson=\"\" data=\"\" />", filePath, buildAction);
                }
                ss.WriteLine("\t</Contents>");

                ss.WriteLine("\t<References>");
                foreach(ReferenceNode refr in project.References)
                    ss.WriteLine("\t\t{0}", BuildReference(solution, refr));
                ss.WriteLine("\t</References>");

                int count = 0;
                foreach(ConfigurationNode conf in solution.Configurations)
                {
                    if(count == 0)
                        ss.WriteLine("\t<Configurations active=\"{0}\">", conf.Name);

                    ss.WriteLine("\t\t<Configuration name=\"{0}\">", conf.Name);
                    ss.WriteLine("\t\t\t<CodeGeneration");
                    ss.WriteLine("\t\t\t\truntime=\"{0}\"", netRuntime);
                    ss.WriteLine("\t\t\t\tcompiler=\"{0}\"", csComp);
                    ss.WriteLine("\t\t\t\twarninglevel=\"{0}\"", conf.Options["WarningLevel"]);
                    ss.WriteLine("\t\t\t\tincludedebuginformation=\"{0}\"", conf.Options["DebugInformation"]);
                    ss.WriteLine("\t\t\t\toptimize=\"{0}\"", conf.Options["OptimizeCode"]);
                    ss.WriteLine("\t\t\t\tunsafecodeallowed=\"{0}\"", conf.Options["AllowUnsafe"]);
                    ss.WriteLine("\t\t\t\tgenerateoverflowchecks=\"{0}\"", conf.Options["CheckUnderflowOverflow"]);
                    ss.WriteLine("\t\t\t\tmainclass=\"{0}\"", project.StartupObject);
                    ss.WriteLine("\t\t\t\ttarget=\"{0}\"", project.Type);
                    ss.WriteLine("\t\t\t\tdefinesymbols=\"{0}\"", conf.Options["CompilerDefines"]);
                    ss.WriteLine("\t\t\t\tgeneratexmldocumentation=\"{0}\"", (((string)conf.Options["XmlDocFile"]).Length > 0));
                    ss.WriteLine("\t\t\t/>");

                    ss.WriteLine("\t\t\t<Output");
                    ss.WriteLine("\t\t\t\tdirectory=\".\\{0}\"", conf.Options["OutputPath"]);
                    ss.WriteLine("\t\t\t\tassembly=\"{0}\"", project.AssemblyName);
                    ss.WriteLine("\t\t\t\texecuteScript=\"\"");
                    ss.WriteLine("\t\t\t\texecuteBeforeBuild=\"\"");
                    ss.WriteLine("\t\t\t\texecuteAfterBuild=\"\"");
                    ss.WriteLine("\t\t\t/>");
                    ss.WriteLine("\t\t</Configuration>");

                    count++;
                }
                ss.WriteLine("\t</Configurations>");
                ss.WriteLine("</Project>");
            }

            m_Kernel.CWDStack.Pop();
        }
        private void CleanSolution(SolutionNode solution)
        {
            m_Kernel.Log.Write("Cleaning SharpDevelop combine and project files for", solution.Name);

            string slnFile = Helper.MakeFilePath(solution.FullPath, solution.Name, "cmbx");
            Helper.DeleteIfExists(slnFile);

            foreach(ProjectNode project in solution.Projects)
                CleanProject(project);

            m_Kernel.Log.Write("");
        }
        private string BuildReference(SolutionNode solution, ReferenceNode refr)
        {
            string ret = "\t\t<Reference type=\"";
            if(solution.ProjectsTable.ContainsKey(refr.Name))
            {
                ret += "Project\" refto=\"" + refr.Name;
                ret += "\" localcopy=\"" + refr.LocalCopy.ToString() + "\" />";
            }
            else
            {
                ProjectNode project = (ProjectNode)refr.Parent;
                string fileRef = FindFileReference(refr.Name, project);

                if(refr.Path != null || fileRef != null)
                {
                    ret += "Assembly\" refto=\"";

                    string finalPath = (refr.Path != null) ? Helper.MakeFilePath(refr.Path, refr.Name, "dll") : fileRef;

                    ret += finalPath;
                    ret += "\" localcopy=\"" + refr.LocalCopy.ToString() + "\" />";
                    return ret;
                }

                ret += "Gac\" refto=\"";
                ret += refr.Name;
                ret += "\" localcopy=\"" + refr.LocalCopy.ToString() + "\" />";
            }

            return ret;
        }
        protected virtual void WriteSolution(SolutionNode solution)
        {
            m_Kernel.Log.Write("Creating Visual Studio {0} solution and project files", m_VersionName);

            foreach(ProjectNode project in solution.Projects)
            {
                m_Kernel.Log.Write("...Creating project: {0}", project.Name);
                WriteProject(solution, project);
            }

            m_Kernel.Log.Write("");
            string solutionFile = Helper.MakeFilePath(solution.FullPath, solution.Name, "sln");
            StreamWriter ss = new StreamWriter(solutionFile);

            m_Kernel.CWDStack.Push();
            Helper.SetCurrentDir(Path.GetDirectoryName(solutionFile));

            using(ss)
            {
                ss.WriteLine("Microsoft Visual Studio Solution File, Format Version {0}", m_SolutionVersion);
                foreach(ProjectNode project in solution.Projects)
                {
                    if(!m_Tools.ContainsKey(project.Language))
                        throw new Exception("Unknown .NET language: " + project.Language);

                    ToolInfo toolInfo = (ToolInfo)m_Tools[project.Language];

                    string path = Helper.MakePathRelativeTo(solution.FullPath, project.FullPath);
                    ss.WriteLine("Project(\"{0}\") = \"{1}\", \"{2}\", \"{{{3}}}\"",
                        toolInfo.Guid, project.Name, Helper.MakeFilePath(path, project.Name,
                        toolInfo.FileExtension), project.Guid.ToString().ToUpper());

                    ss.WriteLine("\tProjectSection(ProjectDependencies) = postProject");
                    ss.WriteLine("\tEndProjectSection");

                    ss.WriteLine("EndProject");
                }

                ss.WriteLine("Global");

                ss.WriteLine("\tGlobalSection(SolutionConfiguration) = preSolution");
                foreach(ConfigurationNode conf in solution.Configurations)
                    ss.WriteLine("\t\t{0} = {0}", conf.Name);
                ss.WriteLine("\tEndGlobalSection");

                ss.WriteLine("\tGlobalSection(ProjectDependencies) = postSolution");
                foreach(ProjectNode project in solution.Projects)
                {
                    for(int i = 0; i < project.References.Count; i++)
                    {
                        ReferenceNode refr = (ReferenceNode)project.References[i];
                        if(solution.ProjectsTable.ContainsKey(refr.Name))
                        {
                            ProjectNode refProject = (ProjectNode)solution.ProjectsTable[refr.Name];
                            ss.WriteLine("\t\t({{{0}}}).{1} = ({{{2}}})",
                                project.Guid.ToString().ToUpper()
                                , i,
                                refProject.Guid.ToString().ToUpper()
                                );
                        }
                    }
                }
                ss.WriteLine("\tEndGlobalSection");

                ss.WriteLine("\tGlobalSection(ProjectConfiguration) = postSolution");
                foreach(ProjectNode project in solution.Projects)
                {
                    foreach(ConfigurationNode conf in solution.Configurations)
                    {
                        ss.WriteLine("\t\t{{{0}}}.{1}.ActiveCfg = {1}|.NET",
                            project.Guid.ToString().ToUpper(),
                            conf.Name);

                        ss.WriteLine("\t\t{{{0}}}.{1}.Build.0 = {1}|.NET",
                            project.Guid.ToString().ToUpper(),
                            conf.Name);
                    }
                }
                ss.WriteLine("\tEndGlobalSection");

                if(solution.Files != null)
                {
                    ss.WriteLine("\tGlobalSection(SolutionItems) = postSolution");
                    foreach(string file in solution.Files)
                        ss.WriteLine("\t\t{0} = {0}", file);
                    ss.WriteLine("\tEndGlobalSection");
                }

                ss.WriteLine("EndGlobal");
            }

            m_Kernel.CWDStack.Pop();
        }
        protected virtual void WriteProject(SolutionNode solution, ProjectNode project)
        {
            if(!m_Tools.ContainsKey(project.Language))
                throw new Exception("Unknown .NET language: " + project.Language);

            ToolInfo toolInfo = (ToolInfo)m_Tools[project.Language];
            string projectFile = Helper.MakeFilePath(project.FullPath, project.Name, toolInfo.FileExtension);
            StreamWriter ps = new StreamWriter(projectFile);

            m_Kernel.CWDStack.Push();
            Helper.SetCurrentDir(Path.GetDirectoryName(projectFile));

            using(ps)
            {
                ps.WriteLine("<VisualStudioProject>");
                ps.WriteLine("\t<{0}", toolInfo.XMLTag);
                ps.WriteLine("\t\tProjectType = \"Local\"");
                ps.WriteLine("\t\tProductVersion = \"{0}\"", m_ProductVersion);
                ps.WriteLine("\t\tSchemaVersion = \"{0}\"", m_SchemaVersion);
                ps.WriteLine("\t\tProjectGuid = \"{{{0}}}\"", project.Guid.ToString().ToUpper());
                ps.WriteLine("\t>");

                ps.WriteLine("\t\t<Build>");

                ps.WriteLine("\t\t\t<Settings");
                ps.WriteLine("\t\t\t\tApplicationIcon = \"{0}\"",project.AppIcon);
                ps.WriteLine("\t\t\t\tAssemblyKeyContainerName = \"\"");
                ps.WriteLine("\t\t\t\tAssemblyName = \"{0}\"", project.AssemblyName);
                ps.WriteLine("\t\t\t\tAssemblyOriginatorKeyFile = \"\"");
                ps.WriteLine("\t\t\t\tDefaultClientScript = \"JScript\"");
                ps.WriteLine("\t\t\t\tDefaultHTMLPageLayout = \"Grid\"");
                ps.WriteLine("\t\t\t\tDefaultTargetSchema = \"IE50\"");
                ps.WriteLine("\t\t\t\tDelaySign = \"false\"");

                if(m_Version == VSVersion.VS70)
                    ps.WriteLine("\t\t\t\tNoStandardLibraries = \"false\"");

                ps.WriteLine("\t\t\t\tOutputType = \"{0}\"", project.Type.ToString());
                ps.WriteLine("\t\t\t\tRootNamespace = \"{0}\"", project.RootNamespace);
                ps.WriteLine("\t\t\t\tStartupObject = \"{0}\"", project.StartupObject);
                ps.WriteLine("\t\t\t>");

                foreach(ConfigurationNode conf in project.Configurations)
                {
                    ps.WriteLine("\t\t\t\t<Config");
                    ps.WriteLine("\t\t\t\t\tName = \"{0}\"", conf.Name);
                    ps.WriteLine("\t\t\t\t\tAllowUnsafeBlocks = \"{0}\"", conf.Options["AllowUnsafe"]);
                    ps.WriteLine("\t\t\t\t\tBaseAddress = \"{0}\"", conf.Options["BaseAddress"]);
                    ps.WriteLine("\t\t\t\t\tCheckForOverflowUnderflow = \"{0}\"", conf.Options["CheckUnderflowOverflow"]);
                    ps.WriteLine("\t\t\t\t\tConfigurationOverrideFile = \"\"");
                    ps.WriteLine("\t\t\t\t\tDefineConstants = \"{0}\"", conf.Options["CompilerDefines"]);
                    ps.WriteLine("\t\t\t\t\tDocumentationFile = \"{0}\"", conf.Options["XmlDocFile"]);
                    ps.WriteLine("\t\t\t\t\tDebugSymbols = \"{0}\"", conf.Options["DebugInformation"]);
                    ps.WriteLine("\t\t\t\t\tFileAlignment = \"{0}\"", conf.Options["FileAlignment"]);
                    ps.WriteLine("\t\t\t\t\tIncrementalBuild = \"{0}\"", conf.Options["IncrementalBuild"]);

                    if(m_Version == VSVersion.VS71)
                    {
                        ps.WriteLine("\t\t\t\t\tNoStdLib = \"{0}\"", conf.Options["NoStdLib"]);
                        ps.WriteLine("\t\t\t\t\tNoWarn = \"{0}\"", conf.Options["SupressWarnings"]);
                    }

                    ps.WriteLine("\t\t\t\t\tOptimize = \"{0}\"", conf.Options["OptimizeCode"]);
                    ps.WriteLine("\t\t\t\t\tOutputPath = \"{0}\"",
                        Helper.EndPath(Helper.NormalizePath(conf.Options["OutputPath"].ToString())));
                    ps.WriteLine("\t\t\t\t\tRegisterForComInterop = \"{0}\"", conf.Options["RegisterCOMInterop"]);
                    ps.WriteLine("\t\t\t\t\tRemoveIntegerChecks = \"{0}\"", conf.Options["RemoveIntegerChecks"]);
                    ps.WriteLine("\t\t\t\t\tTreatWarningsAsErrors = \"{0}\"", conf.Options["WarningsAsErrors"]);
                    ps.WriteLine("\t\t\t\t\tWarningLevel = \"{0}\"", conf.Options["WarningLevel"]);
                    ps.WriteLine("\t\t\t\t/>");
                }

                ps.WriteLine("\t\t\t</Settings>");

                ps.WriteLine("\t\t\t<References>");
                foreach(ReferenceNode refr in project.References)
                {
                    ps.WriteLine("\t\t\t\t<Reference");
                    ps.WriteLine("\t\t\t\t\tName = \"{0}\"", refr.Name);

                    if(solution.ProjectsTable.ContainsKey(refr.Name))
                    {
                        ProjectNode refProject = (ProjectNode)solution.ProjectsTable[refr.Name];
                        ps.WriteLine("\t\t\t\t\tProject = \"{{{0}}}\"", refProject.Guid.ToString().ToUpper());
                        ps.WriteLine("\t\t\t\t\tPackage = \"{0}\"", toolInfo.Guid.ToString().ToUpper());
                    }
                    else
                    {
                        if(refr.Path != null)
                            ps.WriteLine("\t\t\t\t\tHintPath = \"{0}\"", Helper.MakeFilePath(refr.Path, refr.Name, "dll"));

                    }

                    if(refr.LocalCopySpecified)
                        ps.WriteLine("\t\t\t\t\tPrivate = \"{0}\"",refr.LocalCopy);

                    ps.WriteLine("\t\t\t\t/>");
                }
                ps.WriteLine("\t\t\t</References>");

                ps.WriteLine("\t\t</Build>");
                ps.WriteLine("\t\t<Files>");

                ps.WriteLine("\t\t\t<Include>");
                foreach(string file in project.Files)
                {
                    ps.WriteLine("\t\t\t\t<File");
                    ps.WriteLine("\t\t\t\t\tRelPath = \"{0}\"", file.Replace(".\\", ""));
                    ps.WriteLine("\t\t\t\t\tSubType = \"Code\"");
                    ps.WriteLine("\t\t\t\t\tBuildAction = \"{0}\"", project.Files.GetBuildAction(file));
                    ps.WriteLine("\t\t\t\t/>");
                }
                ps.WriteLine("\t\t\t</Include>");

                ps.WriteLine("\t\t</Files>");
                ps.WriteLine("\t</{0}>", toolInfo.XMLTag);
                ps.WriteLine("</VisualStudioProject>");
            }

            ps = new StreamWriter(projectFile + ".user");
            using(ps)
            {
                ps.WriteLine("<VisualStudioProject>");
                ps.WriteLine("\t<{0}>", toolInfo.XMLTag);
                ps.WriteLine("\t\t<Build>");

                ps.WriteLine("\t\t\t<Settings ReferencePath=\"{0}\">", MakeRefPath(project));
                foreach(ConfigurationNode conf in project.Configurations)
                {
                    ps.WriteLine("\t\t\t\t<Config");
                    ps.WriteLine("\t\t\t\t\tName = \"{0}\"", conf.Name);
                    ps.WriteLine("\t\t\t\t/>");
                }
                ps.WriteLine("\t\t\t</Settings>");

                ps.WriteLine("\t\t</Build>");
                ps.WriteLine("\t</{0}>", toolInfo.XMLTag);
                ps.WriteLine("</VisualStudioProject>");
            }

            m_Kernel.CWDStack.Pop();
        }
        protected void CleanSolution(SolutionNode solution)
        {
            m_Kernel.Log.Write("Cleaning Visual Studio {0} solution and project files", m_VersionName, solution.Name);

            string slnFile = Helper.MakeFilePath(solution.FullPath, solution.Name, "sln");
            string suoFile = Helper.MakeFilePath(solution.FullPath, solution.Name, "suo");

            Helper.DeleteIfExists(slnFile);
            Helper.DeleteIfExists(suoFile);

            foreach(ProjectNode project in solution.Projects)
                CleanProject(project);

            m_Kernel.Log.Write("");
        }