menu E4b9a6's blog
rss_feed
E4b9a6's blog
有善始者实繁,能克终者盖寡。

Linux下远程Windows桌面的4种方案实践

作者:E4b9a6, 创建:2023-02-23, 字数:25785, 已阅:504, 最后更新:2023-02-23

这篇文章更新于 637 天前,文中部分信息可能失效,请自行甄别无效内容。

1. 背景

使用Linux发行版最不方便的地方就是缺少一些软件,借助远程桌面工具我们可以很方便的远程Windows来解决常用软件缺失的问题

对于远程桌面,个人需求是

  • 方便快捷的连接方式
  • 高清晰度的远程画面(内网)
  • 支持音频传输(QQ音乐VIP会员的血泪)
  • 支持文字/图片复制粘贴

这些都是原生RDP协议就可以做到的,我自己使用的Linux发行版是Manjaro系统,桌面环境选择的是Gnome3

在Linux下远程Windows可以使用基于RDP协议的软件如最常见的Remmina以及Gnome桌面下的Vinagre软件、Rdesktop软件等

2. 方案

2.1. Remmina

Use other desktops remotely, from a tiny screen or large monitors.

官网链接:https://remmina.org/contributing-to-remmina/

remmina是我最喜欢的远程桌面软件之一,功能非常全面,支持的协议包括但不限于RDP、VNC、SPICE、NX、XDMCP、SSH等等,同时也兼顾非常优秀的界面

支持非常复杂的远程协议配置选项

各个操作系统的安装方式可以参考官方Wiki文档 - How to install remmina

Manjaro下安装Remmina非常简单,只需要使用

Bash
sudo pacman -S remmina

# 如果要支持RDP协议,则需要安装FreeRDP
sudo pacman -S freerdp

在我看来,Remmina的优点如下

  • 优秀的界面设计(颜值是第一生产力)
  • 远程协议的配置选项丰富足以应对复杂的远程桌面(加密方式/认证方式等修改配置)
  • 强大的软件快捷键,如Ctrl+→可以快速切换远程桌面,这在应对多个远程桌面比Windows自带远程桌面还要优秀
  • 丰富的远程协议支持,不管是SSH还是RDP还是NX等远程协议均可以在一个远程客户端中配置完是非常Geek体验
  • 支持配置文件的导出导入
  • ...

Remmina是一个极其优秀的软件,我放弃使用的原因只有一个,那就是他在Gnome桌面下的表现糟糕

  • 配置的远程桌面(各种协议)多的时候崩溃是家常便饭
  • RDP协议音频输出到本机的时候播放卡顿(这点实在令人头疼,Google了挺久没有好的解决方法,在Redhat系的发行版上安装却没有这个问题)
  • 复制/粘贴卡顿严重,经常导致我的Chrome直接无相应(同样的在其他发行版上也不会有这种表现)
  • 新建配置使用到一些没有使用过的选项配置时容易崩溃退出还不保存刚才的操作

基于以上表现,在使用过1年多后,我最终还是放弃了这个非常优秀的远程客户端

如果你没有使用过Linux下的远程桌面客户端,那我非常强烈推荐使用Remmina,他在大多数发行版上表现还是非常稳定的

2.2. Vinagre

Vinagre is a VNC, SSH, RDP and SPICE client for the GNOME desktop environment.

Vinagre是基于GNOME桌面环境的一款支持多种远程协议客户端,根据实际体验来看,可以看成是一款剔除掉复杂配置部分的remmina

界面也是相对简洁,跟remmina外观差别不大

其支持自定义话配置少,优点是上手快,缺点是过于简单的配置在应对一些复杂的远程协议配置时无能为力

例如RDP验证方式更改为冷门方式则有可能无法使用这个软件进行连接

对于打印机/音频资源播放选项的支持目前版本也是缺失的

官方文档:Apps/vinagre - Gnome

所以这个软件如果需求只是简单偶尔远程下远程桌面,那么他还是可以胜任的

2.3. Rdesktop

rdesktop is an open source UNIX client for connecting to Windows Remote Desktop Services, capable of natively speaking Remote Desktop Protocol (RDP) in order to present the user's Windows desktop.

rdesktop是一款开源的UNIX客户端,仅支持RDP协议,也支持复杂的协议配置,使用-h可以看到支持配置的选项非常多

