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
phuclv
  • 37,963
  • 15
  • 156
  • 475
Aaron
  • 3,135
  • 20
  • 51
  • 78
  • Is this something your doing a single instance of, or are are you doing several iterations of differnt users in a loop? – mjolinor Jan 17 '14 at 02: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.. – Aaron Jan 17 '14 at 02:12

6 Answers6

24

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
Michael Sorens
  • 35,361
  • 26
  • 116
  • 172
  • So on line 3 I would just put the command I have my my original post? (the very first thing in the post) – Aaron Jan 18 '14 at 16:07
  • 1
    @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`. – Michael Sorens Jan 18 '14 at 23:04
  • 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. – Aaron Jan 20 '14 at 11:59
  • 1
    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. – Michael Sorens Jan 21 '14 at 00:24
  • 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. – Aaron Jan 21 '14 at 17:06
  • That looks fine so _if_ your code completes in less than 5 seconds, then your variable should have its output. – Michael Sorens Jan 21 '14 at 19:42
  • Hm well without the timeout it would go instantly. Now when I run it, it does its 5 seconds, then doesn't output the full name. Maybe I should have it check to see if its windows xp or 7, then do another command based on that instead.. – Aaron Jan 21 '14 at 21:21
6

You can use Start-Sleep to pause the script:

Start-Sleep -s 5
Roman O
  • 3,172
  • 30
  • 26
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

Dan H
  • 606
  • 4
  • 6
1

Does this help?

$query = (dsquery user -samid $winxp) 
if ($query) {$fullnamexp = ($query | dsget user -display)[1].trim()}
$fullnamexp
mjolinor
  • 66,130
  • 7
  • 114
  • 135
  • Am I to replace what I have with this? – Aaron Jan 17 '14 at 02:52
  • 1
    Yes. I believe it will produce the same result (returning the user full name) but doesn't hang if the user is not found. – mjolinor Jan 17 '14 at 02:54
  • 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. – Aaron Jan 17 '14 at 03:08
  • 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.. – Aaron Jan 17 '14 at 16:00
  • I don't know what's wrong then. I can set $winxp to a samaccountname, and it works fine on my system. – mjolinor Jan 17 '14 at 16:10
  • what's dsquery and dsget? – AnneTheAgile Jan 25 '16 at 15:11
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 }
js2010
  • 23,033
  • 6
  • 64
  • 66
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
pico
  • 1,660
  • 4
  • 22
  • 52