user618: Let's imagine I have a pgn file with each game starting from a tactical position, and I want to identify the games where the solution was the only one. Basically an engine would have to evaluate several possible moves, and the evaluation margin between the first best move and the second best move would have to be above a certain threshold (e.g. >3.00 pawns). I do not want to load up manually every game and look at the engine evaluation - that's the step I am hoping to eliminate.
I am interested to hear of any GUI based solutions, or even script based (e.g. modifications to this - http://sourceforge.net/p/scid/mailman/message/29220017/ - I like this script, but can't get it up and running easily because SCID TCL interpreter on Windows seems to come without Expect package ...)

user4362: It is not too difficult to do this with a python script:
You basically start the engine as a subprocess and communicate via "uci".
I'll post some not very pretty code snippets and try to explain what you have to do:
engine=subprocess.Popen('./stockfish-5-        64',universal_newlines=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE,)

def put(command):
    print command
    engine.stdin.write(command+'\n')

    if command!='quit':
        engine.stdin.write('isready\n')
        while(True):
            text=engine.stdout.readline().strip()   
            print
            print text
            print
            if text == 'readyok':
                return

def get():
    engine.stdin.write('isready\n')
    while(True):
        text=engine.stdout.readline().strip()
        print text
        if text == 'readyok':
            break
        if text !='':
            print text

def getResult(depth):
    Result=[]
    while(True):
        text=engine.stdout.readline().strip()   
        liste=text.split()  
        if text[:22]=="info depth "+str(depth)+" seldepth" and liste[15]=='1':
            Result=[]
        if text[:22]=="info depth "+str(depth)+" seldepth":
            Result.append(text)


        if text[:8] == 'bestmove':
            break

    Scores=[]
    for line in Result:
        liste=line.split()
        Scores.append(liste[7])     

    return Scores

def Game_Analysis(game):
    scorestring=''
    moves=''
    for x in range(len(game)-1):
        moves+=game[x]+' '
        command='position startpos moves '+moves
        put(command)    
        get()
        put('go depth 15')
        Scores=getResult(15)
        for score in Scores:
            scorestring+=score+' '
        scorestring+='\n'
    return scorestring


get()
put('uci')
get()
put('setoption name MultiPV value 20')      
get()

print Game_Analysis(game)

put('stop')
put('quit')

So, get() and put() are for communicating with the engine. 
put('uci') starts the dialog.
put('setoption name MultiPV value 20') tells the engine to return the best twenty moves. (In your case you really only need 2)
command='position startpos moves '+moves
put(command)  This sets up the position, unfortunately the moves aren't pgn but in uci-format. So you'll probably have to transcribe or use FEN.
In GetResult() I extract the 20 best scores of the position. Then you only need to look for a big difference between move one and move two.
Game_Analysis(game) extracts the 20 best scores for every position in a game, here given as a list of uci-formated moves.
To deal with the uci-format and really understand these commands you should have a look at the uci=Universal Chess Interface.

618: <p>Let's imagine I have a pgn file with each game starting from a tactical position, and I want to identify the games where the solution was the only one. Basically an engine would have to evaluate several possible moves, and the evaluation margin between the first best move and the second best move would have to be above a certain threshold (e.g. >3.00 pawns). I do not want to load up manually every game and look at the engine evaluation - that's the step I am hoping to eliminate.</p>

<p>I am interested to hear of any GUI based solutions, or even script based (e.g. modifications to this - <a href="http://sourceforge.net/p/scid/mailman/message/29220017/" rel="nofollow">http://sourceforge.net/p/scid/mailman/message/29220017/</a> - I like this script, but can't get it up and running easily because SCID TCL interpreter on Windows seems to come without Expect package ...)</p>
 4362: <p>It is not too difficult to do this with a python script:
You basically start the engine as a subprocess and communicate via "uci".
I'll post some not very pretty code snippets and try to explain what you have to do:</p>

<pre><code>engine=subprocess.Popen('./stockfish-5-        64',universal_newlines=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE,)

def put(command):
    print command
    engine.stdin.write(command+'\n')

    if command!='quit':
        engine.stdin.write('isready\n')
        while(True):
            text=engine.stdout.readline().strip()   
            print
            print text
            print
            if text == 'readyok':
                return

def get():
    engine.stdin.write('isready\n')
    while(True):
        text=engine.stdout.readline().strip()
        print text
        if text == 'readyok':
            break
        if text !='':
            print text

def getResult(depth):
    Result=[]
    while(True):
        text=engine.stdout.readline().strip()   
        liste=text.split()  
        if text[:22]=="info depth "+str(depth)+" seldepth" and liste[15]=='1':
            Result=[]
        if text[:22]=="info depth "+str(depth)+" seldepth":
            Result.append(text)


        if text[:8] == 'bestmove':
            break

    Scores=[]
    for line in Result:
        liste=line.split()
        Scores.append(liste[7])     

    return Scores

def Game_Analysis(game):
    scorestring=''
    moves=''
    for x in range(len(game)-1):
        moves+=game[x]+' '
        command='position startpos moves '+moves
        put(command)    
        get()
        put('go depth 15')
        Scores=getResult(15)
        for score in Scores:
            scorestring+=score+' '
        scorestring+='\n'
    return scorestring


get()
put('uci')
get()
put('setoption name MultiPV value 20')      
get()

print Game_Analysis(game)

put('stop')
put('quit')
</code></pre>

<p>So, get() and put() are for communicating with the engine. </p>

<p>put('uci') starts the dialog.</p>

<p>put('setoption name MultiPV value 20') tells the engine to return the best twenty moves. (In your case you really only need 2)</p>

<p>command='position startpos moves '+moves<br>
put(command)  This sets up the position, unfortunately the moves aren't pgn but in uci-format. So you'll probably have to transcribe or use FEN.</p>

<p>In GetResult() I extract the 20 best scores of the position. Then you only need to look for a big difference between move one and move two.</p>

<p>Game_Analysis(game) extracts the 20 best scores for every position in a game, here given as a list of uci-formated moves.</p>

<p>To deal with the uci-format and really understand these commands you should have a look at the uci=Universal Chess Interface.</p>