Bash
rdesktop: A Remote Desktop Protocol client.
Version 1.9.0. Copyright (C) 1999-2016 Matthew Chapman et al.
See http://www.rdesktop.org/ for more information.

Usage: rdesktop [options] server[:port]
   -u: user name
   -d: domain
   -s: shell / seamless application to start remotely
   -c: working directory
   -p: password (- to prompt)
   -n: client hostname
   -k: keyboard layout on server (en-us, de, sv, etc.)
   -g: desktop geometry (WxH[@DPI][+X[+Y]])
   -i: enables smartcard authentication, password is used as pin
   -f: full-screen mode
   -b: force bitmap updates
   -L: local codepage
   -A: path to SeamlessRDP shell, this enables SeamlessRDP mode
   -V: tls version (1.0, 1.1, 1.2, defaults to negotiation)
   -B: use BackingStore of X-server (if available)
   -e: disable encryption (French TS)
   -E: disable encryption from client to server
   -m: do not send motion events
   -M: use local mouse cursor
   -C: use private colour map
   -D: hide window manager decorations
   -K: keep window manager key bindings
   -S: caption button size (single application mode)
   -T: window title
   -t: disable use of remote ctrl
   -N: enable numlock synchronization
   -X: embed into another window with a given id.
   -a: connection colour depth
   -z: enable rdp compression
   -x: RDP5 experience (m[odem 28.8], b[roadband], l[an] or hex nr.)
   -P: use persistent bitmap caching
   -r: enable specified device redirection (this flag can be repeated)
         '-r comport:COM1=/dev/ttyS0': enable serial redirection of /dev/ttyS0 to COM1
             or      COM1=/dev/ttyS0,COM2=/dev/ttyS1
         '-r disk:floppy=/mnt/floppy': enable redirection of /mnt/floppy to 'floppy' share
             or   'floppy=/mnt/floppy,cdrom=/mnt/cdrom'
         '-r clientname=<client name>': Set the client name displayed
             for redirected disks
         '-r lptport:LPT1=/dev/lp0': enable parallel redirection of /dev/lp0 to LPT1
             or      LPT1=/dev/lp0,LPT2=/dev/lp1
         '-r printer:mydeskjet': enable printer redirection
             or      mydeskjet="HP LaserJet IIIP" to enter server driver as well
         '-r sound:[local[:driver[:device]]|off|remote]': enable sound redirection
                     remote would leave sound on server
                     available drivers for 'local':
                     alsa:	ALSA output driver, default device: default
                     oss:	OSS output driver, default device: /dev/dsp or $AUDIODEV
                     libao:	libao output driver, default device: system dependent
         '-r clipboard:[off|PRIMARYCLIPBOARD|CLIPBOARD]': enable clipboard
                      redirection.
                      'PRIMARYCLIPBOARD' looks at both PRIMARY and CLIPBOARD
                      when sending data to server.
                      'CLIPBOARD' looks at only CLIPBOARD.
         '-r scard[:"Scard Name"="Alias Name[;Vendor Name]"[,...]]
          example: -r scard:"eToken PRO 00 00"="AKS ifdh 0"
                   "eToken PRO 00 00" -> Device in GNU/Linux and UNIX environment
                   "AKS ifdh 0"       -> Device shown in Windows environment 
          example: -r scard:"eToken PRO 00 00"="AKS ifdh 0;AKS"
                   "eToken PRO 00 00" -> Device in GNU/Linux and UNIX environment
                   "AKS ifdh 0"       -> Device shown in Microsoft Windows environment 
                   "AKS"              -> Device vendor name                 
   -0: attach to console
   -4: use RDP version 4
   -5: use RDP version 5 (default)
   -o: name=value: Adds an additional option to rdesktop.
           sc-csp-name        Specifies the Crypto Service Provider name which
                              is used to authenticate the user by smartcard
           sc-container-name  Specifies the container name, this is usually the username
           sc-reader-name     Smartcard reader name to use
           sc-card-name       Specifies the card name of the smartcard to use
   -v: enable verbose logging

简单的使用例子

Bash
❯ rdesktop -K -g 1920x1080 10.0.0.3

如果不添加任何配置,默认的rdesktop是不支持Windows组合键的,一些比较重要的参数如下

  • -K :支持Windows组合键映射
  • size :指定远程桌面的大小
  • -f :全屏显示

