Solved

Upgrading normal.dotm in a mixed environment

Posted on 2011-03-24
17
2,696 Views
Last Modified: 2012-05-11
I am putt ing challenge out there.

Environment: 2K AD, XP and Windows 7

Problem: I would greatly appreciate it, if someone could assist me with creating a script to
copy the normal.dotm file from a network share, copy it to a temp directory on the users
local computer. The script would then need to look to see if the
normal.dotm file exists in either of these two locations :-

FOR XP
C:\Documents and Settings\UserName\Application Data\Microsoft\Templates

FOR WINDOWS 7
AppData\Roaming\Microsoft\Templates

If normal.dotm exists in either of those locations it would need to be renamed to normal.bak and then
copy the new file to either location. I was hoping to acheive this without using a login script. I was
hoping that That script would reference a text file with a list of the computers that the file has to
be copied too. The idea was to run it as a scheduled task and have the script log to either a
success.txt or failed.txt depending on the returned result. Could anyone please help me with this.

*** I can't use powershell as it doesn't exist within the domain***

Thanks very much ;)
0
Comment
Question by:MuddyOz
  • 8
  • 7
  • 2
17 Comments
 
LVL 5

Accepted Solution

by:
xylog earned 250 total points
ID: 35212373
for /f %%i in (list-of-computers.txt) do call goreplace %%i
goto :EOF

:goreplace
if exist "\\%1\c$\documents and settings" for /f  %%u in ('dir "\\%1\c$\documents and settings\" /ad /b') do if exist "\\%1\c$\Documents and Settings\%%u\Application Data\Microsoft\Templates\normal.dotm" ren "\\%1\c$\Documents and Settings\%%u\Application Data\Microsoft\Templates\normal.dotm" normal.bak && copy \\server\share\normal.dorm "\\%1\c$\Documents and Settings\%%u\Application Data\Microsoft\Templates\normal.dotm"

if exist "\\%1\c$\users" for /f "tokens=*" %%u in ('dir "\\%1\c$\users\" /ad  /b' ) do if exist "\\%1\c$\users\%%u\AppData\Roaming\Microsoft\Templates\normal.dotm" ren "\\%1\c$\users\%%u\AppData\Roaming\Microsoft\Templates\normal.dotm" normal.bak && copy \\server\share\normal.dorm "\\%1\c$\user\%%u\AppData\Roaming\Microsoft\Templates\normal.dotm"



0
 
LVL 65

Assisted Solution

by:RobSampson
RobSampson earned 250 total points
ID: 35212467
Hi, try this.  We use this to copy a new version of the Normal.dotm template if we change it later, based on the modified date of the file.  It does need to be run as a logon script through (or manually by each user), and it doesn't log anything.

Regards,

Rob.
Set objShell = CreateObject("WScript.Shell")
strSource = "\\server\share\newtemplate\normal.dotm"
strDestination = objShell.ExpandEnvironmentStrings("%APPDATA%") & "\Microsoft\Templates"

If Right(strDestination, 1) = "\" Then strDestination = Left(strDestination, Len(strDestination) - 1)
strOldTemplates = ""
bool2007TemplateExists = False
' This section renames any Word 2000 templates from .dot to .dot_bak
For Each objFile In objFSO.GetFolder(strDestination).Files
	If LCase(objFile.Name) = "normal.dotm" Then bool2007TemplateExists = True
	If Right(LCase(objFile.Name), 4) = ".dot" Then
		If strOldTemplates = "" Then
			strOldTemplates = objFile.Path
		Else
			strOldTemplates = strOldTemplates & ";" & objFile.Path
		End If
	End If
Next
arrOldTemplates = Split(strOldTemplates, ";")
For Each strTemplatePath In arrOldTemplates
	If objFSO.FileExists(strTemplatePath & "_bak") = True Then objFSO.DeleteFile strTemplatePath & "_bak"
	objFSO.MoveFile strTemplatePath, strTemplatePath & "_bak"
