cherdeg Posted February 16, 2010 Share Posted February 16, 2010 Hi guys, I'm currently doing a command line application that gets from 0, 1, 2 or 3 commandline parameters and does different things depending on these parameters. I want users to have a time as easy as possible when entering the parameters (foolproof). The parameters are all optional, but when used, some of them need additional information entered. Examples for check.exe (information in <> is required): check ...Checks all and everything with hardest settings check -soft ...Checks all and everything with relaxed settings check -med ...Checks all and everything with medium settings check -single <hostname> -soft ...Checks a single host <hostname> with relaxed settings check -single <hostname> -med ...Checks a single host <hostname> with medium settings check -single <hostname> -hard ...Checks a single host <hostname> with hardest settings check -wg ...Checks all defined Workgroup-Machines with hardest settings check -wg -hard ...Checks all defined Workgroup-Machines with hardest settings check -wg -soft ...Checks all defined Workgroup-Machines with relaxed settings check -ou <OUname> ...Checks all machines in the <OUname> with hardest settings check -ou <OUname> -med ...Checks all machines in the <OUname> with medium settings You get it, I think. Point is a) to catch all input errors: check -ou -med ...should return an error because of the missing <OUname> check -wg -med ...should return an error because of the given but inappropriate <OUname> Also I would like the user not having to care about the sequence as long as everything needed is there. This: check -med -ou <OUname> ...should work exactly as: check -ou <OUname> -med Last, but not least I'd like to allow the user to do something like: check -wg -ou <OUname1> <OUname2> -soft ...Check all defined Workgroup-Machines and all machines in <OUname1> and <OUname2 >with relaxed settings. Is there an intelligent way to parse the commandline parameters, something as a best practice? I'm cycling round this topic for days by now...for-next loops, switch-case, if-elseif...I can't find a solution that is easy to maintain/understand and functional likewise. Can anybody of the pros here please hint me into the correct direction? Best Regards, Chris Link to comment Share on other sites More sharing options...
PsaltyDS Posted February 16, 2010 Share Posted February 16, 2010 Have you reviewed the help file under Command Line Parameters? You could also search the forum for the many examples that use the $CmdLine built-in variable. It's not that complicated. Take a shot at parsing the $CmdLine array, and post some code to talk about if you get stuck. Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
weaponx Posted February 16, 2010 Share Posted February 16, 2010 (edited) I started this at lunch time thinking it would be simple. I was wrong.Codeexpandcollapse popup;--------------------------------- ; CONSTANTS ;--------------------------------- Const $aLevels[3] = ["soft","med","hard"] ;Define global settings Const $aTargets[3][2] = [["single",1],["wg",0],["ou",1]] ;Define global settings (1 = Additional arguments required, 0 = Boolean only) ;--------------------------------- ; GLOBALS ;--------------------------------- Global $sCmd = $CmdLineRaw Global $sCmd = '-wg -ou <OUname1> <OUname2> -soft' ;String for testing ONLY Global $aErrors[1] = [0] ;--------------------------------- ; DEFAULTS ;--------------------------------- $bCheckAll = True ;Check EVERYTHING by default, until overridden $bCheckWorkgroup = False ;Do NOT scan workgroup by default $sLevel = 'hard' ;Assign default level $sCheckSingle = '' ;Skip single scan by default $sCheckOU = '' ;Skip OU by default ;--------------------------------- ; PREPARE ACTIONS ;--------------------------------- ;Remove leading dash if it exists If StringLeft($sCmd,1) = '-' Then $sCmd = StringTrimLeft($sCmd,1) ;Split command line arguments $aArguments = _StringSplitRegExp($sCmd,'\s-') ;Loop through arguments For $X = 1 to $aArguments[0] ;ConsoleWrite('[' & $X & ']: ' & $aArguments[$X] & @CRLF) ;DEBUG ONLY ;Assign argument $sArgument = $aArguments[$X] $sParameters = '' ;Attempt to split argument Local $aTemp = StringRegExp($sArgument,'^(.+?)(?:\s)(.*?)$',1) If Ubound($aTemp) Then $sArgument = $aTemp[0] $sParameters = $aTemp[1] EndIf ;ConsoleWrite("Argument: " & $sArgument & @CRLF) ;ConsoleWrite("Parameters: " & $sParameters & @CRLF) ;Look for target argument, return index if found $iIndex1 = InArray($aTargets,$sArgument) If NOT @ERROR Then ;See if additional parameters are required If $aTargets[$iIndex1][1] Then ;See if any parameters are present If $sParameters <> '' Then $bCheckAll = False ;Disable full check IMPORTANT! Switch $sArgument ;Check a single system Case 'single' $sCheckSingle = $sParameters ;Scan an organizational unit Case 'ou' $sCheckOU = $sParameters Case Else AddError("Argument not supported " & $sArgument) EndSwitch Else AddError("Additional parameters are required for argument: " & $sArgument) EndIf Else $bCheckAll = False ;Disable full check IMPORTANT! Switch $sArgument ;Check Workgroups (No options required) Case 'wg' $bCheckWorkgroup = True Case Else AddError("Argument not supported " & $sArgument) EndSwitch EndIf EndIf ;Look for level argument, return index if found (optional) $iIndex2 = InArray($aLevels,$sArgument) If NOT @ERROR Then $sLevel = $sArgument ;Modify scan level EndIf Next ;--------------------------------- ; PERFORM ACTIONS ;--------------------------------- ;Check everything and stop If $bCheckAll Then CheckAll() Exit EndIf ;Check single (string) then stop If $sCheckSingle <> '' Then CheckSingle() Exit EndIf ;Check workgroups (boolean) If $bCheckWorkgroup Then CheckWorkgroups() ;Check OU (string) If $sCheckOU <> '' Then CheckOU() ;Dump any errors found If $aErrors[0] Then ConsoleWrite('!' & $aErrors[0] & " ERROR(S) FOUND:" & @CRLF) For $X = 1 to $aErrors[0] ConsoleWrite('[' & $X & ']: ' & $aErrors[$X] & @CRLF) Next EndIf ;--------------------------------- ; CHECK FUNCTIONS ;--------------------------------- Func CheckAll() ConsoleWrite("Checking ALL systems (Level: " & $sLevel & ")" & @CRLF) EndFunc Func CheckSingle() ConsoleWrite("Checking single system (Level: " & $sLevel & "): " & $sCheckSingle & @CRLF) EndFunc Func CheckWorkgroups() ConsoleWrite("Checking workgroup (Level: " & $sLevel & ")" & @CRLF) EndFunc Func CheckOU() ConsoleWrite("Checking the following organizational units (Level: " & $sLevel & "):" & @CRLF) $aTemp = StringSplit($sCheckOU,' ') For $X = 1 to $aTemp[0] ConsoleWrite(@TAB & '[' & $X & ']: ' & $aTemp[$X] & @CRLF) Next EndFunc ;--------------------------------- ; COMMON FUNCTIONS ;--------------------------------- Func AddError($sMsg) Local $iCount = Ubound($aErrors) Redim $aErrors[$iCount+1] $aErrors[0] = $iCount $aErrors[$iCount] = $sMsg EndFunc ;Look for string in an array Func InArray($aArray, $sString) ; 1 dimensional array If Ubound($aArray,0) = 1 Then For $Y = 0 to Ubound($aArray)-1 If $aArray[$Y] = $sString Then Return SetError(1,$Y,False) Next Return SetError(1,0,-1) ; 2 dimensional array ElseIf Ubound($aArray,0) = 2 Then For $Y = 0 to Ubound($aArray)-1 If $aArray[$Y][0] = $sString Then ;ConsoleWrite("MATCH" & @CRLF) Return $Y EndIf Next Return SetError(1,0,-1) EndIf EndFunc #cs ---------------------------------------------------------------------------- AutoIt Version: 3.3.0.0 Author: WeaponX Script Function: Split string on regular expression Parameters: String = String to be split Pattern = Pattern to split on IncludeMatch = True / False - Indicates whether or not to include the match in the return (back-reference) Count = Number of splits to perform #ce ---------------------------------------------------------------------------- Func _StringSplitRegExp($sString, $sPattern, $sIncludeMatch = false, $iCount = 0) ;All matches will be replaced with this string Local $sReservedPattern = Chr(0) ;Local $sReservedPattern = "#" Local $sReplacePattern = $sReservedPattern ;Modify the reserve pattern to include back-reference If $sIncludeMatch Then $sReplacePattern = "$0" & $sReplacePattern ;Replace all occurences of the search pattern with a replace string $sTemp = StringRegExpReplace($sString, $sPattern, $sReplacePattern, $iCount) ;Consolewrite($sTemp & @CRLF) ;Strip trailing character if it matches the reserved pattern If StringRight($sTemp, 1) = $sReservedPattern Then $sTemp = StringTrimRight($sTemp, 1) ;Split string using entire reserved string $aResult = StringSplit($sTemp, $sReservedPattern, 1) Return $aResult EndFuncOutputChecking workgroup (Level: hard) Checking the following organizational units (Level: hard): [1]: <OUname1> [2]: <OUname2> Edited February 16, 2010 by weaponx Link to comment Share on other sites More sharing options...
cherdeg Posted February 17, 2010 Author Share Posted February 17, 2010 Have you reviewed the help file under Command Line Parameters? You could also search the forum for the many examples that use the $CmdLine built-in variable. It's not that complicated. Take a shot at parsing the $CmdLine array, and post some code to talk about if you get stuck. Yes I did. I always check the helpfile before posting here to save myself from replies stating "Hey, dumbo, look at the helpfile, check entries for $CmdLine". And no, you're not right: it IS that complicated. But a.) Command Line Parameters The special array $CmdLine is initialized with the command line parameters passed in to your AutoIt script. Note the scriptname is not classed as a parameter; get this information with @ScriptName instead. A parameter that contains spaces must be surrounded by "double quotes". Compiled scripts accept command line parameters in the same way. $CmdLine[0] is number of parameters $CmdLine[1] is param 1 (after the script name) $CmdLine[2] is param 2 etc ... $CmdLine[$CmdLine[0]] is one way to get the last parameter... ...does this not contain any method or example how to work with more complex setups and b.) why should I reinvent the wheel? I'm quite sure that almost everyone of you has done something regarding commandline parameters...so please share. Link to comment Share on other sites More sharing options...
cherdeg Posted February 17, 2010 Author Share Posted February 17, 2010 (edited) I started this at lunch time thinking it would be simple. I was wrong. How long is your lunchtime break? I need some time to check your code - but I'll definitely get you feedback on it. Thanks so long! Okay, back with 1st points: This is great! But the following commands are not processed correctly: Global $sCmd = '-single Host -ou Group-1 Group-3 DC -soft' ;Checking single system (Level: hard): Host Global $sCmd = 'wg -ou Group-1 Group-3 -med' ;Checking workgroup (Level: hard), Checking the following organizational units (Level: hard): Group-1, Group-3 Global $sCmd = '-wg -med' ;Checking workgroup (Level: hard) Do you have a start for me? EDIT: I removed the "NOT" from line 92 to get the correct check level. Edited February 17, 2010 by cherdeg Link to comment Share on other sites More sharing options...
MHz Posted February 17, 2010 Share Posted February 17, 2010 If it is a big amount of cmdline switches to handle then I opt for the abbreviations that i added to the full installed Scite4AutoIt3 editor. You have a choice of "cmdlineselect", "cmdlineselect2", "cmdlineswitch" and "cmdlineswitch2".I will show by example how I typed "cmdlineswitch" (without quotes) into Scite4AutoIt3 and press the space bar to expand the abbreviation into the code structure that magically appears. Typed:cmdlineswitchpressed spacebar to get:#region - CmdlineSwitch If $CMDLINE[0] Then For $i = 1 To $CMDLINE[0] Switch $CMDLINE[$i] Case '/?' MsgBox(0x40000, @ScriptName & ' Help', _ 'Switches are:' & @CRLF _ & @CRLF & '/extract' _ & @CRLF & @TAB & 'Extract files to current directory' _ & @CRLF & '/x' _ & @CRLF & @TAB & '' _ & @CRLF & '/x' _ & @CRLF & @TAB & '' _ & @CRLF & '/x' _ & @CRLF & @TAB & '' _ & @CRLF & '/x' _ & @CRLF & @TAB & '') Exit Case '/extract' FileInstall('?', @ScriptDir & '') Exit Case '/x' Case '/x' Case '/x' Case '/x' Case Else MsgBox(0x40000, 'Incorrect switch used', _ 'Command used:' & @CRLF & $CMDLINERAW & @CRLF & _ @CRLF & 'Use /? for the switches available.') Exit EndSwitch Next EndIf #endregionNow with some changes.expandcollapse popup#cs - test switches to pass /hard /single singlehost ; test1 ok /wg /ou host1,host2,host3 ; test2 ok /wg /ou /host1,host2,host3 ; test3 error #ce #region - CmdlineSwitch Global $settings, $single, $wg, $ou If $CMDLINE[0] Then For $i = 1 To $CMDLINE[0] Switch $CMDLINE[$i] Case '/?' MsgBox(0x40000, @ScriptName & ' Help', _ 'Switches are:' & @CRLF _ & @CRLF & '/extract' _ & @CRLF & @TAB & 'Extract files to current directory' _ & @CRLF & '/soft' _ & @CRLF & @TAB & 'Description' _ & @CRLF & '/med' _ & @CRLF & @TAB & 'Description' _ & @CRLF & '/hard' _ & @CRLF & @TAB & 'Description' _ & @CRLF & '/single' _ & @CRLF & @TAB & 'Description' _ & @CRLF & '/wg' _ & @CRLF & @TAB & 'Description' _ & @CRLF & '/ou' _ & @CRLF & @TAB & 'Description') Exit Case '/extract' FileInstall('?', @ScriptDir & '\?') Exit Case '/soft' $settings = 1 Case '/med' $settings = 2 Case '/hard' $settings = 3 Case '/single' $single = $CMDLINE[$i+1] ; assign next indexed value If StringLeft($single, 1) = '/' Then ConsoleWriteError('Incorrect parameter following /single' & @CRLF) Exit 1 EndIf $i += $i ; increase $i Case '/wg' $wg = True Case '/ou' $ou = $CMDLINE[$i+1] ; assign next indexed value If StringLeft($ou, 1) = '/' Then ConsoleWriteError('Incorrect parameter following /ou' & @CRLF) Exit 1 EndIf $i += $i ; increase $i Case Else MsgBox(0x40000, 'Incorrect switch used', _ 'Command used:' & @CRLF & $CMDLINERAW & @CRLF & _ @CRLF & 'Use /? for the switches available.') Exit EndSwitch Next EndIf #endregion ; set hard settings by default if optin is not selected If Not $settings Then $settings = 3 EndIf ; show variables for this test MsgBox(0, @ScriptName, _ '$settings = ' & $settings & @CRLF & _ '$single = ' & $single & @CRLF & _ '$wg = ' & $wg & @CRLF & _ '$ou = ' & $ou _ )The example is not complete as Msgboxes for a CLI application is perhaps not suitable and error checking is incomplete etc. But it does show you that processing incoming cmdline switches can be achieved in an orderly fashion. Have a look at Jos' AutoIt3Wrapper source in the Scite4AutoIt3 install folder for a similar use of handling cmdline incoming switches. I have done projects that use many switches with the similar technique.May I suggest that you use a comma separated list of hosts for the /ou switch and you can StringSplit them later in your script. And you may notice that I welcome the switches starting with a forward slash and not starting with a dash that is normally used in a posix based system.Test in Scite4AutoIt3 with the commented switches in the script above or with your own combination. Just press Shift+F8 to show parameter window and add parameters to test with then press F5 to run the script. Link to comment Share on other sites More sharing options...
ProgAndy Posted February 17, 2010 Share Posted February 17, 2010 Something I wrote some time ago. It automatically recognizes the connection between a parameter and its value, so you logic for processing the parameters can be simpler. The complete commands of your script are stored in $CMDLINERAW. You can parse it with this function: expandcollapse popup#include <Array.au3> $CMDString = '/a:"value" -big="this -test:1\"23 is & $#@ _ your life" -test=th_3 -tte -äß$=/ätest/h.b' $ResultArray = _ParseCMDLine($CMDString) _ArrayDisplay($ResultArray) ;=============================================================================== ; ; Function Name: _ParseCMDLine($CMDString) ; Description:: Parses a CMD-String to Parameters with Values ; Parameter(s): $CMDString -> String to parse ; Requirement(s): ? ; Return Value(s): Error: 0 and @error = StringRegExp-Error ; Success: 2 Dimensional Array: ; $array[$i][0] : Parameter including value ; $array[$i][1] : Parameter ; $array[$i][2] : Value with quotation marks (only if value has quotaion marks) ; $array[$i][3] : Value without quotation marks ; Author(s): Prog@ndy ; ; Basis: http://regexlib.com/REDetails.aspx?regexp_id=1220 ;=============================================================================== ; Func _ParseCMDLine($CMDString) Local $y, $j, $i, $entry Local $x = StringRegExp($CMDString,'(?:\s*)(?<=[-|/])(?<name>[^\s-|/:|=]*)(?:(?:[:|=](?:("(?<value1>.*?)(?<!\\)")|(?<value>\S*)))|\w*?)',4) If @error Then Return SetError(@error,0,0) Local $ResultArray[UBound($x)][4] For $i = 0 To UBound($x)-1 $entry = $x[$i] For $y = 0 To UBound($entry)-1 $j = $y If $y > 3 Then $j = 3 $ResultArray[$i][$j] = $entry[$y] Next Next Return $ResultArray EndFunc robertocm 1 *GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes Link to comment Share on other sites More sharing options...
PsaltyDS Posted February 17, 2010 Share Posted February 17, 2010 Yes I did. I always check the helpfile before posting here to save myself from replies stating "Hey, dumbo, look at the helpfile, check entries for $CmdLine". It wasn't meant as any commentary on the powers of your AutoIt-Fu. And no, you're not right: it IS that complicated.Didn't seem so: expandcollapse popup#cs check.exe ...Checks all and everything with hardest settings check.exe [Options] ...Where Options are one or more of the following: [-Severity] [-Scope <Target>] Severity options: -soft ...Checks selected target with relaxed settings -med, -medium ...Checks selected target with medium settings -hard (default) ...Checks selected target with hardest settings Scope options: -*, -all (default) ...Checks all and everything -single <Target>, -host <Target> ...Checks the single host <Target> (Target host name is required) -wg, -wkgrp, -workgroup ...Checks all defined Workgroup-Machines -OU <Target> ...Checks all machines in the Target OUname (Target OU name is required) #ce Global $Severity = "HARD", $Scope = "ALL", $Target = "" For $n = 1 To $CmdLine[0] Switch $CmdLine[$n] Case "-soft" $Severity = "SOFT" Case "-med", "-medium" $Severity = "MEDIUM" Case "-hard" $Severity = "HARD" Case "-all", "-*" $Scope = "ALL" Case "-host", "-single" $Scope = "SINGLE" $n += 1 If Not _CheckTarget($n) Then Exit Case "-wg", "-wkgrp", "-workgroup" $Scope = "WORKGROUP" Case "-ou" $Scope = "OU" $n += 1 If Not _CheckTarget($n) Then Exit Case Else MsgBox(16, "Parameter Error", "Invalid parameter in command line: " & StringReplace($CmdLineRaw, $CmdLine[$n], " >>> " & $CmdLine[$n] & " <<< ", 1)) Exit EndSwitch Next MsgBox(64, "Good Parameters", "$Severity = " & $Severity & @CRLF & _ "$Scope = " & $Scope & @CRLF & _ "$Target = " & $Target) Func _CheckTarget($i) If $CmdLine[0] >= $i And $CmdLine[$i] <> "" And StringLeft($CmdLine[$i], 1) <> "-" Then $Target = $CmdLine[$i] Return 1 Else MsgBox(16, "Parameter Error", "Missing required target parameter: " & StringReplace($CmdLineRaw, $CmdLine[$i - 1], $CmdLine[$i - 1] & " >>> ??? <<< ", 1)) Return 0 EndIf EndFunc ;==>_CheckTarget But a.) ...does this not contain any method or example how to work with more complex setups and b.) why should I reinvent the wheel? I'm quite sure that almost everyone of you has done something regarding commandline parameters...so please share.I was suggesting checking the help file for the basics (which you may had already done) then using forum search to find many examples (which you hadn't). Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
cherdeg Posted February 18, 2010 Author Share Posted February 18, 2010 (edited) Hey guys: thank you all. Finally I used Mhz's version; it does the best job as a sceleton for me and was far the easiest to understand and modify. And of course I needed to heavily modify it. Allover complexity didn't vanish also...just have a look: expandcollapse popup; Includes #include <Array.au3> ; Variables Global $s_CRLF = @CRLF Global $s_TAB = @TAB Global $s_IniFile = "test.ini" Global $a_IniOUsRaw Global $a_IniOUs Global $a_CmdLine = $CMDLINE ; a copy of the commandline parameters array Global $s_CmdLineRaw = $CMDLINERAW ; a copy of the commandline parameters raw string Global $s_CheckMode = "G1" ; the check mode: G1 (Group-1), G3 (Group-3) or G4 (Group-4). No parameter means G1 Global $s_Targets = "" ; the string of targets in SINGLE- or OU-Modes Global $a_Execution[3] = ["AUTO", "G1", "WG"] ; the default for execution without commandline parameters ; Debug $a_CmdLine = 0 ;~ $s_CmdLine = "-g4 -ou OU-1 OU-2 OU-3 OU-4 OU-5 /workgroup" ; ok ;~ $s_CmdLine = "-g1 -ou OU-1 OU-2 OU-3 OU-4 OU-5" ; ok ;~ $s_CmdLine = "-g3 -ou OU-1 OU-2 OU-3 OU-4 OU-5" ; ok ;~ $s_CmdLine = "-g1 /SINGLE host-1 host-2 host-3 -wg" ; ok ;~ $s_CmdLine = "-g4 /SINGLE host-1 host-2 host-3" ; ok ;~ $s_CmdLine = "-g1 /SINGLE host-1 host-2 host-3" ; ok ;~ $s_CmdLine = "-g1 -wg" ; ok ;~ $s_CmdLine = "-g4" ; ok ;~ $s_CmdLine = "-?" ; ok $s_CmdLine = "--list" ; ok $a_CmdLine = StringSplit($s_CmdLine, " ") $s_CmdLineRaw = $s_CmdLine ; Main _PrepareCommandline($a_CmdLine) _ParseCommandline($a_Execution, $a_CmdLine) ConsoleWrite($s_CRLF & "Result: " & $s_TAB & $s_TAB & $a_Execution[0] & ", " & $a_Execution[1] & ", " & $a_Execution[2] & $s_CRLF) ; DEBUG ; Functions Func _PrepareCommandline(ByRef $a_CmdLine) _ArrayDisplay($a_CmdLine) ; DEBUG If $a_CmdLine[0] > 1 Then $i_ArrayPosition = "" $s_TmpRecord = "" $a_TmpArray = $a_CmdLine For $i=$a_CmdLine[0] To 1 Step -1 If Not (StringLeft($a_CmdLine[$i], 1) == "-" Or StringLeft($a_CmdLine[$i], 2) == "--" Or StringLeft($a_CmdLine[$i], 1) == "/") Then $s_TmpRecord &= $a_TmpArray[$i] & " " _ArrayDelete($a_TmpArray, $i) $a_TmpArray[0] = UBound($a_TmpArray) EndIf Next For $i_i=1 To $a_CmdLine[0] If ($a_CmdLine[$i_i] == "-ou" Or $a_CmdLine[$i_i] == "-Ou" Or $a_CmdLine[$i_i] == "-OU" Or $a_CmdLine[$i_i] == "--ou" Or $a_CmdLine[$i_i] == "/ou" Or $a_CmdLine[$i_i] == "/Ou" Or $a_CmdLine[$i_i] == "/OU") Then $i_ArrayPosition = $i_i _ArrayInsert($a_TmpArray, $i_ArrayPosition+1, $s_TmpRecord) EndIf If ($a_CmdLine[$i_i] == "-s" Or $a_CmdLine[$i_i] == "-S" Or $a_CmdLine[$i_i] == "-single" Or $a_CmdLine[$i_i] == "-Single" Or $a_CmdLine[$i_i] == "-SINGLE" Or $a_CmdLine[$i_i] == "--single" Or $a_CmdLine[$i_i] == "/s" Or $a_CmdLine[$i_i] == "/S" Or $a_CmdLine[$i_i] == "/single" Or $a_CmdLine[$i_i] == "/Single" Or $a_CmdLine[$i_i] == "/SINGLE") Then $i_ArrayPosition = $i_i _ArrayInsert($a_TmpArray, $i_ArrayPosition+1, $s_TmpRecord) EndIf Next $a_CmdLine = $a_TmpArray EndIf EndFunc Func _ParseCommandline(ByRef $a_Execution, $a_CmdLine) ConsoleWrite("Complete Command: " & $s_TAB & $s_CmdLineRaw & @CRLF) ; DEBUG _ArrayDisplay($a_CmdLine) ; DEBUG If $a_CmdLine[0] Then For $i_i = 1 To $a_CmdLine[0] ConsoleWrite("Found Parameter: " & $s_TAB & $a_CmdLine[$i_i] & @CRLF) ; DEBUG Switch $a_CmdLine[$i_i] Case "-wg", "-Wg", "-WG", "-workgroup", "-Workgroup", "-WORKGROUP", "--workgroup", "/wg", "/Wg", "/WG", "/workgroup", "/Workgroup", "/WORKGROUP" If Not (StringInStr($s_CmdLineRaw, "-s") = 0 or StringInStr($s_CmdLineRaw, "-o") = 0 Or StringInStr($s_CmdLineRaw, "/s") = 0 or StringInStr($s_CmdLineRaw, "/o") = 0) Then $a_Execution[0] = "WG" Case "-s", "-S", "-single", "-Single", "-SINGLE", "--single", "/s", "/S", "/single", "/Single", "/SINGLE" If Not (StringInStr($s_CmdLineRaw, "-w") = 0 Or StringInStr($s_CmdLineRaw, "/w") = 0) Then $a_Execution[2] = "" $a_Execution[0] = "SINGLE" $s_Targets = $a_CmdLine[$i_i+1] Case "-ou", "-Ou", "-OU", "--ou", "/ou", "/Ou", "/OU" If Not (StringInStr($s_CmdLineRaw, "-w") = 0 Or StringInStr($s_CmdLineRaw, "/w") = 0) Then $a_Execution[2] = "" $a_Execution[0] = "OU" $s_Targets = $a_CmdLine[$i_i+1] Case "-g1", "-G1", "/g1", "/G1" $a_Execution[1] = "" Case "-g3", "-G3", "/g3", "/G3" $a_Execution[1] = "G3" Case "-g4", "-G4", "/g4", "/G4" $a_Execution[1] = "G4" Case "-h", "-H", "-help", "-Help", "-HELP", "--help", "-?", "/h", "/H", "/help", "/Help", "/HELP", "/?" ConsoleWrite($s_CRLF & "Result: " & $s_TAB & $s_TAB & "My version runs Func _InputHelp() here" & $s_CRLF) ; DEBUG Exit Case "-l", "-L", "-list", "-List", "-LIST", "--list", "/l", "/L", "/list", "/List", "/LIST" ConsoleWrite($s_CRLF & "Result: " & $s_TAB & $s_TAB & "My version runs Func _ListIniOUs() here" & $s_CRLF) ; DEBUG Exit Case Else If (StringLeft($a_CmdLine[$i_i], 1) == "-" Or StringLeft($a_CmdLine[$i_i], 2) == "--" Or StringLeft($a_CmdLine[$i_i], 1) == "/") Then If $i_i == $a_CmdLine[0] Then ConsoleWrite($s_CRLF & "Result: " & $s_TAB & $s_TAB & "My version runs Func _InputError() here" & $s_CRLF) ; DEBUG Exit EndIf EndIf EndSwitch Next EndIf EndFunc If anyone of you finds a way to strip the code down a little, it's highly appreciated! It would be cool to get rid of the StringInString and great to shorten the comparistons a bit. Best Regards, Chris Edited February 18, 2010 by cherdeg Link to comment Share on other sites More sharing options...
MvGulik Posted February 18, 2010 Share Posted February 18, 2010 (edited) whatever Edited February 7, 2011 by MvGulik "Straight_and_Crooked_Thinking" : A "classic guide to ferreting out untruths, half-truths, and other distortions of facts in political and social discussions.""The Secrets of Quantum Physics" : New and excellent 2 part documentary on Quantum Physics by Jim Al-Khalili. (Dec 2014) "Believing what you know ain't so" ... Knock Knock ... Link to comment Share on other sites More sharing options...
cherdeg Posted February 19, 2010 Author Share Posted February 19, 2010 (edited) So Case "-wg", ... == Case "-wg", "-Wg", "-WG", .... Well it's shorter.Thank you!That's something I didn't even think about - but of course, you're completely right! Edited February 19, 2010 by cherdeg Link to comment Share on other sites More sharing options...
lsakizada Posted August 21, 2010 Share Posted August 21, 2010 (edited) Something I wrote some time ago. It automatically recognizes the connection between a parameter and its value, so you logic for processing the parameters can be simpler. The complete commands of your script are stored in $CMDLINERAW. You can parse it with this function: expandcollapse popup#include <Array.au3> $CMDString = '/a:"value" -big="this -test:1\"23 is & $#@ _ your life" -test=th_3 -tte -äß$=/ätest/h.b' $ResultArray = _ParseCMDLine($CMDString) _ArrayDisplay($ResultArray) ;=============================================================================== ; ; Function Name: _ParseCMDLine($CMDString) ; Description:: Parses a CMD-String to Parameters with Values ; Parameter(s): $CMDString -> String to parse ; Requirement(s): ? ; Return Value(s): Error: 0 and @error = StringRegExp-Error ; Success: 2 Dimensional Array: ; $array[$i][0] : Parameter including value ; $array[$i][1] : Parameter ; $array[$i][2] : Value with quotation marks (only if value has quotaion marks) ; $array[$i][3] : Value without quotation marks ; Author(s): Prog@ndy ; ; Basis: http://regexlib.com/REDetails.aspx?regexp_id=1220 ;=============================================================================== ; Func _ParseCMDLine($CMDString) Local $y, $j, $i, $entry Local $x = StringRegExp($CMDString,'(?:\s*)(?<=[-|/])(?<name>[^\s-|/:|=]*)(?:(?:[:|=](?:("(?<value1>.*?)(?<!\\)")|(?<value>\S*)))|\w*?)',4) If @error Then Return SetError(@error,0,0) Local $ResultArray[UBound($x)][4] For $i = 0 To UBound($x)-1 $entry = $x[$i] For $y = 0 To UBound($entry)-1 $j = $y If $y > 3 Then $j = 3 $ResultArray[$i][$j] = $entry[$y] Next Next Return $ResultArray EndFunc Hi ProgAndy, If the value ended with backslash character then the parsing is incorrect. for examplae, use this $CmdLineRaw. Param1="c:\" Param2="C:\Program Files\SomeDir" regards Edited August 21, 2010 by lsakizada Be Green Now or Never (BGNN)! Link to comment Share on other sites More sharing options...
MvGulik Posted August 21, 2010 Share Posted August 21, 2010 (edited) whatever Edited February 7, 2011 by MvGulik "Straight_and_Crooked_Thinking" : A "classic guide to ferreting out untruths, half-truths, and other distortions of facts in political and social discussions.""The Secrets of Quantum Physics" : New and excellent 2 part documentary on Quantum Physics by Jim Al-Khalili. (Dec 2014) "Believing what you know ain't so" ... Knock Knock ... Link to comment Share on other sites More sharing options...
jmtces Posted July 1, 2016 Share Posted July 1, 2016 On 2/18/2010 at 0:45 AM, MHz said: If it is a big amount of cmdline switches to handle then I opt for the abbreviations that i added to the full installed Scite4AutoIt3 editor. You have a choice of "cmdlineselect", "cmdlineselect2", "cmdlineswitch" and "cmdlineswitch2".  I will show by example how I typed "cmdlineswitch" (without quotes) into Scite4AutoIt3 and press the space bar to expand the abbreviation into the code structure that magically appears. Typed:  cmdlineswitch pressed spacebar to get:  #region - CmdlineSwitch If $CMDLINE[0] Then For $i = 1 To $CMDLINE[0] Switch $CMDLINE[$i] Case '/?' MsgBox(0x40000, @ScriptName & ' Help', _ 'Switches are:' & @CRLF _ & @CRLF & '/extract' _ & @CRLF & @TAB & 'Extract files to current directory' _ & @CRLF & '/x' _ & @CRLF & @TAB & '' _ & @CRLF & '/x' _ & @CRLF & @TAB & '' _ & @CRLF & '/x' _ & @CRLF & @TAB & '' _ & @CRLF & '/x' _ & @CRLF & @TAB & '') Exit Case '/extract' FileInstall('?', @ScriptDir & '') Exit Case '/x' Case '/x' Case '/x' Case '/x' Case Else MsgBox(0x40000, 'Incorrect switch used', _ 'Command used:' & @CRLF & $CMDLINERAW & @CRLF & _ @CRLF & 'Use /? for the switches available.') Exit EndSwitch Next EndIf #endregion  Now with some changes.  expandcollapse popup#cs - test switches to pass /hard /single singlehost ; test1 ok /wg /ou host1,host2,host3 ; test2 ok /wg /ou /host1,host2,host3 ; test3 error #ce #region - CmdlineSwitch Global $settings, $single, $wg, $ou If $CMDLINE[0] Then For $i = 1 To $CMDLINE[0] Switch $CMDLINE[$i] Case '/?' MsgBox(0x40000, @ScriptName & ' Help', _ 'Switches are:' & @CRLF _ & @CRLF & '/extract' _ & @CRLF & @TAB & 'Extract files to current directory' _ & @CRLF & '/soft' _ & @CRLF & @TAB & 'Description' _ & @CRLF & '/med' _ & @CRLF & @TAB & 'Description' _ & @CRLF & '/hard' _ & @CRLF & @TAB & 'Description' _ & @CRLF & '/single' _ & @CRLF & @TAB & 'Description' _ & @CRLF & '/wg' _ & @CRLF & @TAB & 'Description' _ & @CRLF & '/ou' _ & @CRLF & @TAB & 'Description') Exit Case '/extract' FileInstall('?', @ScriptDir & '\?') Exit Case '/soft' $settings = 1 Case '/med' $settings = 2 Case '/hard' $settings = 3 Case '/single' $single = $CMDLINE[$i+1] ; assign next indexed value If StringLeft($single, 1) = '/' Then ConsoleWriteError('Incorrect parameter following /single' & @CRLF) Exit 1 EndIf $i += $i ; increase $i Case '/wg' $wg = True Case '/ou' $ou = $CMDLINE[$i+1] ; assign next indexed value If StringLeft($ou, 1) = '/' Then ConsoleWriteError('Incorrect parameter following /ou' & @CRLF) Exit 1 EndIf $i += $i ; increase $i Case Else MsgBox(0x40000, 'Incorrect switch used', _ 'Command used:' & @CRLF & $CMDLINERAW & @CRLF & _ @CRLF & 'Use /? for the switches available.') Exit EndSwitch Next EndIf #endregion ; set hard settings by default if optin is not selected If Not $settings Then $settings = 3 EndIf ; show variables for this test MsgBox(0, @ScriptName, _ '$settings = ' & $settings & @CRLF & _ '$single = ' & $single & @CRLF & _ '$wg = ' & $wg & @CRLF & _ '$ou = ' & $ou _ ) The example is not complete as Msgboxes for a CLI application is perhaps not suitable and error checking is incomplete etc. But it does show you that processing incoming cmdline switches can be achieved in an orderly fashion. Have a look at Jos' AutoIt3Wrapper source in the Scite4AutoIt3 install folder for a similar use of handling cmdline incoming switches. I have done projects that use many switches with the similar technique.  May I suggest that you use a comma separated list of hosts for the /ou switch and you can StringSplit them later in your script. And you may notice that I welcome the switches starting with a forward slash and not starting with a dash that is normally used in a posix based system.  Test in Scite4AutoIt3 with the commented switches in the script above or with your own combination. Just press Shift+F8 to show parameter window and add parameters to test with then press F5 to run the script.  I slightly modified MHz's first script on this page dated 18 Feb 2010 (quoted above) to parse command line arguments with defaults for omitted arguments... #include <Date.au3>  ;Declare variables and initialize defaults Global $Mode = "MANUAL", $CurShift, $Shift, $LogFile=@YEAR & @MON & @MDAY & ".log" Global $LogsFolder = @ScriptDir & '\Logs\', $LogFileName Global $AMShiftStart = "07:30", $PMShiftStart = "15:30", $NIGHTShiftStart = "00:00" GetLastCompletedShift(@HOUR & ":" & @MIN)   ;Get the last completed shift based on the current time ;GetLastCompletedShift("00:01")   ;Test with times set for different shifts ;GetLastCompletedShift("07:31") ;GetLastCompletedShift("15:31") ConsoleWrite('$Mode: ' & $Mode & @CRLF & "$LogFile: " & $LogFile & @CRLF) ConsoleWrite('$LogsFolder: ' & $LogsFolder & @CRLF & "$LogFileName: " & $LogFileName & @CRLF) ConsoleWrite('$CurShift: ' & $CurShift & @CRLF & "$Shift: " & $Shift & @CRLF) Local $Parms =  $CMDLINE, $Extended =  $CMDLINE, $pntr ConsoleWrite("$Parms[0]" & $Parms[0] & " $Extended[0] " & $Extended[0] & @CRLF) DoCmdLine() AdjustLogDate() $LogFileName = $LogsFolder & $LogFile ConsoleWrite('$Mode: ' & $Mode & @CRLF & "$LogFile: " & $LogFile & @CRLF) ConsoleWrite('$LogsFolder: ' & $LogsFolder & @CRLF & "$LogFileName: " & $LogFileName & @CRLF) ConsoleWrite('$CurShift - ' & $CurShift & @CRLF & "$Shift " & $Shift & @CRLF) ;Do my other functions to load, parse, analyze and email logs here Exit Func DoCmdLine()    If $CMDLINE[0] Then       Local $Parms =  $CMDLINE, $Extended =  $CMDLINE, $pntr       For $i = 1 To $CMDLINE[0]          $Parms[$i] = StringRight($Parms[$i], StringLen($Parms[$i]) - 1)   ;strip off "/"          $pntr = StringInStr($CMDLINE[$i], "=")          If $pntr Then             $Parms[$i] = StringLeft($CMDLINE[$i], $pntr - 1)             $Extended[$i] = StringRight($CMDLINE[$i], StringLen($CMDLINE[$i]) - $pntr)             $Parms[$i] = StringRight($Parms[$i], StringLen($Parms[$i]) - 1)   ;strip off "/"          EndIf          Switch StringUpper($Parms[$i])             Case '?'                MsgBox(0x40000, @ScriptName & ' Help', _                      'Command Line Switches are:' & @CRLF _                      & @CRLF & '/AUTO|MANUAL' _                      & @CRLF & @TAB & 'AUTO - Do all steps to complete and email summary automatically and exit' _                      & @CRLF & @TAB & 'MANUAL - Do all steps to complete and email summary interactively' _                      & @CRLF & @TAB & @TAB & 'default = manual' _                      & @CRLF & '/AM|PM|NIGHT' _                      & @CRLF & @TAB & 'Select one of three shifts (AM, PM or NIGHT)' _                      & @CRLF & @TAB & @TAB & 'default = most recent shift completed' _                      & @CRLF & '/LOGFILE=filename' _                      & @CRLF & @TAB & 'Specify which log file to summarize (filename format - yyyymmdd.log)' _                      & @CRLF & @TAB & @TAB & 'default = most recent log (Logs rotate at midnight)' _                      & @CRLF & '/LOGSFOLDER=path' _                      & @CRLF & @TAB & 'Select the logs folder path to use' _                      & @CRLF & @TAB & @TAB & 'default = ' & $LogsFolder _                      & @CRLF & @CRLF & 'Example = ' & @ScriptName & " /auto /pm /Logfile=20160616.log /logsfolder=C:\NurseCallMon\Logs\")                Exit             Case 'AUTO', 'MANUAL'                $Mode = StringUpper($Parms[$i])             Case 'AM', 'PM', 'NIGHT'                $Shift = StringUpper($Parms[$i])             Case 'LOGFILE'                $LogFile = $Extended[$i]             Case 'LOGSFOLDER'                $LogsFolder = $Extended[$i]                if StringRight($LogsFolder,1)<> "\" Then $LogsFolder = $LogsFolder & "\"             Case Else ConsoleWrite('$Parms[$i] ' & $Parms[$i] & @CRLF & "$Extended[$i] " & $Extended[$i] & @CRLF)                MsgBox(0x40000, 'Incorrect switch used', _                      'Command used:' & @CRLF & $CMDLINERAW & @CRLF & _                      @CRLF & 'Use /? for the switches available.')                Exit          EndSwitch       Next    EndIf EndFunc Func GetLastCompletedShift($tTime)    ;Detect the shift from the current time to find last completed shift    $CurShift = "NIGHT"   ;set Defaults before time tests below    $Shift = "PM"    If $tTime >= $AMShiftStart Then       ;Bump it if after the start of the AM shift       $CurShift = "AM"       $Shift = "NIGHT"    EndIf    If $tTime >= $PMShiftStart Then       ;Bump it if after the start of the AM & PM shifts       $CurShift = "PM"       $Shift = "AM"    EndIf EndFunc Func AdjustLogDate()    ;If NIGHT shift is requested then get the previous days log file since logs are rotated at Midnight    local    $sNewDate    If $Shift = "NIGHT" And $LogFile = @YEAR & @MON & @MDAY & ".log" then       $LogFile = @YEAR & @MON & @MDAY-1 & ".log"       $sNewDate = _DateAdd('d', -1, _NowCalcDate())       $sNewDate = StringLeft($sNewDate,4) & StringMid($sNewDate,6,2) & StringRight($sNewDate,2)       $LogFile = $sNewDate & ".log"    EndIf ConsoleWrite(@ScriptLineNumber & ' $CurShift: ' & $CurShift & @CRLF & "$Shift: " & $Shift & @CRLF & @YEAR & @MON & @MDAY & @CRLF & $sNewDate & @CRLF) EndFunc  Link to comment Share on other sites More sharing options...
GeraldB Posted October 17, 2019 Share Posted October 17, 2019 Considering there is demand for this I wrote this basic parser in a pinch. Paste into a text file named Parameter.au3 then include it atop your script. _GetParameter(String Parameter Name, Optional default value if not found, type bool or string) The default value, if omitted will be an empty string for string types (default) or false for bool types. I added the bool type notion to check for just the existence of a parameter without any specific value as the next $CmdLine, like for example /help or /force etc... The default, string type, will return the next $CmdLine item as such, unless there is nothing behind your parameter in which case it returns the default value as well (empty string). Example usage: If _GetParameter("help", false, "BOOL") Then ; show some help with MsgBox or something like that EndIf $myUser = _GetParameter("user", "NoBody") If $myUser = "NoBody" Then ; handle if no username was provided, like messaging the /user option is mandatory EndIf  expandcollapse popup#include <Array.au3> ; Parameter name should not be prefixed with / or - as we will add this ourself in the search ; Type should be string or bool ; String will return the next $CmdLine value whereas bool will return True or False whether the parameter is found or not ; Default should be the default value in case the option is not given Func _GetParameter($name, $default = Default, $type = "STRING") $uType = StringUpper($type) ; I know = is case insensitive, but just in case... ; if there is no default specified then initialize the $default var according to the type If $default = Default then if $type = "STRING" then $default = "" else $default = false endif EndIf ; First make sure there were command line arguments given else we return the default If $CmdLine[0] = 0 Then Return $default EndIf ; Just in case the dev' uses / or - let's test for that If StringLeft($name, 1) == "-" or StringLeft($name, 1) == "/" Then ; Only search as requested, no variations $i = _ArraySearch($CmdLine, $name) If $type = "STRING" and $i > 0 and $i < $CmdLine[0] Then Return $CmdLine[$i + 1] ElseIf $type = "BOOL" and $i > 0 Then Return True Else Return $default EndIf Else ; Search with / in front of parameter name (Microsoft default) $i = _ArraySearch($CmdLine, "/" & $name) ; If not found try again with - in front of name If $i = -1 Then $i = _ArraySearch($CmdLine, "-" & $name) EndIf If $type = "STRING" and $i > 0 and $i < $CmdLine[0] Then Return $CmdLine[$i + 1] ElseIf $type = "BOOL" and $i > 0 Then Return True Else Return $default EndIf EndIf EndFunc  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