解决的问题
现有的工具都存在一些问题:比如smart Sql,无法一次完成多个库文档生成到一个文件中,且使用过程中存在表结构过多时生成失败问题,像视图、存储过程部分生成也存在一定局限性(无DDL信息,一般没有存储过程);故想研究一下自行代码实现。
基本思路
- 基于ado.net读取元数据,需要啥读啥,目前只包含了表、视图、存储过程,数据库基于oracle;
- 生成对应的html、hhp、hhc文件;
- 调起HTML Help Workshop工具生成chm格式文件。
具体源码
- public class OracleMetadataService : IDisposable
- {
- private readonly OracleConnection _connection;
- public OracleMetadataService(string connectionString)
- {
- _connection = new OracleConnection(connectionString);
- _connection.Open();
- }
- public List<TableInfo> GetTables()
- {
- var tables = new List<TableInfo>();
- // 优化:批量获取表基本信息和列信息
- using (var cmd = new OracleCommand(
- @"SELECT table_name, comments
- FROM user_tab_comments
- WHERE table_type = 'TABLE'
- ORDER BY table_name", _connection))
- {
- using (var reader = cmd.ExecuteReader())
- {
- while (reader.Read())
- {
- var table = new TableInfo
- {
- TableName = reader["table_name"].ToString(),
- Comments = reader["comments"].ToString()
- };
- table.Columns = GetColumns(table.TableName);
- SetPrimaryKeys(table);
- SetForeignKeys(table);
- tables.Add(table);
- }
- }
- }
- Console.WriteLine("表信息获取完成");
- return tables;
- }
- private List<ColumnInfo> GetColumns(string tableName)
- {
- var columns = new List<ColumnInfo>();
- using (var cmd = new OracleCommand(
- @"SELECT
- tc.column_name, data_type, data_length, data_precision, data_scale,
- nullable, data_default, comments
- FROM user_tab_columns tc
- LEFT JOIN user_col_comments cc ON tc.table_name = cc.table_name AND tc.column_name = cc.column_name
- WHERE tc.table_name = :tableName
- ORDER BY column_id", _connection))
- {
- cmd.Parameters.Add("tableName", OracleDbType.Varchar2).Value = tableName;
- using (var reader = cmd.ExecuteReader())
- {
- while (reader.Read())
- {
- columns.Add(new ColumnInfo
- {
- ColumnName = reader["column_name"].ToString(),
- DataType = reader["data_type"].ToString(),
- DataLength = reader["data_length"] as int?,
- DataPrecision = reader["data_precision"] as int?,
- DataScale = reader["data_scale"] as int?,
- Nullable = reader["nullable"].ToString(),
- DefaultValue = reader["data_default"]?.ToString(),
- Comments = reader["comments"]?.ToString()
- });
- }
- }
- }
- return columns;
- }
- private void SetPrimaryKeys(TableInfo table)
- {
- using (var cmd = new OracleCommand(
- @"SELECT cols.column_name
- FROM user_constraints cons, user_cons_columns cols
- WHERE cons.constraint_type = 'P'
- AND cons.constraint_name = cols.constraint_name
- AND cons.table_name = :tableName", _connection))
- {
- cmd.Parameters.Add("tableName", OracleDbType.Varchar2).Value = table.TableName;
- using (var reader = cmd.ExecuteReader())
- {
- while (reader.Read())
- {
- var columnName = reader["column_name"].ToString();
- var column = table.Columns.Find(c => c.ColumnName == columnName);
- if (column != null)
- {
- column.IsPrimaryKey = true;
- }
- }
- }
- }
- }
- private void SetForeignKeys(TableInfo table)
- {
- using (var cmd = new OracleCommand(
- @"SELECT cols.column_name
- FROM user_constraints cons, user_cons_columns cols
- WHERE cons.constraint_type = 'R'
- AND cons.constraint_name = cols.constraint_name
- AND cons.table_name = :tableName", _connection))
- {
- cmd.Parameters.Add("tableName", OracleDbType.Varchar2).Value = table.TableName;
- using (var reader = cmd.ExecuteReader())
- {
- while (reader.Read())
- {
- var columnName = reader["column_name"].ToString();
- var column = table.Columns.Find(c => c.ColumnName == columnName);
- if (column != null)
- {
- column.IsForeignKey = true;
- }
- }
- }
- }
- }
- public List<ViewInfo> GetViews(string owner)
- {
- var views = new List<ViewInfo>();
- // 获取视图基本信息
- using (var cmd = new OracleCommand(
- @"SELECT view_name, text, comments
- FROM user_views v
- LEFT JOIN user_tab_comments tc ON v.view_name = tc.table_name
- ORDER BY view_name", _connection))
- {
- using (var reader = cmd.ExecuteReader())
- {
- while (reader.Read())
- {
- views.Add(new ViewInfo
- {
- ViewName = reader["view_name"].ToString(),
- //Definition = reader.GetOracleClob(0)?.Value,
- Comments = reader["comments"]?.ToString()
- });
- }
- }
- }
- Console.WriteLine($"视图基本信息获取完成");
- // 获取每张视图的列信息
- foreach (var view in views)
- {
- view.Definition = GetViewDDL(_connection, view.ViewName, owner);
- view.Columns = GetColumns(view.ViewName);
- Console.WriteLine($"视图[{view.ViewName}]列信息获取完成");
- }
- return views;
- }
- static string GetViewDDL(OracleConnection connection, string viewName, string schema)
- {
- string sql = @"
- SELECT DBMS_METADATA.GET_DDL('VIEW', :viewName, :schema)
- FROM DUAL";
- using (OracleCommand command = new OracleCommand(sql, connection))
- {
- command.Parameters.Add(":viewName", viewName);
- command.Parameters.Add(":schema", schema);
- command.InitialLOBFetchSize = 1000000;
- object result = command.ExecuteScalar();
- return result != null ? result.ToString() : string.Empty;
- }
- }
- public List<ProcedureInfo> GetProcedures()
- {
- var procedures = new List<ProcedureInfo>();
- // 获取存储过程和函数基本信息
- using (var cmd = new OracleCommand(
- @"SELECT object_name, object_type, status, created, last_ddl_time
- FROM user_objects
- WHERE object_type IN ('PROCEDURE', 'FUNCTION')
- ORDER BY object_type, object_name", _connection))
- {
- using (var reader = cmd.ExecuteReader())
- {
- while (reader.Read())
- {
- procedures.Add(new ProcedureInfo
- {
- ProcedureName = reader["object_name"].ToString(),
- ProcedureType = reader["object_type"].ToString()
- });
- }
- }
- }
- Console.WriteLine($"存储过程基本信息获取完成");
- // 获取每个对象的详细信息和参数
- foreach (var proc in procedures)
- {
- // 获取源代码
- using (var cmd = new OracleCommand(
- @"SELECT text
- FROM user_source
- WHERE name = :procName
- AND type = :procType
- ORDER BY line", _connection))
- {
- cmd.Parameters.Add("procName", OracleDbType.Varchar2).Value = proc.ProcedureName;
- cmd.Parameters.Add("procType", OracleDbType.Varchar2).Value = proc.ProcedureType;
- var source = new System.Text.StringBuilder();
- using (var reader = cmd.ExecuteReader())
- {
- while (reader.Read())
- {
- source.AppendLine(reader["text"].ToString());
- }
- }
- proc.SourceCode = source.ToString();
- }
- // 获取参数信息
- proc.Parameters = GetProcedureParameters(proc.ProcedureName);
- // 如果是函数,获取返回类型
- if (proc.ProcedureType == "FUNCTION")
- {
- using (var cmd = new OracleCommand(
- @"SELECT data_type
- FROM user_arguments
- WHERE object_name = :procName
- AND argument_name IS NULL", _connection))
- {
- cmd.Parameters.Add("procName", OracleDbType.Varchar2).Value = proc.ProcedureName;
- proc.ReturnType = cmd.ExecuteScalar()?.ToString();
- }
- }
- //// 获取注释
- //using (var cmd = new OracleCommand(
- // @"SELECT comments
- // FROM user_procedures
- // WHERE object_name = :procName
- // AND object_type = :procType", _connection))
- //{
- // cmd.Parameters.Add("procName", OracleDbType.Varchar2).Value = proc.ProcedureName;
- // cmd.Parameters.Add("procType", OracleDbType.Varchar2).Value = proc.ProcedureType;
- // proc.Comments = cmd.ExecuteScalar()?.ToString();
- //}
- Console.WriteLine($"存储过程[{proc.ProcedureName}]详细信息获取完成");
- }
- return procedures;
- }
- private List<ParameterInfo> GetProcedureParameters(string procedureName)
- {
- var parameters = new List<ParameterInfo>();
- using (var cmd = new OracleCommand(
- @"SELECT argument_name, data_type, in_out, position
- FROM user_arguments
- WHERE object_name = :procName
- AND argument_name IS NOT NULL
- ORDER BY position", _connection))
- {
- cmd.Parameters.Add("procName", OracleDbType.Varchar2).Value = procedureName;
- using (var reader = cmd.ExecuteReader())
- {
- while (reader.Read())
- {
- parameters.Add(new ParameterInfo
- {
- ParameterName = reader["argument_name"].ToString(),
- DataType = reader["data_type"].ToString(),
- InOut = reader["in_out"].ToString(),
- Position = reader["position"] as int?
- });
- }
- }
- }
- return parameters;
- }
- public void Dispose()
- {
- _connection?.Close();
- _connection?.Dispose();
- }
- }
复制代码- public class HtmlGeneratorService
- {
- private readonly string _outputDirectory;
- public HtmlGeneratorService(string outputDirectory)
- {
- _outputDirectory = outputDirectory;
- Directory.CreateDirectory(_outputDirectory);
- }
- public void GenerateHtmlFiles(Dictionary<string, Tuple<List<TableInfo>, List<ViewInfo>, List<ProcedureInfo>>> dic)
- {
- GenerateIndexFile(dic);
- foreach (var item in dic)
- {
- GenerateTablesFiles(item.Key, item.Value.Item1);
- GenerateViewsFiles(item.Key, item.Value.Item2);
- GenerateProceduresFiles(item.Key, item.Value.Item3);
- }
- GenerateStyleSheet();
- }
- private void GenerateIndexFile(Dictionary<string, Tuple<List<TableInfo>, List<ViewInfo>, List<ProcedureInfo>>> dic)
- {
- var sb = new StringBuilder();
- sb.AppendLine("<!DOCTYPE html>");
- sb.AppendLine("<html>");
- sb.AppendLine("<head>");
- sb.AppendLine($"<title>数据库说明文档</title>");
- sb.AppendLine("<link rel="stylesheet" href="styles.css">");
- sb.AppendLine("</head>");
- sb.AppendLine("<body>");
- sb.AppendLine($"<h1>数据库说明文档</h1>");
- foreach (var item in dic)
- {
- sb.AppendLine($"<h2>{item.Key}</h2>");
- // 表目录
- sb.AppendLine("<h3>Tables</h3>");
- sb.AppendLine("<ul>");
- foreach (var table in item.Value.Item1)
- {
- sb.AppendLine($"<li>{table.TableName} - {table.Comments}</li>");
- }
- sb.AppendLine("</ul>");
- // 视图目录
- sb.AppendLine("<h3>Views</h3>");
- sb.AppendLine("<ul>");
- foreach (var view in item.Value.Item2)
- {
- sb.AppendLine($"<li>{view.ViewName} - {view.Comments}</li>");
- }
- sb.AppendLine("</ul>");
- // 存储过程和函数目录
- sb.AppendLine("<h3>Procedures and Functions</h3>");
- sb.AppendLine("<ul>");
- foreach (var proc in item.Value.Item3)
- {
- sb.AppendLine($"<li>{proc.ProcedureName} ({proc.ProcedureType})</li>");
- }
- sb.AppendLine("</ul>");
- }
- sb.AppendLine("</body>");
- sb.AppendLine("</html>");
- File.WriteAllText(Path.Combine(_outputDirectory, "index.html"), sb.ToString(), Encoding.UTF8);
- }
- private void GenerateTablesFiles(string owner, List<TableInfo> tables)
- {
- var tablesDir = Path.Combine(_outputDirectory, owner, "tables");
- Directory.CreateDirectory(tablesDir);
- foreach (var table in tables)
- {
- var sb = new StringBuilder();
- sb.AppendLine("<!DOCTYPE html>");
- sb.AppendLine("<html>");
- sb.AppendLine("<head>");
- sb.AppendLine($"<title>Table: {table.TableName}</title>");
- sb.AppendLine("<link rel="stylesheet" href="../../styles.css">");
- sb.AppendLine("</head>");
- sb.AppendLine("<body>");
- sb.AppendLine($"<h1>Table: {table.TableName}</h1>");
- sb.AppendLine($"<p>{table.Comments}</p>");
- sb.AppendLine("<h2>Columns</h2>");
- sb.AppendLine("<table class="gridtable">");
- sb.AppendLine("<tr>");
- sb.AppendLine("<th>Name</th>");
- sb.AppendLine("<th>Type</th>");
- sb.AppendLine("<th>Length</th>");
- sb.AppendLine("<th>Precision</th>");
- sb.AppendLine("<th>Scale</th>");
- sb.AppendLine("<th>Nullable</th>");
- sb.AppendLine("<th>Default</th>");
- sb.AppendLine("<th>PK</th>");
- sb.AppendLine("<th>FK</th>");
- sb.AppendLine("<th>Description</th>");
- sb.AppendLine("</tr>");
- foreach (var column in table.Columns)
- {
- sb.AppendLine("<tr>");
- sb.AppendLine($"<td>{column.ColumnName}</td>");
- sb.AppendLine($"<td>{column.DataType}</td>");
- sb.AppendLine($"<td>{column.DataLength}</td>");
- sb.AppendLine($"<td>{column.DataPrecision}</td>");
- sb.AppendLine($"<td>{column.DataScale}</td>");
- sb.AppendLine($"<td>{column.Nullable}</td>");
- sb.AppendLine($"<td>{column.DefaultValue}</td>");
- sb.AppendLine($"<td>{(column.IsPrimaryKey ? "✓" : "")}</td>");
- sb.AppendLine($"<td>{(column.IsForeignKey ? "✓" : "")}</td>");
- sb.AppendLine($"<td>{column.Comments}</td>");
- sb.AppendLine("</tr>");
- }
- sb.AppendLine("</table>");
- sb.AppendLine("<p>Back to Index</p>");
- sb.AppendLine("</body>");
- sb.AppendLine("</html>");
- File.WriteAllText(Path.Combine(tablesDir, $"{table.TableName}.html"), sb.ToString(), Encoding.UTF8);
- }
- }
- private void GenerateViewsFiles(string owner, List<ViewInfo> views)
- {
- var viewsDir = Path.Combine(_outputDirectory, owner, "views");
- Directory.CreateDirectory(viewsDir);
- foreach (var view in views)
- {
- var sb = new StringBuilder();
- sb.AppendLine("<!DOCTYPE html>");
- sb.AppendLine("<html>");
- sb.AppendLine("<head>");
- sb.AppendLine($"<title>View: {view.ViewName}</title>");
- sb.AppendLine("<link rel="stylesheet" href="../../styles.css">");
- sb.AppendLine("</head>");
- sb.AppendLine("<body>");
- sb.AppendLine($"<h1>View: {view.ViewName}</h1>");
- sb.AppendLine($"<p>{view.Comments}</p>");
- sb.AppendLine("<h2>Columns</h2>");
- sb.AppendLine("<table class="gridtable">");
- sb.AppendLine("<tr>");
- sb.AppendLine("<th>Name</th>");
- sb.AppendLine("<th>Type</th>");
- sb.AppendLine("<th>Length</th>");
- sb.AppendLine("<th>Precision</th>");
- sb.AppendLine("<th>Scale</th>");
- sb.AppendLine("<th>Nullable</th>");
- sb.AppendLine("<th>Description</th>");
- sb.AppendLine("</tr>");
- foreach (var column in view.Columns)
- {
- sb.AppendLine("<tr>");
- sb.AppendLine($"<td>{column.ColumnName}</td>");
- sb.AppendLine($"<td>{column.DataType}</td>");
- sb.AppendLine($"<td>{column.DataLength}</td>");
- sb.AppendLine($"<td>{column.DataPrecision}</td>");
- sb.AppendLine($"<td>{column.DataScale}</td>");
- sb.AppendLine($"<td>{column.Nullable}</td>");
- sb.AppendLine($"<td>{column.Comments}</td>");
- sb.AppendLine("</tr>");
- }
- sb.AppendLine("</table>");
- sb.AppendLine("<h2>Definition</h2>");
- sb.AppendLine("<pre>");
- sb.AppendLine(view.Definition);
- sb.AppendLine("</pre>");
- sb.AppendLine("<p>Back to Index</p>");
- sb.AppendLine("</body>");
- sb.AppendLine("</html>");
- File.WriteAllText(Path.Combine(viewsDir, $"{view.ViewName}.html"), sb.ToString(), Encoding.UTF8);
- }
- }
- private void GenerateProceduresFiles(string owner, List<ProcedureInfo> procedures)
- {
- var procsDir = Path.Combine(_outputDirectory, owner, "procedures");
- Directory.CreateDirectory(procsDir);
- foreach (var proc in procedures)
- {
- var sb = new StringBuilder();
- sb.AppendLine("<!DOCTYPE html>");
- sb.AppendLine("<html>");
- sb.AppendLine("<head>");
- sb.AppendLine($"<title>{proc.ProcedureType}: {proc.ProcedureName}</title>");
- sb.AppendLine("<link rel="stylesheet" href="../../styles.css">");
- sb.AppendLine("</head>");
- sb.AppendLine("<body>");
- sb.AppendLine($"<h1>{proc.ProcedureType}: {proc.ProcedureName}</h1>");
- sb.AppendLine($"<p>{proc.Comments}</p>");
- if (proc.ProcedureType == "FUNCTION" && !string.IsNullOrEmpty(proc.ReturnType))
- {
- sb.AppendLine($"<p>Return Type: {proc.ReturnType}</p>");
- }
- if (proc.Parameters.Count > 0)
- {
- sb.AppendLine("<h2>Parameters</h2>");
- sb.AppendLine("<table class="gridtable">");
- sb.AppendLine("<tr>");
- sb.AppendLine("<th>Name</th>");
- sb.AppendLine("<th>Type</th>");
- sb.AppendLine("<th>In/Out</th>");
- sb.AppendLine("<th>Position</th>");
- sb.AppendLine("</tr>");
- foreach (var param in proc.Parameters)
- {
- sb.AppendLine("<tr>");
- sb.AppendLine($"<td>{param.ParameterName}</td>");
- sb.AppendLine($"<td>{param.DataType}</td>");
- sb.AppendLine($"<td>{param.InOut}</td>");
- sb.AppendLine($"<td>{param.Position}</td>");
- sb.AppendLine("</tr>");
- }
- sb.AppendLine("</table>");
- }
- sb.AppendLine("<h2>Source Code</h2>");
- sb.AppendLine("<pre>");
- sb.AppendLine(proc.SourceCode);
- sb.AppendLine("</pre>");
- sb.AppendLine("<p>Back to Index</p>");
- sb.AppendLine("</body>");
- sb.AppendLine("</html>");
- File.WriteAllText(Path.Combine(procsDir, $"{proc.ProcedureName}.html"), sb.ToString(), Encoding.UTF8);
- }
- }
- private void GenerateStyleSheet()
- {
- var css = @"
- body {
- font-family: Consolas, monospace;
- line -height: 1.6;
- margin: 20px;
- color: #808080;
- }
- h1, h2, h3 {
- color: #0066cc;
- }
- table.gridtable {
- width: 100%;
- border-collapse: collapse;
- margin: 15px 0;
- }
- table.gridtable th {
- background-color: #006400;
- color: white;
- text-align: center;
- padding: 3px;
- }
- table.gridtable td {
- border: #ddd;
- padding: 3px;
- }
- table.gridtable tr:nth-child(even) {
- background-color: #f2f2f2;
- }
- pre {
- background-color: #f5f5f5;
- padding: 10px;
- border-radius: 5px;
- overflow-x: auto;
- }
- a {
- color: #A52A2A;
- text-decoration: none;
- }
- a:hover {
- text-decoration: underline;
- }
- ";
- File.WriteAllText(Path.Combine(_outputDirectory, "styles.css"), css);
- }
- }
复制代码- public class ChmCompiler
- {
- private readonly string _htmlHelpCompilerPath;
- public ChmCompiler(string htmlHelpCompilerPath)
- {
- _htmlHelpCompilerPath = htmlHelpCompilerPath;
- }
- public bool Compile(string projectFilePath, string outputChmPath)
- {
- if (!File.Exists(_htmlHelpCompilerPath))
- {
- throw new FileNotFoundException("HTML Help Compiler (hhc.exe) not found at the specified path.");
- }
- if (!File.Exists(projectFilePath))
- {
- throw new FileNotFoundException("HHP project file not found.");
- }
- try
- {
- var process = new Process
- {
- StartInfo = new ProcessStartInfo
- {
- FileName = _htmlHelpCompilerPath,
- Arguments = $""{projectFilePath}"",
- UseShellExecute = false,
- CreateNoWindow = true,
- RedirectStandardOutput = true,
- RedirectStandardError = true
- }
- };
- process.Start();
- process.WaitForExit(60 * 1000);
- //if (process.ExitCode != 0)
- //{
- // var error = process.StandardError.ReadToEnd();
- // throw new Exception($"CHM compilation failed with error: {error}");
- //}
- // 检查生成的CHM文件是否存在
- return File.Exists(outputChmPath);
- }
- catch (Exception ex)
- {
- throw new Exception("Error during CHM compilation: " + ex.Message, ex);
- }
- }
- public void CreateHhpFile(string outputDirectory, string projectName)
- {
- var hhpContent = $@"[OPTIONS]
- Compatibility=1.1 or later
- Compiled file={projectName}.chm
- Contents file={projectName}.hhc
- Default topic=index.html
- Display compile progress=No
- Full-text search=Yes
- Language=0x409 English (United States)
- Title={projectName} Database Documentation
- [FILES]
- ";
- // 添加所有HTML文件
- var htmlFiles = Directory.GetFiles(outputDirectory, "*.html", SearchOption.AllDirectories);
- foreach (var file in htmlFiles)
- {
- var relativePath = file.Substring(outputDirectory.Length + 1);
- hhpContent += relativePath + "\n";
- }
- // 添加CSS文件
- hhpContent += "styles.css\n";
- File.WriteAllText(Path.Combine(outputDirectory, $"{projectName}.hhp"), hhpContent);
- // 创建目录文件 (.hhc)
- CreateHhcFile(outputDirectory, projectName);
- }
- private void CreateHhcFile(string outputDirectory, string projectName)
- {
- var hhcContent = new StringBuilder(@"<!DOCTYPE HTML PUBLIC ""-//IETF//DTD HTML//EN"">
- <HTML>
- <HEAD>
- <meta name=""GENERATOR"" content=""Microsoft® HTML Help Workshop 4.1"">
- </HEAD>
- <BODY>
- <OBJECT type=""text/site properties"">
- <param name=""Window Styles"" value=""0x800025"">
- </OBJECT>
- <UL>
- <LI> <OBJECT type=""text/sitemap"">
- <param name=""Name"" value=""Database Documentation"">
- <param name=""Local"" value=""index.html"">
- </OBJECT>
- <UL>");
- // 获取所有Owner
- var owners = GetAllOwners(outputDirectory);
- foreach (var owner in owners)
- {
- hhcContent.AppendLine($@"
- <LI> <OBJECT type=""text/sitemap"">
- <param name=""Name"" value=""{owner}"">
- </OBJECT>
- <UL>");
- // 添加Tables分组
- hhcContent.AppendLine($@"
- <LI> <OBJECT type=""text/sitemap"">
- <param name=""Name"" value=""Tables"">
- </OBJECT>
- <UL>");
- AddFilesToContent(hhcContent, Path.Combine(outputDirectory, owner, "tables"), outputDirectory);
- hhcContent.AppendLine($@"
- </UL>");
- // 添加Views分组
- hhcContent.AppendLine($@"
- <LI> <OBJECT type=""text/sitemap"">
- <param name=""Name"" value=""Views"">
- </OBJECT>
- <UL>");
- AddFilesToContent(hhcContent, Path.Combine(outputDirectory, owner, "views"), outputDirectory);
- hhcContent.AppendLine($@"
- </UL>");
- // 添加Procedures分组
- hhcContent.AppendLine($@"
- <LI> <OBJECT type=""text/sitemap"">
- <param name=""Name"" value=""Procedures and Functions"">
- </OBJECT>
- <UL>");
- AddFilesToContent(hhcContent, Path.Combine(outputDirectory, owner, "procedures"), outputDirectory);
- hhcContent.AppendLine($@"
- </UL>");
- hhcContent.AppendLine($@"
- </UL>");
- }
- hhcContent.AppendLine($@"
- </UL>
- </UL>
- </BODY>
- </HTML>");
- File.WriteAllText(Path.Combine(outputDirectory, $"{projectName}.hhc"), hhcContent.ToString());
- }
- // 获取所有Owner的辅助方法
- private List<string> GetAllOwners(string outputDirectory)
- {
- // 方法1:从目录结构中获取
- return Directory.GetDirectories(outputDirectory)
- .Select(d => new DirectoryInfo(d).Name)
- .ToList();
- // 方法2:从数据库中获取(需要实现)
- // return GetOwnersFromDatabase();
- }
- // 之前定义的辅助方法
- private void AddFilesToContent(StringBuilder content, string directory, string outputDirectory)
- {
- if (!Directory.Exists(directory))
- {
- return;
- }
- foreach (var file in Directory.GetFiles(directory, "*.html"))
- {
- var itemName = Path.GetFileNameWithoutExtension(file);
- var relativePath = file.Substring(outputDirectory.Length + 1);
- content.AppendLine($@"
- <LI> <OBJECT type=""text/sitemap"">
- <param name=""Name"" value=""{itemName}"">
- <param name=""Local"" value=""{relativePath}"">
- </OBJECT>");
- }
- }
- }
复制代码- internal class Program
- {
- // 查找HHC编译器
- private static string FindHhcCompiler()
- {
- // 检查常见位置
- string[] possiblePaths = new[]
- {
- @"C:\Program Files (x86)\HTML Help Workshop\hhc.exe",
- @"C:\Program Files\HTML Help Workshop\hhc.exe"
- };
- foreach (string path in possiblePaths)
- {
- if (File.Exists(path))
- {
- return path;
- }
- }
- // 检查PATH环境变量
- string pathEnv = Environment.GetEnvironmentVariable("PATH");
- if (!string.IsNullOrEmpty(pathEnv))
- {
- string[] paths = pathEnv.Split(Path.PathSeparator);
- foreach (string path in paths)
- {
- string fullPath = Path.Combine(path.Trim(), "hhc.exe");
- if (File.Exists(fullPath))
- {
- return fullPath;
- }
- }
- }
- return null;
- }
- private static void Main(string[] args)
- {
- Console.WriteLine("Oracle Database CHM Documentation Generator");
- Console.WriteLine("==========================================");
- try
- {
- //数据库列表,自行添加
- List<string> schemaList = new List<string>
- {
- };
- // 配置参数
- var baseDir = Path.Combine(Directory.GetCurrentDirectory(), "OracleDocs");
- var hhcPath = FindHhcCompiler();
- var outputDir = Path.Combine(baseDir, "OracleDocs");
- var dic = new Dictionary<string, Tuple<List<TableInfo>, List<ViewInfo>, List<ProcedureInfo>>>();
- foreach (var item in schemaList)
- {
- var projectName = $"TH_{item}";
- var connectionString = $"";//自行添加
- // 创建服务实例
- using (var metadataService = new OracleMetadataService(connectionString))
- {
- Console.WriteLine("Fetching database metadata...");
- // 获取元数据
- var tables = metadataService.GetTables();
- var views = metadataService.GetViews(projectName);
- var procedures = metadataService.GetProcedures();
- dic.Add(projectName, Tuple.Create(tables, views, procedures));
- Console.WriteLine($"Found {tables.Count} tables, {views.Count} views, {procedures.Count} procedures/functions");
- }
- }
- // 生成HTML文档
- var htmlGenerator = new HtmlGeneratorService(outputDir);
- Console.WriteLine("Generating HTML files...");
- htmlGenerator.GenerateHtmlFiles(dic);
- // 编译CHM
- var chmCompiler = new ChmCompiler(hhcPath);
- Console.WriteLine("Creating CHM project files...");
- chmCompiler.CreateHhpFile(outputDir, "OracleDocs");
- Console.WriteLine("Compiling CHM file...");
- var hhpFilePath = Path.Combine(outputDir, $"TH.hhp");
- var chmFilePath = Path.Combine(outputDir, $"TH.chm");
- //var result = Task.Run(async () => await chmCompiler.RunProcessAsync(hhpFilePath)).Result;
- if (chmCompiler.Compile(hhpFilePath, chmFilePath))
- //if (result == 0)
- {
- Console.WriteLine($"Successfully generated CHM file: {chmFilePath}");
- }
- else
- {
- Console.WriteLine("CHM compilation failed.");
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine($"Error: {ex.Message}");
- if (ex.InnerException != null)
- {
- Console.WriteLine($"Inner exception: {ex.InnerException.Message}");
- }
- }
- Console.WriteLine("Press any key to exit...");
- Console.ReadKey();
- }
- }
复制代码 来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |