C# Script
本文将介绍 Tabular Editor 3 的 C# Script 功能。本文档中的信息可能会发生变更。另外,也别忘了看看我们的脚本库 @csharp-script-library,里面有更多贴近实际场景的示例,展示了你可以如何利用 Tabular Editor 的脚本功能。
为什么要用 C# Script?
Tabular Editor 的界面旨在让你在构建表格模型时,轻松完成大多数常见任务。例如,要一次性更改多个度量值的显示文件夹,只需在资源管理器树中选中这些对象,然后拖放到相应位置即可。资源管理器树的右键菜单提供了更便捷的入口来完成许多任务,例如将对象添加到透视中或从透视中移除、批量重命名对象等。
不过,还有不少常见的工作流任务并不容易通过 UI 完成。因此,Tabular Editor 提供 C# Script,让高级用户可以用 C# 语法编写脚本,更直接地操作已加载的表格模型中的对象。
Code Assist
C# Script 编辑器支持基于 Roslyn 的代码补全和调用提示;从 Tabular Editor 3.23.0 起,补全还支持子字符串匹配和大写首字母缩写匹配。
对象
scripting API 提供对两个顶层对象的访问:Model 和 Selected。前者包含用于操作表格模型中所有对象的方法和属性;后者只公开当前在资源管理器树中选中的对象。
Model 对象是 Microsoft.AnalysisServices.Tabular.Model 类的封装,仅公开其部分属性,并额外提供一些方法和属性,方便对翻译、透视和对象集合进行操作。同样也适用于任何派生对象,例如表、度量值、列等,它们都各自有对应的包装器对象。请参阅 Scripting API,查看 Tabular Editor 包装器库中对象、属性和方法的完整列表。
通过此包装器进行操作的主要优势在于:所有更改都可以在 Tabular Editor UI 中撤销。运行脚本后,按 Ctrl+Z 可撤销该脚本所做的所有更改。在 Tabular Editor 3 中,脚本运行后焦点仍会停留在脚本编辑器中,因此在按 Ctrl+Z 之前,请先单击 TOM Explorer。请参阅 文本编辑器中的撤销。此外,包装器还提供了一些便捷方法,让许多常见任务都能用一行代码完成。下面我们会提供一些示例。我们假设你已经对 C# 和 LINQ 有一定了解,因为这里不会讲解 Tabular Editor 脚本功能中的这些内容。即使你不熟悉 C# 和 LINQ,也应该能跟上下面的示例。
设置对象属性
如果你只想更改某一个对象的某个属性,最简单的方式当然是直接在 UI 中操作。不过作为示例,我们来看如何通过脚本实现同样的效果。
假设你想修改 'FactInternetSales' 表中 [Sales Amount] 度量值的格式字符串。如果你在资源管理器树中找到该度量值,直接将其拖到脚本编辑器即可。随后 Tabular Editor 会生成如下代码,用于在 Tabular Object Model 中表示这个特定的度量值:
Model.Tables["FactInternetSales"].Measures["Sales Amount"]
再加一个点(.) 在最右侧括号后加上英文句点.,就会弹出自动补全菜单,显示这个度量值有哪些属性和方法。在菜单中直接选择 "FormatString",或者输入前几个字母后按 Tab。然后输入等号,后面接 "0.0%"。我们也来修改此度量值的显示文件夹。最终代码应如下所示:
Model.Tables["FactInternetSales"].Measures["Sales Amount"].FormatString = "0.0%";
Model.Tables["FactInternetSales"].Measures["Sales Amount"].DisplayFolder = "New Folder";
注意: 记得在每行末尾加上分号(;)。这是 C# 的要求。如果忘了加,尝试执行脚本时会收到语法错误信息。
按 F5 或点击脚本编辑器上方的“播放”按钮来执行脚本。你会立刻看到该度量值在资源管理器树中移动位置,反映出“显示文件夹”已更改。如果你在属性网格中查看该度量值,也会看到“格式字符串”属性已相应更改。
同时处理多个对象
对象模型中的许多对象实际上都是由多个对象组成的集合。例如,每个表对象都有一个度量值集合。该封装器在这些集合上提供了一系列便捷的属性和方法,便于你一次性为多个对象设置相同的属性。下文将对此进行详细说明。此外,你还可以使用所有标准的 LINQ 扩展方法来筛选和浏览集合中的对象。
下面是一些最常用的 LINQ 扩展方法示例:
Collection.First([predicate])返回集合中第一个满足可选 [predicate] 条件的对象。Collection.Any([predicate])如果集合包含任何对象(可选:满足 [predicate] 条件),则返回 true。Collection.Where(predicate)返回一个集合,该集合是按 predicate 条件从原集合筛选得到的。Collection.Select(map)根据指定的 map,将集合中的每个对象投影为另一个对象。Collection.ForEach(action)对集合中的每个元素执行指定的 action。
在上面的示例中,predicate 是一个 lambda 表达式:以单个对象作为输入,并返回一个布尔值作为输出。例如,如果 Collection 是一个度量值集合,一个典型的 predicate 可能是:
m => m.Name.Contains("Reseller")
该 predicate 仅在度量值的 Name 包含字符串“Reseller”时才会返回 true。如果需要更复杂的逻辑,可以用花括号包裹表达式并使用 return 关键字:
.Where(obj => {
if(obj is Column) {
return false;
}
return obj.Name.Contains("test");
})
回到上面的示例,map 是一个 lambda 表达式:以单个对象作为输入,并返回任意单个对象作为输出。 action 是一个 lambda 表达式:以单个对象作为输入,但不返回任何值。
使用 Model 对象
要快速引用当前已加载的表格模型中的任意对象,你可以将该对象从资源管理器树拖放到 C# Script 编辑器中:

