Updated 2011-12-14 15:42:38 by APN

The Tcl Windows API (TWAPI) extension project provides direct and high level access to Win32 API's on Windows NT platforms (Windows 2000 and later). The TWAPI home page is at http://twapi.magicsplat.com/ .

Note: To make them easier to track, please log bugs at the bug tracker, not here.

News edit

2011/12/14: TWAPI 3.1.17 is now officially released and can be downloaded from the Current Releases [1] folder on sourceforge.

2011/06/22: TWAPI 3.0.32 update released for 3.0.

2010/10/31: A security update for TWAPI 2.2 is available. See [2] for details.

Overview edit

TWAPI implements commands in the following areas:

  • System functions including OS and processor information, shutdown, message formatting
  • User and group management
  • Security and resource access control
  • Window management - window attributes, position, size etc.
  • User input: generation of key/mouse input and hotkey support
  • Basic sound playback functions
  • Windows services
  • Windows event log access
  • Process and thread management
  • Directory change monitoring
  • Windows file and print network shares
  • Named pipe channels
  • Drive information, file system types etc.
  • Network configuration and statistics
  • Connection control and name lookups
  • Clipboard access and monitoring
  • Console mode functions for changing attributes, titles, screen buffers etc.
  • System performance data
  • Window stations and desktops
  • Internationalization
  • Task scheduling
  • Printer management
  • Shell property dialogs, shortcuts and themes
  • Taskbar icons and notifications
  • Windows resource manipulation
  • TWAPI COM support
  • Device notifications (e.g. USB device insertion)
  • Crypto/SSPI interfaces
  • Windows Installer interfaces
  • Power management

Support edit

The TWAPI project page is at sourceforge.

I do not always notice changes to this wiki page so please use the above links.

Obtaining sources edit

TWAPI Alternatives edit

Ffidl also provides access to the Win32 API along with other platforms. Comparing TWAPI and Ffidl on Windows compares it with TWAPI.

Any idea how TWAPI compares with http://zazu.maxwell.syr.edu/nt-tcl/ ?

I would definitely favor TWAPI as it is much newer and in active development. I have used a few parts of the nt-tcl package and it worked fine for me at the time (4 years ago). So I would use TWAPI exclusively and fall back to nt-tcl if there was no alternative. RT 11Apr2005

General discussion edit

RT Just wondering if there's a Win32 call available to learn the cluster size of an NTFS volume. This would let a Tcl program calculate a more accurate space usage for a given set of files. The volume info available in 0.5 doesn't seem to cover that. BTW, thanks for removing external package dependencies in 0.5 :^) - Roy 25Jan2005

APN Could not find where the cluster size info is available. I'm not sure it would even help you estimate the true size since NTFS supports sparse files.

RT I just found on XP that the new native command fsutil can give this (and many more answers). Usage is like:
    fsutil fsinfo ntfsinfo c:

and that yields a nice size chunk of informative information easily parsed. Don't know if this tool can be found on w2000, it's not on my 2k.

To construct twapi arguments programmatically, use eval.

For example, the windows command "netstat -a -o 5" will display network status update every 5 seconds

The twapi create_process command can also launch this process.
  # twapi requires full path for program files
  set nsfile [file join $::env(windir) system32 netstat.exe]
  set opts [list -cmdline "-a -o 5"]
  set e [catch {eval twapi::create_process $nsfile $opts} result]

Lars H: Won't that break if $nsfile contains spaces? The following should be more quoting safe:
  set cmd twapi::create_process
  lappend cmd [file join $::env(windir) system32 netstat.exe]
  lappend cmd -cmdline "-a -o 5"
  set e [catch $cmd result]

RLH; You may be right but I have not had any problems doing it set nsfile [file join $::env(windir) system32 netstat.exe] and I definitely had spaces in my path names.

Lars H: Yes, the "set nsfile" part should be OK. I'd expect problems though when such an $nsfile is subjected to eval. Since that eval is the point that is stressed in the advice, it would be extra severe if it is wrong. Is there a reason for constructing the twapi::create_process options programmatically? Isn't it more likely that the options for the process need to be constructed programmatically?

