Thursday, September 15, 2011

Change file shares via scripting

I've come across a problem where users are filling up their hard disks and we need to move the highest utilization users to a new disk. In order to accomplish this I've setup a robocopy to move their files to a new disk and have it constantly mirrored until after-hours; where we run this script to move the file shares:


:backup original shares:
reg export "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\lanmanserver\Shares" C:\shares-backup.reg /y

setlocal enabledelayedexpansion
:what we need to do is grab the user name and the key...
for /f "tokens=1-2*" %%A IN ('reg query "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\lanmanserver\Shares" ^| findstr /I /C:"E:\User Files\Corporate" ^| sed.exe "s/Path=E:\\User Files\\Corporate/Path=G:\\User Files\\Corporate/"') DO (
echo reg add HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\lanmanserver\Shares /v %%A /t %%B /D "%%C" /f
)

for /f "tokens=1-2*" %%A IN ('reg query "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\lanmanserver\Shares" ^| findstr /I /C:"E:\User Files\Finance" ^| sed.exe "s/Path=E:\\User Files\\Finance/Path=G:\\User Files\\Finance/"') DO (
echo reg add HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\lanmanserver\Shares /v %%A /t %%B /D "%%C" /f
)

net stop server /y
net start server


What this script does is:
1) Backs up the existing share structure
2) Queries the file shares for the specific path of the share we're going to move
3) Using SED.exe we change the drive letter from E: to G:
4) Using reg.exe we overwrite the registry key with the new value
5) we then stop and restart the server service to get the new shares working.

And we set that up as a scheduled task to run after-hours :)

Tuesday, September 13, 2011

Saving and restoring ACL's on OU's

Saving and moving OU ACLs

I’ve written a batch file that will move ACLs from one OU to another. It works by you outputting the results of a ACL from a OU to a text file, specifying the new OU in a batch file and inputting the text file you just created. I use three utilities to accomplish this: adfind.exe, sed.exe and dsacls.exe.
The command to save the text file is:

adfind -b "OU=Users,OU=LAB,DC=LAB,DC=CORP" -f (distinguishedName=OU=Users,OU=LAB,DC=LAB,DC=corp) -sddl++ -resolvesids -onlydacl ntsecuritydescriptor -sddlnotfilter ;inherited| sed.exe "s/;;/; ;/g" | sed.exe "s/;;/; ;/g" | sed.exe "s/;;/; ;/g" | sed.exe "s/;;/; ;/g" > %PATHTOFILE%.txt


From here, you need to delete the header in the text file and the footer.
Once that is done, run this script, changing the two variables at the top:


:RESTORE-OU-ACL.CMD
:Restore OU Properties
SET TARGETOU=OU=Users Accounts,OU=AD Project 3,DC=LAB,DC=CORP
SET TARGETFILE="New Text Document (5).txt"

@ECHO OFF

SETLOCAL ENABLEDELAYEDEXPANSION
for /F "tokens=1-6 delims=;" %%A IN ('type %TARGETFILE%') DO (
SET PROP=
SET INHERIT=0
IF "%%C" EQU " " SET PROP=GA
ECHO CALL :PROPERTYACL %%C
CALL :PROPERTYACL %%C

ECHO CALL :INHERITANCE %%B
CALL :INHERITANCE %%B

SET PROPERTY=
IF /I "%%D" NEQ " " SET PROPERTY=%%D
ECHO PROPERTY=!PROPERTY!
SET TARGET=
IF /I "%%E" NEQ " " SET TARGET=%%E
ECHO TARGET=!TARGET!
ECHO dsacls "%TARGETOU%" !INHERIT! /G "%%F:!PROP!;!PROPERTY!;!TARGET!"
dsacls "%TARGETOU%" !INHERIT! /G "%%F:!PROP!;!PROPERTY!;!TARGET!"

)
GOTO:EOF

