RandomGuest Posted August 14, 2007 Share Posted August 14, 2007 (edited) Is the "AutoIt v3" window necessary?It's created and hidden every time my scripts start, comprising of a text area, presumably for debug output.This'll reveal it:WinSetState("AutoIt v3", "", @SW_SHOW)Question: Is it possible to prevent the hidden window from being created, or to destroy it without exiting my script?I stumbled across this when I was writing an app, spawned by a service, that moves between desktops.It appears on Winsta0\Winlogon if no one's logged in, or Winsta0\Default if someone is.It can get the handle to the Station Winsta0, and if run as localsystem, it can even get the handle to Winlogon, (the welcome screen).But it can't bind to the new desktop if it has a window open (GetLastError returns 170: in use).The C source here works perfectly when spawned with localsystem credentials (service, schedule, psexec, etc...)http://didierstevens.wordpress.com/2006/08...ith-utilmanexe/For the curious, here's my AutoIt translation.expandcollapse popup;Disable the tray icon AutoItSetOption("TrayIconHide", 1) AutoItSetOption("TrayMenuMode", 1) Dim $station_opened = -1 Dim $desktop_opened = -1 Dim $result = "" Dim $flags = "" open_station() If ($station_opened <> -1) Then $result = DllCall('user32.dll', 'int', 'SetProcessWindowStation', 'hwnd', $station_opened) If (@error = 0 AND $result[0] <> 0) Then MsgBox(4096, "Test", "Opened station.") EndIf If ($station_opened <> -1) Then open_desktop() If ($desktop_opened <> -1) Then ;This jumps to the chosen desktop, so long as there aren't any windows on this one $result = DllCall('user32.dll', 'int', 'SetThreadDesktop', 'hwnd', $desktop_opened) If (@error = 0 AND $result[0] <> 0) Then MsgBox(4096, "Test", "Opened desktop.") Else $result = DllCall('Kernel32.dll', 'int', 'GetLastError') MsgBox(4096, "Test", "Failed to switch desktops: " & $result[0]) EndIf EndIf EndIf close_desktop() close_station() ;---------------- Func open_station() ;This comes out to 895 $flags = BitOR(4,32,8,1,256,64,2,512,16) ;WINSTA_ACCESSCLIPBOARD 4 ;WINSTA_ACCESSGLOBALATOMS 32 ;WINSTA_CREATEDESKTOP 8 ;WINSTA_ENUMDESKTOPS 1 ;WINSTA_ENUMERATE 256 ;WINSTA_EXITWINDOWS 64 ;WINSTA_READATTRIBUTES 2 ;WINSTA_READSCREEN 512 ;WINSTA_WRITEATTRIBUTES 16 ;OpenWindowStation gets the handle to the primary display $result = DllCall('user32.dll', 'hwnd', 'OpenWindowStation', 'str', 'WinSta0', 'int', 1, 'int', $flags) If (@error = 0 AND $result[0] <> 0) Then $station_opened = $result[0] EndFunc Func open_desktop() ;This comes out to 511 $flags = BitOR(4,2,64,8,32,16,1,256,128) ;DESKTOP_CREATEMENU 4 ;DESKTOP_CREATEWINDOW 2 ;DESKTOP_ENUMERATE 64 ;DESKTOP_HOOKCONTROL 8 ;DESKTOP_JOURNALPLAYBACK 32 ;DESKTOP_JOURNALRECORD 16 ;DESKTOP_READOBJECTS 1 ;DESKTOP_SWITCHDESKTOP 256 ;DESKTOP_WRITEOBJECTS 128 ;Comment/Uncomment one of these dllcalls... ;OpenDesktop gets a specific virtual desktop: Default (where explorer lives) or Winlogon (Welcome screen) ;$result = DllCall('user32.dll', 'hwnd', 'OpenDesktop', 'str', 'Default', 'int', 0, 'int', 0, 'int', $flags) ;OpenInputDesktop gets whatever desktop is in use $result = DllCall('user32.dll', 'hwnd', 'OpenInputDesktop', 'int', 0, 'int', 0, 'int', $flags) If (@error = 0 AND $result[0] <> 0) Then $desktop_opened = $result[0] EndFunc Func close_desktop() If ($desktop_opened <> -1) Then MsgBox(4096, "Test", "Closing desktop handle (" & $desktop_opened & ")...") DllCall('user32.dll', 'none', 'CloseWindowStation', 'hwnd', $desktop_opened) EndIf EndFunc Func close_station() If ($station_opened <> -1) Then MsgBox(4096, "Test", "Closing station handle (" & $station_opened & ")...") DllCall('user32.dll', 'none', 'CloseWindowStation', 'hwnd', $station_opened) EndIf EndFuncYeah I can, and probably will, put the desktop code in the launcher service.Having a window I didn't create myself irks me. And with callbacks, it's nearly possible to make an AutoIt service...This is my favorite example of a C service; just add a payload. http://www.muukka.net/programming/service.htmlBTW I haven't tried, but it's entirely possible that once an AutoIt script is running on the Winlogon desktop, it could get the controls of the user/pass textfields and automate logins! Edited August 14, 2007 by RandomGuest Link to comment Share on other sites More sharing options...
Mast3rpyr0 Posted August 14, 2007 Share Posted August 14, 2007 Thats a neet find, ive never seen it before but it still comes up with the winsetstate() thing. Maybe you can try the winkill() or winclose() functions? My UDF's : _INetUpdateCheck() My Programs : GameLauncher vAlpha, InfoCrypt, WindowDesigner, ScreenCap, DailyRemindersPick3GeneratorBackupUtility! Other : Bored? Click Here! Link to comment Share on other sites More sharing options...
RandomGuest Posted August 14, 2007 Author Share Posted August 14, 2007 (edited) Maybe you can try the winkill() or winclose() functions?Nah. That'd be too easy. If the window gets a WM_CLOSE message, its internally coded to destroy and exit.Come to think of it, the tray icon's not really gone either, it's only hidden... Edited August 14, 2007 by RandomGuest Link to comment Share on other sites More sharing options...
Mast3rpyr0 Posted August 14, 2007 Share Posted August 14, 2007 Hmm your right. maybe report it as a bug or put in a request to remove it. My UDF's : _INetUpdateCheck() My Programs : GameLauncher vAlpha, InfoCrypt, WindowDesigner, ScreenCap, DailyRemindersPick3GeneratorBackupUtility! Other : Bored? Click Here! Link to comment Share on other sites More sharing options...
Moderators SmOke_N Posted August 14, 2007 Moderators Share Posted August 14, 2007 Hmm your right. maybe report it as a bug or put in a request to remove it.It's no bug, and likely to never get removed. Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer. Link to comment Share on other sites More sharing options...
Valuater Posted August 14, 2007 Share Posted August 14, 2007 Known window... per help $a = AutoItWinGetTitle() one use ; check if process already exists $g_szVersion = "My XP Cleaner" If WinExists($g_szVersion) Then MouseMove(500,5) MsgBox(262208, "* NOTE * ", "*XPClean Menu* was already running ", 5) SoundPlay ($Sound_lnk,1) Exit ; It's already running EndIf AutoItWinSetTitle($g_szVersion) 8) Link to comment Share on other sites More sharing options...
RandomGuest Posted August 14, 2007 Author Share Posted August 14, 2007 Known window... per helpIt's no bug, and likely to never get removed.I understand a number of scripts would break if that function were removed, but couldn't something like this be added the same way as the vista "#requireadmin" directive?#noAutoItWindow#noTray Link to comment Share on other sites More sharing options...
Moderators SmOke_N Posted August 14, 2007 Moderators Share Posted August 14, 2007 I understand a number of scripts would break if that function were removed, but couldn't something like this be added the same way as the vista "#requireadmin" directive?#noAutoItWindow#noTrayNo, I don't know exactly why it's added to be honest... if I had to guess... It's the interpreter's window... so I can't see it going away...It has a classname why not just port all class AutoIt v3 GUI along with what you need? Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer. Link to comment Share on other sites More sharing options...
RandomGuest Posted August 14, 2007 Author Share Posted August 14, 2007 (edited) It has a classname why not just port all class AutoIt v3 GUI along with what you need????If you mean move that window to the new desktop, GUI's can't move, and once a process creates its first GUI, the process is tied to that desktop.It's a MS limitation.I think if the GUI were destroyed, the process would be mobile again.If you mean write my app in another language, my app reads ini files, talks to the network, regex tests strings, spawns msg&input dialogs, and edits the registry.AutoIt does all those things very easily.And the only things stopping it from being able to jump to the Welcome screen, are the automatically generated window and tray.I've seen several requests for login automation. Switching desktops is the key to doing so (You can only find windows/controls within your current desktop).Removing the requirement that one compile a custom C service to spawn the script, would be a significant boon to AutoIt....and there are numerous requests to shed GUI altogether from the command-line guys.If you mean, fork AutoIt's source code to not include the GUI myself. That's a bit over my head. If you mean subclassing or something to override the window's destroy code with a func of my own... or a hook that keeps the script alive mid-closing?New territory. I'd need an example.I'm still hoping modifying the language won't be necessary and that there's a magic DllCall to destroy a window without closing it. ...GrrThe "#NoTrayIcon" directive does exist, but it only hides the tray? TraySetState(2) claims to 'Destroy/Hide' in the doc. Those are two very different actions. Typo? Edited August 15, 2007 by RandomGuest Link to comment Share on other sites More sharing options...
RandomGuest Posted August 15, 2007 Author Share Posted August 15, 2007 (edited) A double post, but a separate thought...In all the n00b C window examples I've seen in the past, there's been an indefinite loop that listens for and repeatedly runs a function that interprets window events with a switch statement.switch (message) { //Various events like WM_COMMAND for clicks... case (WM_CLOSE): //Something politely asked that this close //Offer to save work... //Tell user32.dll to deallocate this GUI DestroyWindow( this_windows_hwnd ); return 0; } case(WM_DESTROY): { //The user32.dll finished DestroyWindow() and sent a WM_DESTROY message //Or something rudely said die //Quit the application PostQuitMessage(0); } }For example, ctrl-alt-del to end a process first sends WM_CLOSE, waits a bit for the app and user32.dll to clean up and die on their own; then it sends WM_DESTROY if it still isn't dead.In either case, polite or rude, PostQuitMessage(0) executes and the app exits.I'd need to somehow call DestroyWindow() then intercept the WM_DESTROY that comes as a result.Intercepting all WM_DESTROYs would be bad practice. Or find a function that does the exact same thing as DestroyWindow() without sending the message at all. Like the dispose method in Java.If one were to edit the AutoIt source code, wrapping the PostQuitMessage() in an if statement checking a global var (maybe wrapping some of WM_CLOSE's case too, leaving the user32 call), and adding AutoItWinExitOnClose(boolean) would do the trick.;Hypothetical way to destroy the window without it exiting altogether AutoItWinExitOnClose(False) WinClose(AutoItWinGetTitle()) ;Reset the variable in case the window is miraculuosly recreated AutoItWinExitOnClose(True)Darn it. How can finding that method, recompiling the interpreter, be easier than finding than a non-invasive way? Of course, this approach assumes the window's initial creation can't be turned off with a directive, and that its absence later won't wreck anything.Edit, to avoid triple-posting:It's absence would indeed wreck things.Looking through the AutoIt source, I can see why they exist now.The tray icon's not a problem after all. "Hiding" the icon essentially deletes it, and "#NoTrayIcon" does, in fact, prevent it from being created.In other contexts, hide means setVisible(false), and destroy means erase from existence.Here it means remove the icon from the tray, and keep the struct that holds its state in case it gets put back later.The hidden window is the parent of everything so it can receive messages to/from the children and destroy them all.It'd take significant rewrite to remove that: making any new windows parentless and adding their handles to a global array with a means to remove themselves from the array when they're destroyed.I suggested a less extreme workaround patch in the bugs feature request forum. Feedback about it might appear there.http://www.autoitscript.com/forum/index.ph...345#entry388493Conclusion: Use a separate GUI-less launcher (scheduled utility or service), running as localsystem, that switches itself to an available desktop, then spawn your AutoIt app from it. Edited August 16, 2007 by RandomGuest Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now