Sign in to follow this  
Followers 0
enaiman

cmd and %cd% (any other way to get the "prompt")

17 posts in this topic

I'm trying for a couple of hours to figure a way to get the prompt value from a cmd window.

I know I can get the text from the window and from the text to "isolate" the string which is the "prompt". It is working but I don't like the way it is done.

I know that the DOS prompt format can be read from env variable "PROMPT" (usually $P$G) and I know that the current path value ($P) is stored in %cd%. That would make it easy enough to get the "prompt" value by having this info.

- I can get very easy the value from "PROMPT" with a simple EnvGet("PROMPT")

The problem:

- I can't get the value for "%cd%"

From a cmd if you type in "echo %cd%" it will return the current path.

If I am looking at all environment variables, %cd% is nowhere to be found and a simple EnvGet("%cd%") returns nothing.

The question: can I get the value for %cd" in a variable?

I tried @WorkingDir and it is not the one I need.

Thanks,


SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script

wannabe "Unbeatable" Tic-Tac-Toe

Paper-Scissor-Rock ... try to beat it anyway :)

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Maybe this.

;ConsoleWrite(  _getDOSOutput('date /T') & @CRLF)
ConsoleWrite( _getDOSOutput("cd") & @CRLF)
;ConsoleWrite(  _getDOSOutput('dir') & @CRLF)

; http://www.autoitscript.com/forum/index.php?showtopic=106254&view=findpost&p=750640
; See StdoutRead() Help file
Func _getDOSOutput($command)
    Local $text = '', $Pid = Run('"' & @ComSpec & '" /c ' & $command, '', @SW_HIDE, 2 + 4)
    While 1
        $text &= StdoutRead($Pid, False, False)
        If @error Then ExitLoop
        Sleep(10)
    WEnd
    Return $text
EndFunc   ;==>_getDOSOutput

Edit: Also try "ConsoleWrite( _getDOSOutput("cd /?") & @CRLF)". "/?" for dos help

Edited by Malkey

Share this post


Link to post
Share on other sites

Thanks for reply, that will work. Unfortunately I can't use that.

I am trying to have an easy way to get the prompt, and to do it every time a command starting with "cd ..." is executed (is changing the path = changing the prompt). That requires that the "original" cmd to stay open.

Actually all these dynamic environment variables: %cd%, %time% and %date% are commands, if you run them, you get the desired results.

My only hope for an easy solve would be if I could "read" somehow the value of %cd%

With every hour it seem to me that I have less and less chances to get this done (been reading meanwhile :) ) and I better do it the way I know.


SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script

wannabe "Unbeatable" Tic-Tac-Toe

Paper-Scissor-Rock ... try to beat it anyway :)

Share this post


Link to post
Share on other sites

Perhaps MsgBox(0, "Test", @WorkingDir)

Also see FileChangeDir() and EnvGet() in the help file.


George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

@GEOSoft

Thanks for the answer but unfortunately it doesn't help. @WorkingDir doesn't return the correct path, and the environment doesn't have any of these variables (%cd%, %date%, %time%).

I've put together something to solve this problem but it's involving writing to a temporary file whenever a "cd .." command is sent, then reading the file. Works but it's "ugly" :)

Still hoping for a more elegant solution.

Edited by enaiman

SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script

wannabe "Unbeatable" Tic-Tac-Toe

Paper-Scissor-Rock ... try to beat it anyway :)

Share this post


Link to post
Share on other sites

The working directory is the same thing as the %cd environment variable. Are you sure you just aren't executing the script from the wrong place?

For instance, if you are in "C:\thisdir" and you run some script that does a message box with @WorkingDir, it should show "C:\thisdir". If this isn't the case, you've got a problem.

Share this post


Link to post
Share on other sites

Are you perhaps doing a runas?


Share this post


Link to post
Share on other sites