:INHERITANCE
REM We need to figure out what ACLS we're dealing with...
FOR /F "tokens=*" %%Z IN ('ECHO %*') DO (
IF '!INHERIT!' EQU '/I:S' GOTO:EOF
ECHO %%Z | FINDSTR /I /C:"[CONT INHERIT]"
IF '!ERRORLEVEL!' EQU '0' SET INHERIT=/I:T
ECHO %%Z | FINDSTR /I /C:"[CONT INHERIT][INHERIT ONLY]"
IF '!ERRORLEVEL!' EQU '0' SET INHERIT=/I:S
ECHO %%Z | FINDSTR /I /C:"INHERIT"
IF '!ERRORLEVEL!' EQU '1' SET INHERIT=/I:P
ECHO INHERIT=!INHERIT!
)
GOTO:EOF

:PROPERTYACL
REM We need to figure out what ACLS we're dealing with...
FOR /F "tokens=*" %%Z IN ('ECHO %*') DO (
ECHO %%Z | FINDSTR /I /C:"WRT PROP"
IF '!ERRORLEVEL!' EQU '0' SET PROP=!PROP!WP
ECHO %%Z | FINDSTR /I /C:"READ PROP"
IF '!ERRORLEVEL!' EQU '0' SET PROP=!PROP!RP
ECHO %%Z | FINDSTR /I /C:"CTL"
IF '!ERRORLEVEL!' EQU '0' SET PROP=CA
ECHO %%Z | FINDSTR /I /C:"[CR CHILD]"
IF '!ERRORLEVEL!' EQU '0' SET PROP=!PROP!CC
ECHO %%Z | FINDSTR /I /C:"[DEL CHILD]"
IF '!ERRORLEVEL!' EQU '0' SET PROP=!PROP!DC
ECHO %%Z | FINDSTR /I /C:"[LIST CHILDREN]"
IF '!ERRORLEVEL!' EQU '0' SET PROP=!PROP!LC
ECHO %%Z | FINDSTR /I /C:"[LIST OBJECT]"
IF '!ERRORLEVEL!' EQU '0' SET PROP=!PROP!LO
ECHO %%Z | FINDSTR /I /C:"[READ]"
IF '!ERRORLEVEL!' EQU '0' SET PROP=!PROP!GR
ECHO %%Z | FINDSTR /I /C:"[FC]"
IF '!ERRORLEVEL!' EQU '0' SET PROP=!PROP!GA

ECHO PROP=!PROP!
)
GOTO:EOF

:/I:P = This Object Only *BLANK*
:/I:S = Child Objects Only [CONT INERIT][INHERIT ONLY]
:/I:T = This object and all child objects [CONT INERIT]
:Blank inheritance = /I:P
:When "Properties" are set, it should be /I:S
:When there are no properties listed at all ACL should be GA

Friday, August 26, 2011

Issue with WSH (Scripting.FileSystemObject 800A01AD)



I recently had a Windows 2008 Server that was unable to execute a VBS script that works with other servers and other combinations of desktops. I decided to break out Process Monitor and try and see if I can figure out what's going on...

To simplify this process, I found this vbs script that trys to utilize the Scripting.FileSystemObject in a script:

cscript Version.vbs

The VBScript program follows:
Option Explicit

Dim objFSO, strFolder

Call MsgBox("WSH Version: " & Wscript.Version _
& vbCrLF & "VBScript major version: " & ScriptEngineMajorVersion _
& vbCrLf & "VBScript minor version: " & ScriptEngineMinorVersion)

strFolder = "C:\Windows"

Set objFSO = CreateObject("Scripting.FileSystemObject")
If (objFSO.FolderExists(strFolder) = True) Then
Call MsgBox("Folder " & strFolder & " exists" _
& vbCrLf & "and the FileSystemObject works fine")
Else
Call MsgBox("Folder " & strFolder & " does NOT exists" _
& vbCrLf & "but the FileSystemObject works fine")
End If



I ran that script on the affected server and, after clicking OK on the WSH Version dialog, I got this message:



