WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

Domain

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

Join Unjoin Rename Computer in Domain

 Keywords:  join unjoin remove rename workstation domain

All you need to do is to call this function and then reboot the computer for the changes to take effect. If you don't reboot then the changes won't have taken effect.

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.

Sample UDFs:

; 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