Jump to content

DaveF

Developers
  • Posts

    629
  • Joined

  • Last visited

1 Follower

About DaveF

  • Birthday 04/30/1966

Profile Information

  • Member Title
    Smells fanboyish.
  • Location
    Arkansas, USA

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

DaveF's Achievements

Universalist

Universalist (7/7)

0

Reputation

  1. My example is just calling Run in a way that give AutoIt the means to send input (with StdinWrite) to the child program that you'd normally provide by typing. I know that I kind of obfuscated things by throwing in the BitOR, but that really is the proper way to combine flag options for a function parameter. If you really feel that there's a bug we'd need to narrow it down to the closest versions that don't and do exhibit the problem, and come up with a kiss-of-death script that can replicate the problem without being tied to particular machines (i.e. your client and server PCs).
  2. I haven't been able to make this hopefully comparable test script break: #include "Constants.au3" $plink = @ProgramFilesDir & "\putty\plink.exe" $server = " user@ipaddress" $command_du = " cd home2; ls" Dim $STD_IN_AND_OUT = BitOR($STDIN_CHILD, $STDOUT_CHILD) $PID = Run ( $plink & $server & $command_du, @ScriptDir, @SW_HIDE, $STD_IN_AND_OUT ) dim $rawlist StdinWrite($PID, "asaNisiMasa" & @CRLF) While 1 $_ = StdoutRead($PID) If @error Then ExitLoop If @extended > 0 Then $rawlist = $rawlist & $_ EndIf WEnd MsgBox(0, "Debug", $rawlist) ...on a XPSP2 32bit VMWare test machine, using AutoIt3 v3.3.0.0 release, v3.3.4.0 release and v3.3.5.6 Beta, both uncompiled and compiled. LondonNDIB, when you said you were getting a "Unable to read from standard input: The handle is invalid." error, was that actually appearing in SciTE's results pane, correct? I'm guessing that since you have no password entry apparent in your example that you've got your PuTTY et al. environment configured to use keyfile authentication, but the references that I see on the Web to that Plink error indicate that it comes from Plink trying to read a password from STDIN when it isn't being provided by a parent program. Hope this helps.
  3. Some clarification into the way that StdoutRead and its relatives work: To human eyes it seems like a program that writes output to a console (e.g. to STDOUT) writes it all in one blurt, and even if it doesn't we'd tend to think that it was an artifact of the console window not drawing fast enough. In actuality, between program idiosyncrasies and the buffering process a program may send even a small amount of output in several writes, and even if you delay reading it you can't rely on a single read getting everything that was written. By default a call to StdoutRead grabs all output of the child process available. The way that you know if that's all output that will ever be forthcoming is by testing the value of @error immediately after StdoutRead; if@error is zero then there's still more data to be had. Your code takes this into account (it exits the loop once @error is non-zero) but the problem is that on every loop it throws away what was read on previous loops; this is what Jos means by concatenation and why his example shows using the &= operator. Your code keeps the next-to-the-last read as the captured data, but it's possible that your child program may have an empty, seemingly empty or incomplete write after the data you're really looking for; better to use Jos's method. Regarding your multiple defines, I'm assuming you need to call your utility program twice to get two results, and that's what you're doing with two calls to Run. Your StdoutRead loops are designed to exit when StdoutRead sets @error to a non-zero value, and (assuming you've run a valid, output producing command) when that happens it almost certainly means the child program has exited. That being the case, in your second example your util exits during the first loop, so there's never anything to be read in the second loop. Clear as mud?
  4. The most robust solution I've found for cases like this is to: 1) Make a stage one script which does the RunAs work; it simply calls the second script with the privileged credentials. I install this script on the local machine in a location that both the interactive user and the run-as user could access. 2) Make a stage two script that (when run as a privileged user) establishes a network connection with DriveMapAdd and performs the tasks that require the network connection. You can install it on separately the local computer, have the stage one script fetch it from a user accessible network share at run time or FileInstall() it locally with the stage one script to a location that the run-as user can read. This script would be essentially your script as it is now with the addition of DriveMapAdd and the removal of RunAsWait. As Jos was hinting a gotcha of running processes as another user is that you don't inherit any network authentication/connectivity from the interactive user. Depending on your network the run-as process might be able to access files from a UNC path if the location is world-readable, but not in every case. DriveMapAdd lets you specify a network path and credentials for accessing it, and by using it you both ensure that you're making the desired connection, and you can also specify a location that isn't world readable for increased security.
  5. Sorry to come in late, but this is a somewhat documented issue with the Virtual Server COM interface, this blog entry has some details about it. As far as working from AutoIt3 is concerned yours is the perfect fix, though I would have used the @ComputerName macro in place of "localhost" for the server name in ObjCreate(). Congrats and cheers. There are any number of jokes about the obfuscated quality of the MSDN library. You'll get the best mileage from it if you use Internet Explorer to browse it, but it is what it is beyond that.
  6. In the very few cases that I've been unable to get a satisfactory silent/unattended install process for a package, I've used a sequential process rather than a loop. You could use ControlClick as you have, but rather than pausing and looping you could use ControlGetText or WinGetText to verify that your install wizard actually advanced to the next pane. The AutoIt v3 Window Info tool in the AutoIt3 program folder can help you determine the names and text from your install wizard. By testing for text after each click you can add some rudimentary error checking/correction to your script that you wouldn't have with click-this-button-'til-it's-clicked-proper loops.
  7. After running your command line, you should ensure that the child process has written everything that it's going to write before making any tests against the string that holds the child output, either by doing as TurionAltec suggested and verifying that the child has exited, or by calling StdoutRead repeatedly in a loop and saving everything returned, a la: While 1 $line &= StdoutRead($foo) If @error Then ExitLoop Wend By the way, the @error tested for in the loop has nothing to do with the success/failure of your child program; setting @error is StdoutRead's way of signalling that there's no more data to be read from the child. Basically the pitfall is trying to act on data that your child process may not have written yet.
  8. You haven't stated what version of Windows you're using, but on any version since Windows 2000 drive mapping is per-profile, so you'd have to be running your script in the user-space of the desired user to see their drive mapping. Since PSEXEC uses a service on the remote end to do its dirty-work, I'll hazard a guess that your script is being run as the system user, which has no drive mapping and which would explain your results. You might try adapting your remote-end script to run a child process as the desired user, either a NET USE command or another AutoIt script.
  9. #include <Constants.au3> ; Tell AutoIt ahead-of-time the variable names we'll use Dim $Filename, $line, $MD5CLI $Filename="C:\Program Files\Windows Media Player\wmplayer.exe" ; MD5: 48CDAB5EB8C952534AE2C5AED72CCB70 ; MD5.EXE is copied to the same folder as the script file for this example ; MD5.EXE could have been anywhere as long as we used the full path $MD5CLI=Run (@ScriptDir & "\md5.exe "& $Filename, @ScriptDir, @SW_HIDE, 2) While 1 ; Try to read any output from MD5.EXE ; StdoutRead will assign a value to the macro variable @error ; if MD5.EXE signals that there's no more to read. ; Using &= below means to add what is read from StdoutRead ; to anything that we've read previously and store in $line ; We must always use a loop with StdoutRead because there's ; no guarantee that the child program writes output in full lines. ; \/ $line &= StdoutRead($MD5CLI) If @error Then ExitLoop ; If we're here assume that there's more to read, go back and loop again WEnd msgbox (0,"StdoutRead ",$line)
  10. Examples. Script 1. #cs ---------------------------------------------------------------------------- Author: DaveF Script Function: Example of RunAs with file on a network share. Script 1 of 2 #ce ---------------------------------------------------------------------------- ; This script will be compiled into the initial EXE file called from ; the network share by the non-privileged, interactive user's session. ; The pre-compiled second-stage script must be present in this script's ; folder at compile time, and this script must of course be recompiled ; if changes are made to the second-stage script. ; Copy embedded, second-stage compiled script to TEMP folder. FileInstall("privileged-installer.exe", @TempDir & "\privileged-installer.exe", 1) ; Run second-stage script. RunAsWait("adminuser", "domain", "adminpass", 1, @TempDir & "\privileged-installer.exe", @TempDir) ; Clean up second-stage script. FileDelete(@TempDir & "\privileged-installer.exe") Script 2, assumed in this example to be compiled as privileged-installer.exe. #cs ---------------------------------------------------------------------------- Author: DaveF Script Function: Example of RunAs with file on a network share. Script 2 of 2 #ce ---------------------------------------------------------------------------- ; This script will be compiled into the second-stage EXE ; which will be FileInstall-embedded in the initially called ; script, which will likely reside on a network share. ; The EXE for this script is being temporarily installed on ; the user's local PC so that the run-as user can access the ; EXE without network access (which won't exist at process ; spawn time). Dim $ourMap ; Establish temporary network connection to network share ; Though we're using the DriveMapAdd we don't have to ; designate a drive letter. $ourMap = DriveMapAdd("", "\\mis\NetAdmin", 0, "userWithAccessToShare", "userpass") ; Test for success in mapping the drive before continuing. If Not $ourMap Then ; Network connection failed. ; We could take action based on the ; value left in @error by DriveMapAdd Else ; Network connection succeeded, continuing. Run("\\mis\NetAdmin\Installers\Cutsheet Archive App\Lookup Cutsheet\CutsheetLookup\Debug\setup.exe") EndIf
  11. RunAs processes don't inherit the network access of the interactive user, so your (run-as privileged) child process doesn't have access to the \\servername share. The most robust solution I've found is to: 1) Make a stage one script which does the RunAs work, simply calling the second script, and install it locally on the PC. 2) Make a stage two script that (when run as a privileged user) establishes a network connection with DriveMapAdd and performs and tasks that require the network connection; install it on the local computer as well or you could have the stage one script fetch it from a user accessible network share at run time. The two stages can be performed by the same script rerunning itself, and I'm confident that one could find example UDFs for doing so on this forum be searching for rerun*...
  12. dummy = DriveGetType("J:") If @error Then ; @error <> 0 tells us the drive wasn't mapped DriveMapAdd("J:", "\\NeXT\tapioca", 0, "name", "pass") $unmap = 1 ; Note that we didn't have an existing map EndIf Run("J:\uninstall.exe --silent", "J:") If $unmap Then ; Disconnect drive DriveMapDel("J:") EndIf Edit: There should probably be something like a For loop before the Run that tests for the existence of the target on the mapped drive, Sleeps and tests again until success or timeout, in case the drive mapping process isn't stabilized by the time that Run is called.
  13. What error(s) are you seeing? Does the same script behave as you wish for it to if you use RunWait instead? Does the problem with getting a quiet install occur with RunWait? Are you accessing files on a network share, as you were in your previous thread?
  14. Dim $Url= "http://www.baidu.com" $XML = ObjCreate("Microsoft.XMLHTTP") $XML.Open("Get", $Url, False ) $XML.Send $Result = $XML.ResponseText $File=FileOpen("Result.htm",130) ; Open file for writing in unicode UTF8 mode. -- DaveF FileWrite($File,$Result) FileClose($File) ShellExecuteWait("notepad.exe","Result.htm") ;FileDelete("Result.htm")
  15. A process created with RunAs[Wait] (or any similar Windows functionality) doesn't inherit any network connections from the parent process. The way that I've worked around this in the past is to have two scripts: one installed on the local machine to copy the second script from the network, run it as the alternate user, wait and delete the second afterward; and the second script which starts off by making a network connection using DriveMapAdd and then doing the rest of the tasks I needed the alternate user's privileges for doing...
×
×
  • Create New...