Version 72 of Matthias Hoffmann - Tcl-Code-Snippets

Updated 2006-04-12 09:44:05

New stuff is organized into subpages...

netsend: sending short messages (Popups) across the Windows-Network


  • These messages apear on nt, w2k, xp-clients if the messenger service is started
  • On Win 3.x 9.x, the winpopup.exe-program must be loaded
  • On MS-DOS LAN-Manager clients, a similar program can be loaded
  • Because of the chaos in microsoft-APIs and some incompatability between os- and network-client versions and internal message-handling and capabilities, sending and receiving network-popups is not a reliable method to deliver important information: some users receive, some users don't, others incedently close the popup window and so on...
  • Messages can be send to a particular user, workstation, all Message Names (*) or a Domain (in other words: to adressable Netbios-Messagenames)
 package provide netsend 1.0
 package require Ffidl   0.5

 ffidl::callout dll_netSend {pointer-utf16 pointer-utf16 pointer-utf16 pointer-utf16 long} long \
                            [ffidl::symbol netapi32.dll NetMessageBufferSend]

 proc netSend {dest mesg {srv {}}} {
      set from $::tcl_platform(user)
      # or:
      # set from [info host]
      return [dll_netSend $srv $dest $from $mesg [expr [string length $mesg]*2]]


 package require netsend 1.0
 puts [netSend hoffmann "This is a Testmessage"]

bgexec: launches processes in background, catches output via fileevent-handler

See Matthias Hoffmann - Tcl-Code-Snippets - Misc - Bgexec for a new, less buggy but not yet translated version of bgexec.

Remarks: unfortunally, STDERR-CATCHing with 2>@ does't seems to work with Windows 2000...... For 8.4.7 and above, there is or will be a fix, see .

A simple ADSI-Example using tcom:

 proc logEvent {evtType args} {
    # ohne Fehlernachricht
    catch {
       set wsh [::tcom::ref createobject "WScript.Shell"]
       $wsh LogEvent $evtType "[regsub -all {\n} $args { - }]"

One more complicated example: return the available Windows-NT- and ADS-Domains and Workgroups as a list:

 proc GetDomains {} {
      set ret {}
      if [catch {::tcom::ref getobject "WinNT:"} d] then {
         return -code error "<getobject 'WinNT:'> failed: $d"
      } else {
         ::tcom::foreach domain $d {
                         if ![catch {::tcom::ref getobject [$domain ADsPath],domain}] {
                            set ct (Domain)
                         } else {
                            set ct (Workgroup)
                         lappend ret [list [$domain Name] $ct]
      return $ret

And another one: get the groups of a given container (that is, a Domain or Workgroup):

 proc GetGroups {container {contype domain}} {
      set ret {}
      # get Domain-/Computerobject
      if [catch {::tcom::ref getobject "WinNT://$container,$contype"} g] then {
         return -code error "<getobject 'WinNT://$container,$contype'> failed: $g"
      ::tcom::foreach m $g {
                      # instead of IF one can use a -filter here...
                      if {[$m Class] == "Group"} {
                         lappend ret [$m Name]
      return $ret

(contype can be domain or computer)

And finally get the users within such a group:

 ( be done...)


  • time to split this page into subpages to keep an overview of what's going on... - in progress meanwhile
  • More ADSI-Examples

Have you considered submitting these for inclusion in tcllib? M.H.: no, I think I haven't yet reached the required level of tcl-knowledge ...

Category Package