可以参考 TOM 文档,了解 Model 及其派生对象上有哪些属性。另外,也可以查看 Scripting API,获取包装对象公开的属性和方法的完整列表。
使用 Selected 对象
在某些工作流中,能够显式引用表格模型中的任何对象非常有用;但有时你希望从资源管理器树中挑选对象,然后只对所选对象执行脚本。这时 Selected 对象就派上用场了。
Selected 对象提供了一组属性,便于识别当前选中的内容,同时也可以将选择范围限定为特定类型的对象。在使用显示文件夹浏览时,如果在资源管理器树中选中了一个或多个文件夹,则其所有子项也会被视为已选中。对于单项选择,请使用要访问的对象类型的单数名称。例如,
Selected.Hierarchy
它指向树中当前选中的层次结构,前提是只选中了一个层次结构。如果要处理多选,请使用该类型的复数名称:
Selected.Hierarchies
单数对象上存在的所有属性,在其复数形式上也同样存在,只有少数例外。这意味着你可以用一行代码一次性为多个对象设置这些属性,而无需使用上面提到的 LINQ 扩展方法。例如,假设你想把当前选中的所有度量值移动到名为 "Test" 的新显示文件夹中:
Selected.Measures.DisplayFolder = "Test";
如果树中当前没有选中任何度量值,上面的代码不会执行任何操作,也不会抛出错误。否则,所有选中的度量值的 DisplayFolder 属性都会被设置为 "Test"(即使这些度量值位于文件夹中也是如此,因为 Selected 对象也会包含所选文件夹内的对象)。如果你使用单数形式 Measure 而不是 Measures,除非当前选择恰好包含一个度量值,否则会报错。
虽然没法一次性设置多个对象的 Name 属性,但还是有一些办法。如果只是想将某个字符串的所有匹配项替换为另一个字符串,可以使用提供的 "Rename" 方法,例如:
Selected.Measures
.Rename("Amount", "Value");
这会将当前所选所有度量值的名称中出现的“Amount”替换为“Value”。或者,也可以按上文所述使用 LINQ 的 ForEach() 方法,以实现更复杂的逻辑:
Selected.Measures
.ForEach(m => if(m.Name.Contains("Reseller")) m.Name += " DEPRECATED");
此示例会在所有已选且名称包含“Reseller”的度量值名称后追加文本“ DEPRECATED”。或者,我们也可以先使用 LINQ 扩展方法 Where() 过滤集合,再应用 ForEach() 操作,得到的结果完全相同:
Selected.Measures
.Where(m => m.Name.Contains("Reseller"))
.ForEach(m => m.Name += " DEPRECATED");
Selected 访问器完整列表
下表列出了 Selected 对象上所有可用的单数和复数访问器。如果当前选择中不恰好包含一个该类型的对象,单数访问器会抛出 SelectionException。如果未选择该类型的任何对象,复数访问器会返回空集合。
| 单数 | 复数 | 对象类型 |
|---|---|---|
Selected.Measure |
Selected.Measures |
度量值 |
Selected.Column |
Selected.Columns |
所有列类型 |
Selected.DataColumn |
Selected.DataColumns |
数据列 |
Selected.CalculatedColumn |
Selected.CalculatedColumns |
计算列 |
Selected.CalculatedTableColumn |
Selected.CalculatedTableColumns |
计算表格列 |
Selected.Hierarchy |
Selected.Hierarchies |
层次结构 |
Selected.Level |
Selected.Levels |
层级 |
Selected.Table |
Selected.Tables |
表格 |
Selected.CalculatedTable |
Selected.CalculatedTables |
计算表格 |
Selected.Partition |
Selected.Partitions |
分区 |
Selected.Role |
Selected.Roles |
模型角色 |
Selected.TablePermission |
Selected.TablePermissions |
表格权限 |
Selected.KPI |
Selected.KPIs |
KPI |
Selected.Calendar |
Selected.Calendars |
日历 |
Selected.CalculationItem |
Selected.CalculationItems |
计算项 |
Selected.Function |
Selected.Functions |
用户自定义函数 |
Selected.DataSource |
Selected.DataSources |
数据源 |
Selected.SingleColumnRelationship |
Selected.SingleColumnRelationships |
关系 |
Selected.Perspective |
Selected.Perspectives |
透视 |
Selected.Culture |
Selected.Cultures |
翻译 |
Note
在 Tabular Editor 3.26.0 中,新增了 角色、KPI、日历、计算项、表权限、函数、数据源、单列关系、计算列、计算表列、数据列、计算表和分区的访问器。
从 Tabular Editor 3.27.0 开始,自上次保存模型以来被删除的对象仍会显示在 TOM Explorer 中,并且仍可被选中。这类对象不属于模型,因此不会出现在上面的访问器中。相反,Selected.Deleted 会列出当前选中的已删除对象,每个对象都具有 Name、ObjectType、Parent 以及 Restore() 方法。 Selected.Deleted.Restore() 会一次性还原它们全部。模型对象还提供了 HasUnsavedChanges 和 Revert(),让脚本能够回滚模型的一部分。详见 @unsaved-changes。
辅助方法
Tabular Editor 提供了一组专用的辅助方法,便于完成某些脚本任务。注意,其中一些方法也可以以扩展方法的形式调用。例如,object.Output(); 与 Output(object); 是等价的。
void Output(object value)- 停止脚本执行,并显示所提供对象的信息。当脚本作为命令行执行的一部分运行时,该方法会将该对象的字符串表示形式写入控制台。void SaveFile(string filePath, string content)- 将文本数据保存到文件的便捷方式。string ReadFile(string filePath)- 从文件加载文本数据的便捷方式。string ExportProperties(IEnumerable<ITabularNamedObject> objects, string properties)- 便捷地将多个对象的一组属性导出为 TSV 字符串。void ImportProperties(string tsvData)- 将 TSV 字符串中的属性导入多个对象的便捷方式。void CustomAction(string name)- 按名称调用宏。void CustomAction(this IEnumerable<ITabularNamedObject> objects, string name)- 对指定对象调用宏。string ConvertDax(string dax, bool useSemicolons)- 在美/英区域设置与非美/英区域设置之间相互转换 DAX 表达式。如果useSemicolons为 true(默认),则会将dax字符串从默认的美/英格式转换为非美/英格式。也就是说,逗号(列表分隔符)会转换为分号,句点(小数分隔符)会转换为逗号。如果将useSemicolons设为 false,则反向转换。void FormatDax(this IEnumerable<IDaxDependantObject> objects, bool shortFormat, bool? skipSpace)- 格式化所提供集合中所有对象上的 DAX 表达式void FormatDax(this IDaxDependantObject obj)- 将对象加入队列,在脚本执行完成时,或调用CallDaxFormatter方法时,对其 DAX 表达式进行格式化。void CallDaxFormatter(bool shortFormat, bool? skipSpace)- 格式化截至目前已入队的对象上的所有 DAX 表达式void Info(string)- 将一条提示信息输出到控制台(仅当脚本在命令行执行过程中运行时)。void Warning(string)- 将一条警告信息输出到控制台(仅当脚本在命令行执行过程中运行时)。void Error(string)- 将一条错误信息输出到控制台(仅当脚本在命令行执行过程中运行时)。T SelectObject(this IEnumerable<T> objects, T preselect = null, string label = "Select object") where T: TabularNamedObject- 向用户显示一个对话框,提示其从指定对象中选择一个。如果用户取消对话框,此方法将返回 null。void CollectVertiPaqAnalyzerStats()- 如果 Tabular Editor 已连接到 Analysis Services 实例,则会运行 VertiPaq分析器统计信息收集器。long GetCardinality(this Column column)- 如果当前模型有可用的 VertiPaq分析器统计信息,此方法将返回指定列的基数。
有关可用帮助方法及其语法的完整列表,请参阅 @script-helper-methods。
调试脚本
如上所述,你可以使用 Output(object); 方法来暂停脚本执行,并打开一个对话框来显示传入对象的信息。你也可以将此方法作为扩展方法使用,通过 object.Output(); 来调用。关闭对话框后,脚本将继续执行。
根据输出对象的类型,对话框会以下面四种方式之一显示:
- 单个对象(例如 string、int 和 DateTime,但不包括派生自 TabularNamedObject 的任何对象)会通过对该对象调用
.ToString()方法,以简单的信息对话框形式显示:

- 单个 TabularNamedObject(例如表、度量值,或 Tabular Editor 中提供的任何其他 TOM NamedMetadataObject)会显示在属性网格中,类似于在 Tree Explorer 中选中对象时的效果。你可以在网格中编辑该对象的属性。但请注意:如果脚本在后续执行过程中遇到错误,并且启用了“自动回滚”——"Auto-Rollback"——这些编辑将自动撤销:

- 任何对象的 IEnumerable(不包括 TabularNamedObject)都会以列表形式显示;列表中的每一项都会显示该 IEnumerable 中对象的
.ToString()值及其类型:

- 任何 TabularNamedObject 的 IEnumerable 都会使对话框左侧显示对象列表,右侧显示属性网格。属性网格会根据列表中当前选中的对象进行填充,并且属性可编辑方式与输出单个 TabularNamedObject 时相同:

你可以勾选左下角的“不再显示更多输出”复选框,以防脚本在后续任何 .Output() 调用时暂停。
以预览方式运行 C# Script
带预览运行操作允许你在提交之前,预览 C# Script 对模型元数据所做的所有更改。在运行不熟悉的脚本或执行批量修改时,这会很有用。
要使用此功能,在工具栏或菜单中点击 脚本 > 带预览运行。流程如下:
- Tabular Editor 会在执行前为模型元数据创建快照
- 脚本将运行直至完成
- Tabular Editor 会将当前模型的元数据状态与执行前创建的快照进行比较
- 如果检测到更改,将弹出预览对话框,以并排的分层差异视图显示模型(执行前与执行后)
- 更改采用颜色区分:绿色表示新增对象,红色表示已删除对象,橙色表示已修改的属性
- 使用 仅显示更改 复选框隐藏未更改的项目,将注意力集中在脚本更改的内容上
- 单击 确定 以接受更改,或单击 还原 以撤销所有更改

