My task is to get the current time with the w32time service from a Windows 2016 Server, and compare it to the time showed on this server. What I find online about this service is synchronising, and doing more complicated stuff, but I simply need the "official" time in the simplest form, so I can compare the two, and check if there is more than a few seconds of difference between the two.
I can get some useful info with
w32tm /stripchart /computer:time.windows.com /samples:1 /dataonly
Which output has the line
09:59:38, +00.1323527s
Is this the difference between the NTP server and my server? Is there a more straightforward way to achieve what I intend to do, or should I just crop this line out the output, and use it?
According to this the +00.1323527 value you see is the actual offset between local time and the target computer time. If you’re seeing differences in the 0.00* range for actual offset, you can be highly confident that you have the correct system time. Anything with less than a second offset is reasonably good as well.
You can strip the time difference out like:
$currentTime, $timeDifference = (& w32tm /stripchart /computer:time.windows.com /samples:1 /dataonly)[-1].Trim("s") -split ',\s*'
$timeDifference
# or if you rather have a numeric value than a string, cast it to Double:
[double]$timeDifference
Related
How do I take a substring where I don't know the length of the thing I want, but I know that the end of it is a CR/LF?
I'm communicating with a server trying to extract some information. The start point of the substring is well defined, but the end point can be variable. In other scripting languages, I'd expect there to be a find() command, but I haven't found one in PowerShell yet. Most articles and SE questions refer to Get-Content, substring, and Select-String, with the intent to replace a CRLF rather than just find it.
The device I am communicating with has a telnet-like command structure. It starts out with it's model as a prompt. You can give it commands and it responds. I'm trying to grab the hostname from it. This is what a prompt, command, and response look like in a terminal:
TSS-752>hostname
Host Name: ThisIsMyHostname
TSS-752>
I want to extract the hostname. I came across IndexOf(), which seems to work like the find command I am looking for. ":" is a good start point, and then I want to truncate it to the next CRLF.
NOTE: I have made my code work to my satisfaction, but in the interest of not receiving anymore downvotes (3 at the time of this writing) or getting banned again, I will not post the solution, nor delete the question. Those are taboo here. Taking into account the requests for more info from the comments has only earned me downvotes, so I think I'm just stuck in the SO-Catch-22.
You could probably have found the first 20 examples in c# outlining this exact same approach, but here goes with PowerShell examples
If you want to find the index at which CR/LF occurs, use String.IndexOf():
PS C:\> " `r`n".IndexOf("`r`n")
2
Use it to calculate the length parameter argument for String.Substring():
$String = " This phrase starts at index 4 ends at some point`r`nand then there's more"
# Define the start index
$Offset = 4
# Find the index of the end marker
$CRLFIndex = $string.IndexOf("`r`n")
# Check that the end marker was actually found
if($CRLFIndex -eq -1){
throw "CRLF not found in string"
}
# Calculate length based on end marker index - start index
$Length = $CRLFIndex - $Offset
# Generate substring
$Substring = $String.Substring($Offset,$Length)
Is there a slick way in PowerShell to ascertain if a past date in another time zone is Daylight Savings or not? Here is the situation, our database is in Europe and the times and dates are local to that server. Since Europe and America start and stop DST at different times, i need to take into account the hour difference for those times.
Thanks for your advice.
There is no need to try to determine whether DST is in effect or not. Just let the .NET Framework do the conversion for you.
First, decide which time zone IDs you are converting from and to.
You said your input time was in Europe, but you didn't specify exactly where. Like the US, Europe has multiple time zones. I'll assume you meant CET/CEST (UTC+1/+2). In Windows, you can use any of the following identifiers for this:
"Central Europe Standard Time"
"Central European Standard Time"
"Romance Standard Time" (why? who knows.)
"W. Europe Standard Time" (don't get fooled by the name, it's still central)
These are all the same (in Windows) except for their display names. If you want to be precise in which one you pick, refer to the CLDR reference.
For the US Central time zone, use "Central Standard Time".
Then just use the TimeZoneInfo.ConvertTimeBySystemTimeZoneId function, as follows:
# collect your input (through db, or whatever mechanism you have)
$inputDateTime = Get-Date -Date "2017-06-27 00:00:00"
# pick your time zones
$fromTimeZone = "Central Europe Standard Time" # EU
$toTimeZone = "Central Standard Time" # USA
# convert
$outputDateTime = [System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId(
$inputDateTime, $fromTimeZone, $toTimeZone)
# output
Write-Output $outputDateTime
I know this is an older thread, but I actually needed to be able to determine whether or not it's DST currently. We have a server whose local TZ is set to UTC (which doesn't see DST) and have an automation that needs to be able to know when it's 4pm local time. So the script is all in UTC, but I can then add an hour or not based on the value of the result of this beast:
$DST = ([System.TimeZoneInfo]::ConvertTimeFromUtc(
(get-date).ToString(),
[System.TimeZoneInfo]::FindSystemTimeZoneById("Central Standard Time")
)).isdaylightsavingtime()
Cole, I love the inspiration as your response was a needle in a haystick and just what I needed. However, it produced an error. After some messing around, I got the following to work:
$isDST = ([System.TimeZoneInfo]::ConvertTimeFromUtc((Get-Date).ToUniversalTime(), [System.TimeZoneInfo]::FindSystemTimeZoneById("Central Standard Time"))).IsDaylightSavingTime()
(in PowerShell v4)
i am running the following command in a cmd:
Prog.exe -time Components_2016_04_19_11.ss
I want to write a batch file that will be run hourly and i need the date in the command to change accordingly - the date needs to be in the format above, and the last part of the date is the current hour minus 7 hours
So if the time now is 1/1/2016 20:43 the command will look like this
Prog.exe -time Components_2016_01_01_13.ss
i need help creating the appropriate batch file
Thanks
For future reference, questions resembling "Write this for me. Here are my requirements." aren't well-received around here. But this time, just to prevent any more unhelpful answers from being posted, I'll help you out with a solution.
Pure batch is really cumbersome with date math. Compensating for midnight, month changes, leap years, etc. can be a nightmare. It's much easier to use a different language -- one which has a proper Date object that will handle calendar quirks without having to hack around them.
Here's a PowerShell solution to your problem:
Prog.exe -time ("Components_{0}.ss" -f (Get-Date).addHours(-7).toString("yyyy_MM_dd_HH"))
That's it, just a one-liner. If you require a batch script, you can employ the PowerShell helper to perform the date math heavy lifting.
#echo off & setlocal
for /f "delims=" %%I in (
'powershell -noprofile "(Get-Date).addHours(-7).toString('yyyy_MM_dd_HH')"'
) do (
Prog.exe -time Components_%%I.ss
)
goto :EOF
Get-Date
Get-Date | Get-Member
you can use this:
$GBL = 0
do{
Prog.exe
Get-Date
sleep 3600
}
while($GBL -lt 1)
$GBL it's a infinity variable for the loop. inside of the do execute the program and use the sleep for wait 3600 seconds or 1 hour for execute again. Get-Date it's for mark the date and time when the code it's executed.
I don't understand if you need this or something else.
You can modify the line of Prog.exe with the code you need.
If you answer me i can help you.
Have a good day (:
My script reads a log file once a minute and selects (and acts upon) the lines where the timestamp begins with the previous minute.
This is easy (the regex is simply "^$timestamp"), but when the log gets big it can take a while.
My thinking is the lines I want will always be near the bottom of the file, so I'd be searching far fewer lines if I started at the bottom and searched upwards, stopping when I get to the minute prior to the one I'm interested in.
My question is, how can I search from the bottom of the file instead of the top? Can I even say "read line $length", or even "read line n" (if so I could do a sort of binary search thing to find the length of the file and work backwards from there)?
Last question: would this even be faster (I'd still like to know how to do it even if it wouldn't be faster)?
Ideally, I'd like to do this all in my own code without installing anything extra.
Thanks
get-content bigfile.txt -tail 10
This words on huge files nearly instantly without any big memory usage.
I did it with a 22 GB text file in my testing.
Doing something like "get-context bigfile.txt | select -Last 10" works but it seems to have to load all of the lines (or objects in powershell) then does the select.
May I suggest just changing the regex to equal Get-Date + whatever time period you want?
For example (and this is without your log so i apologize)
$a = Get-Date
$hr = $a.Hour
$min = $a.Minute
Then work off those values to build out the regex to select the times you want. And if you don't already use it this website is awesome for building regex's quickly and easily http://gskinner.com/RegExr/ .
Got another fix, I think you will like this..
$a = get-content .\biglog.text
Use the length to slice the array from back to front change write host to select-string and your regex or whatever you want to do in reverse..
foreach($x in $a.length..0){ write-host $a[$x] }
Another option after the get-content cmdlet again, this option just reverse orders the array then you are reading $a from bottom to top
[array]::Reverse($a)
dc
If you only want the last bit of the file, depending on the format, you can just do this:
Get-Content C:\Windows\WindowsUpdate.log | Select -last 10
This will return the last 10 lines found in the file.
I am looking to limit the percentage of the CPU time used by a PowerShell process to a certain number -- for the sake of argument, let's imagine it to be 13%.
Other options that are not precisely what I need:
1) Setting priority.
2) Setting CPU affinity.
Basically, we have monitoring software which complains if the total CPU usage gets too high. We have a daily process that sets this off -- mostly harmlessly, but too many false positives in a monitoring system and people become inured to warnings/errors when we do not wish that.
The process itself gets lsass.exe very excited, too, as it runs, and other processes happen, as well.
I do not know PowerShell and am attempting to fix Somebody Else's Powershell. Obviously, a ground-up rewrite would be nice at some future point, but for now, bells are ringing and annoying people.
What you're asking for isn't really possible. The Windows kernel is in charge of scheduling the CPU -- and rightfully so. (I for one don't want to return to real-mode DOS).
The best you can do is insert a long Sleep() in between each line of the script. But there's no guarantee that any particular Powershell cmdlet / function / etc will throttle itself the way you want. The Windows API calls that ultimately execute each statement's dirty work certainly won't.
Ironically, Raymond touched on this topic just a few days ago: http://blogs.msdn.com/oldnewthing/archive/2009/07/27/9849503.aspx
My real suggestion is to modify your script so it looks like:
try {
Stop-CpuMonitor
# ...the current script contents...
}
finally {
Start-CpuMonitor
}
From my experience, there's not a way to stipulate what percentage of the CPU Powershell will get to use. I think the best course of action would be to set the priority of Powershell to Low to allow other tasks/programs to go first. I think the first post has a decent suggestion of using the pauses (I'd upvote, but I'm below the 15 reputation points to do so) and that's something you might look into, but I don't think it will give you the control you're looking for. Sorry my answer is more of a suggestion than a resolution.
/matt
I sincerely doubt there is a particularly simple way to accomplish what you are asking. If CPU concern is a big deal, I would combine a couple of tactics and let the scheduler take care of the rest - it is actually pretty good at managing the load.
The suggestion using ThreadPriority is a bit problematic as PowerShell with spawn each new command in a new Thread, which you could get around by having everything encapsulated on a single line, a cmdlet, or a function of some sort. Better to send the whole powershell process to idle:
Get-Process -name powershell | foreach { $_.PriorityClass = "Idle" }
Note: that will send ALL powershell instances to idle, which may not be the desired effect. And certainly doesn't prevent a script from boosting its own priority either.
Also, as mentioned here - littering your code with sleep commands can be an efficient way to ensure other processes have ample CPU time to process their code. Even 50-100ms is almost an eternity to a processor.
[System.Threading.Thread]::Sleep(50)
Between these two tactics your script will run when it is available, and graciously bow to other CPU demands as they arise.
While I know of no way to actually limit the usage of any process to a particular amount of CPU consumption by percentage, I figured maybe one could alter the priority of the PowerShell thread. So I wrote a quick script and ran a test.
The result was that in both "Normal" and "Lowest", the time taken was about the same. Looking at the CPU meter widget, the CPU usage taken was approximately 27%, but I was running on a quad core box, so that's not surprising. It was taking all of one CPU in both cases. My machine wasn't doing much else at the time, so that was the other 2%, I guess.
Perhaps the results will vary on a busier machine.
Here's the script:
function Spin
{
param($iterations)
for($i = 0; $i -lt $iterations; ++$i)
{
# Do nothing
}
}
$thread = [System.Threading.Thread]::CurrentThread
Write-Host $thread.Priority
$start = [DateTime]::Now
Write-Host "[$start] Start"
Spin 10000000
$end = [DateTime]::Now
Write-Host "[$end] End"
$span = $end - $start
Write-Host "Time: $span"
$thread.Priority = "Lowest"
Write-Host $thread.Priority
$start = [DateTime]::Now
Write-Host "[$start] Start"
Spin 10000000
$end = [DateTime]::Now
Write-Host "[$end] End"
$span = $end - $start
Write-Host "Time: $span"
$thread.Priority = "Normal"
And here's the result:
Normal
[08/06/2009 08:12:38] Start
[08/06/2009 08:12:55] End
Time: 00:00:16.7760000
Lowest
[08/06/2009 08:12:55] Start
[08/06/2009 08:13:11] End
Time: 00:00:16.8570000
Notice also that in the documentation for Thread.Priority it states:
Operating systems are not required to honor the priority of a thread.
A possibility may be using process lasso. I have had nothing but positive results over automatic throttling of processes not excluded by me when the CPU usage surpasses a certain percentage.
Keep in mind that there is a fairly limited free version that you can use to test, if it works for you.
PS: I am not working for anybody. I'm just offering a program that has worked for me in the past.
Use AddType on a C# script literal, which again uses P/Invoke to call the Win32 functions CreateJobObject, SetInformationJobObject (passing a JOBOBJECT_CPU_RATE_CONTROL_INFORMATION) and AssignProcessToJobObject. It will probably be easier to write a wrapper program in C that sets the limits and spawn off the PowerShell script in such a job.