escargo 20 May 2005 - I was looking at how to access functions that seem to be part of Windows Server 2003. I don't know if they are not part of the TWAPI range or not (I suspect not), but I thought I would ask. The particular functions have to do with "rescan disks," which is part of the Disk Manager. If TWAPI won't allow me to access those functions, is there another Tcl way to do it?

escargo 7 Jun 2005 - Looking for unformatted partitions is exactly what I want. I'm working with some programs that do device I/O, not file I/O, so raw devices are exactly what I must find. Let me know if I can help with testing.

APN 2008-06-25 - Finally, only three years later, TWAPI has device io support. In 2.0.10 you can use get_physical_disk_info and find_physical_disks in combination to do the above. The whole device management stuff on Win32 is rather arcane (to me anyways), and it took a while to get motivated enough to get it done.

male 2007-11-20 - May I ask APN how you use create_process to start a process with a different user? (kind of runas) APN 2008-06-25 - Sorry for the late response! But did not notice the question before. See [3] for an example but there are other samples you could google as well. I believe TWAPI has all the requisite raw Win32 calls (as of 2.0.10) but have not put together a complete ready-to-go implementation yet.

escargo 21 Sep 2005 - Can TWAPI be used to inspect the Running Object Table (ROT)?

APN No, I don't think so. There aren't any COM interfaces in TWAPI since I assumed you would be much better off using the TCOM extension for COM-related stuff.

escargo - From what I read about ROT, it identifies objects, not their COM interfaces. So you need to know what the objects are before you can use tcom on them. Since the ROT is part of system state, it seemed like TWAPI would an appropriate way to access it. (See the sample code at the link on the ROT page.)

escargo 10 Mar 2006 - Can TWAPI be used to read and write to raw disk devices (unformatted disks without partitions)?

APN No. Looking at the SDK, it looks like a job for DeviceIOControl but seems non-trivial, particularly for testing. Possibly one could also just call WriteFile after opening the raw device \\.\PhysicalDriveN using CreateFile. I'm afraid of trying something like this on my single development machine and trashing it!

Alastair Davies asks if there is an API to configure wireless networking? For example, I would like to obtain a list of available wireless networks, and to connect to one. I would not be surprised if this were quite straight-forward, in Windows XP at least.

APN You might want to look at WRAPI [4] but you would have to write a Tcl binding for that.

LV June 05, 2006: sure would be useful if this extension became a part of ActiveTcl!

APN 20110212: I believe TWAPI is now available via teapot though there might be a version skew.

MHo: It would be nice if there where some way to register an event source to avoid such stupid error messages within eventvwr.exe. APN Yes it would be nice but I'm not sure how. AFAIK, to register an event source requires a resource in a DLL or other file. So the messages would have to be "bound" to the resource. You could do this with a resource compiler but then you would not need TWAPI. Or am I missing something? MHo That's right. Perhaps the necessary minimal resources/definitions could be build right into twapi.dll. I don't know exactly how to do event source registration by myself (with ms api's this is not uncommon.... smile ;-). No, it can't be built into twapi. Let's say your application wants to log a message "Danger, Danger! Resource do-hickey running low!". That message has to be in some resource, but obviously it can't be in twapi.dll which knows nothing about the application errors. The only way would be to create a resource file on the fly on the target system and that's just too much work. MHo Hm.... The actually message itself sure comes from the caller at runtime; what's missing is the registration of twapi as a valid event source... sure twapi cannot conatin application specific things... As an example, me as a tcl programmer can write generic messages to the eventlog through means of Winserv or tclsvc...APN It's not enough to register twapi.dll as a valid event source. It has to actually contain a valid resource string for the message logged as well. Just registering it will not make the message go away.

neb 2010/09/01: Here's a proc that I wrote for that. It won't register your library, but it will shanghai somebody else's. appmgmts.dll should exist on any XP-class machine, and event 401 has a message string of "%1"; which means it will just replace the whole thing with your message.

