This is an old revision of the document!
With this package, you can join or leave a domain, or change the ou-path for the client within a domain (still experimental, details below). These three functions are conveniently assigned to the action requests setup (join), uninstall (leave), update (relocate).
[Actions] SetLogLevel = 9 ExitOnError = false ScriptErrorMessages = on TraceMode = off StayOnTop = false requiredWinstVersion >= "4.11.5.14" ScriptErrorMessages = false noUpdateScript defVar $DomainRaw$ defVar $Domain$ defVar $DomainCurrent$ defVar $OUPath$ defVar $OUPathCurrent$ defVar $Username$ defVar $Password$ defVar $ExitCode$ defVar $JoinMode$ defVar $UnJoinMode$ defVar $JOIN_DOMAIN$ defVar $ACCT_CREATE$ defVar $ACCT_DELETE$ defVar $WIN9X_UPGRADE$ defVar $DOMAIN_JOIN_IF_JOINED$ defVar $JOIN_UNSECURE$ defVar $MACHINE_PASSWORD_PASSED$ defVar $DEFERRED_SPN_SET$ defVar $INSTALL_INVOCATION$ ;defVar $ACCT_NO_OPTIONS$ ;defVar $ACCT_DEACTIVATE$ ;calculate joinmode from possible constants set $JOIN_DOMAIN$ = "1" set $ACCT_CREATE$ = "2" set $ACCT_DELETE$ = "4" set $WIN9X_UPGRADE$ = "16" set $DOMAIN_JOIN_IF_JOINED$ = "32" set $JOIN_UNSECURE$ = "64" set $MACHINE_PASSWORD_PASSED$ = "128" set $DEFERRED_SPN_SET$ = "256" set $INSTALL_INVOCATION$ = "262144" set $JoinMode$ = calculate($JOIN_DOMAIN$+"+"+$ACCT_CREATE$) ;calculate unjoinmode from possible constants ;set $ACCT_NO_OPTIONS$ = "0" ;set $ACCT_DEACTIVATE$ = "2" ;set $UnJoinMode$ = calculate($ACCT_DEACTIVATE$) ;product property domain_ou has the following syntax: [domain.tld][/ou_1/ou_2] - both segments are optional. ;domain must be the fqdn for the domain to join ;ou-path must consist of the hierarchical list of ou's the client should be put in, every ou must have a leading slash. set $DomainRaw$ = getProductProperty("domain_ou","") ;get domain from product property - if domain is not set, get domain from host identifier. set $Domain$ = takeString(0, splitString($DomainRaw$,"/")) if ($Domain$ = "") set $Domain$ = composeString(getSubList(1 : ,splitString("%HostId%",".")),".") set $DomainRaw$ = $Domain$ + $DomainRaw$ endif ;get ou-path from product property - if ou-path is not set, join client to standard client-ou-path for the domain. ;ou-path will be transformed into ldap-friendly syntax. set $OUPath$ = "" for %OU% in getSubList(1 : ,splitString($DomainRaw$,"/")) do set $OUPath$ = "OU=%OU%,"+$OUPath$ if not ($OUPath$ = "") for %DC% in splitString($Domain$,".") do set $OUPath$ = $OUPath$+"DC=%DC%," set $OUPath$ = strPart($OUPath$,"1",calculate(strLength($OUPath$)+"-1")) endif ;get username + password from, product properties, hide password value in log set $Username$ = getProductProperty("username","") setConfidential getProductProperty("password","") set $Password$ = getProductProperty("password","") ;check if client is in domain if ( takeString(0, getOutStreamFromSection('execwith_vbs_check_domain cscript //nologo //e:vbs')) = "0" ) showBitmap "%ScriptPath%\domain.png" "Active Directory" message "Join domain " + $DomainRaw$ execwith_vbs_domain_join cscript //nologo //e:vbs sub_check_domain_join dosinanicon_gpupdate /WaitOnClose comment "Setting default logon domain, clear previous login user" registry_default_domain /sysnative exitwindows /Reboot else set $DomainCurrent$ = takeString(0, getOutStreamFromSection('execwith_vbs_get_domain cscript //nologo //e:vbs')) ;check if client is already in domain requested if not ( $DomainCurrent$ = $Domain$ ) showBitmap "%ScriptPath%\domain.png" "Active Directory" message "Leave domain " + $DomainCurrent$ execwith_vbs_domain_unjoin cscript //nologo //e:vbs sub_check_domain_unjoin ;TODO remove client from ad ;TODO check exitcode adsi exitwindows /ImmediateReboot else comment "Client is already in requested domain" endif endif ;reset username + password entries in product properties opsiservicecall_unset_username opsiservicecall_unset_password [execwith_vbs_check_domain] Set obj = GetObject("WinMgmts:\\.\root\cimv2:Win32_ComputerSystem.Name='%PCNAME%'") Wscript.Echo obj.PartOfDomain [execwith_vbs_get_domain] Set obj = GetObject("WinMgmts:\\.\root\cimv2:Win32_ComputerSystem.Name='%PCNAME%'") Wscript.Echo obj.Domain [execwith_vbs_domain_join] Set obj = GetObject("WinMgmts:\\.\root\cimv2:Win32_ComputerSystem.Name='%PCNAME%'") res = obj.JoinDomainOrWorkGroup("$Domain$", "$Password$", "$Username$", "$OUPath$", $JoinMode$) Wscript.Quit res [execwith_vbs_domain_unjoin] Set obj = GetObject("WinMgmts:\\.\root\cimv2:Win32_ComputerSystem.Name='%PCNAME%'") res = obj.UnjoinDomainOrWorkgroup("$Password$", "$Username$") ;res = obj.UnjoinDomainOrWorkgroup("$Password$", "$Username$", $UnJoinMode$) Wscript.Quit res [dosinanicon_gpupdate] gpupdate /force exit %ERRORLEVEL% [registry_default_domain] openkey [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon] set "DefaultDomainName" = REG_SZ:"$Domain$" set "AltDefaultDomainName" = REG_SZ:"$Domain$" set "CachePrimaryDomain" = REG_SZ:"$Domain$" openKey [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI] set "LastLoggedOnSAMUser" = REG_SZ:"" set "LastLoggedOnUser" = REG_SZ:"" [opsiservicecall_unset_username] "method": "setProductProperty" "params": [ "%installingProdName%", "username", "", "%hostid%" ] [opsiservicecall_unset_password] "method": "setProductProperty" "params": [ "%installingProdName%", "password", "", "%hostid%" ] [sub_check_domain_unjoin] set $ExitCode$ = getLastExitCode if $ExitCode$ = "0" comment "Success" else logError "UNKNOWN ERROR " & ReturnValue isFatalError endif [sub_check_domain_join] set $ExitCode$ = getLastExitCode if $ExitCode$ = "0" comment "Success" else if $ExitCode$ = "2" logError "Missing OU" isFatalError else if $ExitCode$ = "5" logError "Access denied" isFatalError else if $ExitCode$ = "53" logError "Network path not found" isFatalError else if $ExitCode$ = "87" logError "Parameter incorrect" isFatalError else if $ExitCode$ = "1326" logError "Logon failure, user or pass" isFatalError else if $ExitCode$ = "1355" logError "Domain can not be contacted" isFatalError else if $ExitCode$ = "1909" logError "User account locked out" isFatalError else if $ExitCode$ = "2224" logError "Computer Account allready exists" isFatalError else if $ExitCode$ = "2691" logError "Allready joined" isFatalError else logError "Unknown error " & ReturnValue isFatalError endif endif endif endif endif endif endif endif endif endif
[Actions] SetLogLevel = 9 ExitOnError = false ScriptErrorMessages = on TraceMode = off StayOnTop = false requiredWinstVersion >= "4.11.5.14" ScriptErrorMessages = false defVar $DomainCurrent$ defVar $Username$ defVar $Password$ defVar $ExitCode$ defVar $UnJoinMode$ ;defVar $ACCT_NO_OPTION$ ;defVar $ACCT_DEACTIVATE$ ;calculate unjoinmode from possible constants ;set $ACCT_NO_OPTION$ = "0" ;set $ACCT_DEACTIVATE$ = "2" ;set $UnJoinMode$ = calculate($ACCT_DEACTIVATE$) ;get username + password from, product properties, hide password value in log set $Username$ = getProductProperty("username","") setConfidential getProductProperty("password","") set $Password$ = getProductProperty("password","") ;reset username + password entries in product properties ;opsiservicecall_unset_username ;opsiservicecall_unset_password ;check if client is in domain if not ( takeString(0, getOutStreamFromSection('execwith_vbs_check_domain cscript //nologo //e:vbs')) = "0" ) set $DomainCurrent$ = takeString(0, getOutStreamFromSection('execwith_vbs_get_domain cscript //nologo //e:vbs')) showBitmap "%ScriptPath%\domain.png" "Active Directory" message "Leave domain " + $DomainCurrent$ ;leave domain execwith_vbs_domain_unjoin cscript //nologo //e:vbs sub_check_domain_unjoin ;TODO remove client from ad ;TODO check exitcode adsi ;restart client, script will be re-executed upon next opsi request exitwindows /Reboot else comment "Computer is currently not part of a domain" endif ;reset username + password entries in product properties opsiservicecall_unset_username opsiservicecall_unset_password [execwith_vbs_check_domain] Set obj = GetObject("WinMgmts:\\.\root\cimv2:Win32_ComputerSystem.Name='%PCNAME%'") Wscript.Echo obj.PartOfDomain [execwith_vbs_get_domain] Set obj = GetObject("WinMgmts:\\.\root\cimv2:Win32_ComputerSystem.Name='%PCNAME%'") Wscript.Echo obj.Domain [execwith_vbs_domain_unjoin] Set obj = GetObject("WinMgmts:\\.\root\cimv2:Win32_ComputerSystem.Name='%PCNAME%'") res = obj.UnjoinDomainOrWorkgroup("$Password$", "$Username$") ;res = obj.UnjoinDomainOrWorkgroup("$Password$", "$Username$", $UnJoinMode$) Wscript.Quit res [opsiservicecall_unset_username] "method": "setProductProperty" "params": [ "%installingProdName%", "username", "", "%hostid%" ] [opsiservicecall_unset_password] "method": "setProductProperty" "params": [ "%installingProdName%", "password", "", "%hostid%" ] [sub_check_domain_unjoin] set $ExitCode$ = getLastExitCode if $ExitCode$ = "0" comment "Success" else logError "UNKNOWN ERROR " & ReturnValue isFatalError endif
[Actions] SetLogLevel = 9 ExitOnError = false ScriptErrorMessages = on TraceMode = off StayOnTop = false requiredWinstVersion >= "4.11.5.14" ScriptErrorMessages = false defVar $DomainRaw$ defVar $Domain$ defVar $DomainCurrent$ defVar $OUPath$ defVar $OUPathCurrent$ defVar $Username$ defVar $Password$ defVar $ExitCode$ ;product property domain_ou has the following syntax: [domain.tld][/ou_1/ou_2] - both segments are optional. ;domain must be the fqdn for the domain to join ;ou-path must consist of the hierarchical list of ou's the client should be put in, every ou must have a leading slash. set $DomainRaw$ = getProductProperty("domain_ou","") ;get domain from product property - if domain is not set, get domain from host identifier. set $Domain$ = takeString(0, splitString($DomainRaw$,"/")) if ($Domain$ = "") set $Domain$ = composeString(getSubList(1 : ,splitString("%HostId%",".")),".") set $DomainRaw$ = $Domain$ + $DomainRaw$ endif ;get ou-path from product property - if ou-path is not set, join client to standard client-ou-path for the domain. ;ou-path will be transformed into ldap-friendly syntax. set $OUPath$ = "" for %OU% in getSubList(1 : ,splitString($DomainRaw$,"/")) do set $OUPath$ = "OU=%OU%,"+$OUPath$ if not ($OUPath$ = "") for %DC% in splitString($Domain$,".") do set $OUPath$ = $OUPath$+"DC=%DC%," set $OUPath$ = strPart($OUPath$,"1",calculate(strLength($OUPath$)+"-1")) endif ;get username + password from, product properties, hide password value in log set $Username$ = getProductProperty("username","") setConfidential getProductProperty("password","") set $Password$ = getProductProperty("password","") if not ( takeString(0, getOutStreamFromSection('execwith_vbs_check_domain cscript //nologo //e:vbs')) = "0" ) set $DomainCurrent$ = takeString(0, getOutStreamFromSection('execwith_vbs_get_domain cscript //nologo //e:vbs')) ;check if client is in domain requested if ( $DomainCurrent$ = $Domain$ ) set $OUPathCurrent$ = takeString(0, getOutStreamFromSection('execwith_vbs_get_oupath cscript //nologo //e:vbs')) ;check if client is already in ou-path requested if not ( $OUPathCurrent$ = $OUPath$ ) showBitmap "%ScriptPath%\domain.png" "Active Directory" message "Relocate to ou-path " + $DomainRaw$ execwith_vbs_move_oupath cscript //nologo //e:vbs ;TODO check exitcode adsi dosinanicon_gpupdate /WaitOnClose else comment "Computer is already in the given ou-path" endif else logError "Computer is not part of the domain requested, moving to another ou-path only works within the same domain" isFatalError endif else logError "Computer is currently not part of a domain" isFatalError endif [execwith_vbs_check_domain] Set obj = GetObject("WinMgmts:\\.\root\cimv2:Win32_ComputerSystem.Name='%PCNAME%'") Wscript.Echo obj.PartOfDomain [execwith_vbs_get_domain] Set obj = GetObject("WinMgmts:\\.\root\cimv2:Win32_ComputerSystem.Name='%PCNAME%'") Wscript.Echo obj.Domain [execwith_vbs_get_oupath] Set adoConnection = CreateObject("ADODB.Connection") adoConnection.Provider = "ADsDSOObject" adoConnection.Properties("User ID") = "$Username$" adoConnection.Properties("Password") = "$Password$" adoConnection.Properties("Encrypt Password") = True Set adoCommand = CreateObject("ADODB.Command") adoConnection.Properties("ADSI Flag") = &H200 Or &H1 adoConnection.Open "Active Directory Provider" Set adoCommand.ActiveConnection = adoConnection adoCommand.CommandText = "Select distinguishedName from 'LDAP://$Domain$' where objectClass='computer' and cn='%PCNAME%'" adoCommand.Properties("Searchscope") = 2 Set adoRecordSet = adoCommand.Execute adoRecordSet.MoveFirst OUPathCurrent = adoRecordSet.Fields("distinguishedName").Value Wscript.Echo Mid(OUPathCurrent,InStr(OUPathCurrent,",")+1) [execwith_vbs_move_oupath] Set obj = GetObject("LDAP:") obj.OpenDSObject "LDAP://w8vrsag08.$Domain$/$OUPath$", "$Username$", "$Password$", 1 res = obj.MoveHere("LDAP://CN=%PCNAME%,$OUPathCurrent$", "CN=%PCNAME%") Wscript.Quit res [dosinanicon_gpupdate] gpupdate /force exit %ERRORLEVEL% [opsiservicecall_unset_username] "method": "setProductProperty" "params": [ "%installingProdName%", "username", "", "%hostid%" ] [opsiservicecall_unset_password] "method": "setProductProperty" "params": [ "%installingProdName%", "password", "", "%hostid%" ]