Next

' This section will copy the template if it doesn't exist in the destination
If bool2007TemplateExists = False Then
	If objFSO.FileExists(strSource) = True Then objFSO.CopyFile strSource, strDestination & "\", True
Else
	' This can control the ability to copy a new version of the normal template to each users' templates folder.
	' Set boolCopyNewNormal to False to prevent copying a new version (based on modified date)
	boolCopyNewNormal = True
	If boolCopyNewNormal = True Then
		If objFSO.FileExists(strSource) = True Then
			If CDate(objFSO.GetFile(strSource).DateLastModified) > CDate(objFSO.GetFile(strDestination & "\Normal.dotm").DateLastModified) Then
				intBkpNum = 1
				While objFSO.FileExists(strDestination & "\Normal.dotm_bak" & intBkpNum) = True
					intBkpNum = intBkpNum + 1
				Wend
				objFSO.MoveFile strDestination & "\Normal.dotm", strDestination & "\Normal.dotm_bak" & intBkpNum
				objFSO.CopyFile strSource, strDestination & "\", True
			End If
		End If
	End If
End If

Open in new window

0
 

Author Comment

by:MuddyOz
ID: 35212724
Guys,

Thanks a bunch for your help. I am off work today but when I return I will test and report back. Thanks very much for the prompt reply.
0
 
LVL 5

Expert Comment

by:xylog
ID: 35215286
Missing a colon in the first line, should be:

for /f %%i in (list-of-computers.txt) do call :goreplace %%i

0
 

Author Comment

by:MuddyOz
ID: 35220447
xyloh and ROb,

How could we get a pass of fail result to a txt file when it runs? Could you please help?

Awesome job, Guys!

Muddy
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 35236574
In my code, to record pass and fail (only when actually trying to copy the file if a new one was detected), use this code.

Regards,

Rob.
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("WScript.Shell")
Set objNetwork = CreateObject("WScript.Network")
strSource = "\\server\share\newtemplate\normal.dotm"
strSuccess = "\\server\share\newtemplate\success.txt"
strFail = "\\server\share\newtemplate\fail.txt"
strDestination = objShell.ExpandEnvironmentStrings("%APPDATA%") & "\Microsoft\Templates"

If Right(strDestination, 1) = "\" Then strDestination = Left(strDestination, Len(strDestination) - 1)
strOldTemplates = ""
bool2007TemplateExists = False
' This section renames any Word 2000 templates from .dot to .dot_bak
For Each objFile In objFSO.GetFolder(strDestination).Files
	If LCase(objFile.Name) = "normal.dotm" Then bool2007TemplateExists = True
	If Right(LCase(objFile.Name), 4) = ".dot" Then
		If strOldTemplates = "" Then
			strOldTemplates = objFile.Path
		Else
			strOldTemplates = strOldTemplates & ";" & objFile.Path
		End If
	End If
Next
arrOldTemplates = Split(strOldTemplates, ";")
For Each strTemplatePath In arrOldTemplates
	If objFSO.FileExists(strTemplatePath & "_bak") = True Then objFSO.DeleteFile strTemplatePath & "_bak"
	objFSO.MoveFile strTemplatePath, strTemplatePath & "_bak"
Next

' This section will copy the template if it doesn't exist in the destination
If bool2007TemplateExists = False Then
	If objFSO.FileExists(strSource) = True Then
		On Error Resume Next
		objFSO.CopyFile strSource, strDestination & "\", True
		If Err.Number = 0 Then
			strCopyError = ""
		Else
			strCopyError = "Error " & Err.Number & ": " & Err.Description
		End If
		Err.Clear
		On Error GoTo 0
	End If