This proc uses twapi, and checks for a registration of $src. If it doesn't exist, it rigsters it to the app managements string library. Upshot is that you no longer get the disclaimer. HTH
 proc logevent {msg {type information} {eventid 401} {src "My Default Source Here"}} {
         package require registry
         package require twapi

         if [catch {set h [registry keys HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Eventlog\\Application $src]}] {
                 puts "Big registry troubles! Eventlog Applications appear to be missing!" error
         } elseif {![string length $h]} {
                 puts "$src not found. Writing it."
                 registry set HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Eventlog\\Application\\$src EventMessageFile %SYSTEMROOT%\\system32\\appmgmts.dll expand_sz
                 registry set HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Eventlog\\Application\\$src TypesSupported 31 dword
         }

         if !$eventid {set eventid 401}
         #::twapi::eventlog_log $msg -source $src -type $type -category $eventid
         set h [::twapi::eventlog_open -source $src -write]
         ::twapi::eventlog_write $h $eventid -type $type -category 0 -loguser -params [list $msg]
         ::twapi::eventlog_close $h
 }

For an example of how to use TWAPI to 'draw' in MS Paint, see Using TWAPI with MS Paint.

MHo 2007-10-25: Just a thought: often I only need one or two API-Calls in my tools, which are typically delivered as starpacks. But because TWAPI has become such a big package, my .EXEs grow accordingly. Perhaps it would be better to split up or group the APIs into several separate DLLs...? (We have no intelligent link step which removes unused code...). APN I have often thought of doing this, but the burden of testing separate packages, test suites etc. is more work than I have time for. Currently, twapi.kit is under 300K so it is not a huge bloat for distribution. One alternative you might consider if size is an issue and you only use a few functions is either ffidl or winapi which is layered on top of it. APN As of the 2.1.6 release, TWAPI can be built as a server-only or desktop-only subset. The savings are marginal (server kit is around 100K v/s 300K for the full version) but if you really want, you can build it.

male 2008-10-01: Here one sample of manipulating a Windows message box using TWAPI ... countdownMsgBox

MHo 2009-02-20: I noticed that get_global_group_members does not give back members if that group only contains other groups (that is, no "direct members"). So which way I could perform a recursive resolution of all computers downwards from a given OU? That's the same behaviour as with NET GROUP, indeed. With some complicated combinations of DSQUERY and DSGET I'm not satisfied after hours and thought tcl and twapi could help... APN Do the ADSI COM interfaces not provide any help here?

[no-ids] 2010-04-21: I see that there is a new function called impersonate. Do you have an example of exactly what it does or how to use it? Background: Under certain conditions, I would like to launch my script under a different user than the one logged in. Would it help in this case? APN No. The impersonate_user command impersonates the user in the *current* thread which is not what you want to do (which is create a new process under a different user). You could use the CreateProcessAsUser call but unfortunately matters are not so simple. You need to additional create an appropriate context by loading appropriate registry hives etc. in the new process. That stuff is not encapsulated yet in TWAPI, mainly because exactly how to do it is somewhat murky and not well documented.

[ssing] - 2010-12-22 03:24:00

twapi miss the target when current window is lock or RDP session is in minimize mode.

let me explain it more, I am creating a process via twapi, then a login window appear, I am setting that as a forground window and then sending the credential, problem is that when I run the test & lock the window(local system) or I am running the same test in RDP session & I minimize the RDP session, it will not find out the window with specific text ans unable to set the window as forground and exit with error "Invalid pointer or opaque value: ''."

APN This is not a bug per se. What is unsaid in the documentation, because it is implicitly assumed to be known is that Windows does not allow processes in one desktop session to retrieve information or send messages to windows in another desktop session. That is a Windows security feature and AFAIK there is no way around it. If I misunderstand or if you have reason to believe it is possible, please let me know and I'll investigate further. The specific error you are getting is because you are passing an empty string (returned by find_windows when no window is found) to the set_foreground_window command.

