Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.
Keywords: join unjoin remove rename workstation domain
NOTE: There is no simple registry change that you can make to force a NT/2K/XP system to join or unjoin a domain. The actual domain or workgroup membership information is tucked away down in the LSA database on the workstation, so running these UDF functions is how you get the task done inside WinBatch. Otherwise, you shell out to the NETDOM.EXE program and let it do the task for you from a CMD.EXE console window.
; Domain_Join_UnJoin_UDF.wbt ; 32-bit ; ; This is a WinBatch script file intended to be included via "#include" in another ; script. This file contains UDFs defined to provide support for joining or leaving ; a NT domain and should only be run on workstations and member servers. It should ; not be run on any sort of domain controllers. NT domains and emulated NT domains ; [on Win2K domain controllers running in legacy/compatibility mode] are supported, ; but joining an AD domain and placing the workstation in an OU container is *NOT* ; supported using these UDFs. Instead, if joining a native AD domain is desired ; then use the ADSI extender. ; ; ; The account under which this is run [on the local workstation] must have administrator ; rights [e.g. is a member of the local "Administrators" group] on the workstation or ; else these UDF functions will fail and generate an error. ; ; ; UDFs defined in this library: ; ; JoinDomain(DomainName,Username,Password,Flags) ; ; Parameters: ; ; DomainName = name of domain to join ; Username = username of a domain admin account ; Password = password of the specified domain admin account ; Flags = bit mask of flags that control how the join operation is done ; ; If bit #0 [value = 1 when enabled] is enabled then the machine account ; will be created as part of the join operation. If the machine account ; already exists then it will be modified as necessary to make sure that ; it is ready for use as a workstation trust account. If this flag bit ; is disabled then the machine account will not be created/modified and ; that particular task will have to be done manually before the modified ; workstation can have any processes logon to it using domain credentials. ; ; UnJoinDomain(WorkGroupName,Username,Password,Flags) ; ; Parameters: ; ; WorkGroupName = name of work group to join when leaving the domain ; Username = username of a domain admin account ; Password = password of the specified domain admin account ; Flags = bit mask of flags that control how the unjoin operation is done ; ; If bit #0 [value = 1 when enabled] is enabled then the machine account ; will be disabled as part of the unjoin operation. If this flag bit ; is disabled then the machine account will not be disabled. ; ; RenameComputerInDomain(NewComputerName,Username,Password,Flags) ; ; Parameters: ; ; NewComputerName = new name to which the computer will be renamed ; Username = username of a domain admin account ; Password = password of the specified domain admin account ; Flags = bit mask of flags that control how the unjoin operation is done ; ; If bit #0 [value = 1 when enabled] is enabled then the machine account ; will be renamed as part of the rename operation. If this flag bit ; is disabled then the machine account will not be renamed. ; ; if bit #1 [value = 2 when enabled] is enabled then if the machine account ; for the new computer name already exists [e.g. a duplicate] it will be ; deleted before the existing machine account is renamed. If this flag bit ; is disabled the a previously existing machine account for the new computer ; name will result in an error being generated. ; ; Please note that enabled flag bit #1 will forcibly enable flag bit #0, so ; specifying a Flags value of 2 is the same thing as setting a Flags value ; of 3. ; ; ; ; Minor Error codes used by this UDF library: ; ; 7000 = 'No PDC computer found for the specified domain' ; 7001 = 'Machine account name already exists but is not a machine account' ; 7002 = 'Computer is not currently a member of any domain' ; 7003 = 'Duplicate domain member; new computer name already has an existing machine account' ; 7004 = 'Unable to rename local computer name' ; ; ; This little snippet of code here that checks whether or not the extender is ; already loaded is not really necessary as attempting to load an extender that ; is already loaded will not cause any problems. However, it does demonstrate ; how one would go about determining if an extender had already been loaded ; just in case the AddExtender() call was not being made in this particular ; source code file and the code had to be absolutely 100% certain that the code ; that was including this file had in fact already loaded the extender. ; Get the list of loaded extenders... TempUDF_LoadedExtenders = IntControl(77,42,0,0,0) for TempUDF_I = 1 to ItemCount(TempUDF_LoadedExtenders,@TAB) TempUDF_Item = ItemExtract(TempUDF_I,TempUDF_LoadedExtenders,@TAB) TempUDF_Item = StrUpper(StrCat(FileRoot(TempUDF_Item),'.',FileExtension(TempUDF_Item))) TempUDF_LoadedExtenders = ItemReplace(TempUDF_Item,TempUDF_I,TempUDF_LoadedExtenders,@TAB) next ; Add in a required extender [if it is not already loaded] if (ItemLocate('WWWNT34I.DLL',TempUDF_LoadedExtenders,@TAB) == 0) AddExtender('WWWNT34I.DLL') endif ; Done with some temporary variables that we don't want to leave hanging around in the main script... DropWild('TempUDF_*') #DefineFunction JoinDomain(DomainName,Username,Password,Flags) ; Parse the flags... if (Flags & 1) bCreateAccount = @TRUE else bCreateAccount = @FALSE endif ; Get some computer name info... ComputerName = StrUpper(RegQueryValue(@REGMACHINE,"System\CurrentControlSet\Control\ComputerName\ComputerName[ComputerName]")) WorkstationName = StrCat('\\',ComputerName) MachineAcctName = StrCat(StrLower(ComputerName),'$') MachineAcctPassword = StrLower(ComputerName) ; Get the name of the PDC computer for the domain... PDCName = wntServerList('',DomainName,8) if (PDCName == '') then IntControl(79,-1,7000,'No PDC computer found for the specified domain',0) ; If we have *ANY* connected resources on the PDC then we need to get rid of them so that we can ; make certain that we connect to the PDC using the proper set of credentials when we go to add ; the machine account. ErrorMode(@OFF) ConnResList = wntShareUsers(PDCNAME,WorkstationName,0,2,0) RC = LastError() ErrorMode(@CANCEL) if (RC == 0) for i = 1 to ItemCount(ConnResList,@TAB) ConnResName = ItemExtract(i,ConnResList,@TAB) ErrorMode(@OFF) wntCancelCon(StrCat(PDCName,'\',ConnResName),@TRUE,@TRUE) ErrorMode(@CANCEL) next endif ; Now we connect to the "IPC$" share on the PDC... if ((Username != '') && (Password != '')) TempUsername = Username TempPassword = Password else if ((Username != '') && (Password == '')) TempUsername = Username TempPassword = @NONE else if ((Username == '') && (Password == '')) TempUsername = @DEFAULT TempPassword = @DEFAULT else TempUsername = @DEFAULT TempPassword = Password endif endif endif wntAddDrive(TempUsername,TempPassword,StrCat(PDCName,'\IPC$'),@NONE,@FALSE) if (bCreateAccount) ; Check to see if the machine account already exists. if wntUserExist(PDCName,MachineAcctName,0) ; If it does exist then make sure that it has ; the right type of account flags and that the ; password is reset properly. AcctFlags = wntUserGetDat(PDCName,MachineAcctName,'flags',0) if ((AcctFlags & 4096) == 0) ; Not a workstation account IntControl(79,-1,7001,'Machine account name already exists but is not a machine account',0) endif ; Make sure that the account won't expire, is not locked out, it does not have ; an expired password and it is not disabled... if ((AcctFlags & 16) || (AcctFlags & 2)) ; 16 = locked out, 2 = disabled TempAcctFlags = AcctFlags & ~(16 | 2) wntUserSetDat(PDCName,MachineAcctName,'flags',TempAcctFlags,0) endif if (wntUserGetDat(PDCName,MachineAcctName,'acct_expires',0) != '0000:00:00:00:00:00') wntUserSetDat(PDCName,MachineAcctName,'acct_expires','0000:00:00:00:00:00',0) endif if (wntUserGetDat(PDCName,MachineAcctName,'password_expired',0)) wntUserSetDat(PDCName,MachineAcctName,'password_expired',0,0) endif ; Set the password on the machine account to the default value that is expected to ; exist when a new workstation trust account is set up... wntUserSetDat(PDCName,MachineAcctName,'password',MachineAcctPassword,0) else ; We must set up a workstation trust account from scratch... AcctFlags = 4096 | 1 wntUserAddDat('name',MachineAcctName) wntUserAddDat('flags',AcctFlags) wntUserAddDat('password',MachineAcctPassword) wntUserAdd(PDCName) endif endif ; Get the SID for the domain from the PDC... DomainSID = wntLsaPolGet(PDCName,'PrimaryDomain',2) ; Clean up after ourselves... ErrorMode(@OFF) wntCancelCon(StrCat(PDCName,'\IPC$'),@TRUE,@TRUE) ErrorMode(@CANCEL) ; Set the local computer to thing that it belongs to the domain... wntLsaPolSet('','PrimaryDomain',1,DomainName) wntLsaPolSet('','PrimaryDomain',2,DomainSID) ; Reset the stored & hashed password that the computer will use when signing on using ; its own workstation trust account in the domain... wntLsaPolSet('','PrivateData','$MACHINE.ACC',MachineAcctPassword) ; Make sure that the "Net Logon" service is set to automatically start up... wntSvcCfgSet('','Net Logon',0,1,2) ; Return success return @TRUE #EndFunction #DefineFunction UnJoinDomain(WorkGroupName,Username,Password,Flags) ; Parse the flags... if (Flags & 1) bDisableAccount = @TRUE else bDisableAccount = @FALSE endif ; Get some computer name info... ComputerName = StrUpper(RegQueryValue(@REGMACHINE,"System\CurrentControlSet\Control\ComputerName\ComputerName[ComputerName]")) WorkstationName = StrCat('\\',ComputerName) MachineAcctName = StrCat(StrLower(ComputerName),'$') MachineAcctPassword = StrLower(ComputerName) ; Figure out what domain we are a member of... DomainName = wntLsaPolGet('','PrimaryDomain',1) ; Determine whether the domain is really a domain or if it is a work group DomainSID = wntLsaPolGet('','PrimaryDomain',2) if (DomainSID == '') ; Short circuit here. We're already in a work group, so give an error ; and bail out. IntControl(79,-1,7002,'Computer is not currently a member of any domain',0) endif ; Get the name of the PDC computer for the domain... PDCName = wntServerList('',DomainName,8) if (PDCName == '') then IntControl(79,-1,7000,'No PDC computer found for the specified domain',0) ; If we have *ANY* connected resources on the PDC then we need to get rid of them so that we can ; make certain that we connect to the PDC using the proper set of credentials when we go to ; disable the machine account. ErrorMode(@OFF) ConnResList = wntShareUsers(PDCNAME,WorkstationName,0,2,0) RC = LastError() ErrorMode(@CANCEL) if (RC == 0) for i = 1 to ItemCount(ConnResList,@TAB) ConnResName = ItemExtract(i,ConnResList,@TAB) ErrorMode(@OFF) wntCancelCon(StrCat(PDCName,'\',ConnResName),@TRUE,@TRUE) ErrorMode(@CANCEL) next endif ; Now we connect to the "IPC$" share on the PDC... if ((Username != '') && (Password != '')) TempUsername = Username TempPassword = Password else if ((Username != '') && (Password == '')) TempUsername = Username TempPassword = @NONE else if ((Username == '') && (Password == '')) TempUsername = @DEFAULT TempPassword = @DEFAULT else TempUsername = @DEFAULT TempPassword = Password endif endif endif wntAddDrive(TempUsername,TempPassword,StrCat(PDCName,'\IPC$'),@NONE,@FALSE) if (bDisableAccount) ; Check to see if the machine account already exists. if wntUserExist(PDCName,MachineAcctName,0) ; If it does exist then make sure that it gets ; disabled. AcctFlags = wntUserGetDat(PDCName,MachineAcctName,'flags',0) TempAcctFlags = AcctFlags | 2 wntUserSetDat(PDCName,MachineAcctName,'flags',TempAcctFlags,0) else ; Interesting... There was no machine account, nothing special to do... endif endif ; Clean up after ourselves... ErrorMode(@OFF) wntCancelCon(StrCat(PDCName,'\IPC$'),@TRUE,@TRUE) ErrorMode(@CANCEL) ; Set the local computer to thing that it belongs to the work group... wntLsaPolSet('','PrimaryDomain',1,WorkGroupName) wntLsaPolSet('','PrimaryDomain',2,'') ; Make sure that the "Net Logon" service is set to manually [not automatically] start up... wntSvcCfgSet('','Net Logon',0,1,3) ; Return success return @TRUE #EndFunction #DefineFunction RenameComputerInDomain(NewComputerName,Username,Password,Flags) ; Parse the flags... if (Flags & 1) bRenameAccount = @TRUE else bRenameAccount = @FALSE endif if (Flags & 2) bKillDuplicate = @TRUE bRenameAccount = @TRUE else bKillDuplicate = @FALSE endif ; Get some computer name info... ComputerName = StrUpper(RegQueryValue(@REGMACHINE,"System\CurrentControlSet\Control\ComputerName\ComputerName[ComputerName]")) WorkstationName = StrCat('\\',ComputerName) MachineAcctName = StrCat(StrLower(ComputerName),'$') MachineAcctPassword = StrLower(ComputerName) NewMachineAcctName = StrCat(StrLower(NewComputerName),'$') ; Figure out what domain we are a member of... DomainName = wntLsaPolGet('','PrimaryDomain',1) ; Determine whether the domain is really a domain or if it is a work group DomainSID = wntLsaPolGet('','PrimaryDomain',2) if (DomainSID == '') ; Short circuit here. We're already in a work group, so give an error ; and bail out. IntControl(79,-1,7002,'Computer is not currently a member of any domain',0) endif ; Get the name of the PDC computer for the domain... PDCName = wntServerList('',DomainName,8) if (PDCName == '') then IntControl(79,-1,7000,'No PDC computer found for the specified domain',0) ; If we have *ANY* connected resources on the PDC then we need to get rid of them so that we can ; make certain that we connect to the PDC using the proper set of credentials when we go to ; disable the machine account. ErrorMode(@OFF) ConnResList = wntShareUsers(PDCNAME,WorkstationName,0,2,0) RC = LastError() ErrorMode(@CANCEL) if (RC == 0) for i = 1 to ItemCount(ConnResList,@TAB) ConnResName = ItemExtract(i,ConnResList,@TAB) ErrorMode(@OFF) wntCancelCon(StrCat(PDCName,'\',ConnResName),@TRUE,@TRUE) ErrorMode(@CANCEL) next endif ; Now we connect to the "IPC$" share on the PDC... if ((Username != '') && (Password != '')) TempUsername = Username TempPassword = Password else if ((Username != '') && (Password == '')) TempUsername = Username TempPassword = @NONE else if ((Username == '') && (Password == '')) TempUsername = @DEFAULT TempPassword = @DEFAULT else TempUsername = @DEFAULT TempPassword = Password endif endif endif wntAddDrive(TempUsername,TempPassword,StrCat(PDCName,'\IPC$'),@NONE,@FALSE) if (bRenameAccount) ; Check to see if the machine account already exists. if wntUserExist(PDCName,NewMachineAcctName,0) if (bKillDuplicate) wntUserDel(PDCName,NewMachineAcctName,0) else IntControl(79,-1,7003,'Duplicate domain member; new computer name already has an existing machine account',0) endif endif if wntUserExist(PDCName,MachineAcctName,0) wntUserRename(PDCName,MachineAcctName,NewMachineAcctName,0) endif endif ; Clean up after ourselves... ErrorMode(@OFF) wntCancelCon(StrCat(PDCName,'\IPC$'),@TRUE,@TRUE) ErrorMode(@CANCEL) ; Set the local computer to use a new computer name... Result = IntControl(76,NewComputerName,0,0,0) if (!Result) IntControl(79,-1,7004,'Unable to rename local computer name',0) endif ; Return success return @TRUE #EndFunction
Article ID: W15186
File Created: 2002:09:05:13:50:26
Last Updated: 2002:09:05:13:50:26