I broke out Process Monitor and monitored on the File System. It sounds like it should be a file system error so we'll scope that out first. I filtered for everything but wscript.exe (I executed all my command lines as wscript.exe test.vbs) and nothing appeared. So wscript.exe wasn't even getting to the file system. So I enabled registry filtering and filtered for wscript.exe:


And I reran the script and got this result:



From here I went to another Windows 2008 server and added the missing registry keys (NAME NOT FOUND) and repeated the process again, finding more keys until all were added to the non-functioning server.

I ended up adding the following registry keys:

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Scripting.FileSystemObject]
@="FileSystem Object"

[HKEY_CLASSES_ROOT\Scripting.FileSystemObject\CLSID]
@="{0D43FE01-F093-11CF-8940-00A0C9054228}"

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{0D43FE01-F093-11CF-8940-00A0C9054228}]
@="FileSystem Object"

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{0D43FE01-F093-11CF-8940-00A0C9054228}\InprocServer32]
@="C:\\Windows\\SysWOW64\\scrrun.dll"
"ThreadingModel"="Both"

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{0D43FE01-F093-11CF-8940-00A0C9054228}\ProgID]
@="Scripting.FileSystemObject"

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{0D43FE01-F093-11CF-8940-00A0C9054228}\TypeLib]
@="{420B2830-E718-11CF-893D-00A0C9054228}"

[HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{0D43FE01-F093-11CF-8940-00A0C9054228}\Version]
@="1.0"

[HKEY_CLASSES_ROOT\Wow6432Node\TypeLib\{420B2830-E718-11CF-893D-00A0C9054228}]

[HKEY_CLASSES_ROOT\Wow6432Node\TypeLib\{420B2830-E718-11CF-893D-00A0C9054228}\1.0]
@="Microsoft Scripting Runtime"

[HKEY_CLASSES_ROOT\Wow6432Node\TypeLib\{420B2830-E718-11CF-893D-00A0C9054228}\1.0\0]

[HKEY_CLASSES_ROOT\Wow6432Node\TypeLib\{420B2830-E718-11CF-893D-00A0C9054228}\1.0\0\win32]
@="C:\\Windows\\SysWOW64\\scrrun.dll"

[HKEY_CLASSES_ROOT\Wow6432Node\TypeLib\{420B2830-E718-11CF-893D-00A0C9054228}\1.0\0\win64]
@="C:\\Windows\\system32\\scrrun.dll"

[HKEY_CLASSES_ROOT\Wow6432Node\TypeLib\{420B2830-E718-11CF-893D-00A0C9054228}\1.0\FLAGS]
@="0"

[HKEY_CLASSES_ROOT\Wow6432Node\TypeLib\{420B2830-E718-11CF-893D-00A0C9054228}\1.0\HELPDIR]
@="C:\\Windows\\system32"


For some reason, it is launching the Wscript.exe in a 32bit process (as evidenced by WOW6432Node key). On the working 64bit server I have it is running as a 64bit process.

After entering those registry keys, here is my new result.


Success! Hopefully, if you encounter the same issue, you are not missing any more, or too many more, registry keys. I wonder why they disappeared, but I don't have a way to trace that unfortunately.

Wednesday, August 24, 2011

Awesome AD blog and post

I've only viewed a few AD posts on this blog but this is fantastic.

http://blogs.technet.com/b/lrobins/archive/2011/06/23/quot-admin-free-quot-active-directory-part-2-protected-accounts-and-groups-in-active-directory.aspx

from Laura Robins that discusses minimizing privledges.

Tuesday, August 23, 2011

Watch the folder redirect log live

If you've enabled the folder redirect log, you can watch it on a remote computer using the tail command and SED.exe.

Currently, the fdeploy.log (for XP anyways) stores the log as a binary file with a NULL character between each character. To clean up this output you can pipe tail.exe into sed and tell sed to delete the NULL characters...



To:



The command to watch it is now:
tail -f \\gkwngq1\c$\WINDOWS\Debug\UserMode\fdeploy.log | sed "s/\x00//g"

Cool.