# Windows Shell

Provides functions to read, write and delete registry keys, log events, send keystrokes to the active window, run a program in a new process, and execute programs or commands in a new process, providing methods to interact with the provess’s standard input, output, and error streams.

### Functions

Name | Description
--- | ---
AfxLogEvent | Adds an event entry to a log file.
AfxRegDelete | Deletes a key or one of its values from the registry.
AfxRegRead | Returns the value of a key or value-name from the registry.
AfxRegWrite | Creates a new key, adds another value-name to an existing key (and assigns it a value), or changes the value of an existing value-name.
AfxRun | Runs a program in a new process.
AfxSendKeys | Sends keystrokes to the active window.

### CWhsExec class

Executes a program or command in a new process, providing methods to interact with the provess’s standard input, output, and error streams.

Name | Description
--- | ---
CONSTRUCTOR | Creates an instance of the `CWhsExec` class.
CAST | Returns a pointer to the IWshExec interface.
GetLastResult | Returns the last result code.
GetErrorInfo | Returns a description of the last result code.

Name | Description
--- | ---
CurrentDirectory | Retrieves or changes the current active directory.
GetExitCode | Returns the exit code set by a script or program run using the Exec method.
GetProcessID | The process ID (PID) for a process started with the Exec method.
GetStatus | Provides status information about a script run with the Exec method.
GetStdErr | Provides access to the stderr output stream of the IWshExec interface.
GetStdIn | Exposes the stdin input stream of the IWshExec interface.
GetStdOut | Exposes the stdout output stream of the IWshExec interface.
AppActivate | Activates an application window.
Terminate | Instructs the script engine to end the process started by the Exec method.

## AfxRegRead

Returns the value of a key or value-name from the registry.

    FUNCTION AfxRegRead (BYREF wszKey AS WSTRING) AS DWSTRING

Parameter | Description
--- | ---
wszKey | The registry key name.

#### Usage examples

    print AfxRegRead("HKLM\HARDWARE\DESCRIPTION\System\CentralProcessor\0\ProcessorNameString")
    print AfxRegRead("HKLM\HARDWARE\DESCRIPTION\System\CentralProcessor\0\~Mhz")

## AfxRegWrite

Creates a new key, adds another value-name to an existing key (and assigns it a value), or changes the value of an existing value-name.

    FUNCTION AfxRegWrite (BYREF wszKey AS WSTRING, BYREF dvValue AS DVARIANT, BYREF wszType AS WSTRING) AS HRESULT

Parameter | Description
--- | ---
wszKey | String value indicating the key-name, value-name, or value you want to create, add, or change.
dvValue | The name of the new key you want to create, the name of the value you want to add to an existing key, or the new value you want to assign to an existing value-name.
wszType | String value indicating the value’s data type.