[ssing] - 2010-12-22 06:09:23

Correct,

But in the above problem I am not sending information from one desktop to other, both the above (RDP & local) are two diffferent scenario where I encounter this issue. The thing is I am running test on my local system & I locked the system it fails because it will not identified the login window but on the other hand if the system is unlock it will identify the login window and proceed further. RDP is different scenario, it's when I am runing my whole test from remote machine(provided whole env. is there), RDP session session is just to watch how test is going, If I have a watch on the session It will pass, say I minimize the RDP session window it will fail.

The thing why I am saying this most of the record & play tool used for gui regression test have this feature as they keeps on running test ALAR.

APN Sorry, still not sure exactly what the scenario is. For the moment, let us ignore RDP. For the login case, here is what I did - I set up a continuous loop that every second would do a find_windows using -text and then being that window to the foreground using set_foreground_window. I then locked the system (switch user screen) and logged back in. The loop was running while locked out and after logging in. So it all seems to work. I assume what I did is different from what you are doing. Can you provide a script (smaller the better) that demonstrates the problem, or provide more detail as to the exact scenario? When you way it does not identify the login window, which window are you referring to ? What text and other command options are you using to identify this window?

[ssing] - 2010-12-22 08:00:00

gui login

sorry about recent changes , it was unintentionally.

[ssingh] - 2010-12-23 03:22:29

It seems when the desktop is locked, "twapi::set_foreground_window $win" returns 0, and if the desktop is unlocked it returns 1. can we avoid this?

APN Sorry about the delayed response (holidays and other stuff). Regarding set_foreground_window - that command is a direct call to SetForegroundWindow Win32 API so it is what it is. Also, regarding the original issue, I wrote a small C program to enumerate all windows to verify what twapi is returning as the window list. The results are identical to what twapi returns with and without the login screen. So the only possibility is that either Windows is creating your app window "lazily" (meaning it is only created when it needs to be displayed which would be after the login screen is removed), or something else is going on with you app.

MHo 2011-02-11 - A tip regarding services: every path specification should be an absolut path, sind relative paths do not work with services... something I alway forget, running into trouble again and again...

MHo 2011-02-18 - What´s this: (1)
C:\Dokumente und Einstellungen\Hoffmann>tclsh
% package require twapi;namespace import twapi::*
% comobj
invalid command name "comobj"
% twapi::comobj
wrong # args: should be "twapi::comobj comid ..."
%

APN For reasons lost in the mists of time, you have to explicitly call twapi::import_commands.
package require twapi ; twapi::import_commands
comobj ....

(2) And what's wrong here? APN Added as bug 318593 comobj -iterator fails for some objects on sourceforge.

APN No idea, need to look at it. TWAPI 2.2 fails similarly. As a workaround you can loop explicitly.
(tcl) 53 % set n [$oApps Count]
5
(tcl) 54 % for {set i 0} {$i < $n} {incr i} {set oApp [$oApps Item $i] ; puts [$oApp Name] ; $oApp -destroy}
COM+ Utilities
COM+ QC Dead Letter Queue Listener
COM+ Explorer
MS Software Shadow Copy Provider
System Application
(tcl) 55 % 

MHo: Yes, that's exactly what I've done...

APN Fixed in SF repo for 3.1.

[ssing]Is there any functionality present in twapi like "psexec.exe" do. I mean can we start a remote process with the help of twapi. APN psexec is an application/program. TWAPI is a library. I believe TWAPI contains all the Win32 functionality you would need to write a program like psexec but it is non-trivial. See the bottom of [5] for an outline of how psexec is implemented. You would need to do the same things using TWAPI.

MHo 2011-12-11: Are there any plans to facilitate more console API functions like ReadConsoleOutput? Otherwise it would be hard (or impossible) to use them as the basis for a console mode window manager (what I really need is an up-to-date CTk, but there's no). APN Not likely any time soon. I am about to release a new version, after which it's unlikely I will have much time to work on TWAPI. And what little time I have will be spent on other more important features.