14
$fullnamexp = ((net user $winxp /domain | Select-String "Full Name") -replace "Full Name","").Trim();

If $winxp cannot be found, the command will hang, is there a timeout I can use with this to make it move on after 5-10 seconds? Not sure where I would put it.

Edit- I use this to pull the username:

$reg  = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $tag1)
$key  = $reg.OpenSubKey('SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon')
$winxp = $key.GetValue('DefaultUserName') -replace '^.*?\\'

$winxp is then a login name such as ajstepanik then I put it into: $fullnamexp = ((net user $winxp /domain | Select-String "Full Name") -replace "Full Name","").Trim();

1.21.2014 Update

 $timeoutSeconds = 5
$code = {
    ((net user $winxp /domain | Select-String "Full Name") -replace "Full Name","").Trim(); # your commands here, e.g.
}
$j = Start-Job -ScriptBlock $code
if (Wait-Job $j -Timeout $timeoutSeconds) { $fullnamexp = Receive-Job $j }
Remove-Job -force $j
2
  • Is this something your doing a single instance of, or are are you doing several iterations of differnt users in a loop? Commented Jan 17, 2014 at 2:10
  • I am using the above command in one powershell script twice, one for windows xp, one for windows 7, and the script will only be able to work for 1 of the two, so one will hang and I want it to timeout faster. The bigger script pulls the login name and this line I have posted here translates that username to the full name of the person, but since Im having the bigger script check the registry of winxp and win7, it will only find one or the other which is why I wanted the timeout if possible.. Commented Jan 17, 2014 at 2:12

6 Answers 6

27

While @mjolinor may have indeed provided you an alternative approach, here is a direct answer to your general question: how do you force a timeout in PowerShell?

Wrap whatever you wish to time-limit in a script block, run that as a job, then use the Wait-Job cmdlet to time-limit the operation. Wait-Job will return either at the end of the timeout period or when the script block completes, whichever occurs first. After Wait-Job returns, you can examine the job state ($j.state) to determine whether it was interrupted or not, if it matters to you.

$timeoutSeconds = 5 # set your timeout value here
$j = Start-Job -ScriptBlock {
    # your commands here, e.g.
    Get-Process
    }
"job id = " + $j.id # report the job id as a diagnostic only
Wait-Job $j -Timeout $timeoutSeconds | out-null
if ($j.State -eq "Completed") { "done!" }
elseif ($j.State -eq "Running") { "interrupted" }
else { "???" }
Remove-Job -force $j #cleanup

2014.01.18 Update

Here is a bit more streamlining approach that also includes the practical step of getting information out of the script block with Receive-Job, assuming what you want is generated on stdout:

$timeoutSeconds = 3
$code = {
    # your commands here, e.g.
    Get-ChildItem *.cs | select name
}
$j = Start-Job -ScriptBlock $code
if (Wait-Job $j -Timeout $timeoutSeconds) { Receive-Job $j }
Remove-Job -force $j
Sign up to request clarification or add additional context in comments.

8 Comments

So on line 3 I would just put the command I have my my original post? (the very first thing in the post)
@Aaron: That's correct--with a slight caveat. I have updated my answer to be slightly more useful to you. In the update, fill in the $code block with your commands except for the actual assignment of the output to $fullnamexp. Where you see Receive-Job, do your assignment there, i.e. $fullnamexp = Receive-Job $j.
Hi, I added an update to original post, can you tell me if that is the correct way to put it? I have it like that but it doesn't output anything but it does however wait the amount of seconds I specify.
Close; you need two corrections: (1) The assignment should be on Receive-Job rather than Remove-Job. (2) The text Get-ChildItem *.cs | select name was merely my sample--remove that from your code.
Hey, I updated my post with the fixed code. Can you verify it is correct? I have tested with that code and I do not see any output from it, but I just want to verify it's accurate.
|
6

You can use Start-Sleep to pause the script:

Start-Sleep -s 5

1 Comment

While this answer is correct as stated, it does not address the question. It is just a sleep, not a timeout.
1

net doesn't explicitly allow you to set a time out on it's operations, but you could check out this link on changing the ipv4 timeout for your sockets:

http://www.cyberciti.biz/tips/linux-increasing-or-decreasing-tcp-sockets-timeouts.html

The only thing else I could imagine is spawning a worker thread but I don't even know if that's possible in bash, I'm not fluid enough in it to answer that; plus it opens you up to sync problems and all sorts of multi threaded issues beyond what you're trying to accomplish quickly in a bash script to begin with! :P

Comments

1

Does this help?

$query = (dsquery user -samid $winxp) 
if ($query) {$fullnamexp = ($query | dsget user -display)[1].trim()}
$fullnamexp

6 Comments

Am I to replace what I have with this?
Yes. I believe it will produce the same result (returning the user full name) but doesn't hang if the user is not found.
the $winxp variable going in for example is "ajstepanik" and the line in my OP will take that and turn it into my name(Stepanik, Aaron J. etc etc) when it finds it. Doesn't seem to do that with yours :( I will keep trying it though.
Yeah, I can't get it to work. Doesn't output anything but a blank space. the input is just the username, it should work..
I don't know what's wrong then. I can set $winxp to a samaccountname, and it works fine on my system.
|
1

This solution doesn't work for me. remove-job -force $j takes over 5 seconds in this example.

$timeoutseconds = 1

$start = get-date
$j = start-job -scriptblock { Resolve-DnsName  1.1.1.1 }
if (wait-job $j -timeout $timeoutseconds) { $fullnamexp = receive-job $j } 
remove-job -force $j 
(get-date) - $start


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 5
Milliseconds      : 342
Ticks             : 53426422
TotalDays         : 6.18361365740741E-05
TotalHours        : 0.00148406727777778
TotalMinutes      : 0.0890440366666667
TotalSeconds      : 5.3426422
TotalMilliseconds : 5342.6422

Here's a simple timeout example with notepad:

notepad
if (-not $(wait-process notepad 10; $?)) { stop-process -name notepad }

Comments

0
    $watchdog = 10 #seconds
    $start_time = Get-Date
    $j = Start-Job -ScriptBlock{
        #timeout command
        if ($true) {
            $i = 0
            while($true) {
                Write-Host "Count: $i"
                Start-Sleep -Milliseconds 100
                $i++
            }      
        }
        write-host "Hello"
    }
    while($true) {
        if ($j.HasMoreData) {
            Receive-Job $j
            Start-Sleep -Milliseconds 200
        }
        $current = Get-Date
        $time_span = $current - $start_time
        if ($time_span.TotalSeconds -gt $watchdog) {
            write-host "TIMEOUT!"
            Stop-Job $j
            break
        }
        if (-not $j.HasMoreData -and $j.State -ne 'Running') {
            write-host "Finished"
            break
        }
    }
    Remove-Job $j

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.