There is a workaround if the other methods mentioned don't work as you'd like. You can execute a "dir>C:\Dirlisting.txt" in the console window, and read the 4th line of that file. Everything after the words " Directory of " to the end of the line is the current folder path of where the Dir command was executed. Simple enough to read that text, then delete the file. It's crude but it works. :)


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

I'm trying for a couple of hours to figure a way to get the prompt value from a cmd window.

I know I can get the text from the window and from the text to "isolate" the string which is the "prompt". It is working but I don't like the way it is done.

I know that the DOS prompt format can be read from env variable "PROMPT" (usually $P$G) and I know that the current path value ($P) is stored in %cd%. That would make it easy enough to get the "prompt" value by having this info.

- I can get very easy the value from "PROMPT" with a simple EnvGet("PROMPT")

The problem:

- I can't get the value for "%cd%"

From a cmd if you type in "echo %cd%" it will return the current path.

If I am looking at all environment variables, %cd% is nowhere to be found and a simple EnvGet("%cd%") returns nothing.

The question: can I get the value for %cd" in a variable?

I tried @WorkingDir and it is not the one I need.

Thanks,

enaiman

Sysinternals Process Explorer can do it, and so can you

(PE properties image tab shows current directory)

Ascend4nt has a convenient ready to go UDF of the API's required

Process + Thread + DLL Functions UDFs

http://sites.google.com/site/ascend4ntscode/processfunctions

File + Process Imports and Exports UDFs with PE32+ (x64 Support!)

Get the current working directory for cmd.exe

http://stackoverflow.com/questions/217951/get-the-current-working-directory-for-cmd-exe

Cross process Environment Vars

http://forum.sysinternals.com/topic629.html

Edit: removed unused include, changed on exit close handle code, fixed typo

;some issues with use of Dim and vars already declared/assigned/not used
;in UDF if this line used
;#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6

;place Ascend4nt's UDF in folder of your choice and edit these two lines
#include "PROCESS-ASCENDANT\_ProcessFunctions.au3"
#include "PROCESS-ASCENDANT\_ProcessUndocumented.au3"
#include <ProcessConstants.au3>

;coded by rover 2k11

Opt("MustDeclareVars", 1)
HotKeySet("{ESC}", "Terminate")
Global $aProc[1][3]

;tested on XP only
;continously monitors any open cmd.exe console for current directory change
;open some console windows and change directory at prompt...

;if you want to continuously monitor for new command consoles, then use SetWinEventHook()
;to wait for ConsoleWindowClass class windows creation and add PID and process handle to array

;or modify this example using WinList() to check for and add new consoles

GetCMDConsolesCurDir()

Func GetCMDConsolesCurDir()
    Local $iPIDCon, $iA, $aProcStr
    Local $aList = WinList("[CLASS:ConsoleWindowClass]")
    For $i = 1 To $aList[0][0]
        $iPIDCon = WinGetProcess($aList[$i][1])
        ConsoleWrite("+ Title: " & $aList[$i][0] & @LF & "+ Handle: " & $aList[$i][1] & @LF & "+ PID: " & $iPIDCon & @CRLF)
        $iA = UBound($aProc)
        $aProc[$iA - 1][0] = $iPIDCon
        $aProc[$iA - 1][1] = _ProcessOpen($iPIDCon, $PROCESS_QUERY_INFORMATION + $PROCESS_VM_READ)
        ReDim $aProc[UBound($aProc) + 1][3]
    Next

    Do
        Sleep(100)
        For $j = 0 To UBound($aProc) - 1
            If ProcessExists($aProc[$j][0]) Then
                $aProcStr = _ProcessUDGetStrings($aProc[$j][1])
                If $aProc[$j][2] == $aProcStr[0] Then ContinueLoop
                $aProc[$j][2] = $aProcStr[0]
                ConsoleWrite("- CMD.EXE PID: " & $aProc[$j][0] & " | Current Dir: " & $aProcStr[0] & @CRLF & "Error code: " & @error & @CRLF)
            EndIf
        Next
        $aList = WinList("[CLASS:ConsoleWindowClass]")
    Until $aList[0][0] = 0

    Terminate()