#### Usage examples

    AfxRegWrite("HKCU\Software\ACME\FortuneTeller\", 1, "REG_BINARY")
    AfxRegWrite("HKCU\Software\ACME\FortuneTeller\MindReader"", "Goocher!", "REG_SZ")

## AfxRegDelete

Deletes a key or one of its values from the registry.

    FUNCTION AfxRegDelete (BYREF wszKey AS WSTRING) AS HRESULT

Parameter | Description
--- | ---
wszKey | String value indicating the name of the registry key or key value you want to delete.

#### Usage examples

    AfxRegDelete("HKCU\Software\ACME\FortuneTeller\MindReader")
    AfxRegDelete("HKCU\Software\ACME\FortuneTeller\")
    AfxRegDelete("HKCU\Software\ACME\")

#### Return value

Returns S_OK or an HRESULT error code.

## AfxLogEvent

Adds an event entry to a log file.

    FUNCTION AfxLogEvent (BYVAL nType AS LONG, BYREF wszMessage AS WSTRING) AS HRESULT

Parameter | Description
--- | ---
nType | Integer value representing the event type.
wszMessage | String value containing the log entry text.

There are six event types.

Type | Value
--- | ---
0 | SUCCESS
1 | ERROR
2 | WARNING
4 | INFORMATION
8 | AUDIT_SUCCESS
16 | AUDIT_FAILURE

#### Usage example

    AfxLogEvent(0, "Logon Script Completed Successfully")

## AfxRun

Runs a program in a new process.

    AfxRun (BYREF wszCommand AS WSTRING, BYVAL WindowStyle AS LONG = 0, BYVAL WaitOnReturn AS BOOLEAN = FALSE) AS HRESULT

Parameter | Description
--- | ---
wszCommand | String value indicating the command line you want to run. You must include any parameters you want to pass to the executable file.
WindowStyle | Integer value indicating the appearance of the program’s window. Note that not all programs make use of this information.
WaitOnReturn | Boolean value indicating whether the script should wait for the program to finish executing before continuing to the next statement in your script. If set to true, script execution halts until the program finishes, and Run returns any error code returned by the program. If set to false (the default), the Run method returns immediately after starting the program, automatically returning 0 (not to be interpreted as an error code).

#### Return value

Returns S_OK or an HRESULT error code.

#### Usage example

    AfxRun("Calc")

## AfxSendKeys

Sends keystrokes to the active window.

    FUNCTION AfxSendKeys (BYREF wszKeys AS WSTRING, BYVAL bWait AS BOOLEAN = FALSE) AS HRESULT

Parameter | Description
--- | ---
wszKeys | Integer value representing the event type.
bWait | Boolean value: True or False.

#### Return value

Returns S_OK or an HRESULT error code.

#### Usage example

    AfxRun("calc")
    AfxForceSetForegroundWindow(FindWindow("Windows.UI.Core.CoreWindow", NULL))
    ' ---or-- AfxForceSetForegroundWindow(FindWindow(NULL, "calc"))
    SLEEP 1000
    AfxSendKeys("1{+}")
    SLEEP 500
    AfxSendKeys("2")
    SLEEP 500
    AfxSendKeys("~")
    SLEEP 500
    AfxSendKeys("*3")
    SLEEP 500
    AfxSendKeys("~")
    SLEEP 2500

#### Remarks

Use the SendKeys method to send keystrokes to applications that have no automation interface. Most keyboard characters are represented by a single keystroke. Some keyboard characters are made up of combinations of keystrokes (CTRL+SHIFT+HOME, for example). To send a single keyboard character, send the character itself as the string argument. For example, to send the letter x, send the string argument “x”.

Note: To send a space, send the string ” “.

You can use SendKeys to send more than one keystroke at a time. To do this, create a compound string argument that represents a sequence of keystrokes by appending each keystroke in the sequence to the one before it. For example, to send the keystrokes a, b, and c, you would send the string argument “abc”. The SendKeys method uses some characters as modifiers of characters (instead of using their face-values). This set of special characters consists of parentheses, brackets, braces, and the:

• plus sign “+”, • caret “^”, • percent sign “%”, • and tilde “~”

Send these characters by enclosing them within braces “{}”. For example, to send the plus sign, send the string argument “{+}”. Brackets “[ ]” have no special meaning when used with SendKeys, but you must enclose them within braces to accommodate applications that do give them a special meaning (for dynamic data exchange (DDE) for example).

• To send bracket characters, send the string argument “{[}” for the left bracket and ”{]}” for the right one. • To send brace characters, send the string argument “{{}” for the left brace and “{}}” for the right one.

Some keystrokes do not generate characters (such as ENTER and TAB). Some keystrokes represent actions (such as BACKSPACE and BREAK). To send these kinds of keystrokes, send the arguments shown in the following table:

Key | Argument
--- | ---
BACKSPACE | {BACKSPACE}, {BS}, or {BKSP}
BREAK | {BREAK}
CAPS LOCK | {CAPSLOCK}
DEL or DELETE | {DELETE} or {DEL}
DOWN ARROW | {DOWN}
END | {END}
ENTER | {ENTER} or ~
ESC | {ESC}
HELP | {HELP}
HOME | {HOME}
INS or INSERT | {INSERT} or {INS}
LEFT ARROW | {LEFT}
NUM LOCK | {NUMLOCK}
PAGE DOWN | {PGDN}
PAGE UP | {PGUP}
PRINT SCREEN | {PRTSC}
RIGHT ARROW | {RIGHT}
SCROLL LOCK | {SCROLLLOCK}
TAB | {TAB}
UP ARROW | {UP}
F1 | {F1}
F2 | {F2}
F3 | {F3}
F4 | {F4}
F5 | {F5}
F6 | {F6}
F7 | {F7}
F8 | {F8}
F9 | {F9}
F10 | {F10}
F11 | {F11}
F12 | {F12}
F13 | {F13}
F14 | {F14}
F15 | {F15}
F16 | {F16}

To send keyboard characters that are comprised of a regular keystroke in combination with a SHIFT, CTRL, or ALT, create a compound string argument that represents the keystroke combination. You do this by preceding the regular keystroke with one or more of the following special characters:

Key | Special Character
--- | ---
SHIFT | +
CTRL | ^
ALT | %

Note: When used this way, these special characters are not enclosed within a set of braces.

To specify that a combination of SHIFT, CTRL, and ALT should be held down while several other keys are pressed, create a compound string argument with the modified keystrokes enclosed in parentheses. For example, to send the keystroke combination that specifies that the SHIFT key is held down while:

• e and c are pressed, send the string argument “+(ec)”. • e is pressed, followed by a lone c (with no SHIFT), send the string argument “+ec”.

You can use the SendKeys method to send a pattern of keystrokes that consists of a single keystroke pressed several times in a row. To do this, create a compound string argument that specifies the keystroke you want to repeat, followed by the number of times you want it repeated. You do this using a compound string argument of the form {keystroke number}. For example, to send the letter “x” ten times, you would send the string argument “{x 10}”. Be sure to include a space between keystroke and number.

Note: The only keystroke pattern you can send is the kind that is comprised of a single keystroke pressed several times. For example, you can send “x” ten times, but you cannot do the same for “Ctrl+x”.

Note: You cannot send the PRINT SCREEN key {PRTSC} to an application.

## Constructor

Creates an instance of the `CWhsExec` class.

Runs an application in a child command-shell, providing access to the StdIn/StdOut/StdErr streams.

    CONSTRUCTOR CWhsExec (BYREF wszCommand AS WSTRING)

Parameter | Description
--- | ---
wszCommand | The command to execute.

#### Usage example:

    #include "AfxNova/AfxWsh.inc"
    #include "AfxNova/CTextStream.inc"
    USING AfxNova
    DIM pWshExec AS CWhsExec = "%comspec% /c dir"
    IF pWshExec THEN
       DIM pStdOutStm AS CTextStream = pWshExec.GetStdOut
       IF pStdOutStm THEN
          IF pStdOutStm.EOS = FALSE THEN
             ' // The console uses the CP_OEMCP code page
             DIM dwsOut AS DWSTRING
             dwsOut.OEM = pStdOutStm.ReadAll
             ' // You can also use
             ' DIM dwsOut AS DWSTRING = DWSTRING(pStdOutStm.ReadAll, CP_OEMCP)
             print dwsOut
          END IF
       END IF
    END IF

## CAST

Returns a pointer to the IWshExec interface.

    OPERATOR CAST () AS Afx_IWshExec PTR

## GetLastResult

Returns the result code returned by the last executed method.

    FUNCTION GetLastResult () AS HRESULT

## GetErrorInfo

Returns a description of the last result code.

    FUNCTION GetErrorInfo (BYVAL nError AS LONG = -1) AS DWSTRING

## CurrentDirectory

Retrieves or changes the current active directory.

    [GET] PROPERTY CurrentDirectory () AS DWSTRING
    [SET] PROPERTY CurrentDirectory (BYREF wszDir AS WSTRING) AS HRESULT

Parameter | Description
--- | ---
wszDir | The directory to set.

The [GET] CurrentDirectory returns a string that contains the fully qualified path of the current working directory of the active process.

The [SET] CurrentDirectory sets the current working directory of the active process.

## GetStatus

Provides status information about a script run with the Exec method.

    FUNCTION GetStatus () AS WshExecStatus

#### Return value

The Status property returns a value from the WshExecStatus enumerated type. WshRunning = 0, WshFinished = 1, WshFailed = 2.

## GetStdIn

Exposes the stdin input stream of the IWshExec interface.

    FUNCTION GetStdIn () AS Afx_ITextStream PTR

#### Return value

A pointer to the ITextStream interface.

## GetStdOut

Exposes the stdin output stream of the IWshExec interface.

    FUNCTION GetStdOut () AS Afx_ITextStream PTR

#### Return value

A pointer to the ITextStream interface.

## GetStdErr

Provides access to the stderr output stream of the IWshExec interface.

    FUNCTION GetStdErr () AS Afx_ITextStream PTR

#### Return value

A pointer to the ITextStream interface.

## GetExitCode

Returns the exit code set by a script or program run using the Exec method (called by the constructor).

    FUNCTION GetExitCode () AS LONG

#### Remarks

Executables set an exit code when they finish running. This conveys the status information when a process ends. Often, it is used to send an error code (or some other piece of information) back to the caller. If the process has not finished, the GetExitCode property returns 0. The values returned from GetExitCode** depend on the application that was called.

## GetProcessID

Returns the process ID (PID) for a process started with the Exec method (called by the constructor).

    FUNCTION GetProcessID () AS LONG

#### Remarks

You can use the GetProcessID property to activate an application (as an argument to the AppActivate method).

## AppActivate

Activates an application window.

    FUNCTION AppActivate (BYREF wszTitle AS WSTRING, BYVAL bWait AS BOOLEAN = FALSE) AS BOOLEAN

    FUNCTION AppActivate (BYREF processID AS LONG, BYVAL bWait AS BOOLEAN = FALSE) AS BOOLEAN

Parameter | Description
--- | ---
wszTitle | Specifies which application to activate. This can be a string containing the title of the application (as it appears in the title bar) or the application’s Process ID.
processID | Specifies which application to activate. This can be a string containing the title of the application (as it appears in the title bar) or the application’s Process ID.
bWait | Boolean. TRUE or FALSE.

#### Remarks

The AppActivate method returns a Boolean value that identifies whether the procedure call is successful. This method changes the focus to the named application or window, but it does not affect whether it is maximized or minimized. Focus moves from the activated application window when the user takes action to change the focus (or closes the window).

In determining which application to activate, the specified title is compared to the title string of each running application. If no exact match exists, any application whose title string begins with title is activated. If an application still cannot be found, any application whose title string ends with title is activated. If more than one instance of the application named by title exists, one instance is arbitrarily activated.

## Terminate

Instructs the script engine to end the process started by the Exec method (called by the constructor).

    FUNCTION Terminate

#### Remarks

The Terminate method does not return a value. Use the Terminate method only as a last resort since some applications do not clean up properly. As a general rule, let the process run its course and end on its own. The Terminate method attempts to end a process using the WM_CLOSE message. If that does not work, it kills the process immediately without going through the normal shutdown procedure.