I have come up with a script that will restart a specific service and now I would like to know if there is a way I can get a service start time from event viewer using batch files.
Appreciate if anyone could give me the answer. Thanks!
Use wevtutil.
The service start/stop events are logged in the system event log, there are several ways to open it (use google). Clicking the events we can see a "service entered the running state" event with an ID 7036, let's use it to find the last start time of Application Experience service.
Only one event is needed /c:1 and since it's the last in the log let's reverse the direction with /rd:true:
wevtutil qe system /rd:true /c:1 /q:"Event[EventData[Data[#Name='param1']='Application Experience'] and System[EventID=7036]]
The output is this xml blob:
<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'><System><Provider Name='Service Control Manager' Guid='{555908d1-a6d7-4695-8e1e-26931d2012f4}' EventSourceName='Service Control Manager'/><EventID Qualifiers='16384'>7036</EventID><Version>0</Version><Level>4</Level><Task>0</Task><Opcode>0</Opcode><Keywords>0x8080000000000000</Keywords><TimeCreated SystemTime='2015-10-12T10:43:13.841899000Z'/><EventRecordID>4287264</EventRecordID><Correlation/><Execution ProcessID='800' ThreadID='1804'/><Channel>System</Channel><Computer>zOo</Computer><Security/></System><EventData><Data Name='param1'>Application Experience</Data><Data Name='param2'>running</Data><Binary>410065004C006F006F006B00750070005300760063002F0034000000</Binary></EventData></Event>
Let's extract the date and time.
First remove everything from the beginning up to SystemTime= with string replacement set "xml=!xml:*SystemTime=!":
='2015-10-12T10:43:13.841899000Z'/>.....................................(the rest of the string)
Then split at ' and T and . into tokens: =, 2015-10-12, 10:43:13, 841899000Z, />.... and grab the 2nd and the 3rd:
#echo off
setlocal enableDelayedExpansion
for /f "tokens=*" %%a in ('
wevtutil qe system /rd:true /c:1 ^
/q:"Event[EventData[Data[#Name='param1']='Application Experience'] and System[EventID=7036]]"
') do (
set "xml=%%a" & set "xml=!xml:*SystemTime=!"
for /f "delims='T. tokens=2,3" %%b in ("!xml!") do (
echo Started at date: %%b time: %%c
)
)
endlocal
pause
The date uses YYYY-MM-DD format, the time is 24-hour:
Started at date: 2015-10-12 time: 10:43:13
Related
I have a scenario where I want to detect the mouse movement when movement happens with certain timing slot and it is a first-time movement happened of the mouse when I logged in then catch the current date and time and store to file
Below code works fine:
#echo off
for /f "tokens=1,2" %%u in ('date /t') do set d=%%v
for /f "tokens=1" %%u in ('time /t') do set t=%%u
if "%t:~1,1%"==":" set t=0%t%
For /f "tokens=1,2,3,4,5 delims=/. " %%a in ('date/T') do set dt=%%c-%%b-%%d
set logfile=C:\Users\vvoor\OneDrive\Desktop\wirite\n\login_time_%dt%.txt
echo Login Time : %d% %t% %time:~-5,2% >> %logfile%
This above works fine as expected gives me date and time
But I want the script should automatically trigger and capture the date and time when I log in for the first time and move his mouse for the first time
The time slot is between 12:00 to 2:00 => if mouse movement happen for first time within given time slot then capture current date and time to a text file
cmd has no method to use the mouse. I used Npocmaka's answer to a similar question from here
The batch file Mouse.bat (written by Npocmaka) creates a mouse.exe, which you can use to get the mouse position (and a lot more stuff not needed for your task):
mouse position
which will give you a string like 514x312
First thing is to capture the mouse position into a variable (no need to split it into x and y coordinates, as you just want to compare for equality later)
Then do a simple loop and compare the current position to the saved position:
#echo off
for /f %%a in ('mouse.exe position') do set "initialPos=%%a"
:loop
timeout 2 >nul
for /f %%a in ('mouse.exe position') do set "currentPos=%%a"
if "%currentPos%" == "%initialPos%" goto :loop
echo Mouse has been moved.
Create a scheduled task ("new task", not "simple new task") to run it within the desired time frame.
I wrote a batch file 2 years ago that seemed to work great making a backup copy of an excel spreadsheet daily. All of a sudden 1 day it stopped working properly and began assigning the variables literally instead of pulling the actual date so it just began overwriting itself every day.
I went from getting this file name:
Tasty Schedule 2018 - 04-30-2018
To now getting this filename:
Tasty Schedule 2018 - ~4,2-~6,2-~0,4
Looking at the code it seems obvious where the values are coming from but I am not sure why the date is no longer being pulled. Im assuming there had to be some type of system update that changed something to cause this? What is the best way to fix this? Please see my current code below:
#echo off
for /f "delims=" %%a in ('wmic OS Get localdatetime ^| find "."') do set dt=%%a
set YYYY=%dt:~0,4%
set MM=%dt:~4,2%
set DD=%dt:~6,2%
set HH=%dt:~8,2%
set Min=%dt:~10,2%
set Sec=%dt:~12,2%
set stamp=%MM%-%DD%-%YYYY%
copy "J:\TROY C\2018 Schedule\Tasty Schedule 2018.xlsx" "J:\Joe's Folder\ChocScheduleBackUps\Tasty Schedule 2018 - %stamp%.xlsx"
Launch the following command in a command prompt:
wmic OS Get localdatetime
This should show the date, you can start from there.
Verify your locale settings: the mentioned WMIC command is locale dependent.
In order to make WMIC work, you need to see the following when you run set PATH in a command prompt:
C:\Program Files\7-Zip>set PATH
Path=...;C:\WINDOWS\System32\Wbem;...
(Do no modify C:\Windows directory, your computer will not work anymore)
I solved my issue by adding 'C:\Windows\System32\wbem\' to PATH so that WMIC worked and also adding 'C:\Windows\System32\' to PATH so FIND would work.
Here's an example using RoboCopy instead:
#Echo Off
Set "dStamp="
For /F "Tokens=1-3 Delims=/ " %%A In ('RoboCopy/NJH /L "\|" Null') Do If Not Defined dStamp Set "dStamp=%%B-%%C-%%A"
If Defined dStamp Copy "J:\TROY C\2018 Schedule\Tasty Schedule 2018.xlsx" "J:\Joe's Folder\ChocScheduleBackUps\Tasty Schedule 2018 - %dStamp%.xlsx"
I am able to pull the services which are down and list them in a file with the below code but need help to design the script which can check down services and if startup type is Automatic just start them.
#echo off
wmic service where started=false get name >> stoppedservices.txt
echo "The program has completed"
You can use sc command in the for loop to complete your script:
#echo off
for /f "tokens=*" %%s in ('wmic service where started^=false get name') do (
for /f "tokens=3" %%t in ('sc qc %%s ^|findstr /c:"START_TYPE"') do (
if "%%t"=="2" net start %%s
)
)
echo "The program has completed"
pause>nul
If desired, you can use sc start instead of net start.
net start will return success message after the startup task is completed while sc start will return message as it is processing service startup. If you are a person who likes to see the process completed step by step, net start would be better choice for you.
You could try and do it all using the same WMIC command.
WMIC Service Where "StartMode='Auto' And Started='False'" Call StartService
Just bear in mind that, some services may be either delayed auto starting or pending and this does not take such information into account.
I have a log file where the user login details are stored in below format:
INFO ;servername;2016-02-16 01:50:12,user4#COM;Open Analysis;H5SeLhbEVUKA0ml-kFUw5-151708d6b3Y8Tz;/Metric/core/corePortal;Success;151708fdfgY
INFO ;servername;2016-02-16 01:50:12,user3#COM;Open Analysis;H5SeLhbEVUKA0ml-kFUw5-151708d6b3Y8Tz;/Metric/core/corePortal;Success;151708fdfgY
INFO ;servername;2016-02-17 01:50:12,user1#COM;Open Analysis;H5SeLhbEVUKA0ml-kFUw5-151708d6b3Y8Tz;/Metric/core/corePortal;Success;151708fdfgY
INFO ;servername;2016-02-18 01:50:12,user2#COM;Open Analyss;H5SeLhbEVUKA0ml-kFUw5-151708d6b3Y8Tz;/Metric/core/corePortal;Success;151708fdfgY
Requirement:
I need to get the number of users logged in on a particular date.
Eg: from above log ,it should return me that 2 users(user4 and user3 ) were logged In on 2016-02-16 . Requirement is for a batch file.
#echo off
setlocal EnableDelayedExpansion
for /F "tokens=3 delims=; " %%a in (input.txt) do (
set "d=%%a"
set /A "users[!d:-=_!]+=1"
)
echo Users logged in on all dates:
set users
echo/
echo Users logged in on 2016-02-16: %users[2016_02_16]%
Output:
Users logged in on all dates:
users[2016_02_16]=2
users[2016_02_17]=1
users[2016_02_18]=1
Users logged in on 2016-02-16: 2
You may review a detailed explanation of the array method used in this solution at: Arrays, linked lists and other data structures in cmd.exe (batch) script
Method posted by Aacini will work, but the FOR command is rather slow when processing larger amounts of data. If you have very large files and only need to find the number of users on one particular date, I would recommend using the FIND command, which is faster, because the iteration takes place completely within the command.
If you assume that dates only appear within the date data field in the file, you can use FIND /C "date to find" path\filename This will give a single line as output, including the file name and ending with the number of found lines.
If you suspect that dates may occur in other data fields in the file, the following code may be used:
#echo off
SETLOCAL enabledelayedexpansion
SET srcstring=insert your date here
SET file=insert your path and filename here
FOR /F "tokens=3 delims=; " %%F IN ('FIND "%srcstring%" %file%') DO (
IF "%%F"=="%srcstring%" (SET /A "count+=1")
)
echo %count% users found on date %srcstring%
It uses the faster command FIND to find all lines where the date appears, then uses the slower FOR to check that the date appears in the right data field on the line. Since FORonly iterates through those lines that contain the date, it will be significantly faster.
You never state whether there are non-login lines of a different format within the log. I'm going to assume there are.
You also never state what portion of the login line is static. I'm going to assume only the date/time and username change. So this code will only count successful connections. You will have to adjust the code to match your actual conditions.
If all you want to do is print out the count, then you can use FINDSTR with a regular expression to select the relevant rows, and pipe that to FIND to count the rows.
The code below expects the desired date to be passed as a parameter in YYYY-MM-DD format
#echo off
:CountSuccessfulLogins date
set "dt=%~1"
set "prefix= INFO ;servername;"
set "suffix= .*;Open Analysis;H5SeLhbEVUKA0ml-kFUw5-151708d6b3Y8Tz;/Metric/core/corePortal;Success;151708fdfgY"
findstr /rc:"^%prefix%%dt%%suffix%$" test.log | find /c /v ""
exit /b
If you want the count in a variable, then capture the output with FOR /F
#echo off
:CountSuccessfulLogins date
set "dt=%~1"
set "prefix= INFO ;servername;"
set "suffix= .*;Open Analysis;H5SeLhbEVUKA0ml-kFUw5-151708d6b3Y8Tz;/Metric/core/corePortal;Success;151708fdfgY"
for /f %%N in ('findstr /rc:"^%prefix%%dt%%suffix%$" test.log ^| find /c /v ""') do set cnt=%%N
echo %cnt% Successful Logins on %dt%
exit /b
I would like to know how to create a bat file which on its first run would store the system date and on subsequent run delete a particular file 30 days later.I think if a bat file can be created that would store system date on its first run and the second bat files reads the first file for the date would be better.But how?
As #devio commented, PowerShell is definitely more fully featured: PowerShell Quick Reference
If it has to be a Batch file, this reference explains most commands.
I love powershell, and it is certainly more powerful than batch files, but for this it shouldnt really matter what you use, so if you're comfortable with your batch files you should be able to stick with them.
The only way you'll be able to later recover that date is to store it somewhere (or have your task running the whole time which is unrealistic - think reboots among other things)
You could write the deletion date to the registry or a text file or somewhere else that is 'known', but then you need to have something else running to check 'if its time to act'.
I'd be inclined to just create a scheduled task for the delete during the original script so that I wouldn't have to check up on it. You could even have the delete script you've scheduled clean up the task when it's done.
You could use something like a windowscripting host vb script or js script file. Also scripting languages such as php, python or perl would allow you to do something like this easily and possibly give you much greater flexibility than a shell script.
It's going to take a while to answer this one, but here's the first thing to suggest.
When you want to have a single .BAT (or .CMD) which does something and also does something later based on the first something, one can use the "flag parameter" technique. For example, in a script which accepts a wildcarded list of files to manipulate one could do as follows:
::foo.cmd
#echo off
if %1#==# goto fail
set f=%1
if %1==! goto inner
for %%x in (%f%) do cmd /c %0 ! %%x
goto done
:inner
set f=%2
echo do something with %f%
goto done
:fail
echo %0 {wildcard}
:done
The script is actually written such that it can be called anything, and it will call itself (using %0).
Now how to do date arithmetic is going to take some time to figure out. I hope that much at least gets you started in the right direction.
my setup after after completion of installation would run a bat file(once) that should get the system date(install date) and store in a text file.the main program would be called by another batch file that would read the text file every time for the date assisting it to delete particular files after "N" number of days referencing the install date in the text file.
HI MARK BRACKETT,
when I run batch1 the date is MM\DD\YYYY.But when I run batch2 the startdate is DD and the startmonth is also DD.The final equation is if rundate==nowdate execute command,it should be rundate=>nowdate,cause if pc not switched on rundate.secondly months with 31days the rundate would 31st next month
VBScript, PowerShell, or C# (I use CS-Script to run my C# scripts) would be much cleaner - but sometimes I enjoy a little batch file challenge.
So - this is for 1 month from the current date and time, but it gives you the idea. To actually figure 30 days, I suspect you'd need about 50 lines of IF statements. Or, a single external EXE to calculate it for you.
I think there's a cleaner way to use SET itself to split out the date parts, which would cut this down by about 3 lines - but I don't recall the syntax ATM.
Batch1
ECHO %DATE% > start.txt
Batch2
: Get start date
FOR /F "tokens=1* delims= " %%i IN (start.txt) DO set startDate=%%j
FOR /F "tokens=1,2 eol=/ delims=/ " %%i IN ('echo %startDate%') DO set startMonth=%%i
FOR /F "tokens=1,2 delims=/ eol=/" %%i IN ('echo %startDate%') DO set startDay=%%j
FOR /F "tokens=2,3 delims=/ " %%i IN ('echo %startDate%') DO set startYear=%%j
: Get run month and day as YYYY-MM-DD
SET /A runMonth=%startMonth% + 1
IF %runMonth% LEQ 10 SET runMonth=0%runMonth%
SET runDay=%startDay%
SET runYear=%startYear%
SET runDate=%runYear%-%runMonth%-%runDay%
: Get current month and day as YYYY-MM-DD
FOR /F "tokens=1* delims= " %%i IN ('echo %DATE%') DO set nowDate=%%j
FOR /F "tokens=1,2 eol=/ delims=/ " %%i IN ('echo %nowDate%') DO set nowMonth=%%i
FOR /F "tokens=1,2 delims=/ eol=/" %%i IN ('echo %nowDate%') DO set nowDay=%%j
FOR /F "tokens=2,3 delims=/ " %%i IN ('echo %nowDate%') DO set nowYear=%%j
SET nowDate=%nowYear%-%nowMonth%-%nowDay%
: Compare
IF %nowDate% GEQ %runDate% ECHO Delete!
Note that this doesn't handle year changes appropriately (it'll delete on the year change).