Else
	' This can control the ability to copy a new version of the normal template to each users' templates folder.
	' Set boolCopyNewNormal to False to prevent copying a new version (based on modified date)
	boolCopyNewNormal = True
	If boolCopyNewNormal = True Then
		If objFSO.FileExists(strSource) = True Then
			If CDate(objFSO.GetFile(strSource).DateLastModified) > CDate(objFSO.GetFile(strDestination & "\Normal.dotm").DateLastModified) Then
				intBkpNum = 1
				While objFSO.FileExists(strDestination & "\Normal.dotm_bak" & intBkpNum) = True
					intBkpNum = intBkpNum + 1
				Wend
				On Error Resume Next
				objFSO.MoveFile strDestination & "\Normal.dotm", strDestination & "\Normal.dotm_bak" & intBkpNum
				objFSO.CopyFile strSource, strDestination & "\", True
				If Err.Number = 0 Then
					strCopyError = ""
				Else
					strCopyError = "Error " & Err.Number & ": " & Err.Description
				End If
				Err.Clear
				On Error GoTo 0
			End If
		End If
	End If
End If

If strCopyError = "" Then
	Set objResult = objFSO.OpenTextFile(strSuccess, 8, True)
	objResult.WriteLine Now & " - " & objNetwork.ComputerName & ": " & objNetwork.UserName
	objResult.Close
	Set objResult = Nothing
Else
	Set objResult = objFSO.OpenTextFile(strFail, 8, True)
	objResult.WriteLine Now & " - " & objNetwork.ComputerName & ": " & objNetwork.UserName & " - " & strCopyError
	objResult.Close
	Set objResult = Nothing
End If

Open in new window

0
 

Author Comment

by:MuddyOz
ID: 35339396
Hey Rob,

That script works perfectly mate Well done. Is there anyway that we can get it to do this to a list of computers supplied in a text file? The problem is that I am having is that, there are terminal servers (old 2k) that the application data folder doesn't exist and hence pops an error box up at the user.

Thanksmate.
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 35339405
Is it easier to specify computers that it *shouldn't* run on?  Or, is it easier to just do nothing if the strDestination folder doesn't exist, like so:

Rob.
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("WScript.Shell")
Set objNetwork = CreateObject("WScript.Network")
strSource = "\\server\share\newtemplate\normal.dotm"
strSuccess = "\\server\share\newtemplate\success.txt"
strFail = "\\server\share\newtemplate\fail.txt"
strDestination = objShell.ExpandEnvironmentStrings("%APPDATA%") & "\Microsoft\Templates"