EndFunc   ;==>GetCMDConsolesCurDir



Func Terminate()
    Local $fClose, $sCol = "+"

    For $i = 0 To UBound($aProc) - 1
        If IsPtr($aProc[$i][1]) Then
            $fClose = _ProcessCloseHandle($aProc[$i][1])
            If $fClose = False Then $sCol = "!"
            ConsoleWrite($sCol & " PID: " & $aProc[$i][0] & " Process handle closed: " & $fClose & @CRLF & "Error code: " & @error & @CRLF)
        EndIf
    Next
    Exit
EndFunc   ;==>Terminate
Edited by rover

I see fascists...

Share this post


Link to post
Share on other sites

@RichardRobertson

Try this script (no matter if compiled or not)

#include <Constants.au3>

$CmdPid = Run(@SystemDir & "\cmd.exe", "C:\Windows", @SW_HIDE, $STDERR_MERGED + $STDIN_CHILD)
MsgBox(0, "", @WorkingDir)

It doesn't return C:\Windows at all, @WorkingDir returns the folder where your script/exe is run from.

@rover

Thanks alot for all the work you've put into this answer. It works wonderful and it is much more that what I was expecting. I will shorten it to fit my needs but it's awesome :)

Thanks to all others who contributed to this thread.


SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script

wannabe "Unbeatable" Tic-Tac-Toe

Paper-Scissor-Rock ... try to beat it anyway :)

Share this post


Link to post
Share on other sites

This is to clarify there are two working directories. There is the working directory of cmd.exe (Dos prompt) and the working directory of AutoIt script.

;ConsoleWrite(  _getDOSOutput('ECHO %date%') & @CRLF)

ConsoleWrite( _getDOSOutput("cd") & @CRLF)               ; Working directory of cmd.exe (Dos prompt)
ConsoleWrite( _getDOSOutput("ECHO %cd%") & @CRLF)  ; Working directory of cmd.exe
ConsoleWrite(@WorkingDir & @CRLF) ; Working directory of AutoIt script
ConsoleWrite(@ScriptDir & @CRLF)  ; Working directory of AutoIt script

; http://www.autoitscript.com/forum/index....?showtopic=106254&view=findpos
; See StdoutRead() Help file
Func _getDOSOutput($command)
    Local $text = '', $Pid = Run('"' & @ComSpec & '" /c ' & $command, @WindowsDir, @SW_HIDE, 2 + 4)
    While 1
        $text &= StdoutRead($Pid, False, False)
        If @error Then ExitLoop
        Sleep(10)
    WEnd
    Return StringStripWS($text,2)
EndFunc   ;==>_getDOSOutput

Share this post


Link to post
Share on other sites

@Malkey

Thanks for your input. Your solution works but it is exactly what I was doing previously (getting the whole output, isolating the prompt ...) and I wanted to avoid that. Fortunately Rover's solution was the one I liked very much. y script is basically doing this:

- I open a cmd window at the begining of the script

- I am using StdInWrite and StdOutRead to communicate with that cmd window (sending commands and receiving)

- I need always to know what the prompt is (hence the current path for $p$g prompt) just to be able to detect when a command has finished running so I can send the next one

@rover

Here is what I ended up using:

;place Ascend4nt's UDF in folder of you choice and edit these two lines
#include '_ProcessFunctions.au3'
#include '_ProcessUndocumented.au3'
#include <ProcessConstants.au3>
;coded by rover 2k11

Opt("MustDeclareVars", 1)

Global Const $STDIN_CHILD = 1
Global Const $STDOUT_CHILD = 2
Global Const $STDERR_CHILD = 4
Global Const $STDERR_MERGED = 8
Global Const $STDIO_INHERIT_PARENT = 0x10
Global Const $RUN_CREATE_NEW_CONSOLE = 0x10000

