C# T4模板在项目中的使用

1.什么是t4模版

T4,即4T开头的英文字母组合:Text Template Transformation Toolkit

T4(Text Template Transformation Toolkit)是微软官方在VisualStudio 2008中开始使用的代码生成引擎。在 Visual Studio 中,“T4 文本模板”是由一些文本块和控制逻辑组成的混合模板,它可以生成文本文件。 在 Visual C# 或 Visual Basic 中,控制逻辑编写为程序代码的片段。生成的文件可以是任何类型的文本,例如网页、资源文件或任何语言的程序源代码。现在的VS中只要与代码生成相关的场景基本上都能找T4的身影,比如MVC的视图模板,Entity Framwork的DataContext模板等等。

可以所T4模版课快速帮你生产实体类或者需要重复编写但是格式一致的代码

2.T4模版初试篇

首先看下运行效果:

 我这手里有一个还没有编写实体类的项目,我们拿则个项目来测试下t4模版的强大之处

(1)首先我先新创建一个类库专门存放t4模版

 

(2)新创建一个 DbHelper.ttinclude 模板,主要是数据库操作类

<#+public class config{public static readonly string ConnectionString = "Server=.;Database=XXXX;User ID=sa;Password=你的数据库密码";public static readonly string DbDatabase = "";public static readonly string TableName = "";}
#>
<#+ public class DbHelper{#region GetDbTablespublic static List<string> GetDbTablesNew(string connectionString, string database,string tables = null){ if (!string.IsNullOrEmpty(tables)){tables = string.Format(" and obj.name in ('{0}')", tables.Replace(",", "','"));}string sql = string.Format(@"SELECTobj.name tablenamefrom {0}.sys.objects obj inner join {0}.dbo.sysindexes idx on obj.object_id=idx.id and idx.indid<=1INNER JOIN {0}.sys.schemas schem ON obj.schema_id=schem.schema_idleft join {0}.sys.extended_properties g ON (obj.object_id = g.major_id AND g.minor_id = 0 AND g.name= 'MS_Description')where type='U' {1} order by obj.name", database,tables);DataTable dt = GetDataTable(connectionString, sql);return dt.Rows.Cast<DataRow>().Select(row =>row.Field<string>("tablename")).ToList();}public static List<DbTable> GetDbTables(string connectionString, string database, string tables = null){if (!string.IsNullOrEmpty(tables)){tables = string.Format(" and obj.name in ('{0}')", tables.Replace(",", "','"));}#region SQLstring sql = string.Format(@"SELECTobj.name tablename,schem.name schemname,idx.rows,CAST(CASE WHEN (SELECT COUNT(1) FROM sys.indexes WHERE object_id= obj.OBJECT_ID AND is_primary_key=1) >=1 THEN 1ELSE 0END AS BIT) HasPrimaryKey                                         from {0}.sys.objects obj inner join {0}.dbo.sysindexes idx on obj.object_id=idx.id and idx.indid<=1INNER JOIN {0}.sys.schemas schem ON obj.schema_id=schem.schema_idwhere type='U' {1}order by obj.name", database, tables);#endregionDataTable dt = GetDataTable(connectionString, sql);return dt.Rows.Cast<DataRow>().Select(row => new DbTable{TableName = row.Field<string>("tablename"),SchemaName = row.Field<string>("schemname"),Rows = row.Field<int>("rows"),HasPrimaryKey = row.Field<bool>("HasPrimaryKey")}).ToList();}#endregion#region GetDbColumnspublic static List<DbColumn> GetDbColumns(string connectionString, string database, string tableName, string schema = "dbo"){#region SQLstring sql = string.Format(@"WITH indexCTE AS(SELECT ic.column_id,ic.index_column_id,ic.object_id    FROM {0}.sys.indexes idxINNER JOIN {0}.sys.index_columns ic ON idx.index_id = ic.index_id AND idx.object_id = ic.object_idWHERE  idx.object_id =OBJECT_ID(@tableName) AND idx.is_primary_key=1)selectcolm.column_id ColumnID,CAST(CASE WHEN indexCTE.column_id IS NULL THEN 0 ELSE 1 END AS BIT) IsPrimaryKey,colm.name ColumnName,systype.name ColumnType,colm.is_identity IsIdentity,colm.is_nullable IsNullable,cast(colm.max_length as int) ByteLength,(case when systype.name='nvarchar' and colm.max_length>0 then colm.max_length/2 when systype.name='nchar' and colm.max_length>0 then colm.max_length/2when systype.name='ntext' and colm.max_length>0 then colm.max_length/2 else colm.max_lengthend) CharLength,cast(colm.precision as int) Precision,cast(colm.scale as int) Scale,prop.value Remarkfrom {0}.sys.columns colminner join {0}.sys.types systype on colm.system_type_id=systype.system_type_id and colm.user_type_id=systype.user_type_idleft join {0}.sys.extended_properties prop on colm.object_id=prop.major_id and colm.column_id=prop.minor_idLEFT JOIN indexCTE ON colm.column_id=indexCTE.column_id AND colm.object_id=indexCTE.object_id                                        where colm.object_id=OBJECT_ID(@tableName)order by colm.column_id", database);#endregionSqlParameter param = new SqlParameter("@tableName", SqlDbType.NVarChar, 100) { Value = string.Format("{0}.{1}.{2}", database, schema, tableName) };DataTable dt = GetDataTable(connectionString, sql, param);return dt.Rows.Cast<DataRow>().Select(row => new DbColumn(){ColumnID = row.Field<int>("ColumnID"),IsPrimaryKey = row.Field<bool>("IsPrimaryKey"),ColumnName = row.Field<string>("ColumnName"),ColumnType = row.Field<string>("ColumnType"),IsIdentity = row.Field<bool>("IsIdentity"),IsNullable = row.Field<bool>("IsNullable"),ByteLength = row.Field<int>("ByteLength"),CharLength = row.Field<int>("CharLength"),Precision=row.Field<int>("Precision"),Scale = row.Field<int>("Scale"),Remark = row["Remark"].ToString()}).ToList();}#endregion#region GetDataTablepublic static DataTable GetDataTable(string connectionString, string commandText, params SqlParameter[] parms){using (SqlConnection connection = new SqlConnection(connectionString)){SqlCommand command = connection.CreateCommand();command.CommandText = commandText;command.Parameters.AddRange(parms);SqlDataAdapter adapter = new SqlDataAdapter(command);DataTable dt = new DataTable();adapter.Fill(dt);return dt;}}#endregion#region GetPrimaryKeypublic static string GetPrimaryKey(List<DbColumn> dbColumns){string primaryKey = string.Empty;if (dbColumns!=null&&dbColumns.Count>0){foreach (var item in dbColumns){if (item.IsPrimaryKey==true){primaryKey = item.ColumnName;}}}return primaryKey;}#endregion}#region DbTablepublic sealed class DbTable{public string TableName { get; set; }public string SchemaName { get; set; }public int Rows { get; set; }public bool HasPrimaryKey { get; set; }}#endregion#region DbColumnpublic sealed class DbColumn{public int ColumnID { get; set; }public bool IsPrimaryKey { get; set; }public string ColumnName { get; set; }public string ColumnType { get; set; }public string CSharpType{get{return SqlServerDbTypeMap.MapCsharpType(ColumnType);}}/// <summary>/// /// </summary>public Type CommonType{get{return SqlServerDbTypeMap.MapCommonType(ColumnType);}}public int ByteLength { get; set; }public int CharLength { get; set; }public int Precision{get;set;}public int Scale { get; set; }public bool IsIdentity { get; set; }public bool IsNullable { get; set; }public string Remark { get; set; }}#endregion#region SqlServerDbTypeMappublic class SqlServerDbTypeMap{public static string MapCsharpType(string dbtype){if (string.IsNullOrEmpty(dbtype)) return dbtype;dbtype = dbtype.ToLower();string csharpType = "object";switch (dbtype){case "bigint": csharpType = "long"; break;case "binary": csharpType = "byte[]"; break;case "bit": csharpType = "bool"; break;case "char": csharpType = "string"; break;case "date": csharpType = "DateTime"; break;case "datetime": csharpType = "DateTime"; break;case "datetime2": csharpType = "DateTime"; break;case "datetimeoffset": csharpType = "DateTimeOffset"; break;case "decimal": csharpType = "decimal"; break;case "float": csharpType = "double"; break;case "image": csharpType = "byte[]"; break;case "int": csharpType = "int"; break;case "money": csharpType = "decimal"; break;case "nchar": csharpType = "string"; break;case "ntext": csharpType = "string"; break;case "numeric": csharpType = "decimal"; break;case "nvarchar": csharpType = "string"; break;case "real": csharpType = "Single"; break;case "smalldatetime": csharpType = "DateTime"; break;case "smallint": csharpType = "short"; break;case "smallmoney": csharpType = "decimal"; break;case "sql_variant": csharpType = "object"; break;case "sysname": csharpType = "object"; break;case "text": csharpType = "string"; break;case "time": csharpType = "TimeSpan"; break;case "timestamp": csharpType = "byte[]"; break;case "tinyint": csharpType = "byte"; break;case "uniqueidentifier": csharpType = "Guid"; break;case "varbinary": csharpType = "byte[]"; break;case "varchar": csharpType = "string"; break;case "xml": csharpType = "string"; break;default: csharpType = "object"; break;}return csharpType;}public static Type MapCommonType(string dbtype){if (string.IsNullOrEmpty(dbtype)) return Type.Missing.GetType();dbtype = dbtype.ToLower();Type commonType = typeof(object);switch (dbtype){case "bigint": commonType = typeof(long); break;case "binary": commonType = typeof(byte[]); break;case "bit": commonType = typeof(bool); break;case "char": commonType = typeof(string); break;case "date": commonType = typeof(DateTime); break;case "datetime": commonType = typeof(DateTime); break;case "datetime2": commonType = typeof(DateTime); break;case "datetimeoffset": commonType = typeof(DateTimeOffset); break;case "decimal": commonType = typeof(decimal); break;case "float": commonType = typeof(double); break;case "image": commonType = typeof(byte[]); break;case "int": commonType = typeof(int); break;case "money": commonType = typeof(decimal); break;case "nchar": commonType = typeof(string); break;case "ntext": commonType = typeof(string); break;case "numeric": commonType = typeof(decimal); break;case "nvarchar": commonType = typeof(string); break;case "real": commonType = typeof(Single); break;case "smalldatetime": commonType = typeof(DateTime); break;case "smallint": commonType = typeof(short); break;case "smallmoney": commonType = typeof(decimal); break;case "sql_variant": commonType = typeof(object); break;case "sysname": commonType = typeof(object); break;case "text": commonType = typeof(string); break;case "time": commonType = typeof(TimeSpan); break;case "timestamp": commonType = typeof(byte[]); break;case "tinyint": commonType = typeof(byte); break;case "uniqueidentifier": commonType = typeof(Guid); break;case "varbinary": commonType = typeof(byte[]); break;case "varchar": commonType = typeof(string); break;case "xml": commonType = typeof(string); break;default: commonType = typeof(object); break;}return commonType;}}#endregion#>