If objFSO.FolderExists(strDestination) = True Then
	If Right(strDestination, 1) = "\" Then strDestination = Left(strDestination, Len(strDestination) - 1)
	strOldTemplates = ""
	bool2007TemplateExists = False
	' This section renames any Word 2000 templates from .dot to .dot_bak
	For Each objFile In objFSO.GetFolder(strDestination).Files
		If LCase(objFile.Name) = "normal.dotm" Then bool2007TemplateExists = True
		If Right(LCase(objFile.Name), 4) = ".dot" Then
			If strOldTemplates = "" Then
				strOldTemplates = objFile.Path
			Else
				strOldTemplates = strOldTemplates & ";" & objFile.Path
			End If
		End If
	Next
	arrOldTemplates = Split(strOldTemplates, ";")
	For Each strTemplatePath In arrOldTemplates
		If objFSO.FileExists(strTemplatePath & "_bak") = True Then objFSO.DeleteFile strTemplatePath & "_bak"
		objFSO.MoveFile strTemplatePath, strTemplatePath & "_bak"
	Next
	
	' This section will copy the template if it doesn't exist in the destination
	If bool2007TemplateExists = False Then
		If objFSO.FileExists(strSource) = True Then
			On Error Resume Next
			objFSO.CopyFile strSource, strDestination & "\", True
			If Err.Number = 0 Then
				strCopyError = ""
			Else
				strCopyError = "Error " & Err.Number & ": " & Err.Description
			End If
			Err.Clear
			On Error GoTo 0
		End If
	Else
		' This can control the ability to copy a new version of the normal template to each users' templates folder.
		' Set boolCopyNewNormal to False to prevent copying a new version (based on modified date)
		boolCopyNewNormal = True
		If boolCopyNewNormal = True Then
			If objFSO.FileExists(strSource) = True Then
				If CDate(objFSO.GetFile(strSource).DateLastModified) > CDate(objFSO.GetFile(strDestination & "\Normal.dotm").DateLastModified) Then
					intBkpNum = 1
					While objFSO.FileExists(strDestination & "\Normal.dotm_bak" & intBkpNum) = True
						intBkpNum = intBkpNum + 1
					Wend
					On Error Resume Next
					objFSO.MoveFile strDestination & "\Normal.dotm", strDestination & "\Normal.dotm_bak" & intBkpNum
					objFSO.CopyFile strSource, strDestination & "\", True
					If Err.Number = 0 Then
						strCopyError = ""
					Else
						strCopyError = "Error " & Err.Number & ": " & Err.Description
					End If
					Err.Clear
					On Error GoTo 0
				End If
			End If
		End If
	End If
	
	If strCopyError = "" Then
		Set objResult = objFSO.OpenTextFile(strSuccess, 8, True)
		objResult.WriteLine Now & " - " & objNetwork.ComputerName & ": " & objNetwork.UserName
		objResult.Close
		Set objResult = Nothing
	Else
		Set objResult = objFSO.OpenTextFile(strFail, 8, True)
		objResult.WriteLine Now & " - " & objNetwork.ComputerName & ": " & objNetwork.UserName & " - " & strCopyError
		objResult.Close
		Set objResult = Nothing
	End If
End If

Open in new window

0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 

Author Comment

by:MuddyOz
ID: 35339415
Hey Rob,


Well it would be easier to supply a list NOT to run on. The reason for this is that there are only say 6 servers (assets) that don't need this. Is the above script suitable to use for this?

Scott.
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 35339437
No, I didn't provide the list in the above, but I can....probably just in an array in the script itself....that way you don't have a separate text file.

Rob.
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("WScript.Shell")
Set objNetwork = CreateObject("WScript.Network")
strSource = "\\server\share\newtemplate\normal.dotm"
strSuccess = "\\server\share\newtemplate\success.txt"
strFail = "\\server\share\newtemplate\fail.txt"
strDestination = objShell.ExpandEnvironmentStrings("%APPDATA%") & "\Microsoft\Templates"
arrServersToSkip = Array("Server1", "Server2", "Server3", "Server4", "Server5", "Server6")

blnSkip = False
For Each strServer In strServersToSkip
	If UCase(strServer) = UCase(objNetwork.Hostname) Then blnSkip = True
Next

