Guest Michael R. Mastro II Posted September 13, 2008 Posted September 13, 2008 Hello, I am trying to modify a script from the Windows 2008 server resource kit to fit my needs. I am wondering if anyone can help in this effort. Here is what I have for the script: '========================================================================== ' ' VBScript Source File -- Created with SAPIEN Technologies PrimalScript 2007 ' ' NAME: UDS_UserFolders_Extended_Provision_DFS.vbs ' ' AUTHOR: Dan Holme , Intelliem ' DATE : 11/12/2007 ' ' USAGE: ' cscript.exe UDS_UserFolders_Extended_Provision_DFS.vbs UserFolderPath ' [dfs:Y /server:<servername> ' /userfirstname:<first name> /userlastname:<last name> ' ' Creates a physical and DFS namespace for all user data stores. ' See the Windows Administration Resource Kit for documentation ' ' Neither Microsoft nor Intelliem guarantee the performance ' of scripts, scripting examples or tools. ' ' See http://www.intelliem.com/resourcekit for updates to this script ' ' © 2007 Intelliem, Inc '========================================================================== ' CONFIGURATION BLOCK ' Because configuration is so significant for this script, it has been moved to ' Sub Configuration () Option Explicit Dim FSO, WSHShell Dim sUsernameFolder Dim sUsername, sCommand, sFolder Dim arr, i, ret Dim sUserDataServer, sUserFirst, sUserLast Dim bDFSNamespaceMode, bQuiet Dim DFSUTIL Dim sUserDFSNamespace, sUserDataPath Dim sUserDocsDFSFolder, sUserDocsShareName, sUserDocsPath Dim sUserDesktopDFSFolder, sUserDesktopShareName, sUserDesktopPath Dim sUserFavoritesDFSFolder, sUserFavoritesShareName, sUserFavoritesPath Dim sUserMusicDFSFolder, sUserMusicShareName, sUserMusicPath Dim sUserPicturesDFSFolder, sUserPicturesShareName, sUserPicturesPath Dim sUserVideosDFSFolder, sUserVideosShareName, sUserVideosPath Dim sUserProfileDFSFolder, sUserProfileShareName, sUserProfilePath Dim sUserProfileV2DFSFolder, sUserProfileV2ShareName, sUserProfileV2Path Dim sUserBackupsDFSFolder, sUserBackupsShareName, sUserBackupsPath Dim sDomainNetBIOS, sTemplate_UserData Dim bInheritanceError Create_Common_Objects Check_Arguments Configuration Create_Physical_Namespace If bDFSNamespaceMode Then Create_DFS_Namespace WScript.Echo sUsernameFolder & " provisioned." Sub Create_Physical_Namespace() ' ===================================================================================== ' Create physical namespace for %username% folder and the user's data stores beneath it ' %USERNAME% folder ' Physical path is passed to script as first argument ' and stored in sUsernameFolder variable ' Make sure it exists. If not, create it. If that fails, quit. If Not FolderPath_Create(sUsernameFolder) Then WScript.Echo "Folder could not be found and could not be created." WScript.Quit End If ' Determine the user name by looking at the last folder in the folder path sUsername = FSO.GetFolder(sUsernameFolder).Name ' %USERNAME%\Data ' The parent folder of Documents and Desktop ' Create folder if it does not exist and, if successful, apply a quota. sFolder = sUsernameFolder & "\" & sUserDataPath If FolderPath_Create( sFolder ) Then sCommand = "dirquota quota add /path:""" & sFolder & """ /sourcetemplate:""" & sTemplate_UserData & """" arr = Execute_Capture(sCommand, 10, True) End If ' %USERNAME%\Data\Documents sFolder = sUsernameFolder & "\" & sUserDocsPath If FolderPath_Create( sFolder ) Then ' Management logic here, if any End If ' %USERNAME%\Data\Desktop sFolder = sUsernameFolder & "\" & sUserDesktopPath If FolderPath_Create( sFolder ) Then ' Management logic here, if any End If ' %USERNAME%\Data\Favorites sFolder = sUsernameFolder & "\" & sUserFavoritesPath If FolderPath_Create( sFolder ) Then ' Management logic here, if any End If ' %USERNAME%\Data\Music sFolder = sUsernameFolder & "\" & sUserMusicPath If FolderPath_Create( sFolder ) Then ' Management logic here, if any End If ' %USERNAME%\Data\Pictures sFolder = sUsernameFolder & "\" & sUserPicturesPath If FolderPath_Create( sFolder ) Then ' Management logic here, if any End If ' %USERNAME%\Data\Videos sFolder = sUsernameFolder & "\" & sUserVideosPath If FolderPath_Create( sFolder ) Then ' Management logic here, if any End If ' %USERNAME%\Backups sFolder = sUsernameFolder & "\" & sUserBackupsPath If FolderPath_Create( sFolder ) Then ' Management logic here, if any End If ' %USERNAME%\Profile sFolder = sUsernameFolder & "\" & sUserProfilePath If FolderPath_Create( sFolder ) Then ' Management logic here, if any End If ' %USERNAME%\Profile.V2 sFolder = sUsernameFolder & "\" & sUserProfileV2Path If FolderPath_Create( sFolder ) Then ' Management logic here, if any End If ' INHERITANCE ' Ensure that inheritance is enabled for the %username% folder and the profile folders ' If the roaming profile created the folder first, it will be off! ' WS2008 code using icacls.exe with the new /inheritance switch sCommand = "icacls """ & sUsernameFolder & """ /inheritance:e" arr = Execute_Capture(sCommand, 10, True) if arr(0) > 0 then bInheritanceError = True sCommand = "icacls """ & sUsernameFolder & "\" & sUserProfilePath & """ /inheritance:e" arr = Execute_Capture(sCommand, 10, True) If arr(0) > 0 then bInheritanceError = True sCommand = "icacls """ & sUsernameFolder & "\" & sUserProfileV2Path & """ /inheritance:e" arr = Execute_Capture(sCommand, 10, True) if arr(0) > 0 then bInheritanceError = True If bInheritanceError Then WScript.Echo "There was an error enabling inheritance using icacls.exe." & VbCrLf & VbCrLf & _ "If you are executing this script from a system that is not running" & VbCrLf & _ "Windows Server 2008 or Windows Vista SP1, then the error is expected: " & VbCrLf & _ "older versions of icacls.exe do not support the /inheritance switch." & VbCrLf & VbCrLf & _ "Once the script is complete, you must check to ensure inheritance is enabled" &VbCrLf & _ "on the following folders: " & VbCrLf & _ " - " & sUsernameFolder & VbCrLf & _ " - " & sUsernameFolder & "\Profile" & VbCrLf & _ " - " & sUsernameFolder & "\Profile.V2" & VbCrLf & VbCrLf & _ WScript.Echo End If ' PERMISSIONS AND OWNERSHIP ' We've been creating all of these folders. We need to ensure the user has full control and owns them. ' First, we give the user full control at the %username% folder. ' Inheritance should be enabled on all subfolders, allowing that permission to apply down the tree. sCommand = "icacls """ & sUsernameFolder & """ /grant " & sDomainNetBIOS &"\" & sUsername & ":(CI)(OI)F" arr = Execute_Capture(sCommand, 10, True) ' Log_Command sCommand, arr ' Then we grant ownership to the tree at the end of the routine, so we can blast ownership down with the /T switch sCommand = "icacls """ & sUsernameFolder & """ /setowner " & sDomainNetBIOS &"\" & sUsername & " /T" arr = Execute_Capture(sCommand, 10, True) ' Log_Command sCommand, arr End Sub Sub Create_DFS_Namespace() ' ===================================================================================== ' Create DFS namespace for %username% DFS folder and the user's data stores beneath it Dim sUserDFSFolder ' Define the top-level folder for the user within the DFS namespace sUserDFSFolder = sUserDFSNamespace & "\" & sUsername ' %USERNAME%\Documents sCommand = """" & DFSUTIL & """ link add " & _ sUserDFSFolder & "\" & sUserDocsDFSFolder & _ " \\" & sUserDataServer & "\" & sUserDocsShareName & _ "\" & sUsername & "\" & sUserDocsPath arr = Execute_Capture( sCommand, 10, True) Log_Command sCommand, arr ' %USERNAME%\Desktop sCommand = """" & DFSUTIL & """ link add " & _ sUserDFSFolder & "\" & sUserDesktopDFSFolder & _ " \\" & sUserDataServer & "\" & sUserDesktopShareName & _ "\" & sUsername & "\" & sUserDesktopPath arr = Execute_Capture( sCommand, 10, True) Log_Command sCommand, arr ' %USERNAME%\Favorites sCommand = """" & DFSUTIL & """ link add " & _ sUserDFSFolder & "\" & sUserFavoritesDFSFolder & _ " \\" & sUserDataServer & "\" & sUserFavoritesShareName & _ "\" & sUsername & "\" & sUserFavoritesPath arr = Execute_Capture( sCommand, 10, True) Log_Command sCommand, arr ' %USERNAME%\Music sCommand = """" & DFSUTIL & """ link add " & _ sUserDFSFolder & "\" & sUserMusicDFSFolder & _ " \\" & sUserDataServer & "\" & sUserMusicShareName & _ "\" & sUsername & "\" & sUserMusicPath arr = Execute_Capture( sCommand, 10, True) Log_Command sCommand, arr ' %USERNAME%\Pictures sCommand = """" & DFSUTIL & """ link add " & _ sUserDFSFolder & "\" & sUserPicturesDFSFolder & _ " \\" & sUserDataServer & "\" & sUserPicturesShareName & _ "\" & sUsername & "\" & sUserPicturesPath arr = Execute_Capture( sCommand, 10, True) Log_Command sCommand, arr ' %USERNAME%\Videos sCommand = """" & DFSUTIL & """ link add " & _ sUserDFSFolder & "\" & sUserVideosDFSFolder & _ " \\" & sUserDataServer & "\" & sUserVideosShareName & _ "\" & sUsername & "\" & sUserVideosPath arr = Execute_Capture( sCommand, 10, True) Log_Command sCommand, arr ' %USERNAME%\Profile sCommand = """" & DFSUTIL & """ link add " & _ sUserDFSFolder & "\" & sUserProfileDFSFolder & _ " \\" & sUserDataServer & "\" & sUserProfileShareName & _ "\" & sUsername & "\" & sUserProfilePath arr = Execute_Capture( sCommand, 10, True) Log_Command sCommand, arr ' %USERNAME%\Profile.V2 sCommand = """" & DFSUTIL & """ link add " & _ sUserDFSFolder & "\" & sUserProfileV2DFSFolder & _ " \\" & sUserDataServer & "\" & sUserProfileV2ShareName & _ "\" & sUsername & "\" & sUserProfileV2Path arr = Execute_Capture( sCommand, 10, True) Log_Command sCommand, arr ' %USERNAME%\Backups sCommand = """" & DFSUTIL & """ link add " & _ sUserDFSFolder & "\" & sUserBackupsDFSFolder & _ " \\" & sUserDataServer & "\" & sUserBackupsShareName & _ "\" & sUsername & "\" & sUserBackupsPath arr = Execute_Capture( sCommand, 10, True) Log_Command sCommand, arr ' %USERNAME% ' The root DFS folder for the user, %username%, has subfolders ' with targets but does not itself have targets. ' So it cannot be created with DFSUTIL. Instead, it is created ' when a subfoder (with a target) is created. ' Therefore, we have to wait until a subfolder has been created ' to configure the COMMENT property sCommand = """" & DFSUTIL & """ link comment set " & _ sUserDFSFolder & " """ & sUserLast & ", " & sUserFirst & """" arr = Execute_Capture( sCommand, 10, True) End Sub Sub Create_Common_Objects() Set FSO = CreateObject("Scripting.FileSystemObject") Set WSHShell = CreateObject("Wscript.Shell") End Sub Sub Check_Arguments() Dim sDFS On Error Resume Next If Right(" " & WScript.Arguments(0),1)="?" Then Call Usage() WScript.Quit(0) End If sUsernameFolder = WScript.Arguments(0) If sUsernameFolder = "" Then WScript.Echo "No parent folder provided" WScript.Quit(501) End If On Error GoTo 0 ' Check to see if we're running DFS Namespace creation mode sDFS = WScript.Arguments.Named("dfs") & " " bDFSNamespaceMode = (UCase(Left(sDFS,1))="Y") sUserDataServer = WScript.Arguments.Named("server") sUserFirst = WScript.Arguments.Named("userfirstname") sUserLast = WScript.Arguments.Named("userlastname") If (bDFSNamespaceMode And (sUserDataServer = "")) Then WScript.Echo "Cannot run in DFS Namespace creation mode: /server:<servername> argument required." WScript.Quit(501) End If ' Default for this script is quiet. Must specify /quiet:N to produce output. bQuiet = Not(UCase(Left(WScript.Arguments.Named("quiet") & " ", 1)) = "N") End Sub Sub Configuration() ' Because the definition of the namespace is such a big block of code, ' it is separated into a Sub, allowing some script editing applications ' to "collapse" the Sub for readability ' It is assumed that namespaces are consistent across systems in a ' user data and settings framework. ' SMB share namespace: ' SHARES: users$, profiles$ and backups$ ' all three shares target the same physical <root> ' Physical namespace: ' FOLDERS: <root> ' %username% ' Backups ' Data ' Documents ' Desktop ' Favorites ' Music ' Pictures ' Videos ' Profile ' Profile.V2 ' The DFS namespace is created in this structure: ' DFS: <namespace/root> ' %username% ' Backups ' Documents ' Desktop ' Favorites ' Music ' Pictures ' Profile ' Profile.V2 ' Videos ' All of the structure and assumptions above can be modified to some ' extent by changing configuration below. Also look at the code ' that *generates* the physical and DFS namespaces based on this configuration ' if you need to do further customization ' CONFIGURATION BLOCK ' The physical root (e.g. E:\Users) is assumed to already exist, since ' it only has to be created and shared one time. ' Similarly, it is assumed that the root folder has been shared as ' users$ (caching emabled), profiles$ (caching disabled), and backups$ (caching disabled) ' ' The %username% folder is passed to the script as the first argument ' and is stored in the sUsernameFolder variable ' The parent folder in the physical namespace for Documents and Desktop sUserDataPath = "Data" ' The DFS namespace within which to create the user's folders ' The DFS namespace must be created prior to running this script sUserDFSNamespace = "\\contoso.com\users" ' DFSNamespace\%username%\Documents targets \\<server>\users$\%username%\data\Documents sUserDocsDFSFolder = "Documents" sUserDocsShareName = "Users$" sUserDocsPath = "Data\Documents" ' DFSNamespace\%username%\Desktop targets \\<server>\users$\%username%\data\Desktop sUserDesktopDFSFolder = "Desktop" sUserDesktopShareName = "Users$" sUserDesktopPath = "Data\Desktop" ' DFSNamespace\%username%\Favorites targets \\<server>\users$\%username%\data\Favorites sUserFavoritesDFSFolder = "Favorites" sUserFavoritesShareName = "Users$" sUserFavoritesPath = "Data\Favorites" ' DFSNamespace\%username%\Music targets \\<server>\users$\%username%\data\Music sUserMusicDFSFolder = "Music" sUserMusicShareName = "Users$" sUserMusicPath = "Data\Music" ' DFSNamespace\%username%\Pictures targets \\<server>\users$\%username%\data\Pictures sUserPicturesDFSFolder = "Pictures" sUserPicturesShareName = "Users$" sUserPicturesPath = "Data\Pictures" ' DFSNamespace\%username%\Videos targets \\<server>\users$\%username%\data\Videos sUserVideosDFSFolder = "Videos" sUserVideosShareName = "Users$" sUserVideosPath = "Data\Videos" ' DFSNamespace\%username%\Profile targets \\<server>\profiles$\%username%\Profile sUserProfileDFSFolder = "Profile" sUserProfileShareName = "Profiles$" sUserProfilePath = "Profile" ' DFSNamespace\%username%\Profile.V2 targets \\<server>\profiles$\%username%\Profile.V2 ' this is the Windows Vista user profile folder sUserProfileV2DFSFolder = "Profile.V2" sUserProfileV2ShareName = "Profiles$" sUserProfileV2Path = "Profile.v2" ' DFSNamespace\%username%\Backups targets \\<server>\backups$\%userprofile%\Backups sUserBackupsDFSFolder = "Backups" sUserBackupsShareName = "Backups$" sUserBackupsPath = "Backups" ' Other configuration ' Your domain name sDomainNetBIOS = "CONTOSO" ' The name of the template you want applied to the user's Data folder sTemplate_UserData = "1 GB User Data Storage Limit with 100 MB Extension" ' The path to DFSUTIL.exe (include the full path if it is not in the system path) ' DFSUTIL is installed with the administrative tools for the DFS role DFSUTIL = "dfsutil.exe" End Sub Function FolderPath_Create(FolderPath) ' VERSION 070918 ' Creates a folder path specified by FolderPath ' and returns True (success) or False (failure) ' ' Recursively create a folder path ' This is an "inside out" recursion that starts with the lowest level, ' works its way "up" to the nearest ancestor that exists, then ' creates folders down from there as it works its way out of recursions ' ' INPUT: FolderPath: desired folder path ' OUTPUT: FolderPath_Create: TRUE: success ' FALSE: failure Dim bFolderExists FolderPath_Create = False On Error Resume Next bFolderExists = FSO.FolderExists(FolderPath) If Err.Number <> 0 Then ' This handles scenarios where a sharename in a UNC doesn't exist. ' I was getting Out of Memory errors on the FolderExists method. FolderPath_Create = False Exit Function End If If Not bFolderExists Then ' If the folder doesn't exist already, test its parent ' (RECURSIVE CALL TO SELF) If FolderPath_Create(FSO.GetParentFolderName(FolderPath)) Then ' Create the folder FolderPath_Create = True Call FSO.CreateFolder(FolderPath) End If Else ' This level of folder does exist FolderPath_Create = True End If End Function Function Execute_Capture(ByVal sCommand, ByVal iTimeout, ByVal bTerminate) ' VERSION 070918 ' Executes command in sCommand ' Times out after iTimeout and (optionally) terminates the process ' Returns exit code, StdOut & StdErr ' ' INPUTS: sCommand: Command to run ' iTimeout: Time (in seconds) to wait for process ' bTerminate: TRUE = terminate process after timeout ' FALSE = return from function ' RETURNS: Execute_Capture: *ARRAY* ' (0): Exit code of command ' 0.01 = timed out but NOT terminated ' 0.99 = timed out and TERMINATED ' (1): StdOut ' (2): StdErr Dim oExec, iTimer, iExitCode, sOut, sErr Set oExec = WSHShell.Exec(sCommand) iTimer = 0 Do While oExec.Status = 0 WScript.Sleep 100 iTimer = iTimer + 100 If (iTimer/1000) > iTimeout Then Exit Do Loop If oExec.Status = 0 Then ' Not completed, but timed out If bTerminate Then ' Terminate oExec.Terminate iExitCode = 0.99 Else ' Timeout but do not terminate iExitCode = 0.01 End If Else ' Completed iExitCode = oExec.ExitCode End If sOut = oExec.StdOut.ReadAll sErr = oExec.StdErr.ReadAll Execute_Capture = Array(iExitCode, sOut, sErr) End Function Sub Log_Command(ByVal sCommand, arr) If Not bQuiet And arr(0) <> 0 Then WScript.Echo String(80,"-") WScript.Echo sCommand WScript.Echo "Exit Code: " & arr(0) WScript.Echo "STD OUT" WScript.Echo arr(1) WScript.Echo "STD ERR" WScript.Echo arr(2) WScript.Echo String(80,"-") WScript.Echo VbCrLf End If End Sub Sub Usage() WScript.Echo "UDS_UserFolders_Extended_Provision_DFS" WScript.Echo "======================================" WScript.Echo "Create user data stores and" WScript.Echo "fully-enumerated DFS namespace for a user." WScript.Echo WScript.Echo "USAGE:" WScript.Echo " cscript.exe UDS_UserFolders_Extended_Provision_DFS.vbs" WScript.Echo " UserFolderPath" WScript.Echo " [/DFS:Y /server:<servername>" WScript.Echo " /userfirstname:<first name> /userlastname:<last name>]" WScript.Echo "WHERE:" WScript.Echo WScript.Echo "UserFolderPath" WScript.Echo "--------------" WScript.Echo "Full local or network path to a user's folder," WScript.Echo "e.g. E:\Users\jfine or \\server01\users$\jfine." WScript.Echo "The user's folder will be created if it does not already exist." WScript.Echo "It is assumed that the last folder in the path (e.g. jfine) is the user's" WScript.Echo "pre-Windows 2000 Logon Name. That account must already exist. It is given" WScript.Echo "ownership and Full Control of the folder" WScript.Echo WScript.Echo "/DFS:Y" WScript.Echo "Create a fully enumerated DFS namespace for the user." WScript.Echo "If running in this mode, you also must provide these parameters:" WScript.Echo WScript.Echo "/server:<servername> Server on which the user's data is located" WScript.Echo "/userfirstname:<first name> User's first name" WScript.Echo "/userlastname:<last name> User's last name" WScript.Echo WScript.Echo "In DFS namespace mode, the DFSUTIL command must be in the system path" WScript.Echo "(%PATH%, e.g. System32). DFSUTIL is installed by the DFS admin tools." WScript.Echo WScript.Echo "Run the script from a Windows Vista SP1 or Windows Server 2008 system." WScript.Echo WScript.Echo "Run locally on a Windows Server 2008 server as an adminsitrator." WScript.Echo "-or-" WScript.Echo "Run remotely gainst a Windows Server 2008 or Windows Server 2003 system" WScript.Echo "as a user with sufficient NTFS permissions to create the folders," WScript.Echo "DFS namespace delegation to create the DFS namespace, and the" WScript.Echo "Restore Files And Directories user right to transfer ownership." End Sub Now I want to modify it so that the videos, pictures and music go to different drives and folders than the rest. I would like to have the same structure on those folders though. Where U:\Users\%username%\ would hold the documents and others, I would like it to automatically put Videos in I:\Videos\%username%\videos, and the others in the same structure. This would all be unnoticable to the user since DFS would take care of the rest. Any one know how?
Recommended Posts