(3)再创建一个 ModelAuto.ttinclude 实体类生产模版

<#@ assembly name="System.Core"#>
<#@ assembly name="EnvDTE"#>
<#@ import namespace="System.Collections.Generic"#>
<#@ import namespace="System.IO"#>
<#@ import namespace="System.Text"#>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating"#>
<#+
class Manager
{public struct Block {public int Start, Length;public String Name,OutputPath;}public List<Block> blocks = new List<Block>();public Block currentBlock;public Block footerBlock = new Block();public Block headerBlock = new Block();public ITextTemplatingEngineHost host;public ManagementStrategy strategy;public StringBuilder template;public Manager(ITextTemplatingEngineHost host, StringBuilder template, bool commonHeader) {this.host = host;this.template = template;strategy = ManagementStrategy.Create(host);}public void StartBlock(String name,String outputPath) {currentBlock = new Block { Name = name, Start = template.Length ,OutputPath=outputPath};}public void StartFooter() {footerBlock.Start = template.Length;}public void EndFooter() {footerBlock.Length = template.Length - footerBlock.Start;}public void StartHeader() {headerBlock.Start = template.Length;}public void EndHeader() {headerBlock.Length = template.Length - headerBlock.Start;}    public void EndBlock() {currentBlock.Length = template.Length - currentBlock.Start;blocks.Add(currentBlock);}public void Process(bool split) {String header = template.ToString(headerBlock.Start, headerBlock.Length);String footer = template.ToString(footerBlock.Start, footerBlock.Length);blocks.Reverse();foreach(Block block in blocks) {String fileName = Path.Combine(block.OutputPath, block.Name);if (split) {String content = header + template.ToString(block.Start, block.Length) + footer;strategy.CreateFile(fileName, content);template.Remove(block.Start, block.Length);} else {strategy.DeleteFile(fileName);}}}
}
class ManagementStrategy
{internal static ManagementStrategy Create(ITextTemplatingEngineHost host) {return (host is IServiceProvider) ? new VSManagementStrategy(host) : new ManagementStrategy(host);}internal ManagementStrategy(ITextTemplatingEngineHost host) { }internal virtual void CreateFile(String fileName, String content) {File.WriteAllText(fileName, content);}internal virtual void DeleteFile(String fileName) {if (File.Exists(fileName))File.Delete(fileName);}
}class VSManagementStrategy : ManagementStrategy
{private EnvDTE.ProjectItem templateProjectItem;internal VSManagementStrategy(ITextTemplatingEngineHost host) : base(host) {IServiceProvider hostServiceProvider = (IServiceProvider)host;if (hostServiceProvider == null)throw new ArgumentNullException("Could not obtain hostServiceProvider");EnvDTE.DTE dte = (EnvDTE.DTE)hostServiceProvider.GetService(typeof(EnvDTE.DTE));if (dte == null)throw new ArgumentNullException("Could not obtain DTE from host");templateProjectItem = dte.Solution.FindProjectItem(host.TemplateFile);}internal override void CreateFile(String fileName, String content) {base.CreateFile(fileName, content);//((EventHandler)delegate { templateProjectItem.ProjectItems.AddFromFile(fileName); }).BeginInvoke(null, null, null, null);}internal override void DeleteFile(String fileName) {((EventHandler)delegate { FindAndDeleteFile(fileName); }).BeginInvoke(null, null, null, null);}private void FindAndDeleteFile(String fileName) {foreach(EnvDTE.ProjectItem projectItem in templateProjectItem.ProjectItems) {if (projectItem.get_FileNames(0) == fileName) {projectItem.Delete();return;}}}
}#>

 

(3)创建实体类运行时文本模版

 

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ output extension="/" #>
<#@ assembly name="System.Core.dll" #>
<#@ assembly name="System.Data.dll" #>
<#@ assembly name="System.Data.DataSetExtensions.dll" #>
<#@ assembly name="System.Xml.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Data" #>
<#@ import namespace="System.Data.SqlClient" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.IO" #>
<#@ include file="$(ProjectDir)DbHelper.ttinclude"  #>
<#@ include file="$(ProjectDir)ModelAuto.ttinclude"	#>
<# var manager = new Manager(Host, GenerationEnvironment, true); #>
<# var OutputPath1 =Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(Host.TemplateFile+"..")+"..")+"..");OutputPath1=Path.Combine(OutputPath1,"H5.Framwork","Models_New");if (!Directory.Exists(OutputPath1)){Directory.CreateDirectory(OutputPath1);}
#>
<# foreach (var item in DbHelper.GetDbTablesNew(config.ConnectionString, config.DbDatabase,config.TableName)){var tableName=item.ToString();manager.StartBlock(tableName+".cs",OutputPath1);//文件名#>
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace H5.Framwork.Model
{///<summary>///<#=tableName#>///</summary>[Table("<#=tableName#>")]	public class <#=tableName#>{<# foreach(DbColumn column in DbHelper.GetDbColumns(config.ConnectionString, config.DbDatabase, tableName)){#>/// <summary>/// <#= column.Remark == "" ? column.ColumnName : column.Remark.Replace("\r\n"," ") #>/// </summary><# if(column.IsPrimaryKey) {#>[Key]<#}#><# if(!column.IsNullable) {#>[Required]<# }#>public <#= column.CSharpType#><# if(column.CommonType.IsValueType && column.IsNullable){#>?<#}#> <#=column.ColumnName#> { get; set; }<#}#> }
}	 
<#manager.EndBlock(); }manager.Process(true);#>

我们这里是在同个项目中的Models_New文件夹生产实体类

 

最后只需右键运行自定义工具就可以快速生成实体类了,运行代码上面的gif图所示

当然t4模版不仅仅只能生成实体类还能生产其他固定代码,其他的我们下一次来讲解

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/410434.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Docker中安装Jenkins实时发布.net core 项目(一)

Docker中安装Jenkins实时发布.net core 项目安装docker懒人篇手动安装dockerfile安装jenkins常规安装jenkinsjenkins的安装搜索jenkins拉取jenkins容器jenkins的启动jenkins密码其他安装docker 使用curl安装最新版 curl -fsSL https://get.docker.com/ | sh重启Docker systemc…

Docker中安装Jenkins实时发布.net core 项目(二)

Docker中安装Jenkins实时发布.net core 项目防坑点升级dockerjenkins运行运行命令jenkins拉取git并构建项目其他查看发布文件防坑点 升级docker 首先我们要确认我们在liunx安装的不是1.31.1的docker容器不然在后面的运行中会报错 can not open /etc/sysconfig/docker如果你是…

Jenkins构建 netcore5.0 项目时出现NU3028/NU3037错误的解决方案

我在使用Jenkins自动化部署项目的时候&#xff0c;出现了如下的错误 error NU3028: Package System.IO.Compression 4.3.0 from source https://api.nuget.org/v3/index.json: The repository primary signatures timestamp found a chain building issue: UntrustedRoot: self…

2019长安大学ACM校赛网络同步赛 L XOR

题意 求区间内有多少数x满足x^4x^5x0 1≤l≤r≤1018. 题解 根据异或的性质可以推到 x^4x5x -->x^4xx4x 即x和4x每一位都不同&#xff0c;即x和(x<<2)每一位都不同&#xff0c;就是x中每一位都与他前前一位不同。 那么就很简单了&#xff0c;可以很容易写出数位DP状态f…

贝塞尔曲线 总结

Bzier curve(贝塞尔曲线)是应用于二维图形应用程序的数学曲线。 曲线定义&#xff1a;起始点、终止点&#xff08;也称锚点&#xff09;、控制点。通过调整控制点&#xff0c;贝塞尔曲线的形状会发生变化。 1962年&#xff0c;法国数学家Pierre Bzier第一个研究了这种矢量绘制曲…

python变量标识符_简谈-Python的注释、变量类型、标识符及关键字

在Python程序中&#xff0c;要想支持中文输出&#xff0c;则要在代码前面添加标识符&#xff1a;开发人员在程序中自定义的一些符号和名称 标示符是自己定义的,如变量名 、函数名等 标识符的规则&#xff1a; 标示符由字目、下划线和数字组成&#xff0c;且数字不能开头 python…

win10使用docker desktop安装k8s一直starting解决方法

在docker中启动k8s一直卡在staring当中查了许多文档都写得不明不白的&#xff0c;研究了许久终于解决决定写个帖子来记录一下 1.首先查看本地docker中k8s的版本拉取源码 我们这里是1.19.7 然后我们进入到 k8s下载 去拉取k8s源码 git clone https://codechina.csdn.net/mirr…

Android菜单详解(三)——SubMenu和IconMenu

我们在上一篇介绍了如何在Android中创建和响应选项菜单&#xff0c;今天我们将探索子菜单和图标菜单。 子菜单Sub Menu 子菜单提供了一种自然的组织菜单项的方式&#xff0c;它被大量地运用在windows和其他OS的GUI设计中。Android同样支持子菜单&#xff0c;你可以通过addSubMe…

Liunx下使用Nginx负载均衡

我是centos8得主机 安装命令: yum install nginx 如果为Ubuntu主机 sudo apt-get install nginx 安装完成后&#xff0c;启用并启动Nginx服务&#xff1a; sudo systemctl enable nginxsudo systemctl start nginx 然后我们有2个服务&#xff1a; 一个地址为: http://xx…

如何给微软提反馈建议以及bug

1.相信各位在使用.net core的过程中多多少少遇到了bug和为解决的坑那么我们肿么联系微软反馈问题你 1.找到vs编辑器中的反馈按钮 2.点击进入网址 如果是vs的问题选择visual studio栏目,如果为编译问题或者其他问题请选择对应的栏目 然后写下你的问题和截图&#xff0c;尽量详…

windwos docker安装k8s一直staring的解决方法

今天遇到了一个很奇怪的问题 docker中启动k8s一直卡在starting 然后就不动了&#xff0c;找了很多解决方法终于得到解决这里把解决流程写在这里 1.配置镜像加速器 首先登录阿里云&#xff0c;阿里云有一个免费的镜像加速服务&#xff0c;可以加快拉取docker容器的速度这里一定…

对未标记为可安全执行的脚本_三、??XSS跨站脚本攻击

跨站脚本攻击(Cross Site Scripting)&#xff0c;缩写为XSS。恶意攻击者往Web页面里插入恶意Script代码&#xff0c;当用户浏览该页之时&#xff0c;嵌入其中Web里面的Script代码会被执行&#xff0c;从而达到恶意攻击用户的目的。理论上&#xff0c;所有可输入的地方没有对输入…

.net 使用阿里云RocketMQ

1.首先我们来讲解一下消息队列的作用 比如说我们的订单系统&#xff0c;再客户订单生成了以后&#xff0c;可能会有 快递系统&#xff0c;通知系统&#xff0c;和打印系统需要用到当前订单的详细内容 所以这个时候常规的操作是在A里面通过代码调用B&#xff0c;C &#xff…

tensorflow 目标分割_Tensorflow中的控制流和优化器

控制流只要对tensorflow有一点了解&#xff0c;都应该知道graph是tensorflow最基本的一个结构。Tensorflow的所有计算都是以图作为依据的。图的nodes表示一些基本的数学运算&#xff0c;比如加法&#xff0c;卷积&#xff0c;pool等。Node使用protoBuf来进行描述&#xff0c;包…

Reflector 已经out了,试试ILSpy

Reflector是.NET开发中必备的反编译工具。即使没有用在反编译领域&#xff0c;也常常用它来检查程序集的命名规范&#xff0c;命名空间是否合理&#xff0c;组织类型的方法是否需要改善。举例说明&#xff0c;它有一个可以查看程序集完整名称的功能&#xff0c;请看下图 这里的…

Go语言通过odbc驱动连接华为高斯数据库

1.下载odbc驱动 下载后安装psqlodbc_x64.msi 安装成功后可在odbc数据源中看到以下内容 2.测试odbc驱动 在用户dsn中选择添加 输入对应的连接内容点击test 如果显示以下内容则表示驱动正常可使用odbc连接高斯数据库 3.go 语言编写 其中依赖包需要使用命令安装 go get github.c…

activiti高亮显示图片_【正点原子FPGA连载】第二十章SD卡读BMP图片HDMI显示实验领航者 ZYNQ 之嵌入式开发指南...

1&#xff09;实验平台&#xff1a;正点原子领航者ZYNQ开发板2&#xff09;平台购买地址&#xff1a;https://item.taobao.com/item.htm?&id6061601087613&#xff09;全套实验源码手册视频下载地址&#xff1a;http://www.openedv.com/docs/boards/fpga/zdyz_linhanz.htm…

.net Redis缓存优化提高加载速度和服务器性能(一)

距离上次服务器将图片转义至oss服务器提交加载速度已经有一段时日了 对于图片转移至oss服务器优化前后的结果可以查看我之前编写的文章点击查看 如今随着商户数的增多&#xff0c;数据的增多&#xff0c;服务器的性能再一次达到了顶峰&#xff0c;并且由于是点餐系统的缘故订…

火星人谚语系列之六:一次真实应用

总目录&#xff1a;之一&#xff0c;之二&#xff0c;之三&#xff0c;之四&#xff0c;之五&#xff0c;之六&#xff0c;之七&#xff0c;之八这是2011年7月的一次QQ群对话记录&#xff0c;做了匿名化处理&#xff0c;并重新调整了顺序&#xff0c;以便于阅读。对话的开始&am…

ubuntu 启动图形界面命令_Windows 10 远程连接 Ubuntu 18.04 Server图形界面

目录 0. 环境信息和说明Ubuntu 18.04上安装xrdp远程ubuntu-desktop桌面服务Ubuntu 18.04上安装xrdp远程Xfce桌面服务Ubuntu 18.04上安装vnc远程Xfce桌面服务0.环境信息和说明-----------Ubuntu版本# cat /etc/os-releaseNAME"Ubuntu"VERSION"18.04.3 LTS (Bioni…