If blnSkip = False Then
	If objFSO.FolderExists(strDestination) = True Then
		If Right(strDestination, 1) = "\" Then strDestination = Left(strDestination, Len(strDestination) - 1)
		strOldTemplates = ""
		bool2007TemplateExists = False
		' This section renames any Word 2000 templates from .dot to .dot_bak
		For Each objFile In objFSO.GetFolder(strDestination).Files
			If LCase(objFile.Name) = "normal.dotm" Then bool2007TemplateExists = True
			If Right(LCase(objFile.Name), 4) = ".dot" Then
				If strOldTemplates = "" Then
					strOldTemplates = objFile.Path
				Else
					strOldTemplates = strOldTemplates & ";" & objFile.Path
				End If
			End If
		Next
		arrOldTemplates = Split(strOldTemplates, ";")
		For Each strTemplatePath In arrOldTemplates
			If objFSO.FileExists(strTemplatePath & "_bak") = True Then objFSO.DeleteFile strTemplatePath & "_bak"
			objFSO.MoveFile strTemplatePath, strTemplatePath & "_bak"
		Next
		
		' This section will copy the template if it doesn't exist in the destination
		If bool2007TemplateExists = False Then
			If objFSO.FileExists(strSource) = True Then
				On Error Resume Next
				objFSO.CopyFile strSource, strDestination & "\", True
				If Err.Number = 0 Then
					strCopyError = ""
				Else
					strCopyError = "Error " & Err.Number & ": " & Err.Description
				End If
				Err.Clear
				On Error GoTo 0
			End If
		Else
			' This can control the ability to copy a new version of the normal template to each users' templates folder.
			' Set boolCopyNewNormal to False to prevent copying a new version (based on modified date)
			boolCopyNewNormal = True
			If boolCopyNewNormal = True Then
				If objFSO.FileExists(strSource) = True Then
					If CDate(objFSO.GetFile(strSource).DateLastModified) > CDate(objFSO.GetFile(strDestination & "\Normal.dotm").DateLastModified) Then
						intBkpNum = 1
						While objFSO.FileExists(strDestination & "\Normal.dotm_bak" & intBkpNum) = True
							intBkpNum = intBkpNum + 1
						Wend
						On Error Resume Next
						objFSO.MoveFile strDestination & "\Normal.dotm", strDestination & "\Normal.dotm_bak" & intBkpNum
						objFSO.CopyFile strSource, strDestination & "\", True
						If Err.Number = 0 Then
							strCopyError = ""
						Else
							strCopyError = "Error " & Err.Number & ": " & Err.Description
						End If
						Err.Clear
						On Error GoTo 0
					End If
				End If
			End If
		End If
		
		If strCopyError = "" Then
			Set objResult = objFSO.OpenTextFile(strSuccess, 8, True)
			objResult.WriteLine Now & " - " & objNetwork.ComputerName & ": " & objNetwork.UserName
			objResult.Close
			Set objResult = Nothing
		Else
			Set objResult = objFSO.OpenTextFile(strFail, 8, True)
			objResult.WriteLine Now & " - " & objNetwork.ComputerName & ": " & objNetwork.UserName & " - " & strCopyError
			objResult.Close
			Set objResult = Nothing
		End If
	End If
End If

Open in new window

0
 

Author Comment

by:MuddyOz
ID: 35339448
Oh ok. How would I specify the comuter and or servers that I don't want this file copied too?
0
 

Author Comment

by:MuddyOz
ID: 35339453
Rob,

I'm an idoit, I should of read the script first. Please excuse my stupidity :)

thank you so much!
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 35339454
In the code above, see this line:
arrServersToSkip = Array("Server1", "Server2", "Server3", "Server4", "Server5", "Server6")

Just specify as many servers as you need, and if the current computer is one of those, nothing will happen.

Regards,

Rob.
0
 

Author Comment

by:MuddyOz
ID: 35347421
Hey Rob,

Using that script with specifing the servers I get the following error -

Error Line 11
Char: 1
Object not a collection

Line 11 in my code is the follwoing -

For Each arrServersToskip In strServersToSkip

Where is the string for the servers? Thats what it seems to be complaining about.

Thanks mate

Scott.
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 35347446
Argh! That's embarrassing!  Change that to
For Each strServer In arrServersToSkip

Regards,

Rob.
0
 

Author Comment

by:MuddyOz
ID: 35347571
Hey Rob,

I get a new error saying that 'objNetwork.Hostname' do you know how I can fix this error Rob?

Scott.
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 35347630
Oh, sorry again...I must have been tired....that should be objNetwork.ComputerName

Regards,

Rob.
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("WScript.Shell")
Set objNetwork = CreateObject("WScript.Network")
strSource = "\\server\share\newtemplate\normal.dotm"
strSuccess = "\\server\share\newtemplate\success.txt"
strFail = "\\server\share\newtemplate\fail.txt"
strDestination = objShell.ExpandEnvironmentStrings("%APPDATA%") & "\Microsoft\Templates"
arrServersToSkip = Array("Server1", "Server2", "Server3", "Server4", "Server5", "Server6")

blnSkip = False
For Each strServer In arrServersToSkip
	If UCase(strServer) = UCase(objNetwork.ComputerName) Then blnSkip = True
Next

If blnSkip = False Then
	If objFSO.FolderExists(strDestination) = True Then
		If Right(strDestination, 1) = "\" Then strDestination = Left(strDestination, Len(strDestination) - 1)
		strOldTemplates = ""
		bool2007TemplateExists = False
		' This section renames any Word 2000 templates from .dot to .dot_bak
		For Each objFile In objFSO.GetFolder(strDestination).Files
			If LCase(objFile.Name) = "normal.dotm" Then bool2007TemplateExists = True
			If Right(LCase(objFile.Name), 4) = ".dot" Then
				If strOldTemplates = "" Then
					strOldTemplates = objFile.Path
				Else
					strOldTemplates = strOldTemplates & ";" & objFile.Path
				End If
			End If
		Next
		arrOldTemplates = Split(strOldTemplates, ";")
		For Each strTemplatePath In arrOldTemplates
			If objFSO.FileExists(strTemplatePath & "_bak") = True Then objFSO.DeleteFile strTemplatePath & "_bak"
			objFSO.MoveFile strTemplatePath, strTemplatePath & "_bak"
		Next
		
		' This section will copy the template if it doesn't exist in the destination
		If bool2007TemplateExists = False Then
			If objFSO.FileExists(strSource) = True Then
				On Error Resume Next
				objFSO.CopyFile strSource, strDestination & "\", True
				If Err.Number = 0 Then
					strCopyError = ""
				Else
					strCopyError = "Error " & Err.Number & ": " & Err.Description
				End If
				Err.Clear
				On Error GoTo 0
			End If
		Else
			' This can control the ability to copy a new version of the normal template to each users' templates folder.
			' Set boolCopyNewNormal to False to prevent copying a new version (based on modified date)
			boolCopyNewNormal = True
			If boolCopyNewNormal = True Then
				If objFSO.FileExists(strSource) = True Then
					If CDate(objFSO.GetFile(strSource).DateLastModified) > CDate(objFSO.GetFile(strDestination & "\Normal.dotm").DateLastModified) Then
						intBkpNum = 1
						While objFSO.FileExists(strDestination & "\Normal.dotm_bak" & intBkpNum) = True
							intBkpNum = intBkpNum + 1
						Wend
						On Error Resume Next
						objFSO.MoveFile strDestination & "\Normal.dotm", strDestination & "\Normal.dotm_bak" & intBkpNum
						objFSO.CopyFile strSource, strDestination & "\", True
						If Err.Number = 0 Then
							strCopyError = ""
						Else
							strCopyError = "Error " & Err.Number & ": " & Err.Description
						End If
						Err.Clear
						On Error GoTo 0
					End If
				End If
			End If
		End If
		
		If strCopyError = "" Then
			Set objResult = objFSO.OpenTextFile(strSuccess, 8, True)
			objResult.WriteLine Now & " - " & objNetwork.ComputerName & ": " & objNetwork.UserName
			objResult.Close
			Set objResult = Nothing
		Else
			Set objResult = objFSO.OpenTextFile(strFail, 8, True)
			objResult.WriteLine Now & " - " & objNetwork.ComputerName & ": " & objNetwork.UserName & " - " & strCopyError
			objResult.Close
			Set objResult = Nothing
		End If
	End If
End If

Open in new window

0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

This script will sweep a range of IP addresses (class c only, 255.255.255.0) and report to a log the version of office installed. What it does: 1.)      Creates log file in the directory the script is run from (if it doesn't already exist) 2.)      Sweep…
Use this article to create a batch file to backup a Microsoft SQL Server database to a Windows folder.  The folder can be on the local hard drive or on a network share.  This batch file will query the SQL server to get the current date & time and wi…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now