rdesktop基本符合我的需要了,但我发现在Gnome3上面即使指定了“-K”依旧没有不能使用Win组合键

远程桌面虽然显示有音频输出到remote,但依旧没有任何声音

在简单使用过FreeRDP之后,我打消了深入研究rdesktop的打算

这两个本质上差别不大,FreeRDP在我机器Gnome3上FreeRDP兼容性更好点(没出现任何问题)

2.4. FreeRDP

FreeRDP is a free implementation of the Remote Desktop Protocol (RDP), released under the Apache license.

FreeRDP是一款开源专用于RDP远程协议的软件,Remmina也是他们的产品

FreeRDP支持的配置非常详细,Remmina的RDP插件也是基于FreeRDP实现的,所以才有非常丰富的配置选项

Bash
❯ xfreerdp -h                                                                 ~
[14:45:40:678] [200347:200347] [ERROR][com.winpr.commandline] - Failed at index 1 [-h]: Missing value

FreeRDP - A Free Remote Desktop Protocol Implementation
See www.freerdp.com for more information

Usage: xfreerdp [file] [options] [/v:<server>[:port]]

Syntax:
    /flag (enables flag)
    /option:<value> (specifies option with value)
    +toggle -toggle (enables or disables toggle, where '/' is a synonym of '+')

    /a:<addin>[,<options>]            Addin
    /action-script:<file-name>        Action script
    /admin                            Admin (or console) session
    +aero                             Enable desktop composition
    /app:<path> or ||<alias>          Remote application program
    /app-cmd:<parameters>             Remote application command-line parameters
    /app-file:<file-name>             File to open with remote application
    /app-guid:<app-guid>              Remote application GUID
    /app-icon:<icon-path>             Remote application icon for user interface
    /app-name:<app-name>              Remote application name for user interface
    /app-workdir:<workspace path>     Remote application workspace path
    /assistance:<password>            Remote assistance password
    /auto-request-control             Automatically request remote assistance
                                      input control
    +async-channels                   Enable Asynchronous channels
                                      (experimental)
    +async-input                      Enable Asynchronous input
    +async-update                     Enable Asynchronous update
    /audio-mode:<mode>                Audio output mode
    +auth-only                        Enable Authenticate only
    -authentication                   Disable Authentication (experimental)
    +auto-reconnect                   Enable Automatic reconnection
    /auto-reconnect-max-retries:<retries>
                                      Automatic reconnection maximum retries, 0
                                      for unlimited [0,1000]
    +bitmap-cache                     Enable bitmap cache
    /bpp:<depth>                      Session bpp (color depth)
    /buildconfig                      Print the build configuration
    /cert:[deny,ignore,name:<name>,tofu,fingerprint:<hash>:<hash as hex>
          [,fingerprint:<hash>:<another hash>]]
                                      Certificate accept options. Use with care!
                                      * deny         ... Automatically abort
                                      connection if the certificate does not
                                      match, no user interaction.           *
                                      ignore       ... Ignore the certificate
                                      checks altogether (overrules all other
                                      options)                           * name 
                                             ... Use the alternate <name>
                                      instead of the certificate subject to
                                      match locally stored certificates * tofu  
                                            ... Accept certificate
                                      unconditionally on first connect and deny
                                      on subsequent connections if the
                                      certificate does not match * fingerprints
                                      ... A list of certificate hashes that are
                                      accepted unconditionally for a connection
    /cert-deny                        [deprecated, use /cert:deny] Automatically
                                      abort connection for any certificate that
                                      can not be validated.
    /cert-ignore                      [deprecated, use /cert:ignore] Ignore
                                      certificate
    /cert-name:<name>                 [deprecated, use /cert:name:<name>]
                                      Certificate name
    /cert-tofu                        [deprecated, use /cert:tofu] Automatically
                                      accept certificate on first connect
    /client-build-number:<number>     Client Build Number sent to server
                                      (influences smartcard behaviour, see
                                      [MS-RDPESC])
    /client-hostname:<name>           Client Hostname to send to server
    -clipboard[:[use-selection:<atom>]]
                                      Disable Redirect clipboard.                       
                                      * use-selection:<atom>  ... (X11) Specify
                                      which X selection to access. Default is
                                      CLIPBOARD. PRIMARY is the X-style
                                      middle-click selection.
    /codec-cache:[rfx|nsc|jpeg]       Bitmap codec cache
    -compression                      Disable compression
    /compression-level:<level>        Compression level (0,1,2)
    +credentials-delegation           Enable credentials delegation
    /d:<domain>                       Domain
    -decorations                      Disable Window decorations
    /disp                             Display control
    /drive:<name>,<path>              Redirect directory <path> as named share
                                      <name>. Hotplug support is enabled with
                                      /drive:hotplug,*. This argument provides
                                      the same function as "Drives that I plug
                                      in later" option in MSTSC.
    +drives                           Enable Redirect all mount points as shares
    /dvc:<channel>[,<options>]        Dynamic virtual channel
    /dynamic-resolution               Send resolution updates when the window is
                                      resized
    /echo                             Echo channel
    -encryption                       Disable Encryption (experimental)
    /encryption-methods:[40,][56,][128,][FIPS]
                                      RDP standard security encryption methods
    /f                                Fullscreen mode (<Ctrl>+<Alt>+<Enter>
                                      toggles fullscreen)
    -fast-path                        Disable fast-path input/output
    +fipsmode                         Enable FIPS mode
    /floatbar[:sticky:[on|off],default:[visible|hidden],show:
               [always|fullscreen||window]]
                                      floatbar is disabled by default (when
                                      enabled defaults to sticky in fullscreen
                                      mode)
    -fonts                            Disable smooth fonts (ClearType)
    /frame-ack:<number>               Number of frame acknowledgement
    /from-stdin[:force]               Read credentials from stdin. With <force>
                                      the prompt is done before connection,
                                      otherwise on server request.
    /g:<gateway>[:<port>]             Gateway Hostname
    /gateway-usage-method:[direct|detect]
                                      Gateway usage method
    /gd:<domain>                      Gateway domain
    /gdi:sw|hw                        GDI rendering
    /geometry                         Geometry tracking channel
    +gestures                         Enable Consume multitouch input locally
    /gfx[:[[RFX|AVC420|AVC444],mask:<value>]]
                                      RDP8 graphics pipeline
    /gfx-h264[:[[AVC420|AVC444],mask:<value>] 
               [DEPRECATED] use /gfx:avc420 instead]
                                      RDP8.1 graphics pipeline using H264 codec
    +gfx-progressive                  Enable RDP8 graphics pipeline using progressive
                                      codec
    +gfx-small-cache                  Enable RDP8 graphics pipeline using small cache
                                      mode
    +gfx-thin-client                  Enable RDP8 graphics pipeline using thin client
                                      mode
    +glyph-cache                      Enable Glyph cache (experimental)
    /gp:<password>                    Gateway password
    -grab-keyboard                    Disable Grab keyboard
    -grab-mouse                       Disable Grab mouse
    /gt:[rpc|http|auto]               Gateway transport type
    /gu:[[<domain>\]<user>|<user>[@<domain>]]
                                      Gateway username
    /gat:<access token>               Gateway Access Token
    /h:<height>                       Height
    -heartbeat                        Disable Support heartbeat PDUs
    /help                             Print help
    +home-drive                       Enable Redirect user home as share
    /ipv6                             Prefer IPv6 AAA record over IPv4 A record
    /kbd:0x<id> or <name>             Keyboard layout
    /kbd-lang:0x<id>                  Keyboard active language identifier
    /kbd-fn-key:<value>               Function key value
    /kbd-list                         List keyboard layouts
    /kbd-lang-list                    List keyboard languages
    /kbd-remap:List of <key>=<value>,... pairs to remap scancodes
                                      Keyboard scancode remapping
    /kbd-subtype:<id>                 Keyboard subtype
    /kbd-type:<id>                    Keyboard type
    /load-balance-info:<info-string>  Load balance info
    /log-filters:<tag>:<level>[,<tag>:<level>[,...]]
                                      Set logger filters, see wLog(7) for
                                      details
    /log-level:[OFF|FATAL|ERROR|WARN|INFO|DEBUG|TRACE]
                                      Set the default log level, see wLog(7) for
                                      details
    /max-fast-path-size:<size>        Specify maximum fast-path update size
    /max-loop-time:<time>             Specify maximum time in milliseconds spend
                                      treating packets
    +menu-anims                       Enable menu animations
    /microphone[:[sys:<sys>,][dev:<dev>,][format:<format>,][rate:<rate>,]
                 [channel:<channel>]] Audio input (microphone)
    /monitor-list                     List detected monitors
    /monitors:<id>[,<id>[,...]]       Select monitors to use
    -mouse-motion                     Disable Send mouse motion
    /multimon[:force]                 Use multiple monitors
    +multitouch                       Enable Redirect multitouch input
    +multitransport                   Enable Support multitransport protocol
    -nego                             Disable protocol security negotiation
    /network:[modem|broadband|broadband-low|broadband-high|wan|lan|auto]
                                      Network connection type
    /nsc                              NSCodec support
    +offscreen-cache                  Enable offscreen bitmap cache
    /orientation:[0|90|180|270]       Orientation of display in degrees
    +old-license                      Enable Use the old license workflow (no CAL and
                                      hwId set to 0)
    /p:<password>                     Password
    /parallel[:<name>[,<path>]]       Redirect parallel device
    /parent-window:<window-id>        Parent window id
    +password-is-pin                  Enable Use smart card authentication with
                                      password as smart card PIN
    /pcb:<blob>                       Preconnection Blob
    /pcid:<id>                        Preconnection Id
    /pheight:<height>                 Physical height of display (in
                                      millimeters)
    /play-rfx:<pcap-file>             Replay rfx pcap file
    /port:<number>                    Server port
    -suppress-output                  Disable suppress output when minimized
    +print-reconnect-cookie           Enable Print base64 reconnect cookie after
                                      connecting
    /printer[:<name>[,<driver>]]      Redirect printer device
    /proxy:[<proto>://][<user>:<password>@]<host>:<port>
                                      Proxy settings: override env. var (see
                                      also environment variable below). Protocol
                                      "socks5" should be given explicitly where
                                      "http" is default.
    /pth:<password-hash>              Pass the hash (restricted admin mode)
    /pwidth:<width>                   Physical width of display (in millimeters)
    /rdp2tcp:<executable path[:arg...]>
                                      TCP redirection
    /reconnect-cookie:<base64-cookie> Pass base64 reconnect cookie to the
                                      connection
    /redirect-prefer:<FQDN|IP|NETBIOS>,[...]
                                      Override the preferred redirection order
    /relax-order-checks               Do not check if a RDP order was announced
                                      during capability exchange, only use when
                                      connecting to a buggy server
    /restricted-admin                 Restricted admin mode
    /rfx                              RemoteFX
    /rfx-mode:[image|video]           RemoteFX mode
    /scale:[100|140|180]              Scaling factor of the display
    /scale-desktop:<percentage>       Scaling factor for desktop applications
                                      (value between 100 and 500)
    /scale-device:100|140|180         Scaling factor for app store applications
    /sec:[rdp|tls|nla|ext]            Force specific protocol security
    +sec-ext                          Enable NLA extended protocol security
    -sec-nla                          Disable NLA protocol security
    -sec-rdp                          Disable RDP protocol security
    -sec-tls                          Disable TLS protocol security
    /serial[:<name>[,<path>[,<driver>[,permissive]]]]
                                      Redirect serial device
    /shell:<shell>                    Alternate shell
    /shell-dir:<dir>                  Shell working directory
    /size:<width>x<height> or <percent>%[wh]
                                      Screen size
    /smart-sizing[:<width>x<height>]  Scale remote desktop to window size
    /smartcard[:<str>[,<str>...]]     Redirect the smartcard devices containing
                                      any of the <str> in their names.
    /smartcard-logon                  Activates Smartcard Logon authentication.
                                      (EXPERIMENTAL: NLA not supported)
    /sound[:[sys:<sys>,][dev:<dev>,][format:<format>,][rate:<rate>,]
            [channel:<channel>,][latency:<latency>,][quality:<quality>]]
                                      Audio output (sound)
    /span                             Span screen over multiple monitors
    /spn-class:<service-class>        SPN authentication service class
    /ssh-agent                        SSH Agent forwarding channel
    /t:<title>                        Window title
    -themes                           Disable themes
    /timeout:<time in ms>             Advanced setting for high latency links:
                                      Adjust connection timeout, use if you
                                      encounter timeout failures with your
                                      connection
    /tls-ciphers:[netmon|ma|ciphers]  Allowed TLS ciphers
    /tls-seclevel:<level>             TLS security level - defaults to 1
    -toggle-fullscreen                Disable Alt+Ctrl+Enter to toggle
                                      fullscreen
    /tune:<setting:value>,<setting:value>
                                      [experimental] directly manipulate freerdp
                                      settings, use with extreme caution!
    /tune-list                        Print options allowed for /tune
    /u:[[<domain>\]<user>|<user>[@<domain>]]
                                      Username
    +unmap-buttons                    Enable Let server see real physical pointer
                                      button
    /usb:[dbg,][id:<vid>:<pid>#...,][addr:<bus>:<addr>#...,][auto]
                                      Redirect USB device
    /v:<server>[:port]                Server hostname
    /vc:<channel>[,<options>]         Static virtual channel
    /version                          Print version
    /video                            Video optimized remoting channel
    /vmconnect[:<vmid>]               Hyper-V console (use port 2179, disable
                                      negotiation)
    /w:<width>                        Width
    -wallpaper                        Disable wallpaper
    +window-drag                      Enable full window drag
    /window-position:<xpos>x<ypos>    window position
    /wm-class:<class-name>            Set the WM_CLASS hint for the window
                                      instance
    /workarea                         Use available work area

Examples:
    xfreerdp connection.rdp /p:Pwd123! /f
    xfreerdp /u:CONTOSO\JohnDoe /p:Pwd123! /v:rdp.contoso.com
    xfreerdp /u:JohnDoe /p:Pwd123! /w:1366 /h:768 /v:192.168.1.100:4489
    xfreerdp /u:JohnDoe /p:Pwd123! /vmconnect:C824F53E-95D2-46C6-9A18-23A5BB403532 /v:192.168.1.100

Clipboard Redirection: +clipboard

Drive Redirection: /drive:home,/home/user
Smartcard Redirection: /smartcard:<device>
Serial Port Redirection: /serial:<name>,<device>,[SerCx2|SerCx|Serial],[permissive]
Serial Port Redirection: /serial:COM1,/dev/ttyS0
Parallel Port Redirection: /parallel:<name>,<device>
Printer Redirection: /printer:<device>,<driver>
TCP redirection: /rdp2tcp:/usr/bin/rdp2tcp

Audio Output Redirection: /sound:sys:oss,dev:1,format:1
Audio Output Redirection: /sound:sys:alsa
Audio Input Redirection: /microphone:sys:oss,dev:1,format:1
Audio Input Redirection: /microphone:sys:alsa

Multimedia Redirection: /video
USB Device Redirection: /usb:id:054c:0268#4669:6e6b,addr:04:0c

For Gateways, the https_proxy environment variable is respected:
    export https_proxy=http://proxy.contoso.com:3128/
    xfreerdp /g:rdp.contoso.com ...

More documentation is coming, in the meantime consult source files

简单的使用例子

Bash
xfreerdp /v:10.0.0.3 /u:chancelUser /p:"chancelPasswd" /size:1920x1080 /audio-mode:0

参数解释

  • /audio-mode: 0表示本机播放,1表示远程机器播放
  • /size: 分辨率
  • /v: 远程地址

FreeRDP在我机器Gnome3的桌面环境下表现良好

  • 默认非常优秀的清晰画面
  • 支持音频传输到本机播放
  • 支持文字复制粘贴

将远程的命令注册成全局快捷键,如Ctrl+Alt+1,远程桌面体验极其舒服

3. 结束语

上面列出的4种方案各有优缺,根据不同使用场景自行选择试用,适合就是最好的

但远程体验还是有一个非常不爽的地方,就是图片的复制问题

我发现在Gnome3上很多截图软件都无效,甚至于自带的Gnome3-Screentshot截图到粘贴版也有很大的问题

不过对于图片的截图使用比较少,后续再慢慢检查下具体是什么原因吧


[[replyMessage== null?"发表评论":"发表评论 @ " + replyMessage.m_author]]

account_circle
email
web_asset
textsms

评论列表([[messageResponse.total]])

还没有可以显示的留言...
gravatar
[[messageItem.m_author]] [[messageItem.m_author]]
[[messageItem.create_time]]
[[getEnviron(messageItem.m_environ)]]
[[subMessage.m_author]] [[subMessage.m_author]] @ [[subMessage.parent_message.m_author]] [[subMessage.parent_message.m_author]]
[[subMessage.create_time]]
[[getEnviron(messageItem.m_environ)]]