Skip to content

Instantly share code, notes, and snippets.

@engalar
Last active September 2, 2025 01:45
Show Gist options
  • Select an option

  • Save engalar/53eb1a50d6f619e33215172c7586c6f3 to your computer and use it in GitHub Desktop.

Select an option

Save engalar/53eb1a50d6f619e33215172c7586c6f3 to your computer and use it in GitHub Desktop.
# 这个脚本将逐步解析路径 //Projects$Module[Name='Administration']/DomainModels$DomainModel[0]@DomainModels$Entity[Name='Account']['accessRules'][0]['moduleRoles'][0],找到最终的目标对象(一个模块角色的限定名称 e.g. Administration.Administrator), //Projects$Module[Name='Administration']/Security$ModuleRole[Name='Administrator']。
from System.Collections.Generic import KeyValuePair, IReadOnlyList
from Mendix.StudioPro.ExtensionsAPI.Model.Projects import IProject, IModule
from Mendix.StudioPro.ExtensionsAPI.Model.DomainModels import IEntity, IDomainModel, IAssociation
from Mendix.StudioPro.ExtensionsAPI.Model.Pages import IPage
from Mendix.StudioPro.ExtensionsAPI.Model.Microflows import IMicroflow
from Mendix.StudioPro.ExtensionsAPI.Model.UntypedModel import PropertyType, IModelElement
import json
import clr
clr.AddReference("Mendix.StudioPro.ExtensionsAPI")
# 清除之前的日志信息
PostMessage("backend:clear", "")
# 这是一个非常有用的辅助函数,用于打印任何模型元素的详细信息
def print_element_details(element):
"""打印一个IModelElement的所有属性."""
if not element:
PostMessage("backend:warning", "Element to print is None.")
return
try:
element_type = element.GetType().Name
element_id = element.ID
PostMessage("backend:info", f"\n--- Properties for element of type '{element_type}' (ID: {element_id}) ---")
except:
PostMessage("backend:info", "\n--- Properties for element ---")
properties = element.GetProperties()
for prop in properties:
value_str = str(prop.Value)
if len(value_str) > 100:
value_str = value_str[:100] + "..."
PostMessage("backend:info",
f" - Property: {prop.Name}\n Type: {prop.Type}\n Value: {value_str}")
PostMessage("backend:info", "--------------------------------------------------")
# --- 主要逻辑开始 ---
try:
# 1. 找到名为 'Administration' 的模块
# //Projects$Module[Name='Administration']
admin_module = next((m for m in root.GetUnitsOfType('Projects$Module') if m.Name == 'Administration'), None)
if not admin_module:
raise Exception("Module 'Administration' not found.")
PostMessage("backend:info", f"Step 1: Found module '{admin_module.Name}'")
# 2. 从模块中获取域模型
# /DomainModels$DomainModel[0]
domain_models = admin_module.GetUnitsOfType('DomainModels$DomainModel')
if domain_models.Count == 0:
raise Exception("No Domain Model found in 'Administration' module.")
domain_model = domain_models[0]
PostMessage("backend:info", "Step 2: Found Domain Model.")
# 3. 在域模型中找到名为 'Account' 的实体
# @DomainModels$Entity[Name='Account']
account_entity = next((e for e in domain_model.GetElementsOfType('DomainModels$Entity') if e.Name == 'Account'), None)
if not account_entity:
raise Exception("Entity 'Account' not found in the domain model.")
PostMessage("backend:info", f"Step 3: Found entity '{account_entity.Name}'")
# 4. 获取 'accessRules' 属性并选择第一个访问规则
# ['accessRules'][0]
access_rules_prop = account_entity.GetProperty('accessRules')
if not access_rules_prop or access_rules_prop.Value.Count == 0:
raise Exception("Entity 'Account' has no access rules.")
first_access_rule = access_rules_prop.Value[0]
PostMessage("backend:info", "Step 4: Found the first access rule.")
# 5. 从访问规则中获取第一个 'moduleRoles' 的限定名称
# ['moduleRoles'][0]
module_roles_prop = first_access_rule.GetProperty('moduleRoles')
if not module_roles_prop or module_roles_prop.Value.Count == 0:
raise Exception("The first access rule has no module roles assigned.")
# 'moduleRoles' 的值是一个限定名称的列表,例如 ["Administration.Administrator"]
first_module_role_qualified_name = module_roles_prop.Value[0]
PostMessage("backend:info", f"Step 5: Found the qualified name of the first module role: '{first_module_role_qualified_name}'")
# 6. 解析限定名称,并根据它找到实际的 ModuleRole 对象
if '.' not in first_module_role_qualified_name:
raise Exception(f"Invalid module role qualified name format: '{first_module_role_qualified_name}'. Expected 'ModuleName.RoleName'.")
target_module_name, target_role_name = first_module_role_qualified_name.split('.', 1)
PostMessage("backend:info", f"Step 6a: Parsed name - Module='{target_module_name}', Role='{target_role_name}'")
# 6b. 找到目标模块
target_module = next((m for m in root.GetUnitsOfType('Projects$Module') if m.Name == target_module_name), None)
if not target_module:
raise Exception(f"Referenced module '{target_module_name}' from qualified name not found in the project.")
PostMessage("backend:info", f"Step 6b: Found referenced module '{target_module.Name}'")
# 6c. 在目标模块中找到 ModuleSecurity 单元
module_security_units = target_module.GetUnitsOfType('Security$ModuleSecurity')
if module_security_units.Count == 0:
raise Exception(f"No 'ModuleSecurity' unit found in module '{target_module_name}'.")
module_security = module_security_units[0]
# 6d. 在 ModuleSecurity 中按名称查找 ModuleRole
target_object = next((r for r in module_security.GetElementsOfType('Security$ModuleRole') if r.Name == target_role_name), None)
if not target_object:
raise Exception(f"ModuleRole '{target_role_name}' not found in module '{target_module_name}'.")
PostMessage("backend:info", f"Step 6d: Successfully found the target object (ModuleRole '{target_object.Name}')")
# --- 最终输出 ---
PostMessage("backend:info", "\n✅ --- TARGET OBJECT FOUND --- ✅")
# 模块角色的“值”通常指它的名称。我们直接获取'Name'原生属性。
role_name = target_object.Name
PostMessage("backend:info", f"🎯 The value (Name) of the target object is: '{role_name}'")
# 为了提供更完整的信息,调用辅助函数打印该对象的所有属性
print_element_details(target_object)
except Exception as e:
PostMessage("backend:error", f"An error occurred: {e}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment