Weekly Restart and Log Batch File

May 3, 2020 at 14:21:03
Specs: Windows 7
I have over 300+ computers on my network that I have to restart on a weekly basis. I am looking at trying to create a Batch file for this. My leadership wantes a running log of all of the computers that restart successfully/unsuccessfully as well. I am unsure of how to actually do this though. Any suggestions? We cannot restart all of the workstations at the same time so I was planning on doing them in batches. What I am trying to do is below.

At (Time) warn user logged in that computer will restart in 30 minutes and to save their work before the restart.
At (Time) warn the user that the computer will restart in 5 minutes and to save their work before the restart.
At (Time) restart
Upon successful/unsuccessful restart send a log to (\\Server\Folder)


See More: Weekly Restart and Log Batch File

Reply ↓  Report •

#1
May 3, 2020 at 15:14:24
Could do something like this:

@echo off

shutdown /r /t 1800

:Option

echo PC will restart in 30 min
echo:
echo Abort restart?
echo:
echo [Y] Yes
echo:
echo [N] No
echo:
choice /c YN /n /m "Your choice? "

if %errorlevel%==1 goto:Abort
if %errorlevel%==2 goto:PowerOff
else goto:Option

:Abort

echo %computername% restarted at %date% >> file.txt

shutdown /a
exit

:PowerOff

echo %computername% not restarted at %date% >> file.tx

exit

message edited by Kilavila


Reply ↓  Report •

#2
May 4, 2020 at 08:32:20
Is there a way to have the log sent to our server instead of being stored locally on the machine?

message edited by Zuhan


Reply ↓  Report •

#3
May 4, 2020 at 09:24:25
havent tried this but its worth a shot:

>> \\server\folder\file.txt


if you dont get this to work you could check out powershell.

message edited by Kilavila


Reply ↓  Report •

Related Solutions

#4
May 4, 2020 at 12:12:13
Apparently these computers are on 24/7, or they wouldn't need
to be restarted. In that case -- unless they are actually being
used 24/7 -- I would think you would have them restart in the
middle of the night, when they would not be in use. Is that not
possible?

If they are in use 24/7, is it possible to schedule the restart of
each computer or each bunch of computers for a time when it
is least likely to be in use by that particular user or bunch of
users? Restart could take place if the user is logged out.

I wonder if this might be a job for Windows Task Scheduler.

-- Jeff, in Minneapolis


Reply ↓  Report •

#5
May 4, 2020 at 12:35:39
Yes it would be best to restart these computers when they are not being used.
You could use Task Scheduler to restart and a simple script in startup folder to log it to a file on the server(or something like that).
Btw, do you really need to log when a PC fails to restart?

Reply ↓  Report •

#6
May 4, 2020 at 20:13:20
They are being used 24/7 unfortunately.

Reply ↓  Report •

#7
May 6, 2020 at 05:25:59
Save as .ps1 and schedule to run on fridays. Hope this helps.
For info about script, read the comments.


$User = $env:USERNAME
$Computer = $env:COMPUTERNAME

# Start writing log in the same folder as script($PSScriptRoot)
# Do not overwrite, but add logs to existing file/create file if not exist(-Append/-NoClobber)
# When looking for logs just search for computername, each file will have multiple logs for each PC
Start-Transcript -Path "$PSScriptRoot\$Computer.txt" -Append -Force -NoClobber

# Check if AZSBTools module exists, and install if not
$AZSB = Test-Path "C:\Users\$User\Documents\WindowsPowerShell\Modules\AZSBTools"

if ($AZSB -eq $True)
{
Write-Host "AZSBTools module already installed" -ForegroundColor "Green"
}
else
{
Write-Host "AZSBTools module not found" -ForegroundColor "Red"
Write-Host "Installing AZSBTools module"
Install-Module AZSBTools -Force -AllowClobber -Scope CurrentUser -SkipPublisherCheck -Confirm:$false
Write-Host "AZSBTools module installed" -ForegroundColor "Green"
}

# Check if PSWindowsUpdate module exists, and install if not
$PSWU = Test-Path -Path "C:\Program Files\WindowsPowerShell\Modules\PSWindowsUpdate"

if ($PSWU -eq $True)
{
Write-Host "PSWindowsUpdate module already installed" -ForegroundColor "Green"
}
else
{
Write-Host "PSWindowsUpdate module not found" -ForegroundColor "Red"
Write-Host "Installing PSWindowsUpdate module"
Install-Module PSWindowsUpdate -Force -AllowClobber -Scope CurrentUser -SkipPublisherCheck -Confirm:$false
Write-Host "PSWindowsUpdate module installed" -ForegroundColor "Green"
}

# Using AZSBTools to get first tuesday of this month
# Adding 10 days(installing windows updates the friday after patch tuesday)
$FirstTuesday = Get-DayOfMonth -DayofWeek Tuesday -First
$TargetDate = Get-Date $FirstTuesday.AddDays(10) -Format "yyyy/MM/dd"
$Today = Get-Date -Format "yyyy/MM/dd"

# Comparing todays date with the target date
# If match: install windows updates
if ($Today -eq $TargetDate)
{
Write-Host "Downloading and Installing Windows Updates"
Download-WindowsUpdate -Confirm:$false
Install-WindowsUpdate -Confirm:$false
}
else
{
Write-Host "This computer will Install Windows Updates on this date: $TargetDate"
}

# Schedule a shutdown using CMD, 1800 sec = 30 min
CMD.exe --% /C Shutdown /r /t 1800

# Stopping transcript here(rest of script is for the user)
Stop-Transcript

# Using foreach loops so the user knows how long until restart
$Minutes = 29

# First loop: Minutes
foreach ($i in 1 .. 30)
{
$Seconds = 59

# Second loop: Seconds
foreach ($i in 1 .. 60)
{
Write-Host "Remember to save any documents..."
Write-Host ""
Write-Host "Restarting computer in: $Minutes minutes and $Seconds seconds"
Start-Sleep -Seconds 1
$Seconds = $Seconds - 1
Clear
}
$Minutes = $Minutes - 1
}

message edited by Kilavila


Reply ↓  Report •

#8
May 6, 2020 at 10:26:22
When I brought up the whole automatic reboot thing with my higher ups they demanded that I keep a log of all the computers that restart so they can keep track of computers that are non-compliant. I will give your script a shot and see how it goes. Runs as Powershell right? Is it possible to do the same thing through command prompt? Asking just in case they don't want to use Powershell.

message edited by Zuhan


Reply ↓  Report •

#9
May 6, 2020 at 11:28:45
Yes you can do the same thing with batch, though I dont know if you can update windows with a batch script. But just rebooting machine and logging is fairly easy.

What I would do is just compare your list of machines to the log, and if the computername isnt in the log it didnt go through.

The way I wrote that script it will create a txt file for each machine using the computername as the file name, but you can change that if you want all machines to log to same file.

And yes you run it with PowerShell.

EDIT:
If you want to generate a list of the txt files with PowerShell you can give this a try:

Get-ChildItem -Path "\\Server\Folder\" | Select-Object Name, LastWriteTime, CreationTime | Out-File "Folder\File.txt"

message edited by Kilavila


Reply ↓  Report •

#10
May 9, 2020 at 11:55:54
The reboot isn't to update the machines but to just restart them at certain times. The users do not understand that the machines should be rebooted and fail to do so (including leaving themselves logged in causing more issues for me and my team in the long run.) The batch file is just to reboot and report.

Reply ↓  Report •

#11
May 9, 2020 at 13:09:23
Then just use the last part of the script:

Start-Transcript -Path "$PSScriptRoot\$Computer.txt" -Append -Force -NoClobber

# Schedule a shutdown using CMD, 1800 sec = 30 min
CMD.exe --% /C Shutdown /r /t 1800

Stop-Transcript

# Using foreach loops so the user knows how long until restart
$Minutes = 29

# First loop: Minutes
foreach ($i in 1 .. 30)
{
$Seconds = 59

# Second loop: Seconds
foreach ($i in 1 .. 60)
{
Write-Host "Remember to save any documents..."
Write-Host ""
Write-Host "Restarting computer in: $Minutes minutes and $Seconds seconds"
Start-Sleep -Seconds 1
$Seconds = $Seconds - 1
Clear
}
$Minutes = $Minutes - 1
}

message edited by Kilavila


Reply ↓  Report •

#12
May 10, 2020 at 13:15:43
Cool thanks a lot. These last questions should be my last. Can this run off of one of our servers to reboot our computers or does it have to be on the computers themselves and can the script send the log to a server?

Again thank you for all the help.


Reply ↓  Report •

#13
May 10, 2020 at 14:20:23
No problem.

"Can this run off of one of our servers to reboot our computers"

Yes, there is several ways to do this, though Im not sure what the best way would be.
You can f.ex. use SCCM: https://community.spiceworks.com/to...

Or if you want to do this with PowerShell from the script then you need to enable WinRM on each computer.
Then create a list of all computernames in a txt or csv file, then run a foreach loop and PSSession/Invoke-Command(can be tricky and a bit complicated to get to run correctly). Would look something like this tho:

# Assuming all computernames is in Computers.txt

# Getting all computernames
$Computers = Get-Content -Path "folder\Computers.txt"

# Using foreach loop to run commands pr computername in the txt
foreach ($Computer in $Computers){
# Executing commands with Invoke-Command
Invoke-Command -Computername $Computer -ScriptBlock{
# Commands to be executed on remote machine
}
}


Next one is easier.
"can the script send the log to a server?"

Yes, if you look at the top of the script you will find this command:

Start-Transcript -Path "$PSScriptRoot\$Computer.txt" -Append -Force -NoClobber

