I'm trying to use this function to monitor BSOD remotely I know I have to add a parameter of computername just not sure where
Function Get-BSODInfo{
try {
Invoke-WebRequest -Uri "https://www.nirsoft.net/utils/bluescreenview.zip" -OutFile "$($ENV:Temp)\bluescreeview.zip"
Expand-Archive "$($ENV:Temp)\bluescreeview.zip" -DestinationPath "$($ENV:Temp)" -Force
Start-Process -FilePath "$($ENV:Temp)\Bluescreenview.exe" -ArgumentList "/scomma `"$($ENV:Temp)\Export.csv`"" -Wait
}
catch {
Write-Host "BSODView Command has Failed: $($_.Exception.Message)"
exit 1
}
$BSODs = get-content "$($ENV:Temp)\Export.csv" | ConvertFrom-Csv -Delimiter ',' -Header Dumpfile, Timestamp, Reason, Errorcode, Parameter1, Parameter2, Parameter3, Parameter4, CausedByDriver | foreach-object { $_.Timestamp = [datetime]::Parse($_.timestamp, [System.Globalization.CultureInfo]::CurrentCulture); $_ }
Remove-item "$($ENV:Temp)\Export.csv" -Force
$BSODFilter = $BSODs | where-object { $_.Timestamp -gt ((get-date).addhours(-24)) }
if (!$BSODFilter) {
write-host "Healthy - No BSODs found in the last 24 hours"
}
else {
write-host "Unhealthy - BSOD found. Check Diagnostics"
$BSODFilter
exit 1
}
}
Related
I made a small Powershell script 'Start.ps1' which launches some websites on Windows startup. When I launch it manually, all configured websites are started in Chrome. However, when I run it with task scheduler, the task runs, but Chrome does not start.
schtasks /create /tn "Start" /sc onstart /delay 0000:30 /rl highest /ru system /tr "powershell.exe -file 'C:\Users\myuser\Google Drive\Home\Start.ps1'"
I've also added some logs in my powershell script so I'm sure the script has started:
Function Write-Log {
Param (
[parameter(Mandatory=$True,HelpMessage='Log output')][string]$Log,
[parameter(Mandatory=$True,HelpMessage='Log severity')][ValidateSet('Debug', 'Info', 'Warning', 'Error', 'Unknown')][string]$Severity,
[parameter(Mandatory=$True,HelpMessage='Log message')][string]$Message
)
$Now = Get-Date -Format 'yyyy-MM-dd HH:mm:ss,fff'
$LocalScriptName = Split-Path -Path $myInvocation.ScriptName -Leaf
If ( $Log -eq 'Verbose' ) {
Write-Verbose -Message ('{0}: {1}: {2}: {3}' -f $Now, $LocalScriptName, $Severity, $Message)
}
ElseIf ( $Log -eq 'Debug' ) {
Write-Debug -Message ('{0}: {1}: {2}: {3}' -f $Now, $LocalScriptName, $Severity, $Message)
}
ElseIf ( $Log -eq 'Output' ) {
Write-Verbose -Message ('{0}: {1}: {2}: {3}' -f $Now, $LocalScriptName, $Severity, $Message)
}
ElseIf ( $Log -match '^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])(?::(?<port>\d+))$' -or $Log -match '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$' ) {
$IpOrHost = $log.Split(':')[0]
$Port = $log.Split(':')[1]
If ( $IpOrHost -match '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$' ) {
$Ip = $IpOrHost
}
Else {
$Ip = [Net.Dns]::GetHostAddresses($IpOrHost)[0].IPAddressToString
}
Try {
$LocalHostname = ([Net.Dns]::GetHostByName((& "$env:windir\system32\hostname.exe")).HostName).tolower()
$JsonObject = (New-Object -TypeName PSObject |
Add-Member -PassThru -NotePropertyName NoteProperty -NotePropertyValue logsource -InputObject $LocalHostname |
Add-Member -PassThru -NotePropertyName NoteProperty -NotePropertyValue hostname -InputObject $LocalHostname |
Add-Member -PassThru -NotePropertyName NoteProperty -NotePropertyValue scriptname -InputObject $LocalScriptName |
Add-Member -PassThru -NotePropertyName NoteProperty -NotePropertyValue logtime -InputObject $Now |
Add-Member -PassThru -NotePropertyName NoteProperty -NotePropertyValue severity_label -InputObject $Severity |
Add-Member -PassThru -NotePropertyName NoteProperty -NotePropertyValue message -InputObject $Message )
If ( $psversiontable.psversion.major -ge 3 ) {
$JsonString = $JsonObject | ConvertTo-Json
$JsonString = $JsonString -replace "`n",' ' -replace "`r",' '
}
Else {
$JsonString = $JsonObject | ConvertTo-Json2
}
$Socket = New-Object -TypeName System.Net.Sockets.TCPClient -ArgumentList ($Ip,$Port)
$Stream = $Socket.GetStream()
$Writer = New-Object -TypeName System.IO.StreamWriter -ArgumentList ($Stream)
$Writer.WriteLine($JsonString)
$Writer.Flush()
$Stream.Close()
$Socket.Close()
}
Catch {
Write-Verbose -Message ("{0}: {1}: Error: Something went wrong while trying to send message to logserver `"{2}`"." -f $Now, $LocalScriptName, $Log)
}
Write-Verbose -Message ('{0}: {1}: {2}: Ip: {3} Port: {4} JsonString: {5}' -f $Now, $LocalScriptName, $Severity, $Ip, $Port, $JsonString)
}
ElseIf ($Log -match '^((([a-zA-Z]:)|(\\{2}\w+)|(\\{2}(?:(?:25[0-5]|2[0-4]\d|[01]\d\d|\d?\d)(?(?=\.?\d)\.)){4}))(\\(\w[\w ]*))*)') {
If (Test-Path -Path $Log -pathType container){
Write-Host ('{0}: {1}: Error: Passed Path is a directory. Please provide a file.' -f $Now, $LocalScriptName)
Exit 1
}
ElseIf (!(Test-Path -Path $Log)) {
Try {
$Null = New-Item -Path $Log -ItemType file -Force
}
Catch {
$Now = Get-Date -Format 'yyyy-MM-dd HH:mm:ss,fff'
Write-Host ("{0}: {1}: Error: Write-Log was unable to find or create the path `"{2}`". Please debug.." -f $Now, $LocalScriptName, $Log)
exit 1
}
}
Try {
('{0}: {1}: {2}: {3}' -f $Now, $LocalScriptName, $Severity, $Message) | Out-File -filepath $Log -Append
}
Catch {
Write-Host ("{0}: {1}: Error: Something went wrong while writing to file `"{2}`". It might be locked." -f $Now, $LocalScriptName, $Log)
}
}
}
$Logfile="c:\Tempo\Start.log"
Write-Log $Logfile Info "Initiating Chrome Site Startup"
Start-Process -FilePath "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
Start-Process -FilePath "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" -ArgumentList "https://outsideit.net"
Start-Process -FilePath "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" -ArgumentList "https://psychologischezorgopmaat.be"
Start-Process -FilePath "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" -ArgumentList "https://github.com"
Start-Process -FilePath "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" -ArgumentList "https://gitlab.com"
Start-Process -FilePath "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" -ArgumentList "http://localhost:9200"
Start-Process -FilePath "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" -ArgumentList "http://localhost:5601"
Write-Log $Logfile Info "Finalizing Chrome Site Startup"
How can I make this work in Task Scheduler? I tried running it with SYSTEM and my own user and with the "Run with highest privilege" option.
Always test if the scheduled task is working as intended when you run it manually (Scheduled Tasks - right click your task and Run it). When that works, move on to test if it works as intended when you start up the computer (or whenever, depending on the trigger).
When I imported your task with through cmd with the SYSTEM user account, the default setting was "Run whether user is logged on or not". If I tried to run it manually, the script wouldn't start.
I then changed the user to my account, changed the option to "Run only when the user is logged on", and that fixed the problem for me (many times before, as well). I wasn't able to change this option when using the SYSTEM user.
I'm trying to divide output into two files with following script:
try {
gci C:\Windows\System32 -r -Force | % {
if (!$_.PsIsContainer) {
$_.FullName;
$file = $_.FullName
}
} > paths.txt
} catch [System.UnauthorizedAccessException] {
$file > errors.txt
}
I'm aware that you can't catch non-terminating scripts with catch [System.UnauthorizedAccessException], but I don't want to use -ErrorAction Stop with catch [System.Management.Automation.ActionPreferenceStopException] either (like here), because I won't get all file paths.
This worked for me
$epath2 = $null
Get-ChildItem -Path C:\Windows\System32 -Recurse -Force -Directory -ErrorVariable epath2 |
foreach {
if ($?) {
Out-File -InputObject $_.FullName -FilePath c:\test\paths.txt -Append
}
}
if ($epath2) {
$epath2 |
foreach {
($_.Exception -split "'")[1] | Out-File -FilePath c:\test\errors.txt -Append
}
}
catch the errors in the -ErrorAction variable and send to errors.txt as a second pass. There may be other errors than access denied but you'll know which folders were showing problems
I have a CSV file of file paths. For each path, I want to test if the file exists. If it does, copy to a new location. If it does not, write that path to a "missing files" file.
This is what I have so far...
Import-Csv .\files.csv | ForEach {
If (Test-Path -Path $_.File) {
Write-Output "$($_.File) exists"
} Else {
Write-Output "$($_.File) does NOT exist"
$_.File | Out-File .\missingFiles.txt -Append
}
}
Import-Csv .\files.csv | ForEach {
If (Test-Path -Path $_.File) {
Write-Output "$($_.File) exists"
Copy-Item -Path $_.File -Destination "\\Wherever\You\Want"
} Else {
Write-Output "$($_.File) does NOT exist"
$_.File | Out-File .\missingFiles.txt -Append
}
}
You should not trust the filesystem this way. A file can disappear or change permissions between your Test-Path and your Copy-Item. A safer way to do this (and you may decide you don't need this kind of safety)...
Import-Csv -Path .\files.csv | %{
try {
Copy-Item -Path $_ -Destination <path>
Write-Verbose -Message "Found: $_"
} catch {
$_ | Out-File -Append -Path .\missing.txt
Write-Verbose -Message "Not Found: $_"
}
}
On a Windows Server 2008 R2, 64 bit-machine I am running the following code:
$global:arrServer = #("ph1", "ph2", "ph3")
$global:arrDienste = #("W3SVC", "WAS", "IISADMIN")
$global:strPfad = "D:\WASLogs\"
$global:strLogTime = Get-Date -Format "yyyy-MM-dd--hh-mm-ss"
$global:strLogDatei = $global:strPfad + "WARTUNG--" + $global:strLogTime + ".log"
Log_Abfrage_und_Generierung
Dienste_Stop
Function Dienste_Stop
{
echo "Stop of the services successful?" | Out-File $global:strLogDatei -Append -Force
foreach($strServer in $global:arrServer)
{
$strInterim2 = $strServer + " (" + $global:appServerNamen + ")"
echo " " $strInterim2 | Out-File $global:strLogDatei -Append -Force
foreach($strDienst in $global:arrDienste)
{
$objWmiService = Get-Wmiobject -Class "win32_service" -computer $strServer -filter "name = '$strDienst'"
if( $objWmiService.State )
{
$rtnWert = $objWmiService.stopService()
Switch ($rtnWert.returnvalue)
{
0 { echo "$strDienst stopped!" | Out-File $global:strLogDatei -Append -Force }
2 { echo "$strDienst throws: 'Access denied!'" | Out-File $global:strLogDatei -Append -Force }
3 { echo "Service $strDienst is not existing on $strServer!" | Out-File $global:strLogDatei -Append -Force }
5 { echo "$strDienst already stopped!" | Out-File $global:strLogDatei -Append -Force }
DEFAULT { echo "$strDienst service reports ERROR $($rtnWert.returnValue)" | Out-File $global:strLogDatei -Append -Force }
}
}
else
{
echo "Service $strDienst is not existing on $strServer!" | Out-File $global:strLogDatei -Append -Force
}
}
}
}
Function Log_Abfrage_und_Generierung
{
if([IO.Directory]::Exists($global:strPfad))
{
echo "Nothing happening here."
}
else
{
New-Item -ItemType directory -path $global:strPfad
}
}
This can be reproduced on all computers ph1, ph2 and ph3. However with some other code, WAS can be started, respectively the status can be seen.
Also to note:
All other services can be stopped? Does it has to do with the fact that the path for the WAS is like this? C:\Windows\system32\svchost.exe -k iissvcs
I use WMI on purpose.
What is going on here?
Tia
The problem could be that there are multiple services that depend on WAS which need to be stopped first. The StopService() method does not have an overload to stop dependent services. If this doesn't solve the issue check the response code from StopService to determine the problem in the link above.
It looks like you are handling the code 3 as 'service does not exist'. The docs show this code actually means 'The service cannot be stopped because other services that are running are dependent on it.'
Not sure why you're determined to use WMI when this capability is fully baked into powershell
Stop-Service WAS -Force
Currently I have this code -
Set-ExecutionPolicy Unrestricted
$name = (Get-WmiObject win32_bios).SerialNumber.Trim()
$oldname = (Get-WmiObject win32_computersystem).Name.Trim()
IF ($oldname -eq $name){Exit}
Else{ Rename-computer -ComputerName $oldname -NewName "$name" -force
Start-Sleep -s 5
Restart-Computer}
And I have it set to run as a scheduled task at logon and without the If Else it works perfectly however I don't want it to run every time a user logs in because it will just be a cycle of rebooting. Any help would be greatly appreciated.
I would suggest some changes:
Set-ExecutionPolicy is unnecessary, because if the machine has started processing the script, then the executionpolicy isn't a problem. So remove that, and specify it in the powershell.exe-call instead, like: powershell.exe -executionpolicy unrestricted
Use if($oldname -ne $name) { rename-computer .... } so you can remove the else part. Much cleaner
Try running the modified script below, and report back with the output in the scriptlog.txt-file.
$logpath = "c:\scriptlog.txt"
$name = (Get-WmiObject win32_bios).SerialNumber.Trim()
$oldname = (Get-WmiObject win32_computersystem).Name.Trim()
"NewName is '$name'" | Out-File $logpath -Append
"OldName is '$oldname'" | Out-File $logpath -Append
IF ($oldname -ne $name){
"If-test TRUE" | Out-File $logpath -Append
Rename-computer -ComputerName $oldname -NewName $name -Force
Start-Sleep -s 5
Restart-Computer
} else { #I've added the else-part just because of logging.
"IF-test FALSE" | Out-File $logpath -Append
}