Global $CmdPid = Run(@SystemDir & "\cmd.exe", "C:\windows\help", @SW_HIDE, $STDERR_MERGED + $STDIN_CHILD)
MsgBox(0, "", GetCMDConsoleCurDir($CmdPid))

Func GetCMDConsoleCurDir($pPID)
    Local $aProcStr
    $aProcStr = _ProcessUDGetStrings(_ProcessOpen($pPID, $PROCESS_QUERY_INFORMATION + $PROCESS_VM_READ))
    If @error Then Return SetError(1)
    Return StringTrimRight($aProcStr[0], 1)
EndFunc   ;==>GetCMDConsoleCurDir

It is much simple, and tailored for a specific case :)

I had to add these constants manually because by including "Constants.au3" I got many errors about constants already defined.


SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script

wannabe "Unbeatable" Tic-Tac-Toe

Paper-Scissor-Rock ... try to beat it anyway :)

Share this post


Link to post
Share on other sites

I misunderstood. You are attempting to read the working directory of an external program, not your AutoIt script?

Share this post


Link to post
Share on other sites

He's tring to read the working directory as seen by Windows which will seldom be the AutoIt working dir.


George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Share this post


Link to post
Share on other sites

@RichardRobertson

My bad. Misunderstandings are happening when OP didn't explain clear enough what he needs help with. I should have posted that small example from the begining.

Well, lesson learned :)


SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script

wannabe "Unbeatable" Tic-Tac-Toe

Paper-Scissor-Rock ... try to beat it anyway :)

Share this post


Link to post
Share on other sites

@enaiman

Without _ProcessCloseHandle() you increase your processes

open handle count by one with each call to GetCMDConsoleCurDir()

Your example returns a blank string.

you need ProcessWait() before calling GetCMDConsoleCurDir()

#include '_ProcessFunctions.au3'
#include '_ProcessUndocumented.au3'
#include <ProcessConstants.au3>

Opt("MustDeclareVars", 1)

Global Const $STDIN_CHILD = 1
Global Const $STDOUT_CHILD = 2
Global Const $STDERR_CHILD = 4
Global Const $STDERR_MERGED = 8
Global Const $STDIO_INHERIT_PARENT = 0x10
Global Const $RUN_CREATE_NEW_CONSOLE = 0x10000

Global $CmdPid = Run(@SystemDir & "\cmd.exe", "C:\windows\help", @SW_HIDE, $STDERR_MERGED + $STDIN_CHILD)
ProcessWait($CmdPid, 5)
Global $CurDir = GetCMDConsoleCurDir($CmdPid)
ConsoleWrite("-Error code: "  & @error & @lf & "Error: " & @extended & @CRLF)
MsgBox(0, "", $CurDir)


Func GetCMDConsoleCurDir($pPID)
    Local $hProc = _ProcessOpen($pPID, $PROCESS_QUERY_INFORMATION + $PROCESS_VM_READ)
    If @error Or IsPtr($hProc) = 0 Then Return SetError(1, @error)
    Local $aProcStr = _ProcessUDGetStrings($hProc)
    If @error Or IsArray($aProcStr) = 0 Then Return SetError(2, @error)
    Local $sTemp = StringTrimRight($aProcStr[0], 1)
    SetError(0, @error)
    If _ProcessCloseHandle($hProc) = False Then SetError(3, @error)
    Return $sTemp
EndFunc   ;==>GetCMDConsoleCurDir

I see fascists...

Share this post


Link to post
Share on other sites

@rover

Thank you very much for _ProcessCloseHandle(); I had no idea that I need to close the handle everytime (again: lesson learned) :)

Thank you for the example too - I realised that my @error reading was only for _ProcessUDGetStrings(); you have corrected that; I will use your example.

I have no idea why the example I have posted returned an empty string for you - it works very well on my computer (Win7).


SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script

wannabe "Unbeatable" Tic-Tac-Toe

Paper-Scissor-Rock ... try to beat it anyway :)

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0