Syntax and Meaning of Primary Sections of a opsi-script Script [W/L/M]
As shortly presented in chapter Primary and Secondary Subprograms of a opsi-script script the Actions section of a script can be regarded as a the main method of the opsi-script script and describes the global processing sequence. It may call subroutines - the Sub sections which may then recursively call Sub sections themselves.
The following sections explain syntax and use of the primary sections of a opsi-script script.
Primary Sections [W/L/M]
There are possibly three kinds of primary sections in a script
-
an
Initial
section (may be omitted), -
an
Action
section, -
any number of
Sub
sections -
an
ProfileActions
section
Initial
and Action
section are syntactically equivalent (but Initial has to keep the first place). By convention, in the Initial section some parametrizations of the script execution (e.g. the loglevel) are made. The Action section can be regarded as the main program in a opsi-script script. It contains the sequence of actions that are controlled by the script.
Sub sections are as well syntactically equivalent. But they are a called from the Action section. Then, they can call themselves Sub
sections.
A Sub
section is determined by creating a name that begins with "Sub", e.g. Sub_InstallBrowser
. By writing its name in the Action section we produce a call to the Sub section. The meaning of this call is defined by the content of the section in the script that begins with the bracketed name, in the example [Sub_InstallBrowser]
Subsections of second and higher order cannot host internal sections. Instead, their procedure calls must refer to sections defined in the main script file or defined as external sections (cf. Subprogram Calls). |
If (nested) sub sections are externalized to external files, the called sections has to be in that file where they are called from. According to the complexity of the script they may sometimes have to be placed also in the main file. |
A ProfileActions
section at a normal installation script may be used as a sub section with a special syntax. In a 'userLoginScript' this section will be used as script start (instead of Actions
). See chapter 'User Profile Management' at the opsi-manual and Commands for userLoginScripts / User Profile Management.
Parametrizing opsi-script [W/L/M]
Specification of Logging Level [W/L/M]
The old function LogLevel= is discouraged since opsi-script version 4.10.3. For backward compatibility reasons Loglevels ste by this old function will be increased by 4 before they are used.
|
There are two syntactical variants for specifying the logging level:
-
SetLogLevel
= <number> -
SetLogLevel
= <String expression>
I.e. the number can be given as an integer value or as a string expression (cf. String Expressions, String Values, and String Functions). In the second case, opsi-script tries to evaluate the string expression as a number. There exist ten levels from 0 up to 9.
The logging at the different log levels is:
-
Log level 5:
comments,messages, Execution of sections -
Log level 6:
Statements, New values for stringvars , results of complete boolean expression -
Log level 7:
new values for stringlist vars, output from external processes (ShellScript) if the out put is not assinged to a stringlist variable, results of parts of a boolean expression -
Log level 8:
other stringlist output eg. string lists from stringlist functions and output from external processes (ShellScript) that is assinged to a stringlist variable.
The default value is "7".
see also : opsi-script-configs_default_loglevel
see also : opsi-script-configs_force_min_loglevel
SetDebug_Lib
= <boolean value> //since 4.12.8.0
If false, then log messages from defined functions that are imported from external library files will be suppressed except for Warnings and Errors.
The default value is false.
see also : opsi-script-configs_debug_lib
Logdatei im Append-Mode senden
forceLogInAppendMode =
<boolean value> //since 4.12.3.6
(default=false); if true, log will be send in append mode
Required opsi-script Version [W/L/M]
The statement
requiredOpsiscriptVersion
<RELATION SYMBOL> <NUMBER STRING>
since 4.12.3.6
e.g.
requiredOpsiscriptVersion >= "4.12.3.6"
makes opsi-script check if the desired version state is given. Otherwise an error message windows pops up or is written to the log and the script result is failed.
There is no default.
A identical but outdated version is (since 4.3):
requiredWinstVersion
<RELATIONSSYMBOL> <ZAHLENSTRING>
Reacting on Errors [W/L/M]
There are two kinds of errors which are treated in different ways:
-
illegal statements which cannot be interpreted by opsi-script (syntactical errors),
-
failing statements which cannot be executed because of external, objective reasons (execution errors).
In principal, syntactical errors lead to a 'script is failed' situation, execution errors are logged in a log file to be analysed later.
The behaviour of opsi-script when it recognizes a syntactical error is defined by the configuration statement
-
ScriptErrorMessages =
<boolean value>
If the value is true (default), syntactical errors trigger a pop up window with some informations on the error.
The boolean value may be 'true' or 'false'. Delimiters 'on' or 'off' can be used as well.
Default=true
see also: opsi-script-configs_ScriptErrorMessages
-
FatalOnSyntaxError =
<boolean value>-
'true' = (default) If a syntax error occurs, then the script execution will be stopped and the script result will be set to 'failed'. Also, the message 'Syntax Error' will be passed to the opsi-server.
-
'false' = If a syntax error occurs, then the script execution will not be stopped and the script result will be set to 'success'.
-
In either case above, the syntax error will be logged as 'Critical'.
In either case above, the error counter will be increased by 1.
Since 4.11.3.2
In older versions there was no logging of syntax errors, no increase of error counter, and the result was always set to 'success'.
-
FatalOnRuntimeError =
<boolean value>
A Runtime Error is an script logic error that leads to an forbidden or impossible operation. An Example: You try to get the 5th string from a string list that have only 3 elements.-
'true' = If a runtime error occurs, then the script execution will be stopped and the script result will be set to 'failed'. Also, the message 'Runtime Error' will be passed to the opsi-server.
-
'false' = (default) If a runtime error occurs, then the script execution will not be stopped and the script result will be set to 'success'. The runtime error will be logged as 'Error' and the error counter will be increased by 1.
Since 4.11.4.3
-
There two configuration options for execution errors.
-
ExitOnError =
<boolean value>
This statement defines if the script execution shall terminate when an error occurs. If the value is true or yes the program will stop execution, otherwise errors are just logged (default). -
TraceMode =
<boolean value>
In TraceMode (default false) every log file entry will additionally be shown in message window with an O.K. button.
Staying On Top [W]
-
StayOnTop =
<Wahrheitswert>
With StayOnTop = true (or = on) we request, that - in batch mode - the opsi-script window be on top on the windows which share the screen. That means it should be visible in the "foreground" as long as no other window having the same status wins.
According to the system manual the value cannot be changed while the program is running. But it seems that we can give a new value to it once. |
StayOnTop
has default false in order to avoid that some other process raises an error message which eventually can not be seen if opsi-script keeps staying on top.
Show window mode / Skin / Activity [W/L/M]
-
SetSkinDirectory
<skindir> // [W/L/M]
Sets the skin directory to use and loads the skin. If this command is used wit an empty or invalid path, the default skin dir is used. The default skin dir%OpsiScriptDir%\skin
.
Example:
SetSkinDirectory "%ScriptPath%\testskin"
sleepseconds 1
SetSkinDirectory ""
see also: Skinnable opsi-script
To change the modes of how the opsi-script window is displayed, use these commands:
-
NormalizeWinst
Sets the opsi-script window to the 'normal' mode
-
IconizeWinst
Sets the opsi-script window to the 'minimized' mode
-
MaximizeWinst
//since 4.11.5
Sets the opsi-script window to the 'maximized' mode
-
RestoreWinst
Sets the opsi-script window to the mode before the last change
-
AutoActivityDisplay =
<boolean value> // (default=false) //since 4.11.4.7
If true shows a marquee (endless) progressbar while winbatch/ShellScript sections are running.
see also: AutoActivityDisplay
Reloading the product list [W/L/M]
-
reloadProductList
//since 4.12.6.1
Reloads the product list from the opsi-server after executing the script in opsi-script. If the product list is not empty, opsi-script will process it again.reloadProductList
can be placed anywhere in the Actions section of the script. However, the recommendation is, according to logic, to put the command at the end of the section.
String Expressions, String Values, and String Functions [W/L/M]
A String expression can be
-
an elementary String value
-
a nested String value
-
a String variable
-
the concatenation of other String expressions
-
a String valued function call
Elementary String Values
An elementary String value is any sequence of characters that is enclosed in double or single citations marks, formally:
'"<sequence of characters>"'
or
''<sequence of characters>''
Example:
DefVar $ExampleString$
Set $ExampleString$ = "my Text"
Strings in Strings (Nested String Values)
If the sequence of chars itself contains citation marks we have to use the other kind of citation marks to enclose it:
DefVar $citation$
Set $citation$ = 'he said "Yes"'
If the sequence of chars is containing both kinds of citation marks we must use the following special expression:
EscapeString:
<sequence of characters>
E.g. we can write:
DefVar $Meta_citation$
Set $Meta_citation$ = EscapeString: Set $citation$ = 'he said "Yes"'
Then the variable $Meta_citation$
will exactly contain the complete sequence of chars that follows the colon after "EscapeString" (including the blank). Such, $Meta_citation$
will contain the complete statement:
Set $citation$ = 'he said "Yes"'
String Concatenation
String concatenation is written using the addition sign ("+")
<String expression> +
<String expression>
Example:
DefVar $String1$
DefVar $String2$
DefVar $String3$
DefVar $String4$
Set $String1$ = "my text"
Set $String2$ = "and"
Set $String3$ = "your text"
Set $String4$ = $String1$ + " " + $String2$ + " " + $String3$
$String4$
then has value "my text and your text".
String Variables
A String variable in a primary section "contains" a String value. In an String expression, it can always substitute an elementary string. For how to define and set String variables cf. String (or Text) Variables.
The following sections present the variety of string functions.
String Functions which Return the OS Type
-
GetOS : string
[W/L/M]
The function tells which type of operating system is running.
GetOS` returns one of the following values:-
"Windows_NT" (including Windows 2000 to Windows 10)
-
"Linux"
-
"macos"
-
-
GetNtVersion
[W]
Deprecated - please use use GetMSVersionInfo.
A Windows NT operating system is characterized by a the Windows type number and a subtype number. GetNtVersion returns the precise subtype name. Possible values are
"NT3"
"NT4"
"Win2k" (Windows 5.0)
"WinXP" (Windows 5.1)
"Windows Vista" (Windows 6)
If the NT operating system has higher versions as 6 or there are version not explicitly known the function returns "Win NT" and the complete version number (5.2, … resp. 6.0 ..) . E.g. for Windows Server 2003 R2 Enterprise Edition, we get
"Win NT 5.2"
If the operating system is no Windows NT system the function returns the error value
"No OS of Windows NT type"
-
GetMsVersionInfo
[W]
returns for systems of type Windows NT the Microsoft version info as indicated by the API, e.g. a Windows 7 system produces the result
"6.1"
GetMsVersionInfo | Windows Version |
---|---|
5.0 |
Windows 2000 |
5.1 |
Windows XP (Home, Prof) |
5.2 |
XP 64 Bit, 2003, Home Server, 2003 R2 |
6.0 |
Vista, 2008 |
6.1 |
Windows 7, 2008 R2 |
6.2 |
Windows 8, 2012 |
6.3 |
Windows 8.1, 2012 R2 |
10.0 |
Windows 10 |
see also GetMSVersionMap
-
GetMsVersionName
[W] // since 4.12.4.35
returns for Windows systems the marketing version info, e.g. a Windows 7 system produces the result: "7.0". Window 11 gives "11.0".
GetMsVersionName | Windows Version |
---|---|
5.0 |
Windows 2000 |
5.1 |
Windows XP (Home, Prof) |
5.2 |
XP 64 Bit, 2003, Home Server, 2003 R2 |
6.0 |
Vista, 2008 |
7.0 |
Windows 7, 2008 R2 |
8.0 |
Windows 8, 2012 |
8.1 |
Windows 8.1, 2012 R2 |
10.0 |
Windows 10, 2016, 2019 |
11.0 |
Windows 11, 2022 |
see also GetMSVersionMap
see also GetMsVersionInfo
-
getLinuxDistroType : string
[L]
returns the type of the running Linux distribution an can be used to determine which general syntax we have to use. It may return one of the following values-
'debian' (Debian / Ubuntu → use apt-get)
-
'redhat' (RedHat / CentOs → use yum)
-
'suse' (→ use zypper) (see
getLinuxVersionMap
) [L]
-
-
getMacosVersionInfo : string
//macOS Version Information //since 4.12.1.0 [M]
(seegetMacosVersionMap
) [M]
-
GetSystemType : string
[W/L/M]
checks the installed OS if it can be assumed that the system is 64 Bit. In this case the value is '64 Bit System' otherwise 'x86 System'.
-
getOSArchitecture
// OS Architecture //since 4.12.4.17 checks the installed OS for the processor architecture it is build for. Possible values are:-
x86_32
(Intel / AMD X86 Architecture with 32 Bit) -
x86_64
(Intel / AMD X86 Architecture with 64 Bit) -
arm_64
(ARM Architecture with 64 Bit e.g Apple M1)
-
String Functions for Retrieving Environment or Command Line Data [W/L/M]
-
EnvVar (
<environment variable>`) : string` [W/L/M]
The function reads and returns the momentary value of a system environment variable. E.g., we can retrieve which user is logged in byEnvVar ("Username")
.
-
ParamStr
[W/L/M]
The function passes the the parameter string of the opsi-script command line i.e. the command line parameter which is indicated by /parameter. If there is no such parameter ParamStr returns the empty string.
-
getLastExitCode : string (exitcode)
[W/L/M]
returns a string that contains the value of the exitcode of the last process called by a WinBatch / ShellScript / ExecWith section.
When using a ShellScript or ExecWith section, you will normally get the exitcode from the interpreter that was called. To get the exitcode of your script, you have to define it explicitly.
Example:
ShellScript_exit1
set $ConstTest$ = "1"
set $CompValue$ = getLastExitCode
if ($ConstTest$ = $CompValue$)
comment "ShellScript exitcode passed"
else
set $TestResult$ = "not o.k."
LogWarning "ShellScript exitcode failed"
endif
[ShellScript_exit1]
rem create an errolevel= 1
VERIFY OTHER 2> NUL
echo %ERRORLEVEL%
exit %ERRORLEVEL%
-
GetUserSID(
<Windows Username>`)` [W]
returns the SID for a given user (possibly with domain prefix in the form DOMAIN\USER).
-
GetUsercontext
[W]
returns the string which was given to the opsi-script by the optional parameter/usercontext
. IF this parameter was not userd the returned string is empty.
Reading Values from the Windows Registry and Transforming Values into Registry Format [W]
-
getRegistryValue (
<keystr>, <varstr>)
: string //since 4.12.0.16 [W]
tries to use <keystr> as Registry key and open it and read there the variable <varstr> and return the value of this variable as a string.
If there is no registry key <keystr> or the variable <varstr> does not exist the function produces a warning message in the log file and returns the empty string.
If <varstr> is an empty string, the default entry of the key will be returned.
By Default the registry access mode issysnative
. Using the optional third parameter <access str>, the access mode can be explicitly given. In this case it has to be one of the following values:32bit
,sysnative
,64bit
.
(see also: Chapter 64 Bit)
Example:
getRegistryValue("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", "Shell")
getRegistryValue("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", "Shell","64bit")
-
GetRegistrystringvalue(`"[key] var"
) : string` [W]
This command is discouraged, please use: getRegistryValue
tries to interpret the passed String value as an expression of format
'[KEY] X'
Then, the function tries to open the registry keyKEY
, and, in case it succeeds, to read and return the String value that belongs to the registry variable nameX
.
E.g.
GetRegistryStringValue ("[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon] Shell")
usually yields "Explorer.exe", the default Windows shell program.
If there is no registry key KEY
or the variable X
does not exist the function produces a warning message in the log file and returns the empty string.
For example: If we made a 'standard entry' with the value standard entry at the key HKEY_LOCAL_MACHINE\SOFTWARE\opsi.org\opsi-script-test\test-4.0, we will get with
Set $CompValue$ = GetRegistryStringValue32 ("[HKEY_LOCAL_MACHINE\SOFTWARE\opsi.org\opsi-script-test\test-4.0]")
the following log:
Registry started with redirection (32 Bit)
Registry key [HKEY_LOCAL_MACHINE\SOFTWARE\opsi.org\opsi-script-test\test-4.0] opened
Key closed
The value of the variable "$CompValue$" is now: "standard entry"
-
GetRegistryStringValue32 (`"[key] var"
) : string`
→ see Chapter 64 Bit
see also :getRegistryValue
-
GetRegistryStringValue64 (`"[key] var"
) : string`
→ seegetRegistryValue
-
GetRegistryStringValueSysNative (`"[key] var"
) : string`
→ see Chapter 64 Bit
see also :getRegistryValue
-
RegString(
<string>`)`
is useful for transforming path names into the format which is used in the Windows registry. That is, any backslash is duplicated. E. g.,
RegString ("c:\windows\system\")
yields
'"c:\\windows\\system\\"'
-
which(
<command string>`) : string` //since 4.12.3.6 [W/L/M]
returns the complete path to the given <command string> (if <command string> is in the search path) Just like the well known Unix command 'which'.
Reading Values from ini files [W/L/M]
For historical reasons, there are three functions for reading values from configuration files which have ini file format. Since opsi 3.0 the specific product properties are retrieved from the opsi configuration demon (that may fetch it from a configuration file or from any other backend data container).
In detail:
Ini file format means that the file is a text file and is composed of "sections" each containing key value pairs:
[section1]
Varname1=Value1
Varname2=Value2
...
[section2]
...
The most general function reads the value belonging to some key in some section of some ini file. Any parameter can be given as an arbitrary String expression:
-
GetValueFromInifile (
<file path>, <section>, <key>, <default value>, OPTIONAL <encoding>`) : string` [W/L/M]
The function tries to open the ini file <file path>, retrieve the requested <section> and find the value belonging to the specified <key> which the function will return. If any of these operations fail, <default value> is returned.
Starting from opsi-script 4.12.6.0,GetValueFromInifile
supports a fifth, optional parameter <encoding>, which helps reading the ini file in the correct encoding. We recommend using it in case of special encodings.
GetValueFromInifile("myfile","mysec","mykey","")
GetValueFromInifile("myfile","mysec","mykey","", "utf16-le")
The second function borrows its syntax from the ini file format itself, and may sometimes be easier to use. But since this syntax turns complicated in more general circumstances it is discouraged. The syntax reads:
-
GetIni (
<Stringausdruck> [ <character sequence> ] <character sequence>`)`
(discouraged, use GetValueFromInifile) The <String expression> is interpreted as file name, the first <character sequence> as section name, the second as key name.
Reading Product Properties [W/L/M]
-
GetProductProperty (
<PropertyName>, <DefaultValue>`)`
where $PropertyName$ and $DefaultValue$ are String expressions. If opsi-script is connected to the opsi configuration service the product property is retrieved from the service.
If there is no connection to the opsi server, then the resulting string is constructed in the following way:
Since 4.12.4.32 it is checked if there ist a fileproperties.conf
in the%ScriptPath%
directory. If this file is found, we try to get the value from this file. The file will be interpreted as list of key=value pairs. In case of a string the entry should have the pattern<property name>=<string value>
for examle:myproperty=myentry
.
If there is no fileproperties.conf
or it does not contain the searched entry, so value<default value>
is returned.
The product properties can be used to configure variants of an installation.
E.g. the opsi UltraVNC network viewer installation may be configured using the options
-
viewer = <yes> | <no>
-
policy = <factory_default> |
The installation script branches according to the chosen values for these options which can be retrieved by
GetProductProperty("viewer", "yes")
GetProductProperty("policy", "factory_default")
Since 4.12.4.32: if the file %ScriptPath%\properties.conf
exists with the content:
propstr = from file proplist = ["from file",huhu"]
the following script will be (with out opsi service) successful:
[Actions]
DefStringList $list$
DefVar $str$
set $str$ = GetProductProperty('propstr','')
if $str$ = "from file"
comment "got it"
else
comment "failed"
endif
set $list$ = GetProductPropertyList('proplist','')
if takeString(0,$list$) = "from file"
comment "got it"
else
comment "failed"
endif
-
GetConfidentialProductProperty (
<PropertyName>, <DefaultValue>`)` //since 4.11.5.2
likeGetProductProperty
but handles the resulting value as confidential string.
Useful for getting passwords without logging. see alsoSetConfidential
see also: asConfidential (string)
see also: asConfidential (list) -
IniVar(
<PropertyName>`)`
(discouraged: use GetProductProperty)
Retrieving Data from etc/hosts [W/L/M]
-
GetHostsName(
<string>`)`
returns the host name to a given IP address as it is declared in the local hosts file. If the operating system is "Windows_NT" (according to environment variable OS) "%systemroot%\system32\drivers\etc\" is assumed as host file location, otherwise "C:\Windows\".
-
GetHostsAddr(
<string>`)`
tells the IP address to a given host or alias name.
String Handling [W/L/M]
-
ExtractFilePath (
<path>`) : string` [W/L/M]
interprets the passed String value as file or path name and returns the path part (the string up to the last path delimiter, including it).
Examples:
set $ConstTest$ = "C:\program files\test\"
Set $tmp$ = "C:\program files\test\test.exe"
set $CompValue$ = ExtractFilePath($tmp$)
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
-
ExtractFileExtension (
<path>`) : string` //since 4.12.1 [W/L/M]
interprets the passed String value as file or path name and returns the extension part (the string after the last dot ('.'), including it).
Examples:
set $ConstTest$ = ".exe"
Set $tmp$ = "C:\program files\test\test.exe"
set $CompValue$ = ExtractFileExtension($tmp$)
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
-
ExtractFileName (
<path>`) : string` //since 4.12.1 [W/L/M]
interprets the passed String value as file or path name and returns the file name part (the string after the last path delimiter, not including it).
Examples:
set $ConstTest$ = "test.exe"
Set $tmp$ = "C:\program files\test\test.exe"
set $CompValue$ = ExtractFileName($tmp$)
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
-
forcePathDelims (
<path string>`) : <path string>` // since 4.12.4.21 [W/L/M]
interprets the passed String value as path name and replaces all path delimiter to the char that is specific for the running Operating System (Windows: '\', Linux und macOS: '/').
-
resolveSymlink (
<file name>`) : <file name>` // since 4.12.4.21 [W/L/M]
If the given file <file name> is a symbolic link its targert will be (recursiv) resolved and the result will be returned. In any other case the return value ist the given <file name>.
-
StringSplit (`STRINGWERT1, STRINGWERT2, INDEX
)`
(deprecated: usesplitString
/takeString
)
see also : splitString
see also : takeString
-
takeString (
<index>, <list>`) : string` [W/L/M]
returns from a string list <list> the string with the index <index>.
Often used in combination withsplitstring
:takeString(
<index>,splitString(
<string1>, <string2>`)`
(see also String List Functions and String List Processing).
The result is produced by slicing <string1> where each slice is delimited by an occurrence of <string2>, and then taking the slice with index <index> (where counting starts with 0).
Example:
takeString(3, splitString ("\\server\share\directory", "\"))
returns '"share"',
the given string slpitted at "\" returns the string list:
Index 0 - "" (empty string), because there is nothing before the first "\"
Index 1 - "" (empty string), because there is nothing before the second "\"
Index 2 - "server"
Index 3 - "share"
Index 4 - "directory"
takestring
counts downward, if the index is negative, starting with the number of elements. Therefore,
takestring(-1, $list1$)
denotes the last element of String list $list1$.
see also : setStringInListAtIndex
-
SubstringBefore(
<string1>, <string2>`)`
(deprecated: usesplitString
/takestring
) yields the sequence of characters of stringValue1 up to the beginning of stringValue2.
Example:
SubstringBefore ("C:\programme\staroffice\program\soffice.exe", "\program\soffice.exe")
returns '"C:\programme\staroffice"'.
-
getIndexFromListByContaining
(<list> : stringlist,<search string> : string`)` : <number> : string //since 4.12.0.13 [W/L/M]
Returns a string that holds the index of the first string in <list> which contains <search string>.
Retruns a empty string if no matching string is found.
The check is performed case-insensitive.
see also : [takeFirstStringContaining] -
takeFirstStringContaining(
<list>,<search string>`) : string` [W/L/M]
returns the first string from <list> which contains <search string>.
Retruns a empty string if no matching string is found.
see also : [getIndexFromListByContaining]
-
trim(
<string>`) : string` [W/L/M]
cuts leading and trailing white space from <string>.
-
lower(
<string>`) : string` [W/L/M]
returns <string> with lower case.
-
upper(
<string>`)` [W/L/M]
returns <string> with upper case.
-
contains(
<str>, <substr>`) : bool` //since 4.11.3: true if <substr> in <str> [W/L/M]
A boolean function which returns 'true' if <str> contains <substr>. This function is case sensitive.
Available since 4.11.3
Example:
set $ConstTest$ = "1xy451Xy451XY45" set $CompValue$ ="xy" if contains($ConstTest$, $CompValue$) comment "passed" else set $TestResult$ = "not o.k." LogWarning "failed" endif set $CompValue$ ="xY" if not(contains($ConstTest$, $CompValue$)) comment "passed" else set $TestResult$ = "not o.k." LogWarning "failed" endif
-
stringReplace(
<string>, <oldPattern>, <newPattern>`) : string` //since 4.11.3 [W/L/M]
returns a string, which has all occurrences of <oldPattern> replaced with <newPattern> given then input string <string>. The pattern match is case insensitive.
Example:
set $ConstTest$ = "123451234512345"
set $CompValue$ = stringReplace("1xy451Xy451XY45","xy","23")
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
-
strLength(
<string>`) : string (number)` //since 4.11.3 [W/L/M]
Returns the number of chars in in <string>
Example:
set $tmp$ = "123456789"
set $ConstTest$ = "9"
set $CompValue$ = strLength($tmp$)
if $ConstTest$ = $CompValue$
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $tmp$ = ""
set $ConstTest$ = "0"
set $CompValue$ = strLength($tmp$)
if $ConstTest$ = $CompValue$
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
-
strPos(
<string>, <sub string>`) : string (numner)` //since 4.11.3 [W/L/M]
returns the first position of <sub string> in <string>. If <sub string> is not found, then "0" is the return value. The function is case sensitive.
Example:
set $tmp$ = "1xY451Xy451xy45"
set $ConstTest$ = "7"
set $CompValue$ = strPos($tmp$,"Xy")
if $ConstTest$ = $CompValue$
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $tmp$ = lower("1xY451Xy451xy45")
set $ConstTest$ = "2"
set $CompValue$ = strPos($tmp$,lower("xy"))
if $ConstTest$ = $CompValue$
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
-
strPart(
<string>, <start pos>, <number of chars>`) : string` //since 4.11.3 [W/L/M]
returns the part of <string> starting with <start pos> and include the next <number of chars> chars. If there are fewer than <number of chars> after <start pos>, then the returned string will be the rest of the chars after <start pos>.
The counting of chars starts with 1.
Example:
set $tmp$ = "123456789"
set $ConstTest$ = "34"
set $CompValue$ = strPart($tmp$,"3","2")
if $ConstTest$ = $CompValue$
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $tmp$ = "123456789"
set $ConstTest$ = "56789"
set $CompValue$ = strPart($tmp$, strPos($tmp$,"56"),strLength($tmp$))
if $ConstTest$ = $CompValue$
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
-
unquote(
<string>,<quote-string>`) : string` //since 4.11.2.1 [W/L/M]
returns the unquoted version of <string>, if <string> is quoted with <quote-string>
Only one char (the first char) of <quote-string> is accepted as a quote char. The leading white spaces are ignored.
see also : [unquote2]
set $ConstTest$ = "b" set $CompValue$ = unquote("'b'", "'") comment "compare values" if ($ConstTest$ = $CompValue$) comment "passed" else set $TestResult$ = "not o.k." LogWarning "failed" endif comment "double quote" set $ConstTest$ = "b" set $CompValue$ = unquote('"b"', '"') comment "compare values" if ($ConstTest$ = $CompValue$) comment "passed" else set $TestResult$ = "not o.k." LogWarning "failed" endif comment "quote string will be trimmed and then only the first char is used" comment "note: brackets are different chars" set $ConstTest$ = "b]" set $CompValue$ = unquote("[b]", " [{ ") comment "compare values" if ($ConstTest$ = $CompValue$) comment "passed" else set $TestResult$ = "not o.k." LogWarning "failed" endif comment "not usable to remove brackets" set $ConstTest$ = "b]" set $CompValue$ = unquote("[b]", "[") set $CompValue$ = unquote($CompValue$,"]") set $CompValue$ = unquote("[b]", "]") set $CompValue$ = unquote($CompValue$,"[") set $CompValue$ = unquote(unquote("[b]", "["),"]") comment "compare values" if ($ConstTest$ = $CompValue$) comment "passed" else set $TestResult$ = "not o.k." LogWarning "failed" endif comment "if string not quoted it will be come back without changes" set $ConstTest$ = "b" set $CompValue$ = unquote("b", "'") comment "compare values" if ($ConstTest$ = $CompValue$) comment "passed" else set $TestResult$ = "not o.k." LogWarning "failed" endif
-
unquote2(
<string>,<quote-string>`) : string` //since 4.11.5.2 [W/L/M]
Acts likeunquote(<string>,<quote-string>)
with the following differences:
If <quote-string> contains only one char, so this char will be used as 'start quote char' and 'end quote char'. If <quote-string> contains two chars, so the first char will be used as 'start quote char' and the second char as 'end quote char'. Example: a <quote-string> like "()" will unquote a string like '(hello)'.
The function returns the unchanged <string> if not ('start quote char' AND 'end quote char') is found.
see also : [unquote]
-
HexStrToDecStr (
<hexstring>`) : string` [W/L/M]
returns the decimal representation of the input string if this was the hexadecimal representation of an integer. Leading chars like '0x' or '$' will be ignored. In case of a converting error the function returns a empty string.
-
DecStrToHexStr (
<decstring>, <hexlength>`) : string` [W/L/M]
returns a <hexlength> long string with the the hexadecimal representation of <decstring> if this was the decimal representation of an integer. In case of a converting error the function returns a empty string.
message "DecStrToHexStr"
set $ConstTest$ = "0407"
set $tmp$ = "1031"
set $CompValue$ = DecStrToHexStr($tmp$,"4")
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
message "DecStrToHexStr"
set $ConstTest$ = "407"
set $tmp$ = "1031"
set $CompValue$ = DecStrToHexStr($tmp$,"2")
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
-
base64EncodeStr(
<string>`) : string` [W/L/M]
returns the base64 encoded value of <string>.
-
base64DecodeStr(
<string>`) : string` [W/L/M]
returns the base64 decoded value of <string>.
message "base64EncodeStr"
set $ConstTest$ = "YWJjZGVm"
set $tmp$ = "abcdef"
set $CompValue$ = base64EncodeStr($tmp$)
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
comment ""
comment "------------------------------"
comment "Testing: "
message "base64DecodeStr"
set $ConstTest$ = "abcdef"
set $tmp$ = "YWJjZGVm"
set $CompValue$ = base64DecodeStr($tmp$)
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
-
encryptStringBlow(
<keystring>,<datastring>`) : string` [W/L/M]
Encrypted <datastring> with the Key <keystring> under application of Blowfish and returns the encrypted value.
-
decryptStringBlow(
<keystring>,<datastring>`) : string` [W/L/M]
Decrypts <datastring> with the Key <keystring> under the application of Blowfish and returns the decrypted value.
set $ConstTest$ = "This string is very secret"
set $ConstTest$ = encryptStringBlow("linux123",$ConstTest$)
set $ConstTest$ = decryptStringBlow("linux123",$ConstTest$)
set $CompValue$ = "This string is very secret"
if ($ConstTest$ = $CompValue$)
comment "cryptStringBlow passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing cryptStringBlow failed"
endif
-
md5sumFromFile(
<path to file>`) : string` [W/L/M]
Returns the md5sum that under <path to file> was found.
In case of error returns an empty String.
set $ConstTest$ = md5sumFromFile("%ScriptPath%\test-files\crypt\dummy.msi")
set $CompValue$ = strLoadTextFile("%ScriptPath%\test-files\crypt\dummy.msi.md5")
if ($ConstTest$ = $CompValue$)
comment "md5sumFromFile passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing md5sumFromFile failed"
endif
-
hashFromFile (
<FileName>, <Hashing Algorithm>`)` : string [W/L/M]
This is a platform-independant hashing files functions, which supports 80 hashing algorithms.
Insert in <Hashing Algorithm> one of these supported hashing algorithms : 'Gost', 'Grindahl256', 'Grindahl512', 'HAS160', 'Haval_3_128', 'Haval_4_128', 'Haval_5_128', 'Haval_3_160', 'Haval_4_160', 'Haval_5_160', 'Haval_3_192', 'Haval_4_192', 'Haval_5_192', 'Haval_3_224', 'Haval_4_224', 'Haval_5_224', 'Haval_3_256', 'Haval_4_256', 'Haval_5_256', 'MD2', 'MD4', 'MD5', 'Panama', 'RadioGatun32', 'RadioGatun64', 'RIPEMD', 'RIPEMD128', 'RIPEMD160', 'RIPEMD256', 'RIPEMD320', 'SHA0', 'SHA1', 'SHA2_244', 'SHA2_256', 'SHA2_384', 'SHA2_512', 'SHA2_512_224', 'SHA2_512_256', 'SHA3_224', 'SHA3_256', 'SHA3_384', 'SHA3_512', 'Shake_128', 'Shake_256', 'Snefru_8_128', 'Snefru_8_256', 'Tiger_3_128', 'Tiger_4_128', 'Tiger_5_128', 'Tiger_3_160', 'Tiger_4_160', 'Tiger_5_160', 'Tiger_3_192', 'Tiger_4_192', 'Tiger_5_192', 'Tiger2_3_128', 'Tiger2_4_128', 'Tiger2_5_128', 'Tiger2_3_160', 'Tiger2_4_160', 'Tiger2_5_160', 'Tiger2_3_192', 'Tiger2_4_192', 'Tiger2_5_192', 'WhirlPool', 'Blake2B', 'Blake2S', 'Keccak_224', 'Keccak_256', 'Keccak_288', 'Keccak_384', 'Keccak_512', 'GOST3411_2012_256', 'GOST3411_2012_512', 'Blake2XS', 'Blake2XB', 'Blake3_256', 'Blake3XOF', 'Blake2BP', 'Blake2SP'
encoding=utf8
[Actions]
DefVar $OS$
DefVar $FilePath$
DefVar $HashResult$
DefVar $CompValue$
; This online tool can be used to double check hash results : https://emn178.github.io/online-tools/
Set $OS$ = GetOS
switch $OS$
case "Windows_nt"
comment "We are running on Windows"
Set $FilePath$ = "C:\opsi\crypt\dummy.msi"
endcase
case "Linux"
comment "We are running on Linux"
Set $FilePath$ = "/home/opsi/crypt/dummy.msi"
endcase
case "macos"
comment "We are running on macOS"
Set $FilePath$ = "/home/opsi/crypt/dummy.msi"
endcase
endswitch
if FileExists($FilePath$)
comment "Testing HashFromFile - MD5"
Set $HashResult$ = HashFromFile($FilePath$, "MD5")
Set $CompValue$ = md5sumFromFile($FilePath$)
if ($HashResult$ = $CompValue$)
comment "Testing HashFromFile - MD5 passed"
else
LogWarning "Testing HashFromFile - MD5 failed"
endif
else
LogWarning "File not found"
endif
-
reencodestr(
<str>, <from>, <to>`)` //since 4.11.4.2 [W/L/M]
assumes that <str> is encoded in <from> and returns the in <to> encoded version of <str>. <from> and <to> are encodings as listet in chapter opsi-script encoding.
see also: [reencodestrlist] siehe auch : [loadTextFile]
siehe auch : [strLoadTextFileWithEncoding]
siehe auch : [loadUnicodeTextFile]
siehe auch : [loadTextFileWithEncoding]
see also: Encoding related functions
-
strLoadTextFile (
<file name>`) : string` [W/L/M]
returns the first line of <filename> as String.
see also : [strLoadTextFileWithEncoding]
-
strLoadTextFileWithEncoding (
<filename> , <encoding>`) : string` [W/L/M]
returns the first line of <filename> as String reencodes from <encoding>.
see also : [loadTextFile]
see also : [strLoadTextFile]
see also : [loadUnicodeTextFile]
see also : [loadTextFileWithEncoding]
see also : opsi-script encoding
-
GetShortWinPathName(<longpath string>)
//since 4.11.5.2 [W]
Returns the short path (8.3) from <longpath string>. If ther is no short path for <longpath string>, so you will get an empty string.
Example:GetShortWinPathName("C:\Program Files (x86)")
returns"C:\PROGRA~2"
Other String Functions
-
RandomStr (
<usespecialchars>`): string` [W/L/M]
returns a random String of length 10 where upper case letters, lower case letters and digits are mixed (for creating passwords). More exactly: if usespecialchars = true, it will create a string of 2 lower case chars, 2 upper case chars, 2 special chars and 4 digits. The possible special chars are:
'!','$','(',')','*','+','/',';','=','?','[',']','{','}','ß','~','§','°' if usespecialchars = false, it will create a string of 3 lower case chars, 3 upper case chars and 4 digits.
-
RandomStrWithParameters (<minLength>,<nLowerCases>,<nUpperCases>,<nDigits>,<nSpecialChars>): string
[W/L/M]
returns a random String (useful for creating passwords) according to the input configuration in the parameters, where:-
<minLength>: the length of the string,
-
<nLowerCases>: the count of lower case letters wanted,
-
<nUpperCases>: the count of upper case letters wanted,
-
<nDigits>: the count of digits wanted,
-
<nSpecialChars>: the count of special characters wanted.
Possible special chars are: '!','$','(',')','*','+','/',';','=','?','[',']','{','}','ß','~','§','°'
-
-
RandomIntStr(<number str>) : string
[W/L/M]
returns a number between 0 and <number str> as string.
-
CompareDotSeparatedNumbers(<string1>, <string2>) : string
[W/L/M]
compares two strings of the form <number>[.<number>[.<number>[.<number>]]]
It returns "0" if the strings are equal, "1" if <string1> is higher and "-1" if <string1> is lower than <string2>.
see also:CompareDotSeparatedNumbers(<str1>,<relation str>,<str2>)
: [CompareDotSeparatedNumbers_bool]
see also: [CompareDotSeparatedStrings_str]
Example:
The Code:
comment "Testing: "
message "CompareDotSeparatedNumbers"
set $string1$ = "1.2.3.4.5"
set $string2$ = "1.2.3.4.5"
set $ConstTest$ = "0"
set $CompValue$ = CompareDotSeparatedNumbers($string1$, $string2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
comment $string1$+" is equal to "+$string2$
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $string1$ = "1.2.31.4.5"
set $string2$ = "1.2.13.4.5"
set $ConstTest$ = "1"
set $CompValue$ = CompareDotSeparatedNumbers($string1$, $string2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
comment $string1$+" is higher then "+$string2$
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $string1$ = "1.2.3.4.5"
set $string2$ = "1.2.13.4.5"
set $ConstTest$ = "-1"
set $CompValue$ = CompareDotSeparatedNumbers($string1$, $string2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
comment $string1$+" is lower then "+$string2$
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
comment ""
comment "------------------------------"
comment "Testing: "
message "CompareDotSeparatedStrings"
set $string1$ = "1.a.b.c.3"
set $string2$ = "1.a.b.c.3"
set $ConstTest$ = "0"
set $CompValue$ = CompareDotSeparatedStrings($string1$, $string2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
comment $string1$+" is equal to "+$string2$
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
leads to the following log:
comment: Testing:
message CompareDotSeparatedNumbers
Set $string1$ = "1.2.3.4.5"
The value of the variable "$string1$" is now: "1.2.3.4.5"
Set $string2$ = "1.2.3.4.5"
The value of the variable "$string2$" is now: "1.2.3.4.5"
Set $ConstTest$ = "0"
The value of the variable "$ConstTest$" is now: "0"
Set $CompValue$ = CompareDotSeparatedNumbers($string1$, $string2$)
The value of the variable "$CompValue$" is now: "0"
If
$ConstTest$ = $CompValue$ <<< result true
($ConstTest$ = $CompValue$) <<< result true
Then
comment: passed
comment: 1.2.3.4.5 is equal to 1.2.3.4.5
Else
EndIf
Set $string1$ = "1.2.31.4.5"
The value of the variable "$string1$" is now: "1.2.31.4.5"
Set $string2$ = "1.2.13.4.5"
The value of the variable "$string2$" is now: "1.2.13.4.5"
Set $ConstTest$ = "1"
The value of the variable "$ConstTest$" is now: "1"
Set $CompValue$ = CompareDotSeparatedNumbers($string1$, $string2$)
The value of the variable "$CompValue$" is now: "1"
If
$ConstTest$ = $CompValue$ <<< result true
($ConstTest$ = $CompValue$) <<< result true
Then
comment: passed
comment: 1.2.31.4.5 is higher then 1.2.13.4.5
Else
EndIf
Set $string1$ = "1.2.3.4.5"
The value of the variable "$string1$" is now: "1.2.3.4.5"
Set $string2$ = "1.2.13.4.5"
The value of the variable "$string2$" is now: "1.2.13.4.5"
Set $ConstTest$ = "-1"
The value of the variable "$ConstTest$" is now: "-1"
Set $CompValue$ = CompareDotSeparatedNumbers($string1$, $string2$)
The value of the variable "$CompValue$" is now: "-1"
If
$ConstTest$ = $CompValue$ <<< result true
($ConstTest$ = $CompValue$) <<< result true
Then
comment: passed
comment: 1.2.3.4.5 is lower then 1.2.13.4.5
Else
EndIf
-
CompareDotSeparatedStrings(
<string1>, <string2>`) : string` [W/L/M]
compares two strings of the form <string>.<string>[.<string>[.<string>]]
It returns "0" if the strings are equal, "1" if <string1> is higher and "-1" if <string1> is lower than <string2>. The function is not case sensitive.
see also : [CompareDotSeparatedStrings_bool]
see also : [CompareDotSeparatedNumbers_bool]
Example:
The Code:
comment "Testing: "
message "CompareDotSeparatedStrings"
set $string1$ = "1.a.b.c.3"
set $string2$ = "1.a.b.c.3"
set $ConstTest$ = "0"
set $CompValue$ = CompareDotSeparatedStrings($string1$, $string2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
comment $string1$+" is equal to "+$string2$
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $string1$ = "1.a.b.c.3"
set $string2$ = "1.A.B.C.3"
set $ConstTest$ = "0"
set $CompValue$ = CompareDotSeparatedStrings($string1$, $string2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
comment $string1$+" is equal to "+$string2$
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $string1$ = "1.a.cb.c.3"
set $string2$ = "1.a.b.c.3"
set $ConstTest$ = "1"
set $CompValue$ = CompareDotSeparatedStrings($string1$, $string2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
comment $string1$+" is higher then "+$string2$
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $string1$ = "1.a.ab.c.3"
set $string2$ = "1.a.b.c.3"
set $ConstTest$ = "-1"
set $CompValue$ = CompareDotSeparatedStrings($string1$, $string2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
comment $string1$+" is lower then "+$string2$
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $string1$ = "1.2.13.4.5"
set $string2$ = "1.2.3.4.5"
set $ConstTest$ = "-1"
set $CompValue$ = CompareDotSeparatedStrings($string1$, $string2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
comment $string1$+" is lower then "+$string2$
comment "using CompareDotSeparatedStrings give wrong results on numbers"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $string1$ = "1.2.3.4.5"
set $string2$ = "1.2.13.4.5"
set $ConstTest$ = "1"
set $CompValue$ = CompareDotSeparatedStrings($string1$, $string2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
comment $string1$+" is higher then "+$string2$
comment "using CompareDotSeparatedStrings give wrong results on numbers"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
leads to the following log:
comment: Testing:
message CompareDotSeparatedStrings
Set $string1$ = "1.a.b.c.3"
The value of the variable "$string1$" is now: "1.a.b.c.3"
Set $string2$ = "1.a.b.c.3"
The value of the variable "$string2$" is now: "1.a.b.c.3"
Set $ConstTest$ = "0"
The value of the variable "$ConstTest$" is now: "0"
Set $CompValue$ = CompareDotSeparatedStrings($string1$, $string2$)
The value of the variable "$CompValue$" is now: "0"
If
$ConstTest$ = $CompValue$ <<< result true
($ConstTest$ = $CompValue$) <<< result true
Then
comment: passed
comment: 1.a.b.c.3 is equal to 1.a.b.c.3
Else
EndIf
Set $string1$ = "1.a.b.c.3"
The value of the variable "$string1$" is now: "1.a.b.c.3"
Set $string2$ = "1.A.B.C.3"
The value of the variable "$string2$" is now: "1.A.B.C.3"
Set $ConstTest$ = "0"
The value of the variable "$ConstTest$" is now: "0"
Set $CompValue$ = CompareDotSeparatedStrings($string1$, $string2$)
The value of the variable "$CompValue$" is now: "0"
If
$ConstTest$ = $CompValue$ <<< result true
($ConstTest$ = $CompValue$) <<< result true
Then
comment: passed
comment: 1.a.b.c.3 is equal to 1.A.B.C.3
Else
EndIf
Set $string1$ = "1.a.cb.c.3"
The value of the variable "$string1$" is now: "1.a.cb.c.3"
Set $string2$ = "1.a.b.c.3"
The value of the variable "$string2$" is now: "1.a.b.c.3"
Set $ConstTest$ = "1"
The value of the variable "$ConstTest$" is now: "1"
Set $CompValue$ = CompareDotSeparatedStrings($string1$, $string2$)
The value of the variable "$CompValue$" is now: "1"
If
$ConstTest$ = $CompValue$ <<< result true
($ConstTest$ = $CompValue$) <<< result true
Then
comment: passed
comment: 1.a.cb.c.3 is higher then 1.a.b.c.3
Else
EndIf
Set $string1$ = "1.a.ab.c.3"
The value of the variable "$string1$" is now: "1.a.ab.c.3"
Set $string2$ = "1.a.b.c.3"
The value of the variable "$string2$" is now: "1.a.b.c.3"
Set $ConstTest$ = "-1"
The value of the variable "$ConstTest$" is now: "-1"
Set $CompValue$ = CompareDotSeparatedStrings($string1$, $string2$)
The value of the variable "$CompValue$" is now: "-1"
If
$ConstTest$ = $CompValue$ <<< result true
($ConstTest$ = $CompValue$) <<< result true
Then
comment: passed
comment: 1.a.ab.c.3 is lower then 1.a.b.c.3
Else
EndIf
Set $string1$ = "1.2.13.4.5"
The value of the variable "$string1$" is now: "1.2.13.4.5"
Set $string2$ = "1.2.3.4.5"
The value of the variable "$string2$" is now: "1.2.3.4.5"
Set $ConstTest$ = "-1"
The value of the variable "$ConstTest$" is now: "-1"
Set $CompValue$ = CompareDotSeparatedStrings($string1$, $string2$)
The value of the variable "$CompValue$" is now: "-1"
If
$ConstTest$ = $CompValue$ <<< result true
($ConstTest$ = $CompValue$) <<< result true
Then
comment: passed
comment: 1.2.13.4.5 is lower then 1.2.3.4.5
comment: using CompareDotSeparatedStrings give wrong results on numbers
Else
EndIf
Set $string1$ = "1.2.3.4.5"
The value of the variable "$string1$" is now: "1.2.3.4.5"
Set $string2$ = "1.2.13.4.5"
The value of the variable "$string2$" is now: "1.2.13.4.5"
Set $ConstTest$ = "1"
The value of the variable "$ConstTest$" is now: "1"
Set $CompValue$ = CompareDotSeparatedStrings($string1$, $string2$)
The value of the variable "$CompValue$" is now: "1"
If
$ConstTest$ = $CompValue$ <<< result true
($ConstTest$ = $CompValue$) <<< result true
Then
comment: passed
comment: 1.2.3.4.5 is higher then 1.2.13.4.5
comment: using CompareDotSeparatedStrings give wrong results on numbers
Else
EndIf
-
getDiffTimeSec
[W/L/M]
returns a string with the integer number of seconds since the last call ofmarktime
.
Available since 4.11.3.1
-
timeStampAsFloatStr : string
(Floating Number - format: 'days.decimal days') //since 4.11.6 [W/L/M]
Gives Date and Time from now as string that contains a decimal number in the format: 'days.decimal days'. This Format make it easier to claculate time differences.
-
SidToName(
<well known sid>`)` [W]
returns a string with the localized name of the group with the <well known sid>. For example, if <well known sid> is equal to 'S-1-5-32-544' thenSidToName
returns 'Administrators'.
Available since 4.11.3.1
-
GetMyIpByTarget(
<target ip addr>`)` [W/L/M]
returns a list of interface IP-addresses, which are trying to reach the operating system at <target ip addr>. This function returns a value that is safer than the constant%IPAddress%
.
Since Version 4.11.3.1
Example:
set $CompValue$ = GetMyIpByTarget("%opsiServer%")
see also : [GetIpByName]
see also : [IPAddress]
* GetIpByName(
<ip addr / ip name>`)` [W/L/M]
returns the IP-addresses of the computers with the <ip addr / ip name>
Since Version 4.11.3.2
set $ConstTest$ = "%IPAddress%"
set $string1$ = "%IPAddress%"
set $CompValue$ = getIpByName($string1$)
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $CompValue$ = getIpByName("%HostID%")
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $CompValue$ = getIpByName("%PCName%")
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
see also : [GetMyIpByTarget]
-
stringinput(
< message str>,< boolstr confidential>`) : string` //since 4.12.1.2 [W/L/M]
Interactive function.
Interactive function to get a string from the user. It outputs the < message str> and waits for the Input and returns the input string.
In the grafical mode this is done in a modal Window, in the non grafical mode at the command line.
If < boolstr confidential> = "true" then the input is masked by "*". A button with a eye icon can be used to get a unmasked, readble display.
If < boolstr confidential> = "false" the the input is readable.
-
replaceOpsiConstants(
<string>`) : string` //since 4.12.3.6 [W/L/M]
returns a string, which has all occurrences of opsi constants in <string> replaced with their value.
see also : [replaceOpsiConstants_list]
-
fileHasBom (
<file name>`) : boolean` //since 4.12.4.17 [W/L/M]
This function reads the first 4 bytes of the input file and detects if it has a BOM or not.
If yes, the return value is true else false.
You can know more about BOM encodings here : https://en.wikipedia.org/wiki/Byte_order_mark
see also : opsi-script encoding
see also: Encoding related functions see also : [strLoadTextFileWithEncoding]
see also : [loadUnicodeTextFile]
see also : [loadTextFileWithEncoding]
(String) Functions for Licence Management [W/L/M]
-
DemandLicenseKey(`poolId [, productId [,windowsSoftwareId]]
)`
asks the opsi service via the function getAndAssignSoftwareLicenseKey for a reservation of a licence for the client.
The pool from which the licences is taken may be explicitly given by its ID or is identified via an associated product ID or Windows Software Id (possible, if these associations are defined in the licences configuration).
'poolId', 'productId', 'windowsSoftwareId' are Strings (resp. String expressions).
If no 'poolId' is explicitly given, the first parameter has to be an empty String "". The same procedure is done with other not explicit given Ids.
The function returns the licence key that is taken from the pool.
Examples:
set $mykey$ = DemandLicenseKey ("pool_office2007")
set $mykey$ = DemandLicenseKey ("", "office2007")
set $mykey$ = DemandLicenseKey ("", "", "{3248F0A8-6813-11D6-A77B}")
-
FreeLicense(`poolId [, productId [,windowsSoftwareId]]]
)`
asks the opsi service via the function freeSoftwareLicense to release the current licence reservation. The syntax is analogous to the syntax forDemandLicenseKey
Example:
DefVar $opsiresult$
set $opsiresult$ = FreeLicense("pool_office2007")
'$opsiresult$' becomes the empty String, if no error occurred, and, if an error occurred, the error info text.
Retrieving Error Infos from Service Calls [W/L/M]
-
getLastServiceErrorClass
returns, as its name says, the class name of the error information of the last service call. If the last service call did not produce an error the function returns the value "None".
-
getLastServiceErrorMessage
returns the message String of the last error information resp. "None".
Since the message String is more likely to be changed, it is recommended to base script logic on the class name.
Example:
if getLastServiceErrorClass = "None"
comment "kein Fehler aufgetreten"
endif
String List Functions and String List Processing [W/L/M]
A String list (or a String list value) is a sequence of String values. For this kind of values we have the variable of type String list. Since 4.12.4.32 it is also possible to pass an optional inital value. They are defined by the statement
DefStringList
<VarName> [= <inital value>]
A String list value may be assigned to String list variable:
Set
<VarName> =
<StringListValue>
String list values can be given only as results of string list expressions. These string list expressions can be construced on different ways:
-
by a function that returns a string list
-
by a string list variable
-
since 4.12.4.32 by a json style string that can be read as string list
For the following examples we declare a String list variable '$list1$':
DefStringList $list1$
Since 4.12.4.32 the simplest way is a string in json style that can be read as string list:
["<string>"]
Example:
set $list1$ = '["ab","cd","de"]'
The same result we get by using the function CreateStringlist
:
set $list1$ = createstringlist("ab","cd","de")
There are many ways to create or capture String lists, and many options for processing them, often yielding new String lists. They are presented in the following subsections.
If we refer to variables named like String0, StringVal, .. it is meant that these represent any String expressions.
We start with a special and rather useful kind of String lists: 'maps' – also called hashes or associative arrays – which consist of a lines of the form 'KEY'='VALUE'. In fact, each map should establish a function which associates a 'VALUE' to a 'KEY', and any 'KEY' should occur at most once as the first part of a line (whereas different 'KEY’s may be associated with identical 'VALUE' parts).
Info Maps
-
getHWBiosInfoMap
//since 4.11.4 [L/W]
get hardware information from BIOS and writes them to hash map string list.
There are the folowing keys: (example):
bios.Vendor=Award Software International, Inc. bios.Version=F9b bios.Start Segment=E000 bios.ReleaseDate=07/08/2010 bios.RomSize=1024 k sysinfo.Manufacturer=Gigabyte Technology Co., Ltd. sysinfo.Product Name=GA-MA78GM-UD2H sysinfo.Version= sysinfo.Serial Number= sysinfo.UUID=303032343144323730434336FFFFFFFF sysinfo.SKU Number= sysinfo.Family= board.Manufacturer=Gigabyte Technology Co., Ltd. board.Product=GA-MA78GM-UD2H board.Version=x.x board.Serial Number= board.Asset Tag= board.Feature Flags=01101001 board.Location in Chassis= board.Chassis Handle=6261 board.Board Type=79 Unknown board.Number of Contained Object Handles=116 enclosure.Manufacturer=Gigabyte Technology Co., Ltd. enclosure.Version= enclosure.Serial Number= enclosure.Asset Tag Number= enclosure.Type=Desktop enclosure.Power Supply State=Unknown enclosure.BootUp State=Unknown
-
getMacosVersionMap : stringlist
//macOS Version map //since 4.12.1.0 [M]
Example:
Set $macOSinfomap$ = getMacosVersionMap
gives (for examle) the log:
The value of the variable "$macOSinfomap$" is now: (string 0)Release=11.0 (string 1)Build=20A5364e (string 2)kernel name=Darwin (string 3)node name=vmmac1100onmm1.uib.local (string 4)kernel release=20.1.0 (string 5)kernel version=Darwin Kernel Version 20.1.0: Fri Aug 28 20:45:30 PDT 2020; root:xnu-7195.40.65.0.2~61/RELEASE_X86_64 (string 6)machine=x86_64 (string 7)processor=i386 (string 8)operating system=macOS
-
getLinuxVersionMap : stringlist
//since 4.11.4 [L]
get OS information and writes them to hash map string list.
There are the folowing keys: (example):
Distributor ID=Ubuntu Description=Ubuntu 12.04.2 LTS Release=12.04 Codename=precise kernel name=Linux node name=detlefvm05 kernel release=3.2.0-40-generic-pae kernel version=#64-Ubuntu SMP Mon Mar 25 21:44:41 UTC 2013 machine=i686 processor=athlon hardware platform=i386 operating system=GNU/Linux SubRelease
-
GetMSVersionMap : stringlist
[W]
get OS information and writes them to hash map string list.
see also GetMsVersionInfo
see also GetMsVersionName
There are the folowing keys: * major_version * minor_version * build_number * platform_id * csd_version * service_pack_major * service_pack_minor * suite_mask * product_type_nr * 2003r2 * ReleaseID * prodInfoText * prodInfoNumber
The Results from 'suite_mask' and 'product_type_nr' are integers that can be build by 'or' operations of the following values.
product_type_nr
SuiteMask
-
ReleaseID
which gives you the sub release of 'Windows 10' like e.g. '1511'. The Value comes from the Registry: "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" "ReleaseID" -
prodInfoText
which gives you a string to the edition type like e.g. 'PRODUCT_PROFESSIONAL'. -
prodInfoNumber
which gives you a string with a decimal number of the edition type like e.g. '48'.
ProdInfoNumber und ProdInfoText
DecNum |
HexNum |
Text |
00 |
00 |
An unknown product |
01 |
01 |
Ultimate Edition" |
02 |
02 |
Home Basic Edition |
03 |
03 |
Home Premium Edition |
04 |
04 |
Enterprise Edition |
05 |
05 |
Home Basic Edition |
06 |
06 |
Business Edition |
07 |
07 |
Server Standard Edition (full installation) |
08 |
08 |
Server Datacenter Edition (full installation) |
09 |
09 |
Small Business Server |
10 |
0A |
Server Enterprise Edition (full installation) |
11 |
0B |
Starter Edition |
12 |
0C |
Server Datacenter Edition (core installation) |
13 |
0D |
Server Standard Edition (core installation) |
14 |
0E |
Server Enterprise Edition (core installation) |
15 |
0F |
Server Enterprise Edition for Itanium-based Systems |
16 |
10 |
Business Edition |
17 |
11 |
Web Server Edition (full installation) |
18 |
12 |
Cluster Server Edition |
19 |
13 |
Home Server Edition |
20 |
14 |
Storage Server Express Edition |
21 |
15 |
Storage Server Standard Edition |
22 |
16 |
Storage Server Workgroup Edition |
23 |
17 |
Storage Server Enterprise Edition |
24 |
18 |
Server for Small Business Edition |
25 |
19 |
Small Business Server Premium Edition |
26 |
1A |
PRODUCT_HOME_PREMIUM_N |
27 |
1B |
PRODUCT_ENTERPRISE_N |
28 |
1C |
PRODUCT_ULTIMATE_N |
29 |
1D |
PRODUCT_WEB_SERVER_CORE |
30 |
1E |
Windows Essential Business Server Management Server |
31 |
1F |
Windows Essential Business Server Security Server |
32 |
20 |
Windows Essential Business Server Messaging Server |
33 |
21 |
Server Foundation |
34 |
22 |
PRODUCT_HOME_PREMIUM_SERVER |
35 |
23 |
PRODUCT_SERVER_FOR_SMALLBUSINESS_V |
36 |
24 |
Server Standard Edition without Hyper-V (full installation) |
37 |
25 |
Server Datacenter Edition without Hyper-V (full installation) |
38 |
26 |
Server Enterprise Edition without Hyper-V (full installation) |
39 |
27 |
Server Datacenter Edition without Hyper-V (core installation) |
40 |
28 |
Server Standard Edition without Hyper-V (core installation) |
41 |
29 |
Server Enterprise Edition without Hyper-V (core installation) |
48 |
30 |
PRODUCT_PROFESSIONAL |
49 |
31 |
PRODUCT_PROFESSIONAL_N |
50 |
32 |
PRODUCT_SB_SOLUTION_SERVER |
51 |
33 |
PRODUCT_SERVER_FOR_SB_SOLUTIONS |
52 |
34 |
PRODUCT_STANDARD_SERVER_SOLUTIONS |
53 |
35 |
PRODUCT_STANDARD_SERVER_SOLUTIONS_CORE |
54 |
36 |
PRODUCT_SB_SOLUTION_SERVER_EM |
55 |
37 |
PRODUCT_SERVER_FOR_SB_SOLUTIONS_EM |
56 |
38 |
PRODUCT_SOLUTION_EMBEDDEDSERVER |
57 |
39 |
PRODUCT_SOLUTION_EMBEDDEDSERVER_CORE |
59 |
3B |
PRODUCT_ESSENTIALBUSINESS_SERVER_MGMT |
60 |
3C |
PRODUCT_ESSENTIALBUSINESS_SERVER_ADDL |
61 |
3D |
PRODUCT_ESSENTIALBUSINESS_SERVER_MGMTSVC |
62 |
3E |
PRODUCT_ESSENTIALBUSINESS_SERVER_ADDLSVC |
63 |
3F |
PRODUCT_SMALLBUSINESS_SERVER_PREMIUM_CORE |
64 |
40 |
PRODUCT_CLUSTER_SERVER_V |
65 |
41 |
PRODUCT_EMBEDDED |
66 |
42 |
PRODUCT_STARTER_E |
67 |
43 |
PRODUCT_HOME_BASIC_E |
68 |
44 |
PRODUCT_HOME_PREMIUM_E |
69 |
45 |
PRODUCT_PROFESSIONAL_E |
70 |
46 |
PRODUCT_ENTERPRISE_E |
71 |
47 |
PRODUCT_ULTIMATE_E |
72 |
48 |
PRODUCT_ENTERPRISE_EVALUATION |
84 |
54 |
PRODUCT_ENTERPRISE_N_EVALUATION |
98 |
62 |
PRODUCT_CORE_N |
99 |
63 |
PRODUCT_CORE_COUNTRYSPECIFIC |
100 |
64 |
PRODUCT_CORE_SINGLELANGUAGE |
101 |
65 |
PRODUCT_CORE |
121 |
79 |
PRODUCT_EDUCATION |
122 |
7A |
PRODUCT_EDUCATION_N |
125 |
7D |
Windows Enterprise 2015 LTSB |
126 |
7E |
Windows Enterprise 2015 LTSB N |
129 |
81 |
Windows Enterprise 2015 LTSB Evaluation |
130 |
82 |
Windows Enterprise 2015 LTSB N Evaluation |
Example:
The Code
DefStringList $INST_Resultlist$
DefStringList $INST_Resultlist2$
message "getMSVersionMap"
comment "get value by winst function"
set $INST_Resultlist$ = getMSVersionMap
produces the following log:
message getMSVersionMap
comment: get value by winst function
Set $INST_Resultlist$ = getMSVersionMap
retrieving strings from getMSVersionMap [switch to loglevel 7 for debugging]
(string 0)major_version=5
(string 1)minor_version=1
(string 2)build_number=2600
(string 3)platform_id=2
(string 4)csd_version=Service Pack 3
(string 5)service_pack_major=3
(string 6)service_pack_minor=0
(string 7)suite_mask=256
(string 8)product_type_nr=1
(string 9)2003r2=false
Background infos for getMSVersionMap |
-
getFileInfoMap(
<file name>) : stringlist
[W] -
getFileInfoMap32(
<file name>) : stringlist
//since 4.11.6.6 [W] -
getFileInfoMap64(
<file name>) : stringlist
//since 4.11.6.6 [W] -
getFileInfoMapSynative(
<file name>) : stringlist
//since 4.11.6.6 [W]
retrieves the version infos built into the file FILENAME and writes it to a Stringlist map.
At this moment, there exist the keys,
-
Comments
-
CompanyName
-
FileDescription
-
FileVersion
-
InternalName
-
LegalCopyright
-
LegalTrademarks
-
OriginalFilename
-
PrivateBuild
-
ProductName
-
ProductVersion
-
SpecialBuild
-
Language name <index>
-
Language ID <index>
-
file version with dots
-
file version
-
product version
Usage: If we define and call
DefStringList FileInfo
DefVar $InterestingFile$
Set $InterestingFile$ = "c:\program files\my program.exe"
set FileInfo = getFileInfoMap($InterestingFile$)
we get the value associated with key "FileVersion" from the call
DefVar $result$
set $result$ = getValue("FileVersion", FileInfo)
(for the function getValue cf. Simple String Values generated from String Lists or Files).
Example:
The code:
set $InterestingFile$ = "%OpsiScriptDir%\winst.exe"
if not (FileExists($InterestingFile$))
set $InterestingFile$ = "%OpsiScriptDir%\winst32.exe"
endif
set $INST_Resultlist$ = getFileInfoMap($InterestingFile$)
produce the log:
Set $InterestingFile$ = "N:\develop\delphi\winst32\trunk\winst.exe"
The value of the variable is now: "N:\develop\delphi\winst32\trunk\winst.exe"
If
Starting query if file exist ...
FileExists($InterestingFile$) <<< result true
not (FileExists($InterestingFile$)) <<< result false
Then
EndIf
Set $INST_Resultlist$ = getFileInfoMap($InterestingFile$)
retrieving strings from getFileInfoMap [switch to loglevel 7 for debugging]
(string 0)Language name 0=Deutsch (Deutschland)
(string 1)Language ID 0=1031
(string 2)file version=1125942857039872
(string 3)file version with dots=4.10.8.0
(string 4)product version=1125942857039872
(string 5)Comments=
(string 6)CompanyName=uib gmbh (www.uib.de)
(string 7)FileDescription=opsi.org
(string 8)FileVersion=4.10.8.0
(string 9)InternalName=
(string 10)LegalCopyright=uib gmbh under GPL
(string 11)LegalTrademarks=opsi
(string 12)OriginalFilename=
(string 13)PrivateBuild=
(string 14)ProductName=opsi-script
(string 15)ProductVersion=4.0
(string 16)SpecialBuild=
-
GetLocaleInfoMap
[W]
retrieves the system informations on the locale and writes it to a Stringlist map.
At this moment, there exist the keys:
-
language_id_2chars (two-letter version of the system default language name)
-
language_id (three-letter version of it, including subtype of language) inklusive der Sprachenuntertypen)
-
localized_name_of_language
-
English_name_of_language
-
abbreviated_language_name
-
native_name_of_language
-
country_code
-
localized_name_of_country
-
English_name_of_country
-
abbreviated_country_name
-
native_name_of_country
-
default_language_id
-
default_language_id_decimal
-
default_country_code
-
default_oem_code_page
-
default_ansi_code_page
-
default_mac_code_page
-
system_default_language_id Hexadecimal Windows locale Id
-
system_default_posix Language_Region (Posix Style)
-
system_default_lang_region Language-Region (BCP 47 Style)
The system_default keys gives information about the language of the installed OS. The other keys give information about the locale of the GUI.
Example:
The code:
message "Locale Infos"
set $INST_Resultlist$ = GetLocaleInfoMap
produces e.g the log:
message Locale Infos
Set $INST_Resultlist$ = GetLocaleInfoMap
retrieving strings from GetLocaleInfoMap [switch to loglevel 7 for debugging]
(string 0)language_id_2chars=DE
(string 1)language_id=DEU
(string 2)localized_name_of_language=Deutsch (Deutschland)
(string 3)English_name_of_language=German
(string 4)abbreviated_language_name=DEU
(string 5)native_name_of_language=Deutsch
(string 6)country_code=49
(string 7)localized_name_of_country=Deutschland
(string 8)English_name_of_country=Germany
(string 9)abbreviated_country_name=DEU
(string 10)native_name_of_country=Deutschland
(string 11)default_language_id=0407
(string 12)default_language_id_decimal=1031
(string 13)default_country_code=49
(string 14)default_oem_code_page=850
(string 15)default_ansi_code_page=1252
(string 16)default_mac_code_page=10000
(string 17)system_default_language_id=0407
(string 18)system_default_posix=de_DE
(string 19)system_default_lang_region=de-DE
Usage: If we define and call
DefStringList $languageInfo$
set $languageInfo$ = GetLocaleInfoMap
we get the value associated with key "language_id_2chars" from the call
DefVar $result$
set $result$ = getValue("language_id_2chars", $languageInfo$)
(for the function getValue cf. Simple String Values generated from String Lists or Files). We may now write scripts using a construct like
if getValue("language_id_2chars", languageInfo) = "DE"
; installiere deutsche Version
else
if getValue("language_id_2chars", languageInfo) = "EN"
; installiere englische Version
endif
endif
Background infos for GetLocaleInfoMap: |
-
getLocaleInfo
(deprecated): useGetLocaleInfoMap
.
see also : [GetLocaleInfoMap]
-
getProductMap
// since 4.11.2.4 [W/L/M]
returns a info map of the opsi product you are just installing.
It works only if opsi-script is running in opsi service mode.
keys are: id, name, description, advice, productversion, packageversion, priority, installationstate, lastactionrequest, lastactionresult, installedversion, installedpackage, installedmodificationtime, actionrequest
Example:
set $INST_Resultlist$ = getProductMap
set $string1$ = getValue("id", $INST_Resultlist$)
produces e.g the log:
Set $INST_Resultlist$ = getProductMap
retrieving strings from getProductMap [switch to loglevel 7 for debugging]
(string 0)id=opsi-script-test
(string 1)name=opsi-script test
(string 2)description=Test and example script for opsi-script
(string 3)advice=
(string 4)productversion=4.11.2
(string 5)packageversion=1
(string 6)priority=0
(string 7)installationstate=unknown
(string 8)lastactionrequest=setup
(string 9)lastactionresult=successful
(string 10)installedversion=4.11.2
(string 11)installedpackage=1
(string 12)installedmodificationtime=
(string 13)actionrequest=setup
Set $string1$ = getValue("id", $INST_Resultlist$)
retrieving strings from $INST_Resultlist$ [switch to loglevel 7 for debugging]
(string 0)id=opsi-script-test
(string 1)name=opsi-script test
(string 2)description=Test and example script for opsi-script
(string 3)advice=
(string 4)productversion=4.11.2
(string 5)packageversion=1
(string 6)priority=0
(string 7)installationstate=unknown
(string 8)lastactionrequest=setup
(string 9)lastactionresult=successful
(string 10)installedversion=4.11.2
(string 11)installedpackage=1
(string 12)installedmodificationtime=
(string 13)actionrequest=setup
The value of the variable "$string1$" is now: "opsi-script-test"
-
editmap(
< strlist>`) : stringlist` //since 4.12.1.2 [W/L/M]
Interactive function.
Show the given < strlist> as <key>=<value> pair list to the user and gives the possibility to change values. Returned ist the edited version of <str list>, after the user user finished editing.
In the grafical mode this is done in a modal Window, in the non grafical mode at the command line.
getListFromWMI(
<wmi namespace str>,<wmi class str>,<property list>,<condition str>`) : stringlist` //since 4.12.1.0 [W]
Returns an info map of <wmi class str> that is limited to the properties in <property list> and also is limited by the <condition str>.
If <property list> is empty, all properties of <wmi class str> will be returned.
Attention: If <property list> contains properties that don’t exist in the called WMI class, the query will fail.
Calling with properties is faster than without.
If <wmi namespace str> is empty, it defaults to root\cimv2
.
If an error occurs, an empty list will be returned
Example:
; this is valid because both properties are valid
set $list1$ = createStringList ('Model','Manufacturer')
set $str1$ = 'root\cimv2'
set $str2$ = 'Win32_ComputerSystem'
set $str3$ = ''
set $resultlist$ = getListFromWMI($str1$,$str2$,$list1$,$str3$)
produces e.g the log:
Set $list1$ = createStringList ('Model','Manufacturer')
The value of the variable "$list1$" is now:
(string 0)Model
(string 1)Manufacturer
Set $str1$ = 'root\cimv2'
The value of the variable "$str1$" is now: "root\cimv2"
Set $str2$ = 'Win32_ComputerSystem'
The value of the variable "$str2$" is now: "Win32_ComputerSystem"
Set $str3$ = ''
The value of the variable "$str3$" is now: ""
Set $resultlist$ = getListFromWMI($str1$,$str2$,$list1$,$str3$)
The value of the variable "$resultlist$" is now:
(string 0)Model=HP Pavilion Desktop PC 570-p0xx
(string 1)Manufacturer=HP
Example:
comment "Testing for os architecture"
set $ConstTest$ = GetSystemType
set $list1$ = createStringList ('systemtype')
set $str1$ = ''
set $str2$ = 'Win32_ComputerSystem'
set $str3$ = ''
set $resultlist$ = getListFromWMI($str1$,$str2$,$list1$,$str3$)
produces e.g the log:
comment: Testing for os architecture
Set $ConstTest$ = GetSystemType
The value of the variable "$ConstTest$" is now: "64 Bit System"
Set $list1$ = createStringList ('systemtype')
The value of the variable "$list1$" is now:
(string 0)systemtype
Set $str1$ = ''
The value of the variable "$str1$" is now: ""
Set $str2$ = 'Win32_ComputerSystem'
The value of the variable "$str2$" is now: "Win32_ComputerSystem"
Set $str3$ = ''
The value of the variable "$str3$" is now: ""
Set $resultlist$ = getListFromWMI($str1$,$str2$,$list1$,$str3$)
The value of the variable "$resultlist$" is now:
(string 0)systemtype=x64-based PC
Example:
comment "Testing for freespace"
;wmic LogicalDisk "%Systemdrive%" get freespace
set $list1$ = createStringList ('freespace')
set $str1$ = 'root\cimv2'
set $str2$ = 'Win32_LogicalDisk'
set $str3$ = 'where Name="%Systemdrive%"'
markerrornumber
set $resultlist$ = getListFromWMI($str1$,$str2$,$list1$,$str3$)
if errorsOccuredSinceMark = 0
set $CompValue$ = getValue("freespace", $resultlist$)
set $CompValue$ = calculate($CompValue$+ '-1')
if (HasMinimumSpace ("%Systemdrive%", $CompValue$))
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $CompValue$ = calculate($CompValue$+ '+10')
if (HasMinimumSpace ("%Systemdrive%", $CompValue$))
set $TestResult$ = "not o.k."
LogWarning "failed"
else
comment "passed"
endif
endif
produces e.g the log:
comment: Testing for freespace
Set $list1$ = createStringList ('freespace')
The value of the variable "$list1$" is now:
(string 0)freespace
Set $str1$ = 'root\cimv2'
The value of the variable "$str1$" is now: "root\cimv2"
Set $str2$ = 'Win32_LogicalDisk'
The value of the variable "$str2$" is now: "Win32_LogicalDisk"
Set $str3$ = 'where Name="C:"'
The value of the variable "$str3$" is now: "where Name="C:""
Marked error number 1
Set $resultlist$ = getListFromWMI($str1$,$str2$,$list1$,$str3$)
The value of the variable "$resultlist$" is now:
(string 0)freespace=235092250624
If
errorsOccuredSinceMark = 0 <<< result true
Then
Set $CompValue$ = getValue("freespace", $resultlist$)
The value of the variable "$CompValue$" is now: "235092250624"
Set $CompValue$ = calculate($CompValue$+ '-1')
The value of the variable "$CompValue$" is now: "235092250623"
If
Free on Disk C:: 235.092.250.624 bytes This is more than the required amount of 235.092.250.623 bytes
HasMinimumSpace ("C:", $CompValue$) <<< result true
(HasMinimumSpace ("C:", $CompValue$)) <<< result true
Then
comment: passed
Else
EndIf
Set $CompValue$ = calculate($CompValue$+ '+10')
The value of the variable "$CompValue$" is now: "235092250633"
If
Free on Disk C:: 235.092.250.624 bytes This is less than the required amount of 235.092.250.633 bytes
HasMinimumSpace ("C:", $CompValue$) <<< result false
(HasMinimumSpace ("C:", $CompValue$)) <<< result false
Then
Else
comment: passed
EndIf
EndIf
Example:
comment "Testing for drive count"
;wmic LogicalDisk "%Systemdrive%" get name
set $list1$ = createStringList ('Name')
set $str1$ = ''
set $str2$ = 'Win32_LogicalDisk'
set $str3$ = ''
set $resultlist$ = getListFromWMI($str1$,$str2$,$list1$,$str3$)
set $CompValue$ = count($resultlist$)
set $resultlist$ = powershellCall('get-psdrive -psprovider filesystem | select-object -expand Name')
set $ConstTest$ = count($resultlist$)
if ($ConstTest$ = $CompValue$)
comment "getListFromWMI passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing getListFromWMI failed"
endif
produces e.g the log:
comment: Testing for drive count
The value of the variable "$list1$" is now:
(string 0)Name
The value of the variable "$str1$" is now: ""
The value of the variable "$str2$" is now: "Win32_LogicalDisk"
The value of the variable "$str3$" is now: ""
The value of the variable "$resultlist$" is now:
(string 0)Name=C:
(string 1)Name=D:
(string 2)Name=E:
(string 3)Name=F:
(string 4)Name=L:
(string 5)Name=N:
(string 6)Name=R:
(string 7)Name=S:
(string 8)Name=W:
(string 9)Name=Y:
(string 10)Name=Z:
The value of the variable "$CompValue$" is now: "11"
PowershellCall Executing: get-psdrive -psprovider filesystem | select-object -expand Name ; mode: sysnative
ShellCall Executing: "C:\WINDOWS\system32\\cmd.exe" /C "powershell.exe get-executionpolicy"
Powershell excution policy = Bypass
ShellCall Executing: "C:\WINDOWS\system32\\cmd.exe" /C "powershell.exe set-executionpolicy ByPass"
Execution of tmp-internal powershell.exe winst /sysnative
Save to file with encoding: system
ExitCode 0
The file: c:\opsi.org\tmp\_opsiscript_N97cDr97Km.ps1 has been deleted
ShellCall Executing: "C:\WINDOWS\system32\\cmd.exe" /C "powershell.exe set-executionpolicy Bypass"
The value of the variable "$resultlist$" is now:
(string 0)C
(string 1)D
(string 2)E
(string 3)F
(string 4)L
(string 5)N
(string 6)R
(string 7)S
(string 8)W
(string 9)Y
(string 10)Z
The value of the variable "$ConstTest$" is now: "11"
If
$ConstTest$ = $CompValue$ <<< result true
($ConstTest$ = $CompValue$) <<< result true
Then
comment: getListFromWMI passed
Else
EndIf
-
opsi-wmi-test.exe
You can test your WMI query with a small helper application (opsi-wmi-test.exe).
The application works similar as the function getListFromWMI
.
The user interface of 'opsi-wmi-test' is subdivided in two sections.
At the upper section ('Connection to WMI service') you are asked to input the data which is necessary to connect to the WMI service.
Input here the name of the computer ('Computer') adressed, the WMI namespace ('NameSpace') of the WMI class which shall be used,
and, if necessary, the username ('User') and the password ('Password'). At start of opsi-wmi-test.exe, some default values
('Computer' = localhost
, 'NameSpace' = \root\cimv2
, 'User' = < > , 'Password' = < >) are given.
These parameters allow the connection to the local WMI service and access to the most used WMI classes. (Figure 9.1)
It is also possiple to connect to remote WMI services of other computers in the network by using network name, username and password, respectively.
At the lower section ('Request to WMI service'), you are asked to input the data which is necessary to make the desired query to the WMI service. You must input the WMI class or its alias as well as the properties you like to query for. You can input the WMI class or its alias directly in the respective field ('Class' or 'Alias') or you can select it from a list.(Figure 9.2). You should know that not all WMI Classes have Aliases. If the class zou selected has one, its Alias will be automatically selected in the 'Alias' field. If not, <No Alias> will be displayed. After the WMI class is given, its properties will be displayed in the field 'Available WMI Properties'.
Available properties can be selected and moved into the field 'Selected WMI Properties' using drag & drop or by clicking on the button
(Figure 9.3).
Note: This works also the other way around. Properties can be moved from 'Selected WMI Properties' back to 'Available WMI Properties' via drag & drop or the button .
After moving the desired properties to the field 'Selected WMI Properties' click on the Button 'Execute' to send the query to the WMI service.
You can specify your query within the field 'Condition' using SQL statements (example: where
<property> = <value>).
The final query will be dispalyed in the 'Query' field. It can be copied but not modified there. The result of your query is displayed in a second window (figure 9.4). If the query could not be processed the result is an error message.
In a third window, you wil have all the data about your query : 'Namespace', 'Selected Class', 'Properties list', 'Selected Properties' and 'All available Properties'. You can use all those fields for copying and pasting in your opsi script.
Producing String Lists from Strings [W/L/M]
-
createStringList (
<string0>, <string1> ,…) : stringlist
[W/L/M]
forms a String list from the values of the listed String expressions. For example, by
set $list1$ = createStringList ('a','b', 'c', 'd')
we get a list of the first four letters of the alphabet.
The following two functions produce a String list by splitting some string:
splitString (
<string1>, <string2>`) : stringlist` [W/L/M]
generates the list of partial strings of <string1> (including empty strings) before resp. between the occurences of <string2>. E.g.,
set $list1$ = splitString ("\\server\share\directory", "\")
defines the list
'"", "", "server", "share", "directory"'
If the given string is in the list of confidential strings, so the resulting string parts will also be added to the list of confidential strings.
-
splitStringOnWhiteSpace (
<string>`) : stringlist` [W/L/M]
slices StringVal by the "white spots" in it. E. g.
set $list1$ = splitStringOnWhiteSpace("Status Lokal Remote Netzwerk")
produces the list
'"Status", "Lokal", "Remote", "Netzwerk"'
no matter how many blanks or tabs constitute the white space between the words.
If the given string is in the list of confidential strings, so the resulting string parts will also be added to the list of confidential strings.
Loading Lines of a Text File into a String List
-
loadTextFile (
<file name>`) : stringlist` [W/L/M]
reads the file <file name> and generates the string list, that contains all lines of the file.
-
loadTextFileWithEncoding(
<file name>,
<encoding>`) : stringlist` [W/L/M]
reads the file <file name> and generates the string list, that contains all lines of the file. The string will be reencoded from <encoding> to system encoding.
-
loadUnicodeTextFile (
<file name>`) : stringlist` [W/L/M]
reads the unicode text file <file name> and generates the string list, that contains all lines of the file.
By this call, the strings are converted into the system default 8 bit code.
-
getSectionNames(
<ini-file>`) : stringlist` [W/L/M]
interprets the specified file as an inifile, looks for list of all lines of form
'[<SectionName>]'
and returns the pure section names (without brackets).
-
GetSectionFromInifile(
<ini-file-section>`,<ini-file>
) : stringlist` [W/L/M]
+interprets the specified file as an inifile, looks for the list related to the + '[<ini-file-section>]' chosen in input
+and returns the complete raw section content in a stringlist.
Simple String Values generated from String Lists or Files [W/L/M]
-
composeString (
<string list>, <Link>`) : string` [W/L/M]
With this function, the elements of any String list can be glued to one another, mediated by a "glue string".
E.g. if '$list1$' represents the list 'a', 'b', 'c', 'd', 'e'
by
$line$ = composeString ($list1$, " | ")
we assign the value '"a | b | c | d | e".' to '$line$'.
-
takeString (
<index>, <list>`) : string` [W/L/M]
For example, if '$list1$' represents the list of the first five letters of the alphabet, using
takeString (2, $list1$)
we get string "c" (since list counting starts with 0).
Negative values of index go downwards from the list count value. E.g.,
takeString (-1, $list1$)
return the last list element, that is "e".
see also : setStringInListAtIndex
see also : takeString
-
takeFirstStringContaining(
<list>,<search string>`) : string` [W/L/M]
returns the first string of the list which contains the <search string>.
Returns an empty string if no matching string was found.
-
getValue(
<key string>, <hash string list>) : string
[W/L/M]
This function tries to interpret a String list as list of lines of the form 'key=value'
It looks for the first line, where the string <key> is followed by the equality sign, and returns the remainder of the line (the 'value', the string that starts after the equality sign). If there is no fitting line, it returns the string 'NULL'.
The function is required for using theGetLocaleInfoMap
andgetFileVersionMap
string list functions (cf. Info Maps).
-
setValueByKey(
<key>, <value>, <targetlist>)
: stringlist [W/L/M]
Sets the value of <key> to <value> in the string list <targetlist>. For this, the string list <targetlist> must be a key/value list, which means that every entry is of the form 'key=value'.
If the key/value pairs in <targetlist> are not seperated by=
but by another seperator, then this seperator must be given as an argument to the function.
Example:
Set $KeyValueList$ = createStringList('key1=value1','key2=value2') Set $NewList$ = setValueByKey('key2','newvalue',$KeyValueList$) ; then $NewList$ = ['key1=value1','key2=newvalue'] Set $KeyValueListWithDifferentSeperator$ = createStringList('key1:value1','key2:value2') Set $NewListWithDifferentSeperator$ = setValueByKey('key2','newvalue',$KeyValueListWithDifferentSeperator$,':') ; then $NewListWithDifferentSeperator$ = ['key1:value1','key2:newvalue']
-
getValueBySeparator(
<key string>,<separator string>,<hash string list>) : string
//since 4.11.2.1 [W/L/M]
works likegetValue
but you have to give the <separator string> so that can also work with hashes like
'key:value'
-
getValueFromFile(
<key string>, <file name>`) : string` //since 4.11.4.4 [W/L/M]
Searches in <file name> for a key/value pair with key <key string> and separator string '=' and returns the value. If <key string> is not found it returns an empty string.
-
getValueFromFileBySeparator(
<key string>,<separator string>,<file name>`) : string` //since 4.11.4.4 [W/L/M]
Searches in <file name> for a key/value pair with key <key string> and separator string <separator string> and returns the value. If <key string> is not found it returns an empty string.
-
count (
<list>`) : string (number)` [W/L/M]
returns the number of elements of the string list <list> as string.
e.g. for $list1$ composed as
'a', 'b', 'c', 'd', 'e'
count ($list1$)
has the value "5".
Producing String Lists from opsi-script Sections [W/L/M]
-
retrieveSection (
<section name>`) : stringlist` [W/L/M]
gives the lines of the specified section as string list.
-
getOutStreamFromSection (
<dos section name>`) : stringlist (output)` [W/L/M]
invokes the section and – at this moment implemented only forShellScript
,ExecWith
andExecPython
calls – captures the output to standard out and standard error of the invoked commands writing them into a string list. For example:
set $list$ = getOutStreamFromSection ('ShellScript_netstart') [ShellScript_netstart] net start
$list1$
contains among some surrounding stuff the list of all mounted shares of a PC.
see also : getReturnListFromSection
see also: executeSection
There are 3 shortcuts for simple calls to the shell. At Windows these commands runs in the sysnative mode.
-
shellCall (
<command string>`) : stringlist (output)` //since 4.11.4.2 [W/L/M]
Executing <command string> with the standard shell (cmd.exe / bash)
set $list$= shellCall('net start')
Is a shortcut for this expression:
set $list$ = getOutStreamFromSection ('ShellScript_netstart winst /sysnative')
[ShellScript_netstart]
net start
see also : shellCall_list
-
shellCall (
<command string>`) : noresult` //since 4.11.6.1 [W/L/M]
shellCall('net start')
Is a shortcut for this expression:
ShellScript_netstart winst /sysnative
[ShellScript_netstart]
net start
see also : shellCall
-
shellCall (
<command string>`) : string (exitcode)` //since 4.11.6.1 [W/L/M]
set $exitcode$ = shellCall('net start')
Is a shortcut for this expression:
ShellScript_netstart winst /sysnative
set $exitcode$ = getLastExitcode
[ShellScript_netstart]
net start
see also : shellCall_str
-
getReturnListFromSection (
section name)
[W/L/M]
For some section types - at this moment implemented only forXMLPatch
sections andopsiServiceCall
sections - there is a specificreturn
statement which yields some result of the execution of the section (assumed to be of String list type).
E.g. we may use the statement
set list1 = getReturnListFromSection ('XMLPatch_mime "c:\mimetypes.rdf"')
to get a specific knot list of the XML file mimetypes.rdf
. (More info to XMLPatch sections at XMLPatch Sections in this manual).
Or the list of opsi clients is produced by the reference to a opsi service call:
DefStringList $result$
Set $result$=getReturnListFromSection("opsiservicecall_clientIdsList")
[opsiservicecall_clientIdsList]
"method":"getClientIds_list"
"params":[]
see also : getOutStreamFromSection see also: executeSection
Stringlists from the registry [W]
-
getRegistryKeyList32(
<regkey>`) : stringlist` [W]
Returns a stringlist with the names of all keys within <regkey>.
32 Bit mode (with redirection). Available since 4.11.3
-
getRegistryKeyList64(
<regkey>`) : stringlist`
Returns a stringlist with the names of all keys within <regkey>.
64 Bit mode (without redirection). Available since 4.11.3
-
getRegistryKeyListSysnative(
<regkey>`) : stringlist`
Returns a stringlist with the names of all keys within <regkey>.
Mode (redirection) depends on the architecture of the OS. Available since 4.11.3
-
getRegistryKeyList(
<regkey>, <access str>`) : stringlist`
Summes up the previous three functions, i.e. returns a stringlist with the names of all keys within <regkey>, where the Mode (32bit
,64bit
,sysnative
) is given as <access str>. Available since 4.12.5.0
-
getRegistryVarList32(
<regkey>`) : stringlist`
Returns a stringlist with the names of all value entries associated with key <regkey>.
32 Bit mode (with redirection). Available since 4.11.3
-
getRegistryVarList64(
<regkey>`) : stringlist`
Returns a stringlist with the names of all value entries associated with key <regkey>.
64 Bit mode (without redirection). Available since 4.11.3
-
getRegistryVarListSysnative(
<regkey>`) : stringlist`
Returns a stringlist with the names of all value entries associated with key <regkey>.
Mode (redirection) depends on the architecture of the OS. Available since 4.11.3
-
getRegistryVarList(
<regkey>, <access str>`) : stringlist`
Summes up the previous three functions, i.e. returns a stringlist with the names of all value entries associated with key <regkey>, where the Mode (32bit
,64bit
,sysnative
) is given as <access str>. Available since 4.12.5.0
-
getRegistryVarMap32(
<regkey>`) : stringlist`
Provides a map of all name=value pairs in the given registry key <regkey>.
32 Bit Mode (with redirection). Since 4.11.3
-
getRegistryVarMap64(
<regkey>`) : stringlist`
Provides a map of all name=value pairs in the given registry key <regkey>.
64 Bit Mode (with redirection). Since 4.11.3
-
getRegistryVarMapSysnative(
<regkey>`) : stringlist`
Provides a map of all name=value pairs in the given registry key <regkey>.
Mode depend on the architecture of the operating system. Since 4.11.3
-
getRegistryVarMap(
<regkey>, <access str>`) : stringlist`
Summes up the previous three functions, i.e. provides a map of all name=value pairs in the given registry key <regkey>, where the Mode (32bit
,64bit
,sysnative
) is given as <access str>. Available since 4.12.5.0
Example:
At first, we create entries in the registry with the following example code:
Registry_createkeys /32Bit
[Registry_createkeys]
openkey [HKEY_LOCAL_MACHINE\SOFTWARE\opsi.org\opsi-script-test]
set "var1" = "value1"
set "var2" = REG_SZ:"value2"
set "var3" = REG_EXPAND_SZ:"value3"
set "var4" = REG_DWORD:4294967295
; REG_QWORD is supported since 4.12.6
set "var5" = REG_QWORD:18446744073709551615
set "var6" = REG_BINARY:05 05 05 0F 10
set "var7" = REG_MULTI_SZ:"value6|value7|de"
openkey [HKEY_LOCAL_MACHINE\SOFTWARE\opsi.org\opsi-script-test\key1]
openkey [HKEY_LOCAL_MACHINE\SOFTWARE\opsi.org\opsi-script-test\key2]
openkey [HKEY_LOCAL_MACHINE\SOFTWARE\opsi.org\opsi-script-test\key3]
openkey [HKEY_LOCAL_MACHINE\SOFTWARE\opsi.org\opsi-script-test\key4]
Given the registry entries in the example above, and the following code:
set $list$ = getRegistryVarList32("hklm\software\opsi.org\opsi-script-test")
or
set $list$ = getRegistryVarList("hklm\software\opsi.org\opsi-script-test","32bit")
we will see the following values in the log:
Registry started with redirection (32 Bit) The value of the variable "$list$" is now: (string 0)var1 (string 1)var2 (string 2)var3 (string 3)var4 (string 4)var5 (string 5)var6
If we call:
set $list$ = getRegistryVarMap32("hklm\software\opsi.org\opsi-script-test")
or
set $list$ = getRegistryVarMap("hklm\software\opsi.org\opsi-script-test","32bit")
we will see the following Log:
Registry started with redirection (32 Bit) The value of the variable "$list$" is now: (string 0)var1=value1 (string 1)var2=value2 (string 2)var3=value3 (string 3)var4=444 (string 4)var5=05 05 05 0F 10 (string 5)var6=value6
If we call:
set $list$ = getRegistryKeyList32("hklm\software\opsi.org\opsi-script-test")
or
set $list$ = getRegistryKeyList("hklm\software\opsi.org\opsi-script-test","32bit")
we will get the following key in the log:
Registry started with redirection (32 Bit) The value of the variable "$list$" is now: (string 1)key1 (string 2)key2 (string 3)key3 (string 4)key4
Stringlists from the Product Properties [W/L/M]
-
getProductPropertyList(
<propname>,<default value>`)` [W/L/M] // seit 4.11.3
returns a stringlist of values that are referred to by the multivalue product property <propname>.
If you call the functionGetProductProperty
with a multivalue property, then you will get the selected values in a comma-separated string format. This will lead to problems if the returned values contain any comma chars that are not meant to be parsed.
If there is no connection to the opsi server, then the resulting stringlist is constructed in the following way:
Since 4.12.4.32 it is checked if there ist a fileproperties.conf
in theScriptPath
directory. If this file is found we try to get the value from this file. The file will be interpreted as list of key=value pairs. In case of a stringlist the entry should have the pattern<property name>=<list value>
for examle:myproperty=["entry1","entry2","entry3"]
.
If there is no fileproperties.conf
or it does not contain the searched entry, so value<default value>
is returned.<default value>
decribes the return value if no connection to the opsi-server is available. If<default value>
is a string expression this string is the first element of the returned list. Since 4.11.5.6<default value>
may also be a string list expression. Since 4.12.4.32<default value>
may also be a string list from the kind:'["ab","cd","de"]'
Example:
DefStringList $list$
;Property "dummymulti" has the values: ("ab", "cd", "ef", "g,h")
set $list$ = GetProductPropertyList ("dummymulti","True")
if not ("" = takeFirstStringContaining($list$,"g,h"))
comment "GetProductPropertyList passed"
else
set $TestResult$ = "not o.k."
LogWarning "GetProductPropertyList failed"
endif
set $ConstTest$ = "ab,cd,ef,g,h"
set $CompValue$ = GetProductProperty ("dummymulti","True")
if ($ConstTest$ = $CompValue$)
comment "GetProductProperty passed"
else
set $TestResult$ = "not o.k."
LogWarning "GetProductProperty failed"
endif
;;;;;;another Example to get a list as default-property
DefStringList $list$
DefStringList $propertyList$
Set $propertyList$ = createStringList('ab','cd','de')
Set $list$ = GetProductPropertyList ("dummymulti",$propertyList$)
;;;;;; since 4.12.4.32 also possible:
Set $list$ = GetProductPropertyList ("dummymulti",'["ab","cd","de"]')
Since 4.12.4.32: if the file %ScriptPath%\properties.conf
exists with the content:
propstr = from file proplist = ["from file",huhu"]
the following script will be (with out opsi service) successful:
[Actions]
DefStringList $list$
DefVar $str$
set $str$ = GetProductProperty('propstr','')
if $str$ = "from file"
comment "got it"
else
comment "failed"
endif
set $list$ = GetProductPropertyList('proplist','')
if takeString(0,$list$) = "from file"
comment "got it"
else
comment "failed"
endif
see also : [asConfidential_list]
Other String Lists [W/L/M]
-
getProfilesDirList : stringlist
//since 4.11.3.2 [W/L/M]
Provides a list of paths to the local profiles.
[W]: Profiles that contain the following words will not be considered:-
'localservice'
-
'networkservice'
-
'systemprofile'
-
The profile of 'Default Users' is included in the list.
All User
or Public
are not included in the list.
[L]: You get a list of the existing user directories from all users with a UID >= 1000.
Example:
set $list1$ = getProfilesDirList
results in the following log:
Set $list1$ = getProfilesDirList Registry started with redirection (32 Bit) retrieving strings from getProfilesDirList [switch to loglevel 7 for debugging] (string 0)C:\Users\Administrator (string 1)C:\Users\Default
-
GetProcessList : stringlist
//since 4.11.1.2; gives list of exename;pid;dom/user [W/L/M]
Provides a list of running processes.
For each process you get one line with a ';' separated list of the following process information:-
[W]: 'Name of running exe'. [L]: short name of running process
-
[W/L/M]: 'PID'
-
[W]: 'Domain/User'. [L]: 'User'
-
[L]: 'full command line of the process'
-
-
listFiles (<Path>, <Searchmask>, <SearchSubDirectories>, [<Redirection>]) : stringlist
[W/L/M]
Provides a stringlist of all files found in <Path> (e.g. "C:\Windows\system32") which fits to the given <Searchmask> (e.g. "*.dll"). <Searchmask> may contain multiple elements separated by semicolon.
If <SearchsubDirectories> is set to "True" then all subdirectories within the given <Path> are included in the search. Setting <SearchsubDirectories> to "False" excludes the subdirectories from the search.
[W] Optional the parameter <Redirection> can be set to "64bit" or "SysNative". This enables to search in (system) directories which otherwise are not searchable because of redirection of 32-bit programs at 64-bit systems (only 64bit Windows). See also 64 Bit Support on Windows [W]
example:
message "Test of function listFiles"
DefVar $Path$
DefStringList $Files$
Set $Path$ = "%System%"
Set $Files$ = listFiles($Path$,"*.Devices.*.dll","False")
results in the following log:
message Test of function listFiles (created string list $Files$) Set $Path$ = "C:\Windows\system32" The value of the variable "$Path$" is now: "C:\Windows\system32" Set $Files$ = listFiles($Path$,"*.Devices.*.dll*","False") The value of the variable "$Files$" is now: (string 0)C:\Windows\system32\Windows.Devices.AllJoyn.dll (string 1)C:\Windows\system32\Windows.Devices.Background.dll (string 2)C:\Windows\system32\Windows.Devices.Background.ps.dll (string 3)C:\Windows\system32\Windows.Devices.Bluetooth.dll (string 4)C:\Windows\system32\Windows.Devices.Custom.dll (string 5)C:\Windows\system32\Windows.Devices.Custom.ps.dll (string 6)C:\Windows\system32\Windows.Devices.Enumeration.dll (string 7)C:\Windows\system32\Windows.Devices.Haptics.dll (string 8)C:\Windows\system32\Windows.Devices.HumanInterfaceDevice.dll (string 9)C:\Windows\system32\Windows.Devices.Lights.dll (string 10)C:\Windows\system32\Windows.Devices.LowLevel.dll (string 11)C:\Windows\system32\Windows.Devices.Midi.dll (string 12)C:\Windows\system32\Windows.Devices.Perception.dll (string 13)C:\Windows\system32\Windows.Devices.Picker.dll (string 14)C:\Windows\system32\Windows.Devices.PointOfService.dll (string 15)C:\Windows\system32\Windows.Devices.Portable.dll (string 16)C:\Windows\system32\Windows.Devices.Printers.dll (string 17)C:\Windows\system32\Windows.Devices.Printers.Extensions.dll (string 18)C:\Windows\system32\Windows.Devices.Radios.dll (string 19)C:\Windows\system32\Windows.Devices.Scanners.dll (string 20)C:\Windows\system32\Windows.Devices.Sensors.dll (string 21)C:\Windows\system32\Windows.Devices.SerialCommunication.dll (string 22)C:\Windows\system32\Windows.Devices.SmartCards.dll (string 23)C:\Windows\system32\Windows.Devices.SmartCards.Phone.dll (string 24)C:\Windows\system32\Windows.Devices.Usb.dll (string 25)C:\Windows\system32\Windows.Devices.WiFi.dll (string 26)C:\Windows\system32\Windows.Devices.WiFiDirect.dll (string 27)C:\Windows\system32\Windows.Internal.Devices.Sensors.dll
-
replaceOpsiConstants(
<string list>`) : stringlist` //since 4.12.3.6 [W/L/M] returns a list, which has all occurrences of opsi constants in <string list> replaced with their value.
see also : replaceOpsiConstants (string)
Transforming String Lists [W/L/M]
-
getSubList (
<start index> : <end index>, <list>`) : stringlist` [W/L/M]
returns a partial list of a given list.
E.g., if list represents the list of letters 'a', 'b', 'c', 'd', 'e', by the statement:
set $list1$ = getSubList(1 : 3, $list$)
we get the partial list 'b', 'c', 'd' . Begin index as well as end index have to be interpreted as the index of the first and last included list elements. The counting starts with 0.
Default start index is 0, default end index is the index of the last element of the list.
Therefore, (for the above defined list1) the command
set $list1$ = getSubList(1 : , $list$)
yields the list 'b', 'c', 'd', 'e'.
set $list1$ = getSubList(:, $list$)
produces a copy of the original list.
It is possible to count backwards in order to determine the last index:
set $list1$ = getSubList(1 : -1, $list$)
defines the list of elements starting with the first and ending with the last element of the list – in the above example we again get list 'b', 'c', 'd','e'.
set $list1$ = getSubList(1 : -2, $list$)
defines the list of elements starting with the first and ending with the second to last element of the list – in the above example we get list 'b', 'c', 'd'.
Since version 4.12.0.35 you may beside numbers also use string expressions: strings, string variables or string functions.
set $tmp1$ = "1"
set $tmp2$ = "3"
set $list1$ = getSubList( $tmp1$ : $tmp2$ , $list1$)
set $list2$ = createStringList("","-1","0","1","2","3","4","5","6",)
set $list1$ = getSubList(takestring(3,$list2$):takestring(5,$list2$), $list1$)
-
getListContaining(
<list>,<search string>`) : stringlist` [W/L/M]
returns a list with all strings of <list> that contain <search string>.
-
getListContainingList(
<list1>,<list2>`) : stringlist` //since 4.11.3.7 [W/L/M]
returns the intersection of list1 and list2.
-
getSubListByMatch (
<search string>, <target list>`)` :stringlist //since 4.12.0.14 [W/L/M]
returns the part of <target list> where the string matches with <search string>.
The check is performed case-insensitive.
-
getSubListByMatch (
<search list>, <target list>`)` :stringlist //since 4.12.0.14 [W/L/M]
returns the part of <target list> where the string matches with one of the strings of <search list>.
The check is performed case-insensitive.
-
getSubListByContaining (
<search string>, <target list>`)` :stringlist //since 4.12.0.14 [W/L/M]
returns the part of <target list> where the string contains <search string>.
The check is performed case-insensitive.
-
getSubListByContaining (
<search list>, <target list>`)` :stringlist //since 4.12.0.14 [W/L/M]
returns the part of <target list> where the string contains with one of the strings of <search list>.
The check is performed case-insensitive.
-
getSubListByKey (
<search string>, <target list>`)` :stringlist //since 4.12.0.14 [W/L/M]
returns the part of <target list> where the string starts with '<search string>='.
The check is performed case-insensitive.
-
getSubListByKey (
<search list>, <target list>`)` :stringlist //since 4.12.0.14 [W/L/M]
returns the part of the key/value <target list> where the key is one of the strings of <search list>.
The check is performed case-insensitive.
-
getKeyList (
<list>`)` :stringlist //since 4.12.0.14 [W/L/M]
returns from the the key/value list <list> (in the format key=value) the list of keys.
Is an entry in <list> not in the format key=vakue, the complete string will be part of the result list. -
takeFirstStringContaining(
<list>,<search string>`) : string` [W/L/M]
returns the first string from <list> which contains <search string>.
Return en empty string if <search string> is not found.
see also : [takeFirstStringContaining]
-
addtolist(
<list>,<string>`) : stringlist` //since 4.10.8 [W/L/M]
Appends <string> to the list <list>.
-
addListToList(
<dest list>,<src list>`) : stringlist` //since 4.10.8 [W/L/M]
Appends the list <list2> to the list <list1>.
-
reverse (
<list>`) : stringlist` [W/L/M]
produces the inverted list,
if $list$ is 'a', 'b', 'c', 'd', 'e', by
set $list1$ = reverse ($list$)
we get the $list1$ 'e', 'd', 'c', 'b', 'a'.
-
reencodestrlist(
<list>, <from>, <to>`) : stringlist` //since 4.11.4.2 [W/L/M]
assumes that <list> is encoded in <from> and returns the in <to> encoded version of <list>. <from> and <to> are encodings as listet in chapter opsi-script encoding.
-
removeFromListByContaining(
<search string>`,` <target list>`) : stringlist` //since 4.11.5.1 [W/L/M]
Returns a copy of <target list> where all lines that contains <search string> are removed. The match to <search string> is case insensitiv.
-
removeFromListByContaining(
<search list>`,` <target list>`) : stringlist` //since 4.11.5.1 [W/L/M]
Returns a copy of <target list> where all lines are removed that contains a string out of <search list>. The match to <search list> is case insensitiv.
Examples:
File "%Scriptpath%\test-files\encoding\10lines.txt" is:
line 1 line 2 line 3 line 4 line 5 line 6 line 7 line 8 line 9 line 10
Code from opsi-script-test:
comment ""
comment "------------------------------"
comment "Testing: "
message "removeFromListByContaining"
set $string1$ = "%Scriptpath%\test-files\encoding\10lines.txt"
set $list1$ = loadTextFileWithEncoding($string1$, "cp1252")
comment "search with string"
comment "search with string constant"
set $ConstTest$ = "9"
set $list2$ = removeFromListByContaining("line 5", $list1$)
set $CompValue$ = count($list2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $ConstTest$ = "9"
set $list2$ = removeFromListByContaining("LINE 5", $list1$)
comment "the match is case insensitive"
set $CompValue$ = count($list2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $ConstTest$ = "0"
set $list2$ = removeFromListByContaining("line", $list1$)
set $CompValue$ = count($list2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $ConstTest$ = "8"
comment "searchstr 1 will found in 'line 1' and 'line 10'"
set $list2$ = removeFromListByContaining("1", $list1$)
set $CompValue$ = count($list2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
comment "search with string function"
set $ConstTest$ = "9"
set $list2$ = removeFromListByContaining(trim(" line 5 "), $list1$)
set $CompValue$ = count($list2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
comment "search with string variable"
set $string1$ = "line 5"
set $ConstTest$ = "9"
set $list2$ = removeFromListByContaining($string1$, $list1$)
set $CompValue$ = count($list2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
comment "search with string list"
comment "search with string list variable"
set $list3$ = createStringList ('1', '2', '3', '4', '5')
comment "searchstr 1 will found in 'line 1' and 'line 10'"
set $ConstTest$ = "4"
set $list2$ = removeFromListByContaining($list3$, $list1$)
set $CompValue$ = count($list2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
comment "search with string list variable"
comment "searchstr 1 will found in 'line 1' and 'line 10'"
set $ConstTest$ = "4"
set $list2$ = removeFromListByContaining(createStringList ('1', '2', '3', '4', '5'), $list1$)
set $CompValue$ = count($list2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
-
removeFromListByMatch(
<searchstring>,<target list>`) : stringlist` //since 4.11.6 [W/L/M]
Returns a copy of <target list> where all lines are removed that exactly match a line out of <search list>. The match to <search sting> is case insensitiv.
see also : [removeFromListByContaining_str]
see also : [removeFromListByContaining_list]
-
setStringInListAtIndex(
<newstring>,<list>,<indexstr>`) : stringlist` //since 4.11.6 [W/L/M]
Replaces in the existing stringlist <list> the existing string at <index> by <newstring>. If <index> is to hight, <newstring> will be appended. In case of an error the result is an empty string list.
see also : [takeString]
-
areListsEqual(
<strlist1>, <strlist2>, <flag>`) : boolean`
Evaluates if the 2 stringlists <strlist1> and <strlist2> are equal according to the chosen flag :
If flag='FLAG_AUTOMODE': The function will do a case insensitive comparaison. It handles key/value stringlists (with the structure : 'key1=value1') or simple stringlists.
If flag='FLAG_AUTO_CS' : The function will do a case sensitive comparaison. It also handles both key/value stringlists (with the structure : 'key1=value1') or simple stringlists.
If flag='FLAG_STRING_CS' : The function will do a case sensitive comparaison that only handles simple stringlists (So it does not take into consideration the key/value structure).
Iterating through String Lists [W/L/M]
An important usage of string lists is based on the possibility that the script runs through all elements of a list executing some operation on each string element.
The syntax to define this repetition is:
-
for
%s%in
<list>do
<one statement | sub section>
This expression locally defines a string variable %s% that takes one by one the values of the list elements. <one statement> can be any single statement that can exist in a primary section or (and most interestingly) it may be a subsection call. The locally defined iteration index %s% exists in the whole context of statement, in particular in the subsection if statement is a subsection call.
The replacement mechanism for %s% always works like that for constants: The name of the variable is replaced by the element values. If we iterate through a list 'a','b','c' and the iteration index is named %s%, we get for %s% one by one a, b, c – not the String values. To reproduce the original list elements we have to enclose %s% in citation marks. |
Example: Let $list1$ be the list 'a', 'b', 'c', 'd', 'e', and $line$ a String variable. The statement
for %s% in $list1$ do set $line$ = $line$ + "%s%"
iterates through the list elements internally executing
$line$ = $line$ + "a"
$line$ = $line$ + "b"
$line$ = $line$ + "c"
$line$ = $line$ + "d"
$line$ = $line$ + "e"
Such, finally line has value 'abcde' . If we omitted the citation marks around %s% we would get a syntax error for each iteration step.
Please note: The note variable is only valid in the directly called procedure. If it is needed in sub programs of it its value must be transferred to a global variable.
opsiservicecall and json Related functions [W/L/M]
This functions may be used to analyze and modify JSON expressions. In order to work with these functions, you have to understand the structure of the used JSON expression.
These function can help to use the opsiservicecall sections.
-
jsonIsValid(
<jsonstr>`) : boolean` //since 4.11.6: [W/L/M]
returns 'true' if <jsonstr> is a valid JSON expression.
-
jsonIsArray(
<jsonstr>`) : boolean` //since 4.11.6: [W/L/M]
returns 'true' if <jsonstr> is a valid JSON array.
-
jsonIsObject(
<jsonstr>`) : boolean` //since 4.11.6: [W/L/M]
returns 'true' if <jsonstr> is a valid JSON object.
-
jsonAsObjectHasKey(
<jsonstr>,<keystr>`) : boolean` //since 4.11.6: [W/L/M]
returns 'true' if <jsonstr> is a valid JSON object, which contains <keystr> as key.
The following example returns 'true':
jsonAsObjectHasKey('{"productVersion" : "4.4.1","packageVersion" : "2","productId" : "jedit"}','productId')
-
jsonAsArrayCountElements(
<jsonstr>`) : intstr` //since 4.11.6: [W/L/M]
if <jsonstr> is a valid JSON array, the function returns the number of elements in the array.
In case of an error, the result is '"0"'
-
jsonAsObjectCountElements(
<jsonstr>`) : intstr` //since 4.11.6: [W/L/M]
if <jsonstr> is a valid JSON object, the function returns the number of elements in the object.
In case of an error, the result is '"0"'
-
jsonAsArrayGetElementByIndex(
<jsonstr>, <indexstr>`) : jsonstring` //since 4.11.6: [W/L/M]
if <jsonstr> is a valid JSON array, the function returns the element at the index <indexstr>.
The index starts with "0".
In case of an error, the result is '""'
-
jsonAsObjectGetValueByKey(
<jsonstr>, <keystr>`) : valuestring` //since 4.11.6: [W/L/M]
returns from the JSON object <jsonstr>, the value of the key <keystr>.
In case of an error, the result is '""'
-
jsonAsObjectSetValueByKey(
<jsonstr>, <keystr>,<valuestring>`) : jsonstring` //since 4.11.6: [W/L/M]
returns a string with a JSON object. This object is the given <jsonstr>, where the value of the key <keystr> is set to <valuestring>. If the key <keystr> did not exist, it will be created.
If you are sure that you want to create <valuestring> as string value (and not as number or boolean, …) , than we recommend to use the function: [jsonAsObjectSetStringtypeValueByKey].
In case of an error, the result is '""'
-
jsonAsObjectSetStringtypeValueByKey(
<jsonstr>, <keystr>,<valuestring>`) : jsonstring` //since 4.11.6: [W/L/M]
returns a string with a JSON object. This object is the given <jsonstr>, where the value of the key <keystr> is set to <valuestring> as a string (quoted). If the key <keystr> did not exist, it will be created.
If you are not want to create <valuestring> as string value (but as number or boolean, …) , than we recommend to use the function: [jsonAsObjectSetValueByKey].
In case of an error, the result is '""'
-
jsonAsObjectDeleteByKey(
<jsonstr>, <keystr>`) : jsonstring` //since 4.11.6.4: [W/L/M]
returns a string with a JSON object. This object is the given <jsonstr>, where the value of the key - value pair with the key <keystr> is removed.
-
jsonAsArrayPutObjectByIndex(
<jsonstr>, <indexstr>, <objectstr>`) : jsonstring` //since 4.11.6: [W/L/M]
returns a string with a JSON array. This array is the given <jsonstr>, where at the index <indexstr> the object <objectstr> is set.
In case of an error, the result is '""'
-
jsonAsArrayDeleteObjectByIndex(
<jsonstr>, <indexstr>`) : jsonstring` //since 4.11.6.4: [W/L/M]
returns a string with a JSON array. This array is the given <jsonstr>, where the object at the index <indexstr> is removed.
In case of an error, the result is '""'
-
jsonAsArrayToStringList(
<jsonstr>`) : stringlist` //since 4.11.6: [W/L/M]
returns a stringlist that contains the elements of the given JSON array <jsonstr>, with one element per line.
-
jsonStringListToJsonArray(
<strlist>`) : jsonstr` //since 4.11.6: [W/L/M]
returns a string that contains a JSON array that is constructed from the given string list <strlist>, where every line of this list is handled as one array element.
-
jsonAsObjectGetKeyList(
<jsonstr>`) : stringlist` //since 4.11.6: [W/L/M]
returns the list of keys that are found in the JSON object <jsonstr>.
Example: Restoring productOnClient entries from a file to the server:
DefVar $poc_file$
DefVar $objectStr$
DefVar $ArrayStr$
DefVar $pid$
DefStringlist $resultlist$
DefStringlist $resultlist1$
DefStringlist $productIdList$
DefStringlist $pocList$
Message "Delete productOnClient from opsi backend ..."
set $resultlist$ = getReturnListFromSection("opsiservicecall_getPOC")
Set $ArrayStr$ = takestring(0, $resultlist$)
if not(jsonIsValid($ArrayStr$))
LogError "got no valid json from Service"
isFatalError
endif
if not(jsonIsArray($ArrayStr$))
LogError "got no json Array from Service"
isFatalError
endif
comment "extract productIds ..."
comment "clean target list"
set $productIdList$ = emptylist($productIdList$)
comment "get stringlist "
set $pocList$ = jsonAsArrayToStringList($ArrayStr$)
for %aktpoc% in $pocList$ do sub_fill_product_ids
for %aktProductId% in $productIdList$ do opsiServiceCall_del_productOnClient
Message "Restore productOnClient from file ..."
comment " get Restore data from file ..."
Set $ArrayStr$ = strLoadTextFile($poc_file$)
if not(jsonIsValid($ArrayStr$))
LogError "got no valid json from file"
isFatalError
endif
if not(jsonIsArray($ArrayStr$))
LogError "got no json Array from file"
isFatalError
endif
comment "get list from array"
set $pocList$ = jsonAsArrayToStringList($ArrayStr$)
comment "loop over list"
for %pocindex% = "0" to calculate(count($pocList$)+"-1") do sub_set_clientid_in_poclist
comment "convert modified list to jason array"
set $ArrayStr$ = jsonStringListToJsonArray($pocList$)
set $ArrayStr$ = unquote2($ArrayStr$,"[]")
comment "write back"
opsiServiceCall_updatePOC
[sub_fill_product_ids]
set $objectstr$ = '%aktpoc%'
set $pid$ = jsonAsObjectGetValueByKey($objectstr$, "productId" )
set $productIdList$ = addToList($productIdList$,$pid$)
[sub_set_clientid_in_poclist]
set $objectStr$ = takeString("%pocindex%", $poclist$)
set $objectStr$ = jsonAsObjectSetStringtypeValueByKey(($objectStr$, "clientId","%opsiserviceUser%")
set $poclist$ = setStringInListAtIndex($objectStr$,$poclist$,"%pocindex%")
[opsiServiceCall_updatePOC]
"method": "productOnClient_updateObjects"
"params": [
'$ArrayStr$',
]
[opsiservicecall_getPOC]
"method": "productOnClient_getObjects"
"params":[
"[]",
'{"clientId":"%opsiserviceUser%","productType":"LocalbootProduct"}'
]
[opsiServiceCall_del_productOnClient]
"method": "productOnClient_delete"
"params": [
'%aktProductId%',
'%opsiserviceuser%',
]
Calculating with numbers [W/L/M]
opsi-script scripts do not have a special type of varibles for numbers. But there are some functions to help calculating with numbers.
-
calculate(
<arithmetic string expression>`) : string (number)`
this string function calculates the arithemtic expression of the string <str> and returns the rounded result as a string.
Internally the calculations are done with real numbers. This function acceptsthe operators`, `-`, `*`, `/` and round brackets `(`,`)`. + In case of an error, an empty string is returned and the error counter is incremented. If the passed string contains any characters other than numbers, valid operators and brackets, this results in an error. + If the second operand is missing, the first operand is also taken as the second operand and vice versa: 5 = 10 ; 5* = 25. So the strings that are used to assemble the argument should be validated by the funktion `isNumber
.
(since version 4.11.3.5)
see also : [isNumber]
Example:
set $ConstTest$ = "0"
set $CompValue$ = calculate("-1+1")
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $ConstTest$ = "1"
set $CompValue$ = calculate("0+1")
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $ConstTest$ = "-1"
set $CompValue$ = calculate("0-1")
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $string1$ = "5"
set $string2$ = "5"
set $ConstTest$ = "25"
set $CompValue$ = calculate($string1$+"*"+$string2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $string1$ = "5"
set $string2$ = "5"
set $ConstTest$ = "1"
set $CompValue$ = calculate($string1$+"/"+$string2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $string1$ = "5"
set $string2$ = "0"
set $ConstTest$ = ""
comment " expecting devision by zero error and empty string result"
set $CompValue$ = calculate($string1$+"/"+$string2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $string1$ = "9"
set $string2$ = "10"
set $ConstTest$ = "1"
comment "result 0.9 is rounded to 1 "
set $CompValue$ = calculate($string1$+"/"+$string2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $string1$ = "10"
set $string2$ = "9"
set $ConstTest$ = "1"
comment "result 1.1111 is rounded to 1 "
set $CompValue$ = calculate($string1$+"/"+$string2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $string1$ = "5"
set $string2$ = "5"
set $ConstTest$ = "55"
comment " rule * before +"
set $CompValue$ = calculate($string1$+"+"+$string2$+"*10")
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $string1$ = "5"
set $string2$ = "5"
set $ConstTest$ = "100"
comment "brackets before rule * before + "
set $CompValue$ = calculate("("+$string1$+"+"+$string2$+")*10")
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $string1$ = "5"
set $string2$ = "ten"
set $ConstTest$ = ""
comment "invalid char error"
set $CompValue$ = calculate($string1$+"*"+$string2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $string1$ = "5"
set $string2$ = ""
set $ConstTest$ = "25"
comment "5* is interpreted as 5*5"
set $CompValue$ = calculate($string1$+"*")
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $string1$ = "5"
set $string2$ = ""
set $ConstTest$ = "10"
comment "5+ is interpreted as 5+5"
set $CompValue$ = calculate($string1$+"+")
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $string1$ = "nothing"
set $string2$ = "foo"
set $ConstTest$ = ""
comment "invalid char error"
set $CompValue$ = calculate($string1$+"*"+$string2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $string1$ = "5"
set $string2$ = "foo"
set $ConstTest$ = ""
comment "invalid char error"
set $CompValue$ = calculate($string1$+"/"+$string2$)
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
For more examples refer to the product 'opsi-script-test' at the section '$Flag_calculate$ = "on"'
There is as well a comparison expression for comparing Strings as (integer) numbers. If any of them cannot be converted to a number an error will be indicated.
This number comparison expression has the same form as the String comparison but for an INT prefix of the comparison sign:
<String expression> INT<comparison sign> <String expression>
Such, we can build expressions as
if $Name1$ INT<= $Name2$
or
if $Number1$ INT>= $Number2$
see also: Boolean Expressions
-
isNumber(
<str>`) : bool` //since 4.11.3: true if <str> represents an integer [W/L/M]
Boolean function which returns 'true' if <str> represents an integer.
see also : [calculate]
XML2 Functions [W/L/M]
The XML2 implementation is new (4.2019 Version 4.12.1). This means some parts of the implementation may be incomplete. So some things wil be subject of changes. If you find some problems or have need for additional features, do not hasitate to contact us. These 'XML2' section and functions replaces the older and Windows only 'XMLPatch' section XMLPatch Sections. |
For the wording in this chapter see the chapter 'XML2 Sections' / 'XML structure and wording' XML structure and wording
XML files are normally encoded in UTF-8. So the 'XML2' functions expect the given XML files in UTF-8.
The XML2 Section also expect the encoding of the given xml file should be UTF-8 by default but here we have the possibility to work also with different encodings.
getXml2DocumentFromFile(
<path to xml file>`) : xml2stringlist` //since 4.12.1
Reads the xml file <path to xml file> and returns a string list that may be used in other xml2 functions as <xml2stringlist>
For example see 'XML2 Sections' / 'Examples' XML2 Examples
getXml2Document(
<stringlist with xml>`) : xml2stringlist` //since 4.12.1
If <stringlist with xml> contains valid xml data the function returns a string list that may be used in other xml2 functions as <xml2stringlist>
xml2GetFirstChildNodeByName(
<xml2stringlist>, <node name str>`) : xml2stringlist` //since 4.12.1.
Searches in the given <xml2stringlist> the first occurence of a node with the name <node name str> and returns this node (with all child nodes) as a xml2stringlist.
For example see 'XML2 Sections' / 'Examples' XML2 Examples
getXml2UniqueChildnodeByName(
<xml2stringlist>, <node name str>`) : xml2stringlist` //since 4.12.1.
Searches in the given <xml2stringlist> the occurences of a nodes with the name <node name str> and if there is only one, this one is returned (with all child nodes) as a xml2stringlist.
If there is none or more than one child found, a empty string list is returned.
getXml2AttributeValueByKey(
<xml2stringlist>, <attr name str>`) : string` //since 4.12.1.
Searches in the given <xml2stringlist> the first node and in this node an attribute with the name <attr name str> and returns the value of this attribute.
If not found or on any other error, a empty string will be returned.
For example see 'XML2 Sections' / 'Examples' XML2 Examples
getXml2Text(
<xml2stringlist>`) : string` //since 4.12.1.
Returns the xml data given by <xml2stringlist> as a single line string.
see also : XML related functions (XML2)
see also : XML2 Section
TOML files Functions [W/L/M]
Starting from opsi-script v. 4.12.5, opsi-script allows TOML files handling.
opsi-script currently does not support the handling of comments within TOML files. Pasting data into tables/areas with comments may delete them. |
The official TOML spezifications can be found here: https://toml.io/en/ |
TOML files are usually encoded in UTF-8. So the 'TOML' functions expect the given TOML files to be in UTF-8.
Description of the TOML functions available in opsi-script
The following functions can be used in an opsiscript file:
-
LoadTOMLFile(
<TOMLfilePath: String>`) : StringList` //since 4.12.5.0
Loads the TOML file <TOML file path> and returns a string list of the file content
-
ReadTOMLFile(
<TOMLfilePath: String>`) : String` //since 4.12.5.0
Reads the TOML file <TOML file path> and returns a string of the file content.
This String is the one to be used for manipulating TOML files in the upcoming functions.
Please keep in mind that this function does not preserve comments. |
-
GetTOMLAsStringList(
<TOMLcontents: String>`) : StringList` //since 4.12.5.0
Parses the TOML String contents <TOMLcontents> and returns a String List of the parsed TOML content.
-
GetTOMLAsString(
<TOMLcontents: String>`) : String` //since 4.12.5.0
Parses the TOML String contents <TOMLcontents> and returns a String of the parsed TOML content.
-
GetTOMLKeys(
<TOMLcontents: String>`) : StringList` //since 4.12.5.0
Searches in the given <TOMLcontents> String for all the keys of the root table and returns a stringList of the found keys.
If no key is found, an empty string list will be returned.
This function only returns the keys of the given String, parsed as a root table, including the names of its sections(sub-tables). It does not include the keys of any sub-Table. |
-
GetTOMLTableNames(
<TOMLcontents: String>`) : StringList` //since 4.12.5.0
Searches in the given <TOMLcontents> String for all the tables of the root table and returns a stringList of the found tables' names.
If no table is found, an empty string list will be returned.
-
GetTOMLTable(
<TOMLcontents: String> , <table name : String>`) : StringList` //since 4.12.5.0
Searches in the given <TOMLcontents> for a table with the given <table name> and returns a String List of the found Table content.
-
GetTOMLTableAsString(
<TOMLcontents: String> , <table name : String>`) : String` //since 4.12.5.0
Searches in the given <TOMLcontents> for a table with the given <table name> and returns a String of the found Table content.
-
GetValueFromTOML(
<TOMLcontents: String> , <keyPath: String> , <defaultValue: String>`) : String` //since 4.12.5.0
Searches in the given <TOMLcontents> String for the key defined with the <keyPath>, which is :-
A simple key name if the key is in the root table.
-
A composed key path : a succession of the tables' names containing the searched key-value pair. For example : "Table.subTable.key"
and returns a String of the corresponding value, if found.
-
If the given key is not found, or the given key path is incorrect or incomplete, or no value was found, the input <defaultValue> string will be returned.
This function returns the exact value as a String output. So, for example if the searched value is a string with content "opsi", the result of this function is : '"opsi"' |
-
ModifyTOML(
<TOMLcontents: String> , <command: String> , <keyPath: String> , <value: String>`) : String` //since 4.12.5.0
This function allows to modify the <TOMLcontents> String given as input with the help of 4 commands :-
'ADD' : Adds the input <keyPath>-<value> pair if the key does not exist. It returns a new modified TOMLcontens String.
But, if the <keyPath> exists, this function does not do any modifications. The same input <TOMLcontents> String will be returned. -
'SET' : Sets a new <keyPath>-<value> pair if the key does not exist, and even if it exists. The corresponding value will be changed with the new input <value>.
The function returns the new modified TOMLcontens String. -
'CHANGE ' : Changes the corresponding value of the input <keyPath> to the given <value>. It returns a new modified TOMLcontens String.
But if the keyPath does not exist, nothing will be done. The same input <TOMLcontents> String will be returned. -
'DEL' : Deletes the <keyPath> and its found value. It returns a new modified TOMLcontens String.
But if the keyPath does not exist, nothing will be done. The same input <TOMLcontents> String will be returned.
-
If any treatment exception occurs, the same input <TOMLcontents> String will be returned.
If any error occurs, an empty String will be returned.
Keep in mind that adding new values must respect the TOML notation within the input String parameter. |
For example :
-
if you want to add a String type value with the content "New value", it should be written between double quotes as follows :
<value> = ' "New value" ' -
if you want to add a Boolean type value with the content True, it should be written as follows :
<value> = ' True ' -
if you want to add a Number type value with the content 1.1, it should be written as follows :
<value> = ' 1.1 ' -
if you want to add an Array type value with the content ["first value", "second value"], it should be written as follows :
<value> = ' ["first value", "second value"] ' -
if you want to add a Date type value with the content 2022-02-02T16:16:00Z-16:16, it should be written as follows :
<value> = ' 2022-02-02T16:16:00Z-16:16 '
All detailed examples are included in the following opsi-script example.
-
DeleteTableFromTOML(
<TOMLcontents: String> , <tablePath: String>`) : String` //since 4.12.5.0
Deletes the whole given <tablePath>, with its key-values and sub-tables if they exist, from the given <TOMLcontents> String.
If the given <tablePath> is not found, no modifications are done and the same input <TOMLcontents> string will be returned.
-
SaveToTOMLFile(
<TOMLcontents: String> , <TOML file Path: String>`) : boolean` //since 4.12.5
This function gives back the input <TOMLcontents> String to a formatted TOML file content and stores it in the given <TOML file Path>.
If saving the file run without errors, "True" will be returned.
If any errors occur, "False" will be returned.
-
ConvertTOMLtoJSON(
<TOMLcontents: String>`) : String` //since 4.12.5.0
Converts the given <TOMLcontents> String to a JSON formatted String.
-
ConvertTOMLfileToJSONfile(
<TOMLfilePath: String> , <JSONfilePath: String>`) : boolean` //since 4.12.5.0
This function converts the content of the first given <TOMLfilePath> to a JSON formatted content and saves it in the second given <JSONfilePath>.
If saving the file run without errors, "True" will be returned.
If any errors occur, "False" will be returned.
Example:
File "TOMLfile.toml" is:
# This is a TOML document. title = "TOML Example" [owner] name = "Tom Preston-Werner" dob = 1979-05-27T07:32:00-08:00 [database] server = "192.168.1.1" ports = [ 8000, 8001, 8002 ] connection_max = 5000 enabled = true [servers] [servers.alpha] ip = "10.0.0.1" dc = "eqdc10" [servers.beta] ip = "10.0.0.2" dc = "eqdc10" [clients] data = [ ["gamma", "delta"], [1, 2] ] hosts = [ "alpha", "omega" ]
comment "Testing TOML functions"
DefVar $TOMLFile$
DefVar $TOMLString$
DefStringList $TOMLlist$
DefVar $TOMLdata$
Set $TOMLFile$ = $HomeTestFiles$ + "TOMLfile.toml"
Set $TOMLlist$ = LoadTOMLFile($TOMLFile$)
Set $TOMLString$ = ReadTOMLFile($TOMLFile$)
Set $TOMLlist$ = GetTOMLKeys($TOMLString$)
Set $TOMLlist$ = GetTOMLTableNames($TOMLString$)
Set $TOMLlist$ = GetTOMLTable($TOMLString$, "owner")
Set $TOMLdata$ = GetTOMLTableAsString($TOMLString$, "owner")
Set $TOMLdata$ = GetTOMLTableAsString($TOMLString$, "servers")
Set $TOMLlist$ = GetTOMLTableNames($TOMLdata$)
Set $TOMLdata$ = GetValueFromTOML( $TOMLString$ , "" , "defaultValue" )
Set $TOMLdata$ = GetValueFromTOML( $TOMLString$ , " " , "defaultValue" )
Set $TOMLdata$ = GetValueFromTOML( $TOMLString$ , "key" , "defaultValue" )
Set $TOMLdata$ = GetValueFromTOML( $TOMLString$ , "title" , "defaultValue" )
Set $TOMLdata$ = GetValueFromTOML( $TOMLString$ , "owner.name" , "defaultValue")
Set $TOMLdata$ = GetValueFromTOML( $TOMLString$ , "servers.alpha.ip" , "defaultValue")
Set $TOMLdata$ = GetValueFromTOML( $TOMLString$ , "servers.beta.key" , "defaultValue" )
Set $TOMLdata$ = GetValueFromTOML( $TOMLString$ , "clients.data " , "defaultValue" )
Set $TOMLdata$ = GetValueFromTOML( $TOMLString$ , "database.ports" , "defaultValue" )
Set $TOMLdata$ = GetValueFromTOML( $TOMLString$ , "database.connection_max" , "defaultValue")
Set $TOMLdata$ = GetValueFromTOML( $TOMLString$ , "database.enabled" , "defaultValue")
Set $TOMLdata$ = GetValueFromTOML( $TOMLString$ , "servers.beta" , "defaultValue")
Set $TOMLString$ = ModifyTOML($TOMLString$, 'ADD', 'title', '"newADDvalueInRootTable"')
Set $TOMLString$ = ModifyTOML($TOMLString$, 'ADD', 'newADDkeyInRootTable', '"newADDvalueInRootTable"')
Set $TOMLString$ = ModifyTOML($TOMLString$, 'ADD', 'servers.alpha.a.newADDkeyInAlphaA', '"newADDvalueInAlphaA"')
Set $TOMLString$ = ModifyTOML($TOMLString$, 'ADD', 'newTable.newADDtableKey', '"newADDtableValue"')
Set $TOMLString$ = ModifyTOML($TOMLString$, 'ADD', 'newTable.newStringKey', '"newStringValue"')
Set $TOMLString$ = ModifyTOML($TOMLString$, 'ADD', 'newTable.newIntegerKey', '1')
Set $TOMLString$ = ModifyTOML($TOMLString$, 'ADD', 'newTable.newFloatKey', '10.1')
Set $TOMLString$ = ModifyTOML($TOMLString$, 'ADD', 'newTable.newDateKey', '2022-02-02T16:16:00Z-16:16')
Set $TOMLString$ = ModifyTOML($TOMLString$, 'ADD', 'newTable.newArray', '[ "a", "b", "c" ]')
Set $TOMLString$ = ModifyTOML($TOMLString$, 'SET',' newADDkeyInRootTable', '"newSETValueInRootTable"')
Set $TOMLString$ = ModifyTOML($TOMLString$, 'SET', 'newSETkeyInRootTable', '"newSETValueInRootTable"')
Set $TOMLString$ = ModifyTOML($TOMLString$, 'SET', 'servers.alpha.a.newADDkeyInAlphaA', '"newSETValueInAlphaA"')
Set $TOMLString$ = ModifyTOML($TOMLString$, 'SET', 'newTable.newADDtableKey', '"newSETtableValue"'
Set $TOMLString$ = ModifyTOML($TOMLString$, 'CHANGE', 'newCHANGEkeyInRootTable', ' "newCHANGEValueInRootTable" ')
Set $TOMLString$ = ModifyTOML($TOMLString$, 'CHANGE', 'newSETkeyInRootTable', '"newCHANGEValueInRootTable"')
Set $TOMLString$ = ModifyTOML($TOMLString$, 'CHANGE', 'servers.alpha.a.newADDkeyInAlphaA', '"newCHANGEValueInAlphaA"')
Set $TOMLString$ = ModifyTOML($TOMLString$, 'CHANGE', 'newCHANGETable.newCHANGEtableKey', ' "newCHANGEtableValue" '
Set $TOMLString$ = ModifyTOML($TOMLString$, 'DEL', 'newSETkeyInRootTable', '')
Set $TOMLString$ = ModifyTOML($TOMLString$, 'DEL', 'DELkeyInRootTable', '')
Set $TOMLString$ = ModifyTOML($TOMLString$, 'DEL', 'servers.alpha.a.newADDkeyInAlphaA', '')
Set $TOMLString$ = ModifyTOML($TOMLString$, 'DEL', 'DELTable.DELtableKey', '')
Set $TOMLString$ = DeleteTableFromTOML($TOMLString$, "newTable")
Set $newTOMLFile$ = $HomeTestFiles$ + "TOMLempty.toml"
Set $TestString$ = booltostring(SaveToTOMLFile($TOMLString$,$newTOMLFile$))
Set $newJSONFile$ = $HomeTestFiles$ + "myJSONfromTOMLdata.json"
set $TestString$ = booltostring(ConvertTOMLfileToJSONfile($newTOMLFile$,$newJSONFile$))
After running the script, the content of the TOML-File is:
# This is a TOML document. title = "TOML Example" newADDkeyInRootTable = "newSETValueInRootTable" [owner] name = "Tom Preston-Werner" dob = 1979-05-27T07:32:00Z-07:32 [database] server = "192.168.1.1" ports = [ 8000, 8001, 8002 ] connection_max = 5000 enabled = true [servers] [servers.alpha] ip = "10.0.0.1" dc = "eqdc10" [servers.alpha.a] [servers.beta] ip = "10.0.0.2" dc = "eqdc10" [clients] data = [ [ "gamma", "delta" ], [ 1, 2 ] ] hosts = [ "alpha", "omega" ]
Regular expression related functions [W/L/M]
Working with regular expressions has some disadvantages: Finding the correct regular expression can be difficult. So use tools to test your expressions. Code written with regular expressions is hard to read. Make comments in your code that explain what you try to do. |
There are different kinds of regular expressions: Perl, Javascript, Java, …
The kind of regular expression implemented here is a variant of the perl style
or PCRE
.
A detailed documentation of the here used variant you will find at:
https://regex.sorokin.engineer/en/latest/regular_expressions.html
You should use a tool to test your regular expression. We recommend the 'opsi-regexpr-tester.exe' application. You can download it here: https://download.uib.de/opsi4.2/misc/helper/opsiRegExprTest.exe |
-
opsi-regexpr-tester.exe
This application (opsi-regexpr-tester.exe) helps you test your Regular Expression.
The user interface of 'opsi-regexpr-tester' offers you two fields :
First field ('Regular Expression :') is where you are asked to input the Regular Expression you want to test.
Second field ('Text :') is where you should input the text on which you want to test your regular expression.
Then, you can insert Pattern Modifiers Flags, explained in details in the documentation previously mentioned :
https://regex.sorokin.engineer/en/latest/regular_expressions.html
We propose 6 flags :
-
i, case-insensitive
-
m, multi-line strings
-
s, single line strings
-
g, greediness
-
x, eXtended syntax
-
r, Russian ranges
You can select the ones you want to insert by checking the corresponding box. They will be automatically added at the beginning of the 'Regular Expression :' field. Please note that the flags are always put before the corresponding regular expression part !
Finally, you can click on the button "Examine" to test your Regular Expression.
If your regular expression matches the text or part of it, a successful result will appear, and the matches will be coloured in green on you text.
If your regular expression does not match the text or any part of it, a failure text result will appear.
You can clear both the Regular Expression and the Text fields by clicking on the button "Clear".
-
isRegexMatch(
<string>, <pattern>`) : boolean`
It will return 'true' if the pattern matches the string and return 'false' if pattern does not matches the string,
where pattern is the regular expression and the string would be searched for the matches.
Example:
comment "Testing with matching string"
set $ConstTest$ = "true"
set $CompValue$ = booltostring(isRegexMatch('abc efg', '.*abc.*'))
if ($ConstTest$ = $CompValue$)
comment "isRegexMatch passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing isRegexMatch failed"
endif
comment "Testing with non matching string"
set $ConstTest$ = "false"
set $CompValue$ = booltostring(isRegexMatch('abc efg', '.*xyz.*'))
if ($ConstTest$ = $CompValue$)
comment "isRegexMatch passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing isRegexMatch failed"
endif
-
getSubListByContainingRegex(
<pattern>, <target list>`) : stringlist`
It will extract a sublist from target list by matching a single pattern,
where sublist is a list of whole lines containing the pattern. -
getSubListByContainingRegex(
<pattern list>, <target list>`) : stringlist`
It will extract a sublist from target list by matching a list of patterns,
where sublist is a list of whole lines containing any of the patterns in the pattern list.
Example:
comment "Testing with a single pattern"
set $string1$ = "\w+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,6}"
set $list1$ = createStringList('uib gmbh','example@xyz.com and example2@xyz.com', 'client')
set $ConstTest$ = "example@xyz.com and example2@xyz.com"
set $list2$ = getSubListByContainingRegex($string1$, $list1$)
set $CompValue$ = composeString ($list2$, " | ")
if ($ConstTest$ = $CompValue$)
comment "getSubListByContainingRegex passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing getSubListByContainingRegex failed"
endif
comment "Testing with a list of patterns"
set $list3$ = createStringList('\w+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,6}','.*uib')
set $ConstTest$ = "uib gmbh | example@xyz.com and example2@xyz.com"
set $list2$ = getSubListByContainingRegex($list3$, $list1$)
set $CompValue$ = composeString ($list2$, " | ")
if ($ConstTest$ = $CompValue$)
comment "getSubListByContainingRegex passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing getSubListByContainingRegex failed"
endif
-
getRegexMatchList(
<pattern>, <target list>`) : stringlist`
It will extract a sublist from the target list by matching a single pattern,
where sublist is a list of exact matches for the pattern. -
getRegexMatchList(
<pattern list>, <target list>`) : stringlist`
It will extract a sublist from the target list by matching a list of patterns,
where sublist is a list of exact matches for any of the patterns in the pattern list.
Example:
comment "Testing with a single pattern"
set $string1$ = "\w+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,6}"
set $list1$ = createStringList('uib gmbh','client','example@xyz.com and example2@xyz.com')
set $ConstTest$ = "example@xyz.com | example2@xyz.com"
set $list2$ = getRegexMatchList($string1$, $list1$)
set $CompValue$ = composeString ($list2$, " | ")
if ($ConstTest$ = $CompValue$)
comment "getRegexMatchList passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing getRegexMatchList failed"
endif
comment "Testing with a list of patterns"
set $list3$ = createStringList('\w+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,6}','.*uib')
set $ConstTest$ = "uib | example@xyz.com | example2@xyz.com"
set $list2$ = getRegexMatchList($list3$, $list1$)
set $CompValue$ = composeString ($list2$, " | ")
if ($ConstTest$ = $CompValue$)
comment "getRegexMatchList passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing getRegexMatchList failed"
endif
-
removeFromListByContainingRegex(
<pattern>, <target list>`) : stringlist`
remove whole matching lines for a single pattern. -
removeFromListByContainingRegex(
<pattern list>, <target list>`) : stringlist`
remove whole matching lines for any of the patterns in the pattern list.
Example:
comment "Searching with a single expression"
set $string1$ = "\w+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,6}"
set $list1$ = createStringList('uib gmbh','client','example@xyz.com and example2@xyz.com')
set $ConstTest$ = "uib gmbh | client"
set $list2$ = removeFromListByContainingRegex($string1$, $list1$)
set $CompValue$ = composeString ($list2$, " | ")
if ($ConstTest$ = $CompValue$)
comment "removeFromListByContainingRegex passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing removeFromListByContainingRegex failed"
endif
comment "Searching with a list of expressions"
set $list3$ = createStringList('\w+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,6}','.*uib')
set $ConstTest$ = "client"
set $list2$ = removeFromListByContainingRegex($list3$, $list1$)
set $CompValue$ = composeString ($list2$, " | ")
if ($ConstTest$ = $CompValue$)
comment "removeFromListByContainingRegex passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing removeFromListByContainingRegex failed"
endif
-
stringReplaceRegex(
<string>, <pattern>, <replacement string>`) : string`
Replace exact matches in string with the replacement string.
Example:
set $ConstTest$ = "xyz abc gmbh"
set $CompValue$ = stringReplaceRegex('uib gmbh','.*uib', 'xyz abc')
if ($ConstTest$ = $CompValue$)
comment "stringReplaceRegex passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing stringReplaceRegex failed"
endif
-
stringReplaceRegexInList(
<target list>, <pattern>, <replacement string>`) : stringlist`
Replace exact matches in the target list with the replacement string.
Example:
set $string1$ = "\w+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,6}"
set $string2$ = "MATCH REMOVED"
set $list1$ = createStringList('uib gmbh','client','example@xyz.com and example2@xyz.com')
set $ConstTest$ = 'uib gmbh | client | MATCH REMOVED and MATCH REMOVED'
set $list2$ = stringReplaceRegexInList($list1$, $string1$, $string2$)
set $CompValue$ = composeString ($list2$, " | ")
if ($ConstTest$ = $CompValue$)
comment "stringReplaceRegexInList passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing stringReplaceRegexInList failed"
endif
For further examples see the product 'opsi-script-test'
expecially the file sub-scripts/regex.opsiscript
URL related functions [W/L/M]
These functions can be used to analyze and create URLs.
They convert string URLs to a string list with the URL components:
'Protocol=proto' 'Username=usr' 'Password=pwd' 'Host=host' 'Port=8080' 'Path=/path/' 'Document=doc' 'Params=param' 'Bookmark=bookmark'
-
parseUrl(
<url string>`) : stringlist`
Return url components as stringlist for the given <url string>.
Example:
comment "Testing parseUrl with all fields"
set $string1$ = "proto://usr:pwd@host:8080/path/doc?param#bookmark"
set $list1$ = createStringList('Protocol=proto','Username=usr','Password=pwd', 'Host=host', 'Port=8080', 'Path=/path/', 'Document=doc', 'Params=param', 'Bookmark=bookmark')
set $ConstTest$ = composeString ($list1$, " | ")
set $list2$ = parseUrl($string1$)
set $CompValue$ = composeString ($list2$, " | ")
if ($ConstTest$ = $CompValue$)
comment "parseUrl passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing parseUrl failed"
endif
comment "Testing parseUrl with some fields"
set $string1$ = "ftp://example.abc.edu/"
set $list1$ = createStringList('Protocol=ftp','Username=','Password=', 'Host=example.abc.edu', 'Port=0', 'Path=/', 'Document=', 'Params=', 'Bookmark=')
set $ConstTest$ = composeString ($list1$, " | ")
set $list2$ = parseUrl($string1$)
set $CompValue$ = composeString ($list2$, " | ")
if ($ConstTest$ = $CompValue$)
comment "parseUrl passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing parseUrl failed"
endif
-
createUrl(
<urlcomponents list>`) : string`
return url string for the given urlcomponents.
The <urlcomponents list> has not to be complete. You may give only the needed parts.
Example:
comment "Testing createUrl with all fields"
set $list1$ = createStringList('Protocol=proto','Username=usr','Password=pwd', 'Host=host', 'Port=8080', 'Path=/path/', 'Document=doc', 'Params=param', 'Bookmark=bookmark')
set $ConstTest$ = "proto://usr:pwd@host:8080/path/doc?param#bookmark"
set $CompValue$ = createUrl($list1$)
if ($ConstTest$ = $CompValue$)
comment "createUrl passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing createUrl failed"
endif
comment "Testing createUrl with some fields"
set $list1$ = createStringList('Protocol=https','Host=www.example.com', 'Path=/b-c-d-330002341216/')
set $ConstTest$ = "https://www.example.com/b-c-d-330002341216/"
set $CompValue$ = createUrl($list1$)
if ($ConstTest$ = $CompValue$)
comment "createUrl passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing createUrl failed"
endif
For further examples see the product 'opsi-script-test'
expecially the file sub-scripts/urlparser.opsiscript
Network related functions [W/L/M]
-
isValidIP4 (
<ip4adr>`) : boolean`
return true if the IPv4 address is valid.
Example:
comment "Testing with valid IPv4 address"
set $ConstTest$ = "true"
set $CompValue$ = booltostring(isValidIP4("255.255.0.0"))
if ($ConstTest$ = $CompValue$)
comment "isValidIP4 passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing isValidIP4 failed"
endif
comment "Testing with invalid IPv4 address"
set $ConstTest$ = "false"
set $CompValue$ = booltostring(isValidIP4("255.256.0.0"))
if ($ConstTest$ = $CompValue$)
comment "isValidIP4 passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing isValidIP4 failed"
endif
-
isValidIP4Network (
<ip4adr>, <netmask>`) : boolean`
return true if the given ipv4 address is a valid network address
Netmask can be given in both cidr and dotted-decimal notation.
Example:
comment "Testing with valid network address, where netmask is in cidr notation"
set $ConstTest$ = "true"
set $CompValue$ = booltostring(isValidIP4Network('192.168.0.0','24'))
if ($ConstTest$ = $CompValue$)
comment "isValidIP4Network passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing isValidIP4Network failed"
endif
comment "Testing with valid network address, where netmask is in dotted-decimal notation"
set $ConstTest$ = "true"
set $CompValue$ = booltostring(isValidIP4Network('192.168.0.0','255.255.255.0'))
if ($ConstTest$ = $CompValue$)
comment "isValidIP4Network passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing isValidIP4Network failed"
endif
comment "Testing with invalid network address"
set $ConstTest$ = "false"
set $CompValue$ = booltostring(isValidIP4Network('198.51.100.223','21'))
if ($ConstTest$ = $CompValue$)
comment "isValidIP4Network passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing isValidIP4Network failed"
endif
-
isValidIP4Host (
<ip4adr>, <netmask>`) : boolean`
return true if the given ipv4 address is a valid host address
Netmask can be given in both cidr and dotted-decimal notation.
Example:
comment "Testing with valid host address, where netmask is in dotted-decimal notation"
set $ConstTest$ = "true"
set $CompValue$ = booltostring(isValidIP4Host('198.51.104.254', '255.255.248.0'))
if ($ConstTest$ = $CompValue$)
comment "isValidIP4Host passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing isValidIP4Host failed"
endif
comment "Testing with valid host address, where netmask is in cidr notation"
set $ConstTest$ = "true"
set $CompValue$ = booltostring(isValidIP4Host('198.51.104.254', '21'))
if ($ConstTest$ = $CompValue$)
comment "isValidIP4Host passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing isValidIP4Host failed"
endif
comment "Testing with invalid host address"
set $ConstTest$ = "false"
set $CompValue$ = booltostring(isValidIP4Host('198.51.104.0', '21'))
if ($ConstTest$ = $CompValue$)
comment "isValidIP4Host passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing isValidIP4Host failed"
endif
-
getIP4NetworkByAdrAndMask(
<ip4adr>, <netmask>`) : string`
return network address for the given IP address and netmask.
Netmask can be given in both cidr and dotted-decimal notation.
Example:
comment "Testing with netmask in cidr notation "
set $ConstTest$ = "198.48.0.0"
set $CompValue$ = getIP4NetworkByAdrAndMask('198.51.100.223', '12')
if ($ConstTest$ = $CompValue$)
comment "getIP4NetworkByAdrAndMask passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing getIP4NetworkByAdrAndMask failed"
endif
comment "Testing with netmask in dotted decimal notation "
set $ConstTest$ = "198.48.0.0"
set $CompValue$ = getIP4NetworkByAdrAndMask('198.51.100.223', '255.240.0.0')
if ($ConstTest$ = $CompValue$)
comment "getIP4NetworkByAdrAndMask passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing getIP4NetworkByAdrAndMask failed"
endif
-
getDefaultNetmaskByIP4adr (
<ip4adr>`) : string`
return default netmask for the given IPv4 address
Example:
set $ConstTest$ = "255.255.0.0"
set $CompValue$ = getDefaultNetmaskByIP4adr("128.42.5.4")
if ($ConstTest$ = $CompValue$)
comment "getDefaultNetmaskByIP4adr passed"
else
set $TestResult$ = "not o.k."
LogWarning "testing getDefaultNetmaskByIP4adr failed"
endif
-
cidrToNetmask (<string>) : string
//since 4.12.4.37
Returns the netmask (dotted decimal notation) for the given IPv4 CIDR-Suffix.
cidr ⇐ 0 results to "0.0.0.0"
cidr >= 32 results to "255.255.255.255"
Empty or invalid input results to an empty string
see also : [netmaskToCidr]
see also : [getDefaultNetmaskByIP4adr]
see also : [getIP4NetworkByAdrAndMask]
Beispiel:
set $netmask$ = cidrToNetmask("24")
comment "expected: 255.255.255.0"
set $netmask$ = cidrToNetmask("16")
comment "expected: 255.255.0.0"
set $netmask$ = cidrToNetmask("-1")
comment "expected: 0.0.0.0"
set $netmask$ = cidrToNetmask("55")
comment "expected: 255.255.255.255"
set $netmask$ = cidrToNetmask("")
comment "expected: "
-
netmaskToCidr (<string>) : string
//since 4.12.4.37
Returns the IPv4 CIDR-Suffix for the given netmask (dotted decimal notation).
Empty or invalid input results to an empty string
see also : [cidrToNetmask]
see also : [getDefaultNetmaskByIP4adr]
see also : [getIP4NetworkByAdrAndMask]
Beispiel:
set $cidr$ = netmaskToCidr("255.255.255.0")
comment "expected: 24"
set $cidr$ = netmaskToCidr("255.255.0.0")
comment "expected: 16"
set $cidr$ = netmaskToCidr("255.255.10.0")
comment "(invalid input) expected: "
set $cidr$ = netmaskToCidr("")
comment "(empty input) expected: "
-
isValidFQDN (<domainName>) : boolean
returns true if the input string is a Fully Qualified Domain Name (FQDN) and false if not. A Fully Qualified Domain Name (FQDN) has the following conditions :-
Its total length should not exceed 254 characters,
-
It should have at least 3 dot-separated labels,
-
Each label’s length should not exceed 63 characters,
-
Labels contain only letters, numbers and dashes,
-
The last label (TLD) should contain only letters and should have at least 2 characters,
-
Each label starts with a letter or a number (no dashes)
-
Example:
Message "Testing of isValidFQDN"
SetLogLevel=7
DefVar $TestResult$
DefVar $CompValue$
DefStringList $CorrectFQDNs$
DefStringList $IncorrectFQDNs$
Set $CorrectFQDNs$ = CreateStringList("www.uib.de", "opsi-script.uib.de", "m.opsi.org", "a-a.b-b.cc", "a1b2.c3d4.e5f6.g7h8.i9j0.zz", "1a-2b.3c_4d.5e-6f.zzz","123.123.com")
Set $IncorrectFQDNs$ = CreateStringList("abcde", "uib.de", "www.uib", "www.uib.d", "-script.uib.de", "_script.uib.de", "www.uib.00", "a1b2.c3d4.e5f6", "aaa.-bbb.zz", "#aaa.bbb.zz", "a+a.bbb.zz", "a?a.bbb.zz")
DefFunc myFQDNTester($expected$ : string, $fqdn$ : string, ref $TestResult$ : string) : void
DefVar $CompValue$
set $CompValue$ = booltostring(isValidFQDN($fqdn$))
if $CompValue$ = $expected$
comment "Testing isValidFQDN succeeded"
else
set $TestResult$ = "not o.k."
LogWarning "Testing isValidFQDN failed"
endif
endfunc
for %s% in $CorrectFQDNs$ do myFQDNTester("true","%s%",$TestResult$)
for %s% in $IncorrectFQDNs$ do myFQDNTester("false","%s%",$TestResult$)
For further examples see the product 'opsi-script-test'
expecially the file sub-scripts/networkcalc.opsiscript
Process and Script Related functions [W/L/M]
-
waitForPackageLock(
<seconds timeout string>,<bool should we kill>`) : bool` //since 4.11.6.1 [L]
Returnstrue
if the Linux package system is not locked by an other process. If it is locked, it waits <seconds timeout string> to get the lock. If the timeout is reached and <bool should we kill> istrue
than the locking process is killed but using this feature ist not recommended.
-
processIsRunning(
<process name>`) : boolean` //since 4.11.6.1 [W/L/M]
Returnstrue
if <process name> is found in the process list
-
isProcessChildOf(<searchprocstr>, <parentprocstr>): bool
//since 4.12.4.35 [W/L/M]
Returnstrue
if the process <searchprocstr> is a child of <parentprocstr>.
Example:if isProcessChildOf('%opsiscriptprocname%', 'opsiclientd.exe') comment "running in opsi service context" endif
-
shellCall (
<command string>`) : stringlist (output)` //since 4.11.4.2 [W/L/M]
Executing <command string> with the standard shell (cmd.exe / bash)set $list$= shellCall('net start')
is a shortcut for this expression:
set $list$ = getOutStreamFromSection ('ShellScript_netstart winst /sysnative') [ShellScript_netstart] net start
-
shellCall (
<command string>`) : noresult` //since 4.11.6.1 [W/L/M]shellCall('net start')
is a shortcut for this expression:
ShellScript_netstart winst /sysnative [ShellScript_netstart] net start
-
shellCall (
<command string>`) : string (exitcode)` //since 4.11.6.1 [W/L/M]set $exitcode$ = shellCall('net start')
is a shortcut for this expression:
ShellScript_netstart winst /sysnative set $exitcode$ = getLastExitcode [ShellScript_netstart] net start
-
powershellCall(
<commandstr> [,<access str>='sysnative' [,<policy bool str>='true']]) : stringlist (output)
//since 4.12.0.16 [W]
powershellCall(
<commandstr> [,<access str>='sysnative' [,<policy bool str>='true'][, <optionstr> = '']]) : stringlist (output)
//since 4.12.4.28 [W]
Runs <command string> with the PowerShell.
More exactly the PowerShell runs a script that looks like:trap { write-output $_ ; exit 1 } <commandstr> exit $LASTEXITCODE
The first line of the script makes sure that we get no exit code = 0 if the script fails with an exception. The last line gives the exit code of previous command back.
The architecture of the called powershell.exe issysnative
by default. Using the optional second parameter <access str> you may change this default. In this case it has to be one of the following values:32bit
,sysnative
,64bit
.
(see also: Chapter 64 Bit)
By Windows default the PowerShell has the execution policyRetricted
which do not allow to run any unsigned scripts. In order to run scripts thepowershellCall
function does by default the following: The current execution policy is backuped and the execution policy is set toRemoteSigned
. Then the script will be executed and finally the execution policy is restored. This default behaviour may be switched off by setting the optional third parameter <policy bool str> to "false".
If thepowershellCall
function is called where a stringlist is expected it returns a stringlist that contains the output of <commandstr>.
Since 4.12.4.35:
If the execution policyAllSigned
is detected, the PowerShell will be modified from calling the temporay script by-File
to-Command Get-Content -Path <tempfilename> | Out-String | Invoke-Expression
. In this mode the execution policy is ignored. In this mode any givenPASSPARAS
are also ignored.
Since 4.12.4.28:
The optional <optionstr> may be used to pass additional modifiers to the function. Because the fuctonpowershellcall
calls internal anExecwith
section, all possibleExcewith
modifier maybe also given in the <optionstr>. For details see here: [opsi-script-execwith-params].
Example:set $list$= powershellCall('Get-Process -ProcessName "opsi*"')
Is a shortcut for this expression:
set $policy$ = takeString(0,shellCall('powershell.exe get-executionpolicy')) shellCall('powershell.exe set-executionpolicy RemoteSigned') set $list$ = getOutStreamFromSection ('Execwith_ps powershell.exe winst /sysnative') shellCall('powershell.exe set-executionpolicy '+$policy$) [Execwith_ps] trap { write-output $_ ; exit 1 } Get-Process -ProcessName "opsi*" exit $LASTEXITCODE
Note on PowerShell command 'Get-Partition'
The output of the PowerShell commandGet-Partition
contains NULL characters\u0000
in the columnDriveLetter
where there is no drive letter. This leads in opsi-script to problems with directly reading the output ofGet-Partition
. If you like to use the output ofGet-Partition
in your script, we recommend the solution:DefStringlist $ResultList$ PowershellCall('Get-Partition > "%opsiUserTmpDir%\Get-Partition.txt"') Set $ResultList$ = LoadTextFile("%opsiUserTmpDir%\Get-Partition.txt")
Here, the output of
Get-Partition
is written to a file first and so the problem with the NULL characters is handled.
-
powershellCall(
<commandstr> [,<access str>='sysnative' [,<policy bool str>='true']]) : noresult
//since 4.12.0.16 [W]
powershellCall(
<commandstr> [,<access str>='sysnative' [,<policy bool str>='true'][, <optionstr> = '']]) : noresult
//since 4.12.4.28 [W]
see [powershellCall_list]
The functionpowershellCall
may also be called where no result is expected.
Example:powershellCall('Get-Process -ProcessName "opsi*"')
-
powershellCall(
<commandstr> [,<access str>='sysnative' [,<policy bool str>='true']]) : string (exitcode)
//since 4.12.0.16 [W]
powershellCall(
<commandstr> [,<access str>='sysnative' [,<policy bool str>='true'][, <optionstr> = '']]) : string (exitcode)
//since 4.12.4.28 [W]
see [powershellCall_list]
If thepowershellCall
function is called where a string is expected it returns a string that contains the exit code of the executed script.
Example:set $exitcode$ = powershellCall('Get-Process -ProcessName "opsi*"')
-
processCall(
<string>`) : string (exitcode)` //since 4.11.6.1 [W/L/M]
Starts the command binary <string> as process and returns the exitcode.set $exitcode$ = processCall('setup.exe /S')
is a shortcut for this expression:
Winbatch_setup set $exitcode$ = getLastExitcode [Winbatch_setup] setup.exe /S
In fact
processCall
is internal a winbatch call, so all thewinbatch
modifiers are also allowed forprocessCall
-
/LetThemGo
This is the contrary to/WaitOnClose
. It is used if opsi-script shall proceed while the started processes run in their own threads. -
/TimeOutSeconds
<seconds>
A timeout setting. After waiting <seconds>, opsi-script will end the process.
Since version 4.11.3, /TimeOutSeconds may be used without a waiting condition (e.g./WaitForProcessEnding
) but not in combination with/WaitSeconds
.
Since version 4.11.4.6 the time progress from start until timeout is displayed by the progressbar. -
/WaitSeconds
[number of seconds]
If a call includes the parameter /WaitSeconds [number of seconds], then opsi-script is waiting for [number of seconds] before proceeding. In the default configuration, we also wait for any programs that are currently running to finish. If we combine the parameter /WaitSeconds with the option/LetThemGo
, then opsi-script continues processing after the waiting time is finished. -
/WaitForProcessEnding
<program name>
Waits for the process called <program name> to end.
Should be combined with/TimeOutSeconds
. -
/32Bit
//since 4.11.3.5 [W]
This is the default. The paths within the section are assumed to be 32 bit pathes.
Example:c:\windows\system32\regedit.exe
calls (even when running on a 64 bit system) the 32 bit 'regedit.exe'. -
/64Bit
//since 4.11.3.5 [W]
The paths within the section are assumed to be 64 bit paths.
Example:c:\windows\system32\regedit.exe
executes (running on a 64 bit system) the 64 bit 'regedit.exe'. -
/SysNative
//since 4.11.3.5 [W]
The paths within the section are assigned according to the OS architecture interpretiert.
Example:c:\windows\system32\regedit.exe
running on a 64bit system calls the 64 bit 'regedit.exe' and running on a 32 bit system the 32 bit 'regedit.exe'.
-
Special Commands [W/L/M]
-
Killtask
<process name> ` : noresult` [W/L/M]
tries to stop all processes that execute the program named by the string expression.
E.g.
killtask "winword.exe"
-
ChangeDirectory
<directory> ` : noresult` //since 4.11.2.6 [W/L/M]
Set the given directory as working directory of the opsi-script. Affects all subsequent actions (e.g. winbatch sections) and will be reset at the end of a script. Beispiel :
ChangeDirectory "%SCRIPTPATH%\programm"
-
UpdateEnvironment
//since 4.11.5.1 [W]
Sends Windows the signal to reload the environment values from the registry. This statement may be called after any rocess that may have changed the environment (e.g. Registry section or setup program). Even if the program that runs after the opsi-script get the new environment, the next process that is started (via ShellScript or Winbatch) from this opsi-script instance will still inherit the old environment. To start a subsequent process with the new environment you have to usewinbatch
with the/RunElevated
parameter.
Works only with NT6 and up.
Example:
comment "Set Environment Variables and check for it ...."
Registry_add_environment /sysnative
UpdateEnvironment
comment "This will not work because the environment is inherited from the running process"
set $list$ = shellCall('set opsi-script-test')
comment "This will work because this new started process will get a new environment"
winbatch_check_environment /RunElevated
if ("42" = getlastExitCode)
comment "passed"
else
comment "failed"
endif
[Registry_add_environment]
openkey [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment]
set "opsi-script-test"="deleteme"
[winbatch_check_environment]
"%system%\cmd.exe" /c "if %opsi-script-test%==deleteme exit 42"
-
sleepSeconds
<string> [W/L/M]
breaks the program execution for <string> seconds. <string> has to represent an Integer Value
-
markTime
[W/L/M]
sets a time stamp for the current system time and logs it.
-
diffTime
[W/L/M]
logs the time passed since the lastmarktime
.
-
runningInWanMode
//since 4.12.4.17 [W/L/M]
Returnstrue
if the script is running in the 'WAN mode'. This means that the constant%opsiserviceurl%
points not to the opsi server but to localhost.
-
isCertInstalledInSystem(
<label>`) : boolstring` [W/L/M] //since 4.12.4.37
Returnstrue
if a CA certificate wich is identified by <label> is found in the OS system certificatestore.
see also : [importCertToSystem]
see also : [removeCertFromSystem]
see also : [listCertificatesFromSystem]
Example see [listCertificatesFromSystem]
-
importCertToSystem(
<filename>`) : noresult` [W/L/M] //since 4.12.4.37
Imports a CA certificate which is given by <filename> to the OS system certificatestore.
see also : [isCertInstalledInSystem]
see also : [removeCertFromSystem]
see also : [listCertificatesFromSystem]
Example see [listCertificatesFromSystem]
-
removeCertFromSystem(
<label>`) : noresult` [W/L/M] //since 4.12.4.37
Removes a CA certificate which is identified by <label> from the OS system certificatestore.
see also : [isCertInstalledInSystem]
see also : [importCertToSystem]
see also : [listCertificatesFromSystem]
Example see [listCertificatesFromSystem]
-
listCertificatesFromSystem
: stringlist` [W/L/M] //since 4.12.4.37
Returns a stringlist with the labels of all CA certificates wich are found in the OS system certificatestore.
see also : [isCertInstalledInSystem]
see also : [importCertToSystem]
see also : [removeCertFromSystem]
Example:
set $list$ = listCertificatesFromSystem
if "" = takeFirstStringContaining($list$,"opsi-script-test test CA")
comment "not found"
endif
ImportCertToSystem('opsi-script-test-CA.pem')
if isCertInstalledInSystem("opsi-script-test test CA")
comment "found"
removeCertFromSystem("opsi-script-test test CA")
if not(isCertInstalledInSystem("opsi-script-test test CA"))
comment "CA succesful removed"
endif
endif
Control the logging
-
comment
<string> orcomment
= <const string> [W/L/M]
writes the value of the String expression resp. the sequence of characters into the log file.
-
LogError
<string> orLogError
= <const string> [W/L/M]
writes additional error messages to the log file and increments the error counter by one.
-
LogWarning
<string> orLogWarning
= <const string> [W/L/M]
writes additional warning messages to the log file and increments the warning counter by one.
-
includelog
<file name> <tail size> //since 4.11.2.1 [W/L/M] -
includelog
<file name> <tail size> [<encoding>] //since 4.11.4.1 [W/L/M]
Includes the file <file name> as a log file, where the last <tail size> lines of the full log are written into this log file. If you start another program that produces a log file, you could see that other program’s log file in the opsi-script script log using this command.
Since version 4.11.3.2, a negative <tail size> can be given, which will then include the first <tail size> lines from the top of the log file (referred to as 'Head' mode).
Since version 4.11.4.1 there is an optional third parameter which may be used to give the encoding of the file to include. You may give one of the well known encodings described in the encodings chapter. If you give 'auto' opsi-script try to detect the encoding (and may fail). The default is 'system' which means the default OS encoding is used.
Example:
includelog "%Scriptpath%\test-files\10lines.txt" "5" includelog "%Scriptpath%\test-files\10lines_utf16.txt" "5" "ucs2be"
see: opsi-script encoding
-
SetConfidential
<secret string> [W/L/M]
This is to prevent confidential information (like passwords) from being logged. In the logfile the confidential information will be replaced by '(confidential)'.
When the loglevel is set to '9', the confidential information will be logged.
(since version 4.11.3.5)
Example:
message "SetConfidential"
SetConfidential "forbidden"
comment "This is a forbidden string"
comment "shown in the should be in the log file: This is a ***(confidential)*** string"
Log:
message SetConfidential
comment: This is a ***(secret)*** string
comment: should be in the log file: This is a ***(confidential)*** string
-
asConfidential(
<secret string expression>)
: string //since 4.12.0.16 [W/L/M]
This function should be used to get confidential strings from an other string function without without logging the secret string. The Function work in the following sequence:-
Backup the current log level.
-
Set the log level to Warning. (4)
-
Resolve the given string expression (for example calling the given string function).
-
Add the resulting string to the list of confidential strings that should be not logged..
-
Restore of the inital log level.
-
Return the resulting string.
-
Example:
set $ConstTest$ = asConfidential(stringReplace("this is my old secret", "old", "new"))
comment "this is my new secret"
comment "should be in the log file: ***(confidential)*** "
Log:
Set $ConstTest$ = asConfidential(stringReplace("this is my old secret", "old", "new"))
The value of the variable "$ConstTest$" is now: "***(confidential)***"
comment: This is a ***(confidential)*** string
comment: should be in the log file: This is a ***(confidential)*** string----
see also : [SetConfidential] see also : [GetConfidentialProductProperty] see also : [asConfidential_list]
-
asConfidential(
<secret stringlist expression>) : stringlist
//since 4.12.4.15 [W/L/M]
This function should be used to get confidential stringlist from an other stringlist function without without logging the secret strings. The Function work like the string functionasconfidential
, but for stringlists.
Commands for User Information and User Interaction [W/L/M]
-
Message
<string expression>
bzw.
Message
= <sequence of characters>
lets opsi-script display the value of the String expression resp. the sequence of chars in the batch window in the top information line. The text is kept as long as no newmessage
is set.
Example:
Message "Installation von "+$productid$
-
ShowMessageFile
<file name>
interprets the String expression as text file name, tries to read the text and show it in a user information window. Execution stops until the user confirms reading. E.g. by a command like
ShowMessageFile "p:\login\day.msg"
one can realize a "Message of the Day" mechanism.
-
ShowBitMap
[<image name>] [<inscription>]
places the image denoted by the <image name> (in BMP, JPEG or PNG format, size 160x160 pixel) and shows the inscription.
<image name> and <inscription> are String expressions.
Example:
ShowBitmap "%scriptpath%\" + $ProductId$ + ".png" "$ProductId$"
-
Pause
<string> orPause
= <const string>
display the text given as a String expression or as a sequence of chars in a information window waiting until the user confirms the continuation.
-
Stop
<string> orstop
= <const string>
halt program execution if the user confirms it. The String expression resp. the (possibly empty) sequence of chars explain to the user what is supposed to be stopped.
-
setActionProgress <string>
: noresult //since 4.11.3 [W/L/M]
Transfers <string> as ActionProgress of the running script to the opsi server. By Default the ActionProgress is 'installing' while a script is running. The value of ActionProgreas is displayed at the configed.
Commands for userLoginScripts / User Profile Management
-
GetScriptMode
//since 4.11.2.1
give one of the possible values 'Machine','Login':-
'Machine' - the script is not running as 'userLoginScript'
-
'Login' - the script is running as 'userLoginScript'
-
-
GetUserSID(
<Windows Username>`)`
see also : [GetUserSID]
-
GetLoggedInUser
//since 4.11.1.2 -
GetUsercontext
//since 4.11.1.2
returns the username in whose context the opsi-script is just running.
see also : [GetUsercontext]
-
saveVersionToProfile
//since 4.11.2.1
save productversion-packageversion to local profile
It is designed to be used in userLoginScripts.
This command is used in combination withreadVersionFromProfile
orscriptWasExecutedBefore
. It marks that the 'userLoginScript' for this product in this product version and package version was excuted for the actual user. The inrormation is saved at the file "%CurrentAppdataDir%\.opsi.org\userLoginScripts.ini"
-
readVersionFromProfile
//since 4.11.2.1
returns a string with the productversion-packageversion for the running opsi product which was read from local profile. See also:saveVersionToProfile
It is designed to be used in userLoginScripts.
-
scriptWasExecutedBefore
//since 4.11.2.1
This Boolean functionscriptWasExecutedBefore
checks if there is a version stamp in the profile (like you may do with thereadVersionFromProfile
command) It returns 'true' if saved and running productversion-packageversion are identical. Then it set a new stamp to the profile (like you may do with thesaveVersionToProfile
command). So you may just use this single command in a if statement.
It is designed to be used in userLoginScripts.
-
isLoginScript
//since 4.11.2.1
This booleasn function returns 'true' if the script is running as 'userLoginScript'. See also:GetScriptMode
see also : [GetScriptMode]
for to do loop
Useful for multiple calls of a single command or of a sub-section
Syntax:
for
%<temporary string variable>% =
<start string> to
<end string> do
<one statement> //since 4.11.5 [W/L/M]
The temporary varibale %<temporary string variable>% must not be declared and is available in the called sub-section as constant.
Example:
Code from opsi-script-test:
message "for to loop"
set $ConstTest$ = "12345"
set $CompValue$ = ""
for %s% = "1" to "5" do sub_iteration_test
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
[sub_iteration_test]
set $CompValue$ = $CompValue$ + '%s%'
produces the log:
message for to loop
Set $ConstTest$ = "12345"
The value of the variable "$ConstTest$" is now: "12345"
Set $CompValue$ = ""
The value of the variable "$CompValue$" is now: ""
~~~~~~ Looping through: '1', '2', '3', '4', '5'
~~~~~~~ Start Sub ~~~~~~~ sub_iteration_test
Set $CompValue$ = $CompValue$ + '1'
The value of the variable "$CompValue$" is now: "1"
~~~~~~~ End Sub ~~~~~~~ sub_iteration_test
~~~~~~~ Start Sub ~~~~~~~ sub_iteration_test
Set $CompValue$ = $CompValue$ + '2'
The value of the variable "$CompValue$" is now: "12"
~~~~~~~ End Sub ~~~~~~~ sub_iteration_test
~~~~~~~ Start Sub ~~~~~~~ sub_iteration_test
Set $CompValue$ = $CompValue$ + '3'
The value of the variable "$CompValue$" is now: "123"
~~~~~~~ End Sub ~~~~~~~ sub_iteration_test
~~~~~~~ Start Sub ~~~~~~~ sub_iteration_test
Set $CompValue$ = $CompValue$ + '4'
The value of the variable "$CompValue$" is now: "1234"
~~~~~~~ End Sub ~~~~~~~ sub_iteration_test
~~~~~~~ Start Sub ~~~~~~~ sub_iteration_test
Set $CompValue$ = $CompValue$ + '5'
The value of the variable "$CompValue$" is now: "12345"
~~~~~~~ End Sub ~~~~~~~ sub_iteration_test
~~~~~~ End Loop
If
$ConstTest$ = $CompValue$ <<< result true
($ConstTest$ = $CompValue$) <<< result true
Then
comment: passed
Else
EndIf
Switch / Case Statement [W/L/M]
Syntax:
Switch <string expression> Case <string const> <statement(s)> EndCase [DefaultCase <statement(s)> EndCase] EndSwitch
Switch / Case can not be nested (it is not allowed to have switch
insied of a case
).
There is an other possibillity for the same purpose: You may use the since 4.12.4.37 possible if-elseif-else
statements. These if-elseif-else
statements can be nested.
see: [IfElseEndif]
Examples:
Code from opsi-script-test:
set $ConstTest$ = "5"
Switch $ConstTest$
Case "1"
set $CompValue$ = "1"
EndCase
Case "2"
set $CompValue$ = "2"
EndCase
Case "3"
set $CompValue$ = "3"
EndCase
Case "4"
set $CompValue$ = "4"
EndCase
Case "5"
set $CompValue$ = "5"
EndCase
Case "6"
set $CompValue$ = "6"
EndCase
Case "7"
set $CompValue$ = "7"
EndCase
DefaultCase
set $CompValue$ = "notexisting"
EndCase
EndSwitch
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
.
[Sub_check_exitcode]
comment "Test for installation success via exit code"
set $ExitCode$ = getLastExitCode
; informations to exit codes see
; http://msdn.microsoft.com/en-us/library/aa372835(VS.85).aspx
; http://msdn.microsoft.com/en-us/library/aa368542.aspx
Switch $ExitCode$
Case "0"
comment "Looks good: setup program gives exitcode zero"
EndCase
Case "1605"
comment "ERROR_UNKNOWN_PRODUCT 1605"
comment "This action is only valid for products that are currently installed."
comment "Uninstall of a not installed product failed - no problem"
EndCase
Case "1641"
comment "looks good: setup program gives exitcode 1641"
comment "ERROR_SUCCESS_REBOOT_INITIATED 164"
comment "The installer has initiated a restart."
comment "This message is indicative of a success."
ExitWindows /Reboot
EndCase
Case "3010"
comment "looks good: setup program gives exitcode 3010"
comment "ERROR_SUCCESS_REBOOT_REQUIRED 3010"
comment "A restart is required to complete the install."
comment "This message is indicative of a success."
ExitWindows /Reboot
EndCase
DefaultCase
logError "Fatal: Setup program gives an unknown exitcode unequal zero: " + $ExitCode$
isFatalError "Exit Code: "+ $ExitCode$
EndCase
EndSwitch
Conditional Statements (if Statements)
In primary sections, the execution of a statement or a sequence of statements can be made dependent on some condition.
Example
;Which Windows version?
DefVar $MSVersion$
Set $MSVersion$ = GetMsVersionInfo
if CompareDotSeparatedNumbers($MSVersion$,">=","6")
sub_install_win7
else
if ( $MSVersion$ = "5.1" )
sub_install_winXP
else
stop "not a supported OS-Version"
endif
endif
Since version 4.12.4.37 opsi-script also can handle a elseif
statement.
Example:
Defvar $OS$
set $OS$ = GetOS
if $OS$ = "Windows_NT"
comment "We are on Windows"
elseif $OS$ = "Linux"
comment "We are on Linux"
elseif $OS$ = "macos"
comment "We are on macOS"
else
LogWarning "Unsupported OS"
endif
General Syntax
The syntax of the complete if
statement is:
if
<condition>
<sequence of statements>
elseif
<sequence of statements>
else
<sequence of statements>
endif
The else
part may be omitted.
The elseif
part may be omitted.
if
statements may be nested. That is, in the sequence of statements that depend on an if clause (no matter if inside the if or the else or the elseif part) another if statement may occur.
<condition> is a <Boolean expression> . A Boolean (or logical) expression can be constructed as a (String) value comparison, by Boolean operators, or by certain function calls which evaluate to true or false. Up to now these Boolean values cannot be explicitly represented in a opsi-script script).
Boolean Expressions
The String comparison (which is a Boolean expression) has the form
<String expression> <comparison sign> <String expression>
where <comparison sign> is one of the signs
<
⇐
=
>=
>
String comparisons in opsi-script are case independent.
Inequality must be expressed by a NOT()
expression which is presented below.
There is as well a comparison expression for comparing Strings as (integer) numbers. If any of them cannot be converted to a number an error will be indicated.
This number comparison expression has the same form as the String comparison but for an INT prefix of the comparison sign:
<String expression> INT<comparison sign> <String expression>
Such, we can build expressions as
if $Name1$ INT<= $Name2$
or
if $Number1$ INT>= $Number2$
Boolean operators are AND
, OR
, and NOT()
(case does not matter). If b1, b2 and b3 are Boolean expressions the combined expressions
b1 AND
b2
b1 OR
b2
NOT(
b3 )
are Boolean expressions as well denoting respectively the conjunction (AND
), the disjunction (OR
) and the negation (NOT
).
A Boolean expression can be enclosed in parentheses (such producing a new Boolean expression with the same value).
The common rules of Boolean operator priority ("and" before "or") are at this moment not implemented. An expression with more than one operator is interpreted from left to right. For clarity, in a Boolean expression that combines AND
and OR
operators parentheses should be employed, e.g. we should explicitly write
b1 OR
(b2 AND
b3)
or
(b1 OR
b2) AND
b3
The second example describes what would be executed if there were no parentheses - whereas the common interpretation would run as the other line indicates.
Boolean operators can be conceived as special Boolean valued functions (the negation operator demonstrates this very clearly).
There are some more Boolean functions implemented. Every call of such a function constitutes a Boolean expression as well:
-
FileExists (
<file name>`) : bool` [W/L/M]
returns 'true' if the denoted file or directory exists otherwise 'false'. -
FileExists32
(<file name>) see Chapter 64 Bit support -
FileExists64
(<file name>) see Chapter 64 Bit support -
FileExistsSysNative
(<file name>) see Chapter 64 Bit support
-
FileOrFolderExists
(<file or folder path> [,<access str>]) : boolean //since 4.12.4.14 [W/L/M]
returns 'true' if the denoted file or directory exists, otherwise 'false'.+ The optional second parameter <access str> is only for Windows : You should enter '32bit', '64bit' or 'sysnative'.Otherwise, 'sysnative' is the default for <access str>. see Chapter 64 Bit support
see also: [DirectoryExists]
see also: [FileExists]
-
DirectoryExists (
<path>) : bool
//since 4.12.1 [W/L/M]
Tests if <path> points to a directory.
<access str> = one of 32bit, 64bit, sysnative ; default sysnative ; ignored at non windows
see also: [FileOrFolderExists]
see also: [FileExists]
Examples:
if ($INST_SystemType$ = "64 Bit System")
set $ConstTest$ = "true"
Set $tmp$ = "C:\Windows\system32\Boot"
set $tmp1$ = "64bit"
set $CompValue$ = boolToString(DirectoryExists($tmp$,$tmp1$))
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $ConstTest$ = "true"
Set $tmp$ = "C:\Windows\system32\Boot"
set $tmp1$ = "sysnative"
set $CompValue$ = boolToString(DirectoryExists($tmp$,$tmp1$))
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $ConstTest$ = "true"
Set $tmp$ = "C:\Windows\system32\Boot"
; fall back to sysnative
set $CompValue$ = boolToString(DirectoryExists($tmp$))
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
set $ConstTest$ = "false"
Set $tmp$ = "C:\Windows\system32\Boot"
set $tmp1$ = "32bit"
set $CompValue$ = boolToString(DirectoryExists($tmp$,$tmp1$))
if ($ConstTest$ = $CompValue$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
endif
-
fileIsSymlink
(<file name>) // since 4.12.4.21 [W/L/M]
returns 'true' if the denoted file exists and is a symbolic link, otherwise 'false'.
-
LineExistsIn (
<string>, <file name>`) : bool` [W/L/M]
returns 'true' if the text file denoted by <file name> contains a line as specified in the first parameter where each parameter is a String expression. Otherwise (or if the file does not exist) it returns 'false'.
-
LineBeginning_ExistsIn (
<string>, <file name>`) : bool` [W/L/M]
returns 'true' if there is line that begins with <string> in the text file denoted by <file name> (each parameter being a string expression). Otherwise (or if the file does not exist) it returns 'false'.
-
LineContaining_ExistsIn(
<string>, <file name>) : bool
[W/L/M]
returns 'true' if there is line that contains <string> in the text file denoted by <file name> (each parameter being a string expression). Otherwise (or if the file does not exist) it returns 'false'.
-
XMLAddNamespace
(<XMLfilename>, <XMLelementname>, <XMLnamespace>)
inserts a XML namespace definition into the first XML element with the given name (if not existing). It gives back if an insertion took place. (The opsi-script XML patch section need the definitions of namespace.)
The file must be formatted that an element tag has no line breaks in it. For an example, cf. cookbook cook-book.adoc#opsi-script-cookbook-xmlnamespace.
-
XMLRemoveNamespace
(<XMLfilename>, <XMLelementname>, <XMLnamespace>)
removes the XML namespace definition from the XML element. It gives back if an removal took place. We need this to simulate that an original file is unchanged. For an example, cf. cookbook cook-book.adoc#opsi-script-cookbook-xmlnamespace.
-
HasMinimumSpace
(<Laufwerksname>, <Kapazität>)
returns true if at least a capacity capacity is left on drive drivename. capacity as well as drivename syntactically are String expressions. The capacity may be given as a number without unit specification (then interpreted as bytes) or with unit specifications "kB", "MB", or "GB" (case independent).
Example:
if not (HasMinimumSpace ("%SYSTEMDRIVE%", "500 MB")) LogError "Not enough space on %SystemDrive%, 500MB on drive %SystemDrive% needed" isFatalError endif
-
opsiLicenseManagementEnabled
: bool
returns 'true' if the opsi license management module is enabled.
-
runningAsAdmin
Returns 'true' if the currently running script was executed with Administrator privileges.
Available since 4.11.1.1 -
isLoginScript
Returns 'true' if the currently running script was called as 'userLoginScript' using the opsi extension 'User Profile Management'.
Available since 4.11.2.1
see also : [isLoginScript] -
contains(
<str>, <substr>`) : bool` //since 4.11.3: true if <substr> in <str> [W/L/M]
Boolean function which returns 'true' if <str> contains <substr>. This function is case sensitive.
see also : [contains]
-
isNumber(
<str>`) : bool` //since 4.11.3: true if <str> represents an integer [W/L/M]
Boolean function which returns 'true' if <str> represents an integer.
see also : [isNumber]
-
runningOnUefi
Boolean function which returns 'true' if the running OS was booted in UEFI mode.
Available since 4.11.4.3
-
runningInPE
//since 4.12.0.13: [W/L/M]
true if the running OS is a Windows PE
-
runningInWAnMode
//since 4.12.4.16: [W/L/M]
Boolean function which returns 'true' if at the running opsi-service context the opsiserver = localhost is.
-
isDriveReady(
<drive letter>`)` //since 4.11.4.4: [W]
true: if the drive can be accessed
-
saveTextFile(
<list>, < filename>`) : bool` [W/L/M]
true: if list is succesfully written to file
-
saveTextFileWithEncoding(
<list>, < filename>, <encoding>`) : bool` //since 4.11.6.4 [W/L/M]
true: if list is succesfully written to file [W/L/M]
-
saveUnicodeTextFile(
<list>, < filename>, <encoding>`) : bool` //since 4.12.4.14 [W/L/M]
specific for unicode encoding
returns true: if list is succesfully written to unicode file [W/L/M]
-
CompareDotSeparatedNumbers(
<str1>,<relation str>,<str2>`) : bool` //since 4.11.5.2: [W/L/M]
compares two strings of the form <number>[.<number>[.<number>[.<number>]]]
by the <relation str> which may be one of [<,⇐,=,>=,>].
Since version 4.12.4.28: -
While comparing a pair of <number>, if at least one of them has leading zeros, then the comparison is done as if these <number> were the fractional part of a floating number, i.e.
17 > 018
because0.17 > 0.018
. -
While comparing a pair of <number>, if at least one of them has as last a non-numeric char then the comparison uses in the first step the leading number part. In case of equality, a comparison of the trailing chars is done. E.g.
1.23a < 1.23b
and1.24a > 1.23b
. see also: string functionCompareDotSeparatedNumbers(
<string1>, <string2>`)` : [CompareDotSeparatedNumbers_str]
see also: string functionCompareDotSeparatedStrings(
<string1>, <string2>`)` : [CompareDotSeparatedStrings_str]
see also: [CompareDotSeparatedStrings_bool]
Example:
The code:
set $string1$ = "1.2.30.4.5"
set $string2$ = "1.20.30.4.5"
if CompareDotSeparatedNumbers($string1$, "<", $string2$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
if CompareDotSeparatedNumbers($string1$, "<=", $string2$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
if CompareDotSeparatedNumbers($string1$, "=<", $string2$)
comment "passed"
else
set $TestResult$ = "not o.k."
LogWarning "failed"
endif
if CompareDotSeparatedNumbers($string1$, "=", $string2$)
set $TestResult$ = "not o.k."
LogWarning "failed"
else
comment "passed"
endif
if CompareDotSeparatedNumbers($string1$, ">=", $string2$)
set $TestResult$ = "not o.k."
LogWarning "failed"
else
comment "passed"
endif
if CompareDotSeparatedNumbers($string1$, "=>", $string2$)
set $TestResult$ = "not o.k."
LogWarning "failed"
else
comment "passed"
endif
if CompareDotSeparatedNumbers($string1$, ">", $string2$)
set $TestResult$ = "not o.k."
LogWarning "failed"
else
comment "passed"
endif
produce the log:
Set $string1$ = "1.2.30.4.5"
The value of the variable "$string1$" is now: "1.2.30.4.5"
Set $string2$ = "1.20.30.4.5"
The value of the variable "$string2$" is now: "1.20.30.4.5"
If
Checking if "1.2.30.4.5" is "<" than / as "1.20.30.4.5"
CompareDotSeparatedNumbers($string1$, "<", $string2$) <<< result true
Then
comment: passed
Else
EndIf
If
Checking if "1.2.30.4.5" is "<=" than / as "1.20.30.4.5"
CompareDotSeparatedNumbers($string1$, "<=", $string2$) <<< result true
Then
comment: passed
Else
EndIf
If
Checking if "1.2.30.4.5" is "=<" than / as "1.20.30.4.5"
CompareDotSeparatedNumbers($string1$, "=<", $string2$) <<< result true
Then
comment: passed
Else
EndIf
If
Checking if "1.2.30.4.5" is "=" than / as "1.20.30.4.5"
CompareDotSeparatedNumbers($string1$, "=", $string2$) <<< result false
Then
Else
comment: passed
EndIf
If
Checking if "1.2.30.4.5" is ">=" than / as "1.20.30.4.5"
CompareDotSeparatedNumbers($string1$, ">=", $string2$) <<< result false
Then
Else
comment: passed
EndIf
If
Checking if "1.2.30.4.5" is "=>" than / as "1.20.30.4.5"
CompareDotSeparatedNumbers($string1$, "=>", $string2$) <<< result false
Then
Else
comment: passed
EndIf
If
Checking if "1.2.30.4.5" is ">" than / as "1.20.30.4.5"
CompareDotSeparatedNumbers($string1$, ">", $string2$) <<< result false
Then
Else
comment: passed
EndIf
Additional since 4.12.4.28:
if CompareDotSeparatedNumbers("4.2.2", ">", "4.2.00079") comment "passed" else set $TestResult$ = "not o.k." LogWarning "failed" endif if CompareDotSeparatedNumbers("0.9.8h", ">", "0.9.8e") comment "passed" else set $TestResult$ = "not o.k." LogWarning "failed" endif
-
CompareDotSeparatedStrings(
<str1>,<relation str>,<str2>`) : bool` //since 4.11.5.2: [W/L/M]
compares two strings of the form <str>[.<str>[.<str>[.<str>]]]
by the <relation str> which may be one of [<,⇐,=,>=,>].
see also: string functionCompareDotSeparatedStrings(
<string1>, <string2>`)` : [CompareDotSeparatedStrings_str]`
see also: [CompareDotSeparatedNumbers_bool]
see also: [CompareDotSeparatedNumbers_str]
-
boolToString(
<boolean expression>`)` : bool string (true/false) // since 4.12.0.0 [W/L/M]
-
stringToBool(
<string expression: true/false>`)` : boolean // since 4.12.0.0 [W/L/M]
-
RegKeyExists(
<regkey>[,<access str>]) : bool
//since 4.12.0.16 [W]
Check if the given string expression <regkey> exists as registry key. If the registry key was found the result value isttrue
in all other casesfalse
.
By Default the registry access mode issysnative
. Using the optional second parameter <access str>, the access mode can be explicitly given. In this case it has to be one of the following values:32bit
,sysnative
,64bit
.
(see also: Chapter 64 Bit support)
Examples:
RegKeyExists("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon")
RegKeyExists("HKEY_LOCAL_MACHINE\SOFTWARE\opsi.org\general","32bit")
-
RegVarExists(
<regkey>, <var str>) : bool
//since 4.12.0.16 [W]
Check if the given string expression <regkey> exists as registry key and if there is a variable with name <var str>. If both was found the result value isttrue
in all other casesfalse
.
By Default the registry access mode issysnative
. Using the optional second parameter <access str>, the access mode can be explicitly given. In this case it has to be one of the following values:32bit
,sysnative
,64bit
.
(see also: Chapter 64 Bit support)
Examples:
RegVarExists("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon","Shell")
RegVarExists("HKEY_LOCAL_MACHINE\SOFTWARE\opsi.org\general","bootmode","32bit")
-
runningWithGui : bool`
//since 4.12.3.6 [W/L/M] true: if the running OS has a GUI (at Win+Mac always true)[M/L/W]
isPingReachable(<host>) : boolean
//since 4.12.3.6 [W/L/M]
Gives back true if the host given by <host> is reachable by ping. <host> may be a IP-Number or a IP-Name.
Include Commands
Using include commands can lead to confusing code. Use with caution if you are a beginner. |
Include Commands: Syntax
The include_*
commands may be used to add external script files to the currently-running script at runtime. The include_*
command can include external script files either as an insert (after the current line) or as an append (after the last line). The include commands may be used anywhere in a primary section. The external script files may contain their own include commands.
The include commands are available since version 4.11.3
-
include_insert
<file name>
inserts <file name> after the current line into the running script. So the first line of the included file is the next line that will be executed by opsi-script.
-
include_append
<file name>
appends the content of <file name> to the running script. This kind of insert is normally used to include sections from a library.
In both cases <file name> is:
-
A complete path to an existing file. [W/L/M]
-
A existing file in
%ScriptPath%
[W/L/M] -
A file in
%opsiScriptHelperPath%\lib
[W]
Is equivalent to: '%ProgramFiles32Dir%\opsi.org\opsiScriptHelper\lib' -
A existing file in
%ScriptPath%/../lib
[W/L/M] -
A existing file in
%OpsiScriptDir%\lib
[W]
The tests for the location of the <file name> are done in the order above. opsi-script uses the first file it finds that has a matching name.
Example:
When we run that contains the following commands:
[Actions]
include_append "section_Files_del_tmp_dummy.opsiinc"
include_insert "include-test1.opsiinc"
The file include-test1.opsiinc
is run first. The contents of the included file include-test1.opsiinc
are:
DefVar $inctestvar$
set $inctestvar$ = "inctest"
Files_del_tmp_dummy
include_append "section_Files_copy_inctest.opsiinc"
Files_copy_inctest
if fileExists("c:\opsi.org\tmp\dummy.txt")
comment "passed"
else
comment "failed"
set $TestResult$ = "not o.k."
LogWarning "include test failed"
endif
if fileExists("%scriptpath%\test-files\dummy.txt")
comment "passed"
else
comment "failed"
set $TestResult$ = "not o.k."
LogWarning "include test failed"
endif
Files_del_tmp_dummy
The contents of the included file section_Files_copy_inctest.opsiinc
are:
[Files_copy_inctest]
copy "%scriptpath%\test-files\dummy.txt" "c:\opsi.org\tmp"
Since the call to Files_del_tmp_dummy happens inside of include-test1.opsiinc
without section_Files_del_tmp_dummy.opsiinc
being referenced inside of include-test1.opsiinc
, we must call include_append "section_Files_del_tmp_dummy.opsiinc" at the very beginning of our script. Otherwise, opsi-script will report that Files_del_tmp_dummy is not defined.
The contents of the included file section_Files_del_tmp_dummy.opsiinc
are:
[Files_del_tmp_dummy]
del -f "c:\opsi.org\tmp\dummyt.txt"
Include Commands: Library
The following include files are shipped with version 4.11.3, and are located in %OpsiScriptDir%\lib
:
insert_check_exit_code.opsiinc
:
; opsi include file
DefVar $ExitCode$
include_append "section_sub_check_exitcode.opsiinc"
insert_get_licensekey.opsiinc
:
; opsi include file
DefVar $LicenseRequired$
DefVar $LicenseKey$
DefVar $LicensePool$
include_append "section_sub_get_licensekey.opsiinc"
section_sub_check_exit_code.opsiinc
:
;opsi include file
[Sub_check_exitcode]
comment "Test for installation success via exit code"
set $ExitCode$ = getLastExitCode
; informations to exit codes see
; http://msdn.microsoft.com/en-us/library/aa372835(VS.85).aspx
; http://msdn.microsoft.com/en-us/library/aa368542.aspx
if ($ExitCode$ = "0")
comment "Looks good: setup program gives exitcode zero"
else
comment "Setup program gives a exitcode unequal zero: " + $ExitCode$
if ($ExitCode$ = "1605")
comment "ERROR_UNKNOWN_PRODUCT 1605 This action is only valid for products that are currently installed."
comment "Uninstall of a not installed product failed - no problem"
else
if ($ExitCode$ = "1641")
comment "looks good: setup program gives exitcode 1641"
comment "ERROR_SUCCESS_REBOOT_INITIATED 1641 The installer has initiated a restart. This message is indicative of a success."
ExitWindows /Reboot
else
if ($ExitCode$ = "3010")
comment "looks good: setup program gives exitcode 3010"
comment "ERROR_SUCCESS_REBOOT_REQUIRED 3010 A restart is required to complete the install. This message is indicative of a success."
ExitWindows /Reboot
else
logError "Fatal: Setup program gives an unknown exitcode unequal zero: " + $ExitCode$
isFatalError "Exit Code: "+ $ExitCode$
endif
endif
endif
endif
section_sub_get_licensekey.opsiinc
:
; opsi include file
[Sub_get_licensekey]
if opsiLicenseManagementEnabled
comment "License management is enabled and will be used"
comment "Trying to get a license key"
Set $LicenseKey$ = demandLicenseKey ($LicensePool$)
; If there is an assignment of exactly one license pool to the product the following call is possible:
; Set $LicenseKey$ = demandLicenseKey ("", $ProductId$)
;
; If there is an assignment of a license pool to a windows software id, it is possible to use:
; DefVar $WindowsSoftwareId$
; $WindowsSoftwareId$ = "..."
; Set $LicenseKey$ = demandLicenseKey ("", "", $WindowsSoftwareId$)
DefVar $ServiceErrorClass$
set $ServiceErrorClass$ = getLastServiceErrorClass
comment "Error class: " + $ServiceErrorClass$
if $ServiceErrorClass$ = "None"
comment "Everything fine, we got the license key '" + $LicenseKey$ + "'"
else
if $ServiceErrorClass$ = "LicenseConfigurationError"
LogError "Fatal: license configuration must be corrected"
LogError getLastServiceErrorMessage
isFatalError $ServiceErrorClass$
else
if $ServiceErrorClass$ = "LicenseMissingError"
LogError "Fatal: required license is not supplied"
isFatalError $ServiceErrorClass$
endif
endif
endif
else
LogError "Fatal: license required, but license management not enabled"
isFatalError "No Licensemanagement"
endif
Subprogram Calls
Statements in primary sections which refer to instructions declared elsewhere are subprogram calls.,
if ($MSVersion$>="6")
sub_install_win7
else
if ( $MSVersion$ = "5.1" )
sub_install_winXP
else
stop "not a supported OS-Version"
endif
endif
In this example the statement:
sub_install_winXP
"calls" the section titled '[sub_install_winXP]' which is placed somewhere else in the script. E.g. we may have
[sub_install_winXP]
Files_copy_XP
WinBatch_SetupXP
Generally, there are three ways to place the referred instructions:
-
The most common target of a sub program call is some other internal section in the very script file where the calling statement is placed (as in the example).
-
We may put the referred instructions into another file which serves as an external section.
-
Any String list can be used as list of instructions for a sub program call.
We describe the syntax of sub program calls in detail:
Syntax of Procedure Calling
Formally, the syntax can be given by
'<proc. type>(<proc. name> | <External proc. file> | <String list function> )'
This expression may supplemented by one ore ore parameters (procedure type dependent).
That means: A procedure call consists of three main parts.
The first part is the subprogram type specifier.
Examples of type names are 'Sub' (we call a procedure of type sub that is a again a primary section) or 'Files' and 'WinBatch' (calls of special secondary sections). The complete overview of the existing sub program types is given at Subprogram Calls.
The second part determines where and how the lines of sub program are to be found.
-
The subprogram is a sequence of lines situated in the executed opsi-script script as another internal section. Then a name (constituted from letters, digits, and some special characters) has to be appended to the type specifier (without space) in order to form an unique section name.
sub_install_winXP
or
files_copy_winXP
Section names are case independent as any other string. -
If the type specifier stands alone a String list expression or a String expression is expected. If the expression following the type specifier cannot be resolved as a String list expression (cf. case (3)) it is assumed to be a String expression. The string is then interpreted as a file name. opsi-script tries to open the file as a text file and interprets its lines as an external section of the specified type.
E.g.
sub "p:\install\opsiutils\mainroutine.opsiscript"
tries to execute the lines of mainroutine.opsiscript as statements of a sub section.
The searche rule is:
<file name> may be:
-
A complete path to an existing file. [W/L/M]
-
A existing file in
%ScriptPath%
[W/L/M] -
A file in
%opsiScriptHelperPath%\lib
[W]
Is equivalent to: '%ProgramFiles32Dir%\opsi.org\opsiScriptHelper\lib' -
A existing file in
%ScriptPath%/../lib
[W/L/M] -
A existing file in
%OpsiScriptDir%\lib
[W]
The tests for the location of the <file name> are done in the order above. opsi-script uses the first file it finds that has a matching name.
-
If the expression following a pure section type specifier is resolvable as a String list expression the lines of the list are interpreted as the statements of the section.
This mechanism can e.g. be used to load a file that has unicode format and then treat it by the usual mechanisms
registry loadUnicodeTextFile("%scriptpath%/opsiorgkey.reg") /regedit
Syntactically, this line is composed of three main parts:
* registry
, the core statement specifying the section type,
* loadUnicodeTextFile(…)
, a String list expression specifying how to get the lines of a registry section resp. its surrogate.
* /regedit
, parametrizing the registry call.
In this example, the call parameter already gives an example for the third part of a subsection call:
The third part of a procedure call comprises type specific call options.
For a reference of the call options cf. the descriptions of the section calls in Secondary Sections.
Controlling Reboot
The command ExitWindows
is used to control reboots , shutdown and similar actions which should take place after the opsi-script it self is terminated. The name of the command and the fact that there is no 'ExitWindows' without modifier has histrical reasons: Working on Windows 3.1 you could exit windows to go back to the DOS level.
-
ExitWindows /RebootWanted
DEPRECATED: a reboot request is registered which should be executed when all installations requests are treated, and the last script has finished.
In fact, this command is now treated as anExitWindows /Reboot
(since otherwise an installation could fail because a required product is not yet completely installed).
-
ExitWindows /Reboot
triggers the reboot after opsi-script has finished the currently treated script.
-
ExitWindows /ImmediateReboot
breaks the normal execution of a script anywhere inside it. When this command is called opsi-script runs as directly as possible to its end entailing the system ExitWindows call. In the context of an installed opsi-client-agent it is guaranteed that after rebooting opsi-script runs again into the script that was aborted. Therefore, the script has to take provisions that the execution continues after the point where it was left the turn before (otherwise we may get an infinite loop …) Cf. the example in this section.
-
ExitWindows /ImmediateLogout
The normal execution of a script breaks at the point of the call, and the opsi-script stops running. This behaviour is needed if an automated user log in for some other user shall take place (cf. [opsi-script-cookbook-local-admin]).
-
ExitWindows /ShutdownWanted
sets a flag in the registry that the PC shuts down when all installations requests are treated, and the last script has finished.
How flags may be set to ensure that the script does not run into an infinite loop when ExitWindows /ImmediateReboot
is called we demonstrate by the following code fragment:
DefVar $OS$
DefVar $Flag$
DefVar $WinstRegKey$
set $OS$=EnvVar("OS")
if $OS$="Windows_NT"
Set $WinstRegKey$ = "HKLM\SOFTWARE\opsi.org\winst"
Set $Flag$ = GetRegistryStringValue("["+$WinstRegKey$+"] "+"RebootFlag")
if not ($Flag$ = "1")
;=========================
; Statements BEFORE Reboot
Files_doSomething
; initialize reboot ...
Set $Flag$ = "1"
Registry_SaveRebootFlag
ExitWindows /ImmediateReboot
else
;=========================
; Statements AFTER Reboot
; set back reboot flag
Set $Flag$ = "0"
Registry_SaveRebootFlag
; the work part after reboot:
Files_doMore
endif
endif
[Registry_SaveRebootFlag]
openKey [$WinstRegKey$]
set "RebootFlag" = "$Flag$"
[Files_doSomething]
; a section executed before reboot
[Files_doMore]
; a section executed after reboot
Abort script and keep track of failed installations
If a product installation fails, then this should be signaled to the server.
Due to the fact that there is no automatic method that detects a failed installation, testing for a failed installation has to be done using script commands.
To indicate in a opsi-script script that the installation is failed we have to call the statement:
isFatalError
If this statement is called, then opsi-script stops the normal execution of the script and sets the product result to 'failed' (otherwise it is 'success').
Since 4.11.3.2 there is a new variant of this command:
-
isFatalError
<string>
in this case, a short error message string is passed as 'actionProgress' to the opsi-server and displayed in the opsi-configed.
For example, a "fatal error" shall be triggered if there is not as much space left as it is needed for an installation:
DefVar $SpaceNeeded$"
Set $SpaceNeeded$" = "200 MB"
DefVar $LogErrorMessage$
Set $LogErrorMessage$ = "Not enough space on drive . Required "
Set $LogErrorMessage$ = $LogErrorMessage$ + $SpaceNeeded$"
if not(HasMinimumSpace ("%SYSTEMDRIVE%", $SpaceNeeded$))
LogError $LogErrorMessage$
isFatalError
; finish execution and set ProductState to failed
else
; we start the installation
; ...
endif
It is also possible to state
isFatalError
depending on the number of errors which occured in some critical part of an installation script. In order to do this we initialize the error counting by the command
-
markErrorNumber
Initialize the error counting.
The number of execution errors which occur after setting the counter can be queried by the the number valued functionerrorsOccurredSinceMark
+
-
errorsOccurredSinceMark
We can evaluate the result in a numerical comparison condition (that as yet is only implemented for this expression). E. g. we may state
if errorsOccurredSinceMark > 0
For increasing the number of counted errors depending on certain circumstances (that do not directly produce an error) we may use the logError
statement.
We may test this by the following script example:
markErrorNumber
; Errors occuring after this mark are counted and
; will possibly be regarded as fatal
logError "test error"
; we write "test error" into the log file
; and increase the number of errors by 1
; for testing, comment out this line
if errorsOccurredSinceMark > 0
; we finish script execution as quick as possible
; and set the product state to "failed"
isFatalError
; but comment writing is not stopped
comment "error occured"
else
; no error occured, lets log this:
comment "no error occured"
endif
-
isSuccess
//since 4.11.3.7 [W/L/M]
Abort the script as successful.
-
noUpdateScript
//since 4.11.3.7 [W/L/M]
Do not run an update script after setup even if there is one.
-
isSuspended
//since 4.11.4.1 [W/L/M] Abort the script without notice to the server. The action request remain unchanged.
Local functions [W/L/M]
Since version 4.12, the opsi-script has also local functions.
An example:
DefFunc myFunc(val $str1$ : string, $str2$ : string) : string
set $result$ = $str1$ + $str2$
endfunc
Concept
There are a lot possibilities to structure opsi-script code:
-
sub
Sections -
sub
Sections in external files -
'include' Statements
But all these possibilities are not functional to create reusable external code that can be exchanged between scripts or opsi administrators without problems.
The reason is, that this code is not encapsulated and use global variables.
The defined local functions presented here now solves this problem. With this concept it is possible to write functions that can be collected and maintained in external libraries.
In consequence we will start to build up a central opsi-script library which is maintained by uib and the opsi community.
In order to reach this target we have implemented the following concepts:
-
Functions with return value:
The functions have a return value which is of the typestring
orstringlist
. Executing such function can be performed wherever a string expression or a stringlist is expected.
Functions with no return value are also allowed and have to be declared asvoid
(since 4.12.0.16). -
Freely definable function call parameters:
Parameters can be passed to a function. These parameters are defined when the function is actually declared. The call parameters can be of typestring
orstringlist
.
The call parameters are available as local variables within the function.
The call parameters can be passed as 'CallByValue' or 'callByReference'. 'CallByValue' is the default. That means, if no call method is specified explicitly, then 'CallByValue' will be applied. In the case that 'CallByValue' needs to be explicitly specified, then the keywordval
should be used. 'CallByValue' means, that the value of a variable used during the call is copied to the call variable.
'CallByReference' must be specified explicitly using the keywordref
. 'callByReference' means that a connection is created between the variable used as parameter when calling the function and the local variable that represents the call parameter inside the function. Changing the local variable of the call parameter has a direct effect on the variable used during such call. -
Local Variables:
A function contains local variables: Implicitly, the call parameters are available as local variables and the variable$result$
which is from the type of the returned value. Further variables can be defined within the function.
All these variables are local, which means that they are only visible within this function. A local variable with the same name of a global variable masks the corresponding global variable within the function. -
Nested functions:
A local function can in turn have one or even more definitions of local functions. These functions are only visible within the function in which they are defined. -
Recursive calls:
A function can call itself recursively. -
Primary and secondary sections within functions:
The function body can contain its own sections of it. These are local to this function, that means that these sections are only visible within the function.
Syntax
Definition
DefFunc <func name>([calltype parameter ptype][,[calltype parameter ptype]]) : ftype <function body> endfunc
Where:
-
DefFunc
is the keyword used to start defining a local function. -
'<func name>' is the freely chosen name of the function.
-
'calltype' is the call type of the parameter [
val
|ref
].val
='Call by Value',ref
='Call by Reference'. Default:val
-
'parameter' is the freely selected name of the call parameter which is available as a local variable within the function under the aforementioned name.
-
'ptype' is the type of data of the parameter and either
string
orstringlist
. -
'ftype' is the type of data of the function and either
string
,stringlist
orvoid
.void
declares that no result is returned. -
'<function body>' is the body of the function which must conform to the opsi-script syntax.
In this part there is the automaticly decared local variable$result$
which should take the result of the function an so have the data type of the function. -
endfunc
is the keyword used to end defining a local function.
A local function has to be defined before you can call the function.
Examples
Simple function that connects two strings:
[actions]
DefVar $mystr$
DefVar $str1$
set $str1$ = 'ha'
DefFunc myFunc(val $str1$ : string, $str2$ : string) : string
set $result$ = $str1$ + $str2$
endfunc
set $mystr$ = myFunc("he","ho")
set $mystr$ = myFunc("he",timeStampAsFloatStr)
set $mystr$ = myFunc("he",$str1$)
Expected results:
-
'heho'
-
'he42921.809'
-
'heha'
Function of the type stringlist
which will deliver a string
and a stringlist
:
[actions]
DefVar $mystr$
DefVar $str1$
DefStringlist $list1$
DefStringlist $list2$
set $str1$ = 'ha'
DefFunc myFunc1(val $str1$ : string, $list1$ : stringlist) : stringlist
set $result$ = createStringlist($str1$ , takeString(2,$list1$))
endfunc
set $list2$ = splitstring("/etc/opsi/huhu","/")
set $list1$ = myFunc1("hi",$list2$)
Expected results:
-
$list1$ = [hi,opsi]
Function of type string
to which a boolean string
will be deliver:
[actions]
DefFunc myFunc2($str1$ : string) : string
set $result$ = booltostring($str1$)
endfunc
if stringtobool(myfunc2('1 > 0'))
comment "true"
else
comment "false"
endif
Expected results:
-
'true'
Function of the type string to which a string is passed with local variable:
[actions]
DefVar $mystr$
DefFunc myFunc3($str1$ : string) : string
DefVar $locstr1$
set $locstr1$ = '123'
set $result$ = $locstr1$ + $str1$
endfunc
set $mystr$ = myFunc3("he")
Expected results:
-
'123he'
Function of the type string
to which a string is passed with local variable and nested function:
[actions]
DefVar $mystr$
DefFunc myFunc4($str1$ : string) : string
DefVar $locstr1$
DefFunc myFunc5($str1$ : string) : string
set $result$ = 'inner' + $str1$
endfunc
set $locstr1$ = '123'
set $result$ = $str1$ + myFunc5($locstr1$)
endfunc
set $mystr$ = myFunc4("outer")
Expected results:
-
'outerinner123'
Simple function of type string
which pass a` string` by reference with a local variable:
[actions]
DefVar $mystr$
DefVar $str1$
DefVar $str2$
set $str1$ = 'ha'
set $str2$ = 'hi'
DefFunc myFunc6(ref $str1$ : string) : string
DefVar $locstr1$
set $locstr1$ = '123'
set $str1$ = 'setinlocal'
set $result$ = $locstr1$ + $str1$
endfunc
set $mystr$ = myFunc6($str2$)
set $mystr$ = $str1$ + $str2$
Expected results:
-
'123setinlocal'
-
'hasetinlocal'
Function of type stringlist
which will pass a variable of type stringlist
with a 'call by reference' also with a local stringlist
variable:
[actions]
DefVar $mystr$
DefStringlist $list1$
DefStringlist $list2$
et $list2$ = splitstring("/etc/opsi/huhu","/")
DefFunc myFunc7(ref $list1$ : stringlist) : stringlist
DefStringlist $loclist1$
set $loclist1$ = splitstring("/a/b/c","/")
set $list1$ = createStringList('setinlocal')
set $loclist1$ = addListToList($loclist1$,$list1$)
set $result$ = $loclist1$
endfunc
set $list1$ = myFunc7($list2$)
comment "$list2$ index 0: " + takestring(0,$list2$)
Expected results:
-
$list1$ = [,a,b,c,setinlocal]
-
'setinlocal'
Function of type stringlist
which pass a string
with a local variable and a local secondary section:
[actions]
DefStringlist $list1$
DefFunc myFunc8($str1$ : string) : stringlist
DefStringlist $loclist1$
set $loclist1$ = getoutstreamfromsection("ShellScript_test")
set $result$ = $loclist1$
[ShellScript_test]
set -x
$str1$
endfunc
set $list1$ = myFunc8('pwd')
Expected results:
-
$list1$ = [+ pwd, /home/uib/gitwork/lazarus/opsi-script]
Function of type void
(no return value) which pass a string
with a local variable:
[actions]
ScriptErrorMessages = false
DefVar $str1$
set $str1$ = 'haha'
DefFunc myNoResultFunc(ref $str1$ : string) : void
set $str1$ = "huhu"
endfunc
myNoResultFunc($str1$)
comment "$str1$ is: "+$str1$
Expected results:
-
$str1$ is: huhu
Function of type string
with no parameter:
[actions]
ScriptErrorMessages = false
DefVar $str1$
DefFunc myNoParamFunc() : string
set $result$ = "huhu"
endfunc
set $str1$ = myNoParamFunc()
Expected results:
-
$str1$ is: huhu
Import of libraries of functions [W/L/M]
importLib
<string expr> ; import library // since 4.12.0.0
<string expr> : <file name>[.<file extension>][::
<function name>]
If no '.<file extension>' is given .opsiscript
is used as default.
If no '::<function name>' is given, all function from the given file will be imported.
<file name> is:
-
A complete path to an existing file. [W/L/M]
-
A existing file in
%ScriptPath%
[W/L/M] -
A file in
%opsiScriptHelperPath%\lib
[W]
Is equivalent to: '%ProgramFiles32Dir%\opsi.org\opsiScriptHelper\lib' -
A existing file in
%ScriptPath%/../lib
[W/L/M] -
A existing file in
%OpsiScriptDir%\lib
[W] or/usr/share/opsi-script/lib
[L]
The tests for the location of the <file name> are done in the order above. opsi-script uses the first file it finds that has a matching name.
User Profile Management [W/L/M]
This extension does not work in combination with the WAN extension! Please do not activate the login event on WAN clients. |
Introduction
The opsi-script has a number of special commands for making modifications in profiles. However, this works only on local profiles and is largely useless when using Roaming Profiles. With the opsi extension User Profile Management it is possible to make changes to these profiles. This is done by starting the opsi-script when the user logs in, in order to execute special userLoginScripts.
Concept
If the profiles cannot be patched while installing software on the machine, a clear distinction must be made between the 'machine part' and the 'profile part' of the installation. This can be done both within a script or by storing the 'profile part' in a separate script. In many installations this is already done by executing the 'profile parts' as part of a domain login script.
Depending on the practice, the 'profile parts' of opsi products are available as part of the opsi scripts for installation and deinstallation, as well as part of a domain login script. The aim of this extension is to be able to integrate both variants as simple as possible in the new mechanism.
The core concepts of this opsi extension are:
-
Executing special userLoginScripts when the user logs in
As part of the user login, the opsi-script is started but executed in a special mode in which only userLoginScripts stored in the products are executed. -
Executing these scripts with administrative rights but in the context of the logged in user
Domain login scripts are executed by the user with user rights. The opsi userLoginScripts are executed by the opsi-script, which runs with administrative rights. At the same time, the opsi-script moves into the context of the user who has logged in, so that the profile can be manipulated with the same commands as in a domain login script. -
Execution of these scripts within the opsi-service context
The opsi userLoginScripts run within the opsi-service context and thus have information via script constants about the product name, version and package version currently being processed. Furthermore, the values of the product properties are available as well as any other information which may be queried via opsiservicalls.
New and changed opsi-script functions
-
Call parameter
/allloginscripts
or/loginscripts
Executing opsi-script in the opsi-service context with the additional parameter/allloginscripts
or/loginscripts
essentially has the following effects:-
The products that have a 'userLoginScript' are determined.
With/allloginscripts
the userLoginScripts are executed for all of these products.
With/loginscripts
, only the loginscripts are executed on a client for which the client knows the corresponding product, i.e. the product is installed or was installed.
See also: Configuration -
The logged in user will be identified, and constants for the current user, e.g. %CurrentAppdataDir% will be directed to the corresponding directories of the logged in user. Likewise, registry operations (
Registry
sections andGetRegistryString
) which refer to HKCU are carried out in such a way that the data comes from the registry branch of the user.
-
-
Call parameter
/silent
The call parameter/silent
ensures that the window of opsi-script is not displayed during script processing. -
Function
GetScriptMode
In order to distinguish in a script in which mode the script is currently being executed, the functionGetScriptMode
returns two possible values:-
'Machine'
The script is not executed as 'userLoginScript' (but e.g. as setup or uninstall script). -
'Login'
The script is executed as 'userLoginScript'.
-
-
New primary section ProfileActions
This new section can be used to bundle actions for user profiles. Here a syntax can be used which enables this section to be used both as part of a normal login script and as a 'userLoginScript'. This primary section is evaluated in different ways, depending on whether the script is running in machine mode or login mode (i.e. as userLoginScript).-
'Login'
If a script runs as 'userLoginScript' and contains a section ProfileActions, script processing is started in this section (and not in Actions). -
'Machine'
If a script runs as a normal installation script, section ProfileActions can be called as a sub-section, similar to a 'sub'-section. The following applies to the processing of this section: '/AllNtUserDats' is implicitly set for all 'registry'-section calls. '/AllNtUserProfiles' is implicitly set for all 'Files'-section calls.
Since version 4.11.3.2 the following also applies: '/AllNtUserProfiles' is implicitly set for all 'Patches'-section calls.
-
-
Registry sections
-
Registry sections that work on 'HKCU' or 'HKEY_CURRENT_USER' are executed in login script mode so that the changes end up in the branch of the logged-in user. The same applies to the functions
GetRegistryStringValue*
. -
Registry sections which are called in normal mode ('Machine') with the modifier '/AllNtUserDats' can now contain the root 'HKCU' or 'HKEY_CURRENT_USER' in the
openkey
command. This makes it possible to run the same registry section in different modes.
-
-
Winbatch/ShellScript/ExecWith sections with
/RunAsLoggedOnUser
Even if opsi-script is started via the login event, it runs in the SYSTEM context and not in the context of the user who has just logged in. A Winbatch, ShellScript or ExecWith section with the option/RunAsLoggedOnUser
can be used to start a process in the context of this user. -
Avoid unnecessary script execution:
The commandsaveVersionToProfile
can be used to stored in the current profile that the userLoginscript for this product has been executed in this version. The string functionreadVersionFromProfile
or the boolean functionscriptWasExecutedBefore
can be used to check whether the userLoginScript for this product has already run in this version and whether it needs to be executed again. For this purpose, this function first reads in a possibly existing version stamp from the profile (as is possible withreadVersionFromProfile
) and compares it with the currently running version. The return value (true/false) results from the comparison. Then the current values are written back to the profile (as is possible withsaveVersionToProfile
). So you only need thisscriptWasExecutedBefore
function in anif
-statement to check whether the script has already run.
Furthermore, the string list functiongetProductMap
provides an info map from which you can see whether the current product is installed or uninstalled etc. -
Any kind of
ExitWindows
command will be ignored. -
Logging
The logs of userLoginScripts are written to:
c:\opsi.org\log\<user login name>_login.log
These log files are also transferred to the opsi server. A new log file is appended to an existing one. The opsi-server ensures that these files are limited in size (max. 5 MB). On the opsi server, these logs are stored as /var/log/opsi/userlogin/<clientid>.log
In the opsi management interface (opsi-configed), these logs are displayed in an additional sub-tab 'userlogin' in the 'Log files' tab.
Examples of userLoginScripts
First, two examples that are structured as they could also be used in domain login scripts.
A very simple generic example:
[Actions]
requiredWinstVersion >= "4.11.3.2"
Message "Example Profile Patch ...."
Files_profile_copy
Registry_currentuser_set
Patches_profile_ini "%userprofiledir%\opsi-script-test.ini"
[Files_profile_copy]
copy "%Scriptpath%\profiles\*.*" "%CurrentAppdataDir%\ACME"
[Registry_currentuser_set]
openkey [HKCU\Software\ACME]
set "show_greeting_window" = "no"
[Patches_profile_ini]
add [secdummy] dummy1=add1
An example for Firefox configuration:
[Actions]
requiredWinstVersion >= "4.11.3.2"
Message "Firefox Profile Patch ...."
DefVar $akt_profile_ini$
DefVar $rel_prefs_path$
comment "check for existing profile ..."
Set $akt_profile_ini$ = "%CurrentAppdataDir%\Mozilla\Firefox\profiles.ini"
if FileExists($akt_profile_ini$)
Set $rel_prefs_path$ = GetValueFromInifile($akt_profile_ini$,"Profile0","Path","")
if FileExists("%CurrentAppdataDir%\Mozilla\Firefox\\"+$rel_prefs_path$)
comment "We found the profile and will now patch it ....."
endif
else
comment "no firefox profile found for user"
endif
Next we show an example, which extends the first one, that shows how to also delete items from the profile. Depending on whether the product is installed or was uninstalled on the computer, a different part of the script is executed:
[Actions]
requiredWinstVersion >= "4.11.3.2"
Message "Example Profile Patch ...."
if getValue("installationstate", getProductMap) = "installed"
comment "Product is installed"
Files_profile_copy
Registry_currentuser_set
Patches_profile_ini "%userprofiledir%\opsi-script-test.ini"
endif
if getValue("lastactionrequest", getProductMap) = "uninstall"
comment "Product was uninstalled"
Files_profile_del
Registry_currentuser_del
endif
[Files_profile_copy]
copy "%Scriptpath%\profiles\*.*" "%CurrentAppdataDir%\ACME"
[Registry_currentuser_set]
openkey [HKCU\Software\ACME]
set "show_greeting_window" = "no"
[Files_profile_del]
del -s -f "%CurrentAppdataDir%\ACME"
del "%userprofiledir%\opsi-script-test.ini"
[Patches_profile_ini]
add [secdummy] dummy1=add1
[Registry_currentuser_del]
deletekey [HKCU\Software\ACME]
Now an example that uses the setup script (setup32.opsiscript and delsub32.opsiscript) to avoid unnecessary duplication of the code:
setup32.opsiscript:
[Actions]
requiredWinstVersion >= "4.11.3.2"
DefVar $MsiId$
DefVar $UninstallProgram$
DefVar $ProductId$
DefVar $InstallDir$
; ----------------------------------------------------------------
; - Please edit the following values -
; ----------------------------------------------------------------
Set $ProductId$ = "ACME"
Set $InstallDir$ = "%ProgramFiles32Dir%\ACME"
; ----------------------------------------------------------------
if GetScriptMode = "Machine"
comment "Show product picture"
ShowBitmap "%ScriptPath%\\" + $ProductId$ + ".png" $ProductId$
if FileExists("%ScriptPath%\delsub32.opsiscript")
comment "Start uninstall sub section"
Sub "%ScriptPath%\delsub32.opsiscript"
endif
Message "Installing " + $ProductId$ + " ..."
comment "Start setup program"
Winbatch_install
comment "Patch the local Profiles ..."
Registry_currentuser_set /AllNtUserDats
Files_profile_copy /AllNtUserProfiles
Patches_profile_ini "%userprofiledir%\opsi-script-test.ini" /AllNtUserProfiles
endif
if GetScriptMode = "Login"
comment "login part"
Files_profile_copy
Registry_currentuser_set
Patches_profile_ini "%userprofiledir%\opsi-script-test.ini"
endif
[Winbatch_install]
"%ScriptPath%\setup.exe" /sp- /silent /norestart
[Files_profile_copy]
copy "%Scriptpath%\profiles\*.*" "%CurrentProfileDir%\Appdata\ACME"
[Registry_currentuser_set]
openkey [HKCU\Software\ACME]
set "show_greeting_window" = "no"
[Patches_profile_ini]
add [secdummy] dummy1=add1
delsub32.opsiscript:
Message "Uninstalling " + $ProductId$ + " ..."
if GetScriptMode = "Machine"
comment "The machine part ..."
Set $UninstallProgram$ = $InstallDir$ + "\uninstall.exe"
if FileExists($UninstallProgram$)
comment "Uninstall program found, starting uninstall"
Winbatch_uninstall
endif
; does also work since 4.11.2.1
Registry_currentuser_del /AllNtUserDats
Files_profile_del /AllNtUserProfiles
endif
if GetScriptMode = "Login"
comment "The profile part ..."
Files_profile_del
Registry_currentuser_del
endif
[Winbatch_uninstall]
"$UninstallProgram$" /silent /norestart
[Files_profile_del]
del -s -f "%CurrentAppdataDir%\ACME"
del "%userprofiledir%\opsi-script-test.ini"
[Registry_currentuser_del]
deletekey [HKCU\Software\ACME]
Now an example which is a variant of the previous example. The code is simplified by using the new primary section ProfileActions and the script can be used both as an installation script and as a 'userLoginScript'.
[Actions]
requiredWinstVersion >= "4.11.3.2"
DefVar $ProductId$
DefVar $InstallDir$
Set $ProductId$ = "ACME"
Set $InstallDir$ = "%ProgramFiles32Dir%\ACME"
comment "Show product picture"
ShowBitmap "%ScriptPath%\\" + $ProductId$ + ".png" $ProductId$
Message "Installing " + $ProductId$ + " ..."
comment "Start setup program"
Winbatch_install
comment "Patch the local Profiles ..."
ProfileActions
[ProfileActions]
comment "login part"
Files_profile_copy
Registry_currentuser_set
Patches_profile_ini "%userprofiledir%\opsi-script-test.ini"
[Winbatch_install]
"%ScriptPath%\setup.exe" /sp- /silent /norestart
[Files_profile_copy]
copy "%Scriptpath%\profiles\*.*" "%CurrentProfileDir%\Appdata\ACME"
[Registry_currentuser_set]
openkey [HKCU\Software\ACME]
set "show_greeting_window" = "no"
[Patches_profile_ini]
add [secdummy] dummy1=add1
Now a variant, which notes in the profile whether the script for this product has already been executed in this version and for this user.
A line with the product information is written to the file %AppData%\.opsi.org\userLoginScripts.ini
.
[Actions]
requiredWinstVersion >= "4.11.3.2"
Message "Example Profile Patch ...."
comment "Did we run this script before ? - and set version stamp in profile"
if not (scriptWasExecutedBefore)
comment "loginscript was not run yet "
Files_profile_copy
Registry_currentuser_set
Patches_profile_ini "%userprofiledir%\opsi-script-test.ini"
endif
[Files_profile_copy]
copy "%Scriptpath%\profiles\*.*" "%CurrentAppdataDir%\ACME"
[Registry_currentuser_set]
openkey [HKCU\Software\ACME]
set "show_greeting_window" = "no"
[Patches_profile_ini]
add [secdummy] dummy1=add1
Configuration
In order to use the 'User Profile Management' extension, the login event must be activated in the configuration of opsiclientd. For this event (if the current opsi-client-agent is installed on the client) opsi-script will be started with the additional parameter '/allloginscripts' or '/loginscripts'.
-
/allloginscripts
means that when you log in all loginscripts that are known to the server are executed, regardless of whether the corresponding product is known to the client (i.e. the product is installed or was installed) or not. -
/loginscripts
means that when you log in, only those loginscripts are run on a client for which the client knows the corresponding product, i.e. the product is installed or was installed. (Technically: where there a productOnClient object for this client exists with:
(installationStatus
=installed
)
oractionResult
=successful
) and (lastAction
=uninstall
).
Login scripts for products that were never installed on this client will not be executed.
This is the default.
You can activate the login event on the command line as follows: (usually you only want to activate individual clients for testing, therefore the value is 'false' on the server side)
opsi-admin -d method config_createBool opsiclientd.event_user_login.active "user_login active" false
The parameter '/silent' can also be used as an additional opsi-script parameter, which prevents the opsi-script window from being displayed.
This is the default.
opsi-admin -d method config_createUnicode opsiclientd.event_user_login.action_processor_command "user_login action_processor" "%action_processor.command% /sessionid %service_session% /loginscripts /silent" "%action_processor.command% /sessionid %service_session% /loginscripts /silent"
Settings configured this way can be modified in the opsi management interface in the 'Host parameters' tab, server or client-specific.