如果脚本失败(编译或运行时错误),所有模型元数据更改都会自动回滚,并且不会显示预览对话框。如果脚本成功但未检测到任何元数据更改,则会改为显示一条信息。
脚本执行产生的所有模型元数据更改都会封装在一次撤销事务中。即使在预览对话框中接受了更改,你仍然可以撤销整个操作。单击 TOM Explorer 并按 Ctrl+Z,或在 编辑 菜单中选择模型撤销条目。
Important
预览与撤销功能仅适用于模型元数据更改。如果脚本执行写入文件、数据库或发起 Web 请求等外部操作,这些操作会立即执行,且无法撤销。预览对话框不会尝试分析脚本代码——其原理是比较执行前后的模型元数据状态。
Tip
只要在 工具 > 偏好 > AI 功能 > AI 助手 中启用 预览更改,AI 助手 自行运行脚本时就会显示此对话框。该选项默认开启,因此在应用 AI 生成的模型更改之前,你始终有机会先进行检查。
Note
预览对话框不适用于代理通过 MCP 服务器 运行的脚本。这些脚本会先编译,并通过安全分析检查,然后以原子方式对模型运行。代理会收到一份结构化的更改摘要,而这些更改也会在 TOM Explorer 和属性视图 中标记出来,方便你稍后查看或还原。
.NET 引用
你可以像在普通的 C# 源代码中一样,使用 using 关键字来简化类名等写法。此外,你还可以使用语法 #r "<assembly name or DLL path>" 来包含外部程序集,方式与 Azure Functions 中使用的 .csx 脚本类似。
例如,下面的脚本现在将按预期工作:
// Assembly references must be at the very top of the file:
#r "System.IO.Compression"
// Using keywords must come before any other statements:
using System.IO.Compression;
using System.IO;
var xyz = 123;
// Using statements still work the way they're supposed to:
using(var data = new MemoryStream())
using(var zip = new ZipArchive(data, ZipArchiveMode.Create))
{
// ...
}
默认情况下,为了便于完成常见任务,Tabular Editor 会自动添加以下 using 指令(即使脚本中未显式声明):
using System;
using System.Linq;
using System.Collections.Generic;
using Newtonsoft.Json;
using TabularEditor.TOMWrapper;
using TabularEditor.TOMWrapper.Utils;
using TabularEditor.UI;
此外,默认还会加载以下 .NET Framework 程序集:
- System.Dll
- System.Core.Dll
- System.Data.Dll
- System.Windows.Forms.Dll
- Microsoft.Csharp.Dll
- Newtonsoft.Json.Dll
- TomWrapper.Dll
- TabularEditor.Exe
- Microsoft.AnalysisServices.Tabular.Dll
访问环境变量
通过 Tabular Editor CLI 运行 C# Script 时(尤其是在 CI/CD 流水线中),可以使用环境变量向脚本传递参数。这是推荐的做法,因为 Tabular Editor CLI 执行的 C# Script 不支持传统的命令行参数。
Note
当管理员设置了 BlockUnsafeScripts 策略时,Environment 是被拒绝的类型之一。参见 管理员策略。
读取环境变量
在脚本中使用 Environment.GetEnvironmentVariable() 方法读取环境变量:
// Read environment variables
var serverName = Environment.GetEnvironmentVariable("SERVER_NAME");
var environment = Environment.GetEnvironmentVariable("ENVIRONMENT");
// Use them in your script
foreach(var dataSource in Model.DataSources.OfType<ProviderDataSource>())
{
if(dataSource.Name == "SQLDW")
{
dataSource.ConnectionString = dataSource.ConnectionString
.Replace("{SERVER}", serverName)
.Replace("{ENV}", environment);
}
}
Info($"Updated connection strings for {environment} environment");
Azure DevOps 集成
环境变量可与 Azure DevOps 流水线无缝集成,因为默认情况下,所有流水线变量都会自动作为环境变量提供。
Azure DevOps YAML 流水线示例:
variables:
targetServer: 'Production'
targetDatabase: 'AdventureWorks'
steps:
- task: PowerShell@2
displayName: 'Deploy Model with Parameters'
env:
SERVER_NAME: $(targetServer)
DATABASE_NAME: $(targetDatabase)
inputs:
targetType: 'inline'
script: |
TabularEditor.exe "Model.bim" -S "DeploymentScript.csx" -D "$(targetServer)" "$(targetDatabase)" -O -V -E -W
在此示例中,脚本 DeploymentScript.csx 可以通过 Environment.GetEnvironmentVariable() 访问 SERVER_NAME 和 DATABASE_NAME。
常见使用场景
环境变量尤其适用于:
- 动态连接字符串:根据部署环境(Dev、UAT、Production)更新数据源连接
- 条件逻辑:根据目标环境应用不同的转换
- 部署配置:基于参数控制要部署或修改的对象
- 多环境支持:在不同环境中复用同一脚本,只需使用不同的值
示例——按环境修改:
var environment = Environment.GetEnvironmentVariable("DEPLOY_ENV") ?? "Development";
var refreshPolicy = Environment.GetEnvironmentVariable("ENABLE_REFRESH_POLICY") == "true";
// Apply environment-specific settings
foreach(var table in Model.Tables)
{
if(environment == "Production" && !refreshPolicy)
{
// Disable incremental refresh policies in production if specified
table.EnableRefreshPolicy = false;
}
}
Info($"Configured model for {environment} environment");
管理员策略
脚本功能可以集中管理,因此,脚本在你自己的电脑上能做的事,在由 IT 部门管理的电脑上不一定也能做。这由两项 策略 决定。
DisableCSharpScripts 会直接禁用脚本功能:既不能创建脚本,也不能执行脚本;启用 DisableMacros 时,宏也一样。
BlockUnsafeScripts 是折中方案,也是作为脚本作者最该了解的一项策略。脚本和宏仍可继续使用,但前提是它们的操作仅限于语义模型内部。凡是读取或写入文件、发出 Web 请求、启动其他程序、用 #r 引用外部程序集,或直接向服务器发送命令的脚本,都会在运行前被拒绝。
什么算是在模型内部操作
系统会通过分析已编译的脚本来做出判断,而不是搜索脚本文本,因此,任何以间接方式达到同样目的的做法也会被拒绝:通过 Type.GetType 或 InvokeMember 进行反射、表达式树和委托调用、Activator、AppDomain、Environment、接受路径或 URL 的 XML 读取器和写入器,以及基于类型名称的反序列化。
在 帮助程序方法 中,有三个会向模型外部写入内容,因此被视为不安全:
| 被拒绝 | 仍可用 |
|---|---|
SaveFile, ExecuteCommand, Bpa.ExportCsv |
ReadFile, ExecuteDax, EvaluateDax, ExecuteReader, ExportProperties |
TOM 对象模型中的所有内容都没问题,System、System.Linq、System.Collections.Generic 和 Newtonsoft.Json 也一样。在实际使用中,创建和修改模型对象的脚本不受影响,而将内容导出到磁盘的脚本则会受影响。
脚本被拒绝运行时的提示
脚本未运行 对话框会显示策略名称以及脚本使用了哪些内容,状态栏则会显示 脚本已被组织策略阻止。错误列表会保持为空,因为这不是编译错误:脚本本身有效,只是不允许在这里运行。运行并预览 的行为相同,也不会显示预览对话框。
宏在保存时会被分析。保存会成功,并且会有一个对话框告诉你这个宏已保存,但无法运行。被阻止的宏不会出现在任何菜单中,因此不会被误运行;它会显示在 View > Macros 下,并且其 Blocked 列会被填充。把它改回到允许范围内后,它的菜单项就会恢复,无需重启 Tabular Editor。
在命令行中,te script、te macro run 和 te bpa run --fix 也会以同样的方式拒绝执行,并以非零退出码退出,同时在 JSON 输出中报告 blockedByPolicy。
Note
BlockUnsafeScripts 需要 Tabular Editor 3 企业版。如果在未获得该功能许可的副本上设置了此值,那么在激活企业版许可证之前,任何脚本或宏都无法运行,无论是否安全。 Tabular Editor CLI 不区分版本,只会直接应用该策略。
兼容性
Tabular Editor 2、Tabular Editor 3(Desktop)和 Tabular Editor CLI 的脚本 API 基本兼容,但在某些情况下,你可能需要根据当前运行的宿主环境来有条件地编译代码。 CLI 宿主定义了 TECLI 预处理器符号;TE3 Desktop 定义了 TE3(以及与当前次版本对应的版本符号,例如 TE3_3_15_OR_GREATER);而 TE2 两者都不定义。预处理器指令是在 Tabular Editor 3.10.0 中引入的。用它们来编写可移植脚本:
#if TECLI
// CLI host - no UI APIs available
Info($"Running under the CLI on {Environment.OSVersion.Platform}");
#elif TE3
// TE3 Desktop - UI APIs are available
ShowMessage("Hello from TE3");
#else
// TE2 (legacy) - neither TECLI nor TE3 is defined
Info("Hello from TE2");
#endif
#if TE3_3_15_OR_GREATER
// Gated on a specific TE3 minor version
#endif
有一个 CLI 特有的注意事项:由于 CLI 没有可弹出的 UI,TE3-Desktop 的 UI 辅助方法 SelectMeasure()、SelectTable()、SelectColumn()、SelectObject() 和 SelectObjects() 在 te script 下会抛出 NotSupportedException。在不同宿主之间共享脚本时,请用 #if TE3(或 try/catch)把这类调用包起来。
如果你想在脚本运行时知道 Tabular Editor 的具体版本,可以查看程序集版本:
var currentVersion = typeof(Model).Assembly.GetName().Version;
Info(currentVersion.ToString());
公开的产品版本号(例如 "2.20.2" 或 "3.10.1")可以通过以下代码获取:
using System.Diagnostics;
var productVersion = FileVersionInfo.GetVersionInfo(Selected.GetType().Assembly.Location).ProductVersion;
productVersion.Output(); // productVersion is a string ("2.20.2" or "3.10.1", for example)
如果你只想要主版本号(整数),可以用:
var majorVersion = Selected.GetType().Assembly.GetName().Version.Major;
majorVersion.Output(); // majorVersion is an integer (2 or 3)
已知问题和限制
- 由于脚本的执行方式,某些脚本操作可能导致 Tabular Editor 3 应用程序崩溃或无响应。例如,包含无限循环(
while(true) {})的脚本会导致应用程序卡死。如果出现这种情况,你需要通过 Windows 任务管理器结束 Tabular Editor 进程。
如果你打算将脚本保存为宏,请注意以下限制:
- 如果脚本主体包含带访问修饰符(
public、static等)的本地方法,则无法将该脚本保存为宏。删除这些访问修饰符,或改为将该方法移到一个类中。 - 目前宏不支持在脚本主体中使用
await关键字。如果脚本主体调用了异步方法,应使用MyAsyncMethod.Wait()或MyAsyncMethod.Result,而不是await MyAsyncMethod()。在脚本中其他位置定义的async方法里使用await是可以的。