$PSScriptRoot means "the folder the script is located in", but you can just change that to any path you want..
So lets say you want all logs to be saved in f.ex. the documents folder, it would look like this:

# If script is running from the server
Start-Transcript -Path "C:\Users\Administrator\Documents\$Computer.txt" -Append -Force -NoClobber

# If script is running on each computer(NB. the logged in user would need access to that folder, and if not then you would need to add credentials to the script)
Start-Transcript -Path "\\ServerName\Folder\Sub-Folder\$Computer.txt" -Append -Force -NoClobber


Last thing:
If you send this script to each computer to run it locally then you should change a setting on each machine:

Set-ExecutionPolicy Unrestricted

This is normally set to Restricted and will only allow you to run scripts that were made on the local computer.
This is just a safety feature so you dont shoot your self in the foot.
To check the Execution Policy on a computer:

Get-ExecutionPolicy


This post got a bit long, anyway hope it helps. Probably easiest to go with the SCCM solution.

message edited by Kilavila


Reply ↓  Report •

#14
May 11, 2020 at 13:14:27
When running the script with the windows update I get this in the log that's created.

Transcript started, output file is C:\Users\derek.butler\Desktop\U-WS0044.txt
AZSBTools module not found
Installing AZSBTools module
Install-Module : The term 'Install-Module' is not recognized as the name of a
cmdlet, function, script file, or operable program. Check the spelling of the
name, or if a path was included, verify that the path is correct and try again.
At C:\Users\derek.butler\Desktop\Test_Reboot_With_Update.ps1:20 char:1
+ Install-Module AZSBTools -Force -AllowClobber -Scope CurrentUser
-SkipPublisherC ...
+ ~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Install-Module:String) [], Comm
andNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException

AZSBTools module installed
PSWindowsUpdate module not found
Installing PSWindowsUpdate module
Install-Module : The term 'Install-Module' is not recognized as the name of a
cmdlet, function, script file, or operable program. Check the spelling of the
name, or if a path was included, verify that the path is correct and try again.
At C:\Users\derek.butler\Desktop\Test_Reboot_With_Update.ps1:35 char:1
+ Install-Module PSWindowsUpdate -Force -AllowClobber -Scope CurrentUser
-SkipPubl ...
+ ~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Install-Module:String) [], Comm
andNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException

PSWindowsUpdate module installed
Get-DayOfMonth : The term 'Get-DayOfMonth' is not recognized as the name of a
cmdlet, function, script file, or operable program. Check the spelling of the
name, or if a path was included, verify that the path is correct and try again.
At C:\Users\derek.butler\Desktop\Test_Reboot_With_Update.ps1:41 char:17
+ $FirstTuesday = Get-DayOfMonth -DayofWeek Tuesday -First
+ ~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Get-DayOfMonth:String) [], Comm
andNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException

You cannot call a method on a null-valued expression.
At C:\Users\derek.butler\Desktop\Test_Reboot_With_Update.ps1:42 char:1
+ $TargetDate = Get-Date $FirstTuesday.AddDays(10) -Format "yyyy/MM/dd"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

This computer will Install Windows Updates on this date:
**********************
Windows PowerShell transcript end
End time: 20200512045713
**********************


Reply ↓  Report •

#15
May 11, 2020 at 13:47:10
Seems you have an issue with modules, what Powershell version is this?

$PSVersionTable will display the info.

When i tested that script it worked, i have PsVersion 5.1

Anyany, if you dont wish to update the machines with PowerShell you dont have to troubleshoot this, just use that last script(no modules needed). It will restart the machines and log it.


Reply ↓  Report •

#16
May 11, 2020 at 19:19:16
3.0 lol, We are unable to update due to it breaking the "Baseline" that we are allowed to have.

Reply ↓  Report •

#17
May 12, 2020 at 00:23:17
Ah i see. Well the last script(#11) should work fine.

Reply ↓  Report •

#18
May 12, 2020 at 08:21:05
Cool, thank you. Is there a similar script for windows update for 3.0? Leadership is being a pain in the ass now. If not that's fine, I'll use #11.

Reply ↓  Report •

#19
May 12, 2020 at 15:05:14
https://www.powershellgallery.com/p...

https://www.powershellgallery.com/p...

The update module(PSWindowsUpdate) says the minimum version is 3.0, but you might need to change the parameters to get it to work.

As for AZSBTools module i used to get the correct date for updates, it would seem it needs version 5.0 for some functions if not all.

Would be easier to update powershell, but if thats a "no go" then look in the documentation for alternative parameters/commands.

I know that PSWindowsUpdate have multiple commands. F.ex. to download updates you can use:
Get-WindowsUpdate
Download-WindowsUpdate

Hope this was of some help. Good luck


Reply ↓  Report •

#20
May 12, 2020 at 19:06:59
Thank you for all the help you have given me. It is very much appreciated.

Reply ↓  Report •

Ask Question