Menu

Passing /C to command.com for custom URL handler

Help
2018-08-20
2018-08-22
  • Albert Chin-A-Young

    I have a custom URL handler that calls a .bat file which then launches PuTTY. When the .bat file executes, a cmd.exe window appears which then launches PuTTY. I know I can pass /c to cmd.exe to avoid the creation of the cmd.exe window. Can I tell KeePass to invoke cmd.exe with /C?

     
  • wellread1

    wellread1 - 2018-08-20

    Can I tell KeePass to invoke cmd.exe with /C?

    Use cmd://cmd.exe /C

    For more information see Executing command lines in the KeePass URL Field Capabilities documentation.

     
  • Paul

    Paul - 2018-08-21

    Put exit at the end of your batch file.

    cheers, Paul

     
  • Albert Chin-A-Young

    Thanks. I modified my URL-handler to:

    cmd://cmd.exe /C "H:\pamssh.bat" {BASE:RMVSCM}
    

    but the command window still appears followed by the Putty window. Is there a way to avoid the command window appearing? I presume cmd://cmd.exe has Keepass invoking cmd.exe with /C rather than the initial cmd.exe being passed /C to avoid the command window.

     

    Last edit: Albert Chin-A-Young 2018-08-21
  • wellread1

    wellread1 - 2018-08-21

    Did you add the exit to the end of your batch file?

     
    • Albert Chin-A-Young

      I have EXIT /b at the end of the file.

       
  • wellread1

    wellread1 - 2018-08-21

    When you run your batch file outside of KeePass, does the console window stay open until you exit PuTTY?

     
    • Albert Chin-A-Young

      cmd invocation of pamssh.bat

      If I execute my script from the cmd promp as above, only the Putty window appears.

       
  • Albert Chin-A-Young

    Attached is the .bat script. It just launches putty with a temporary file that contains "root@<servername>". This temporary file is removed once putty terminates.</servername>

    @ECHO off
    
    SETLOCAL EnableExtensions EnableDelayedExpansion
    
    SET pamSSHRelayServer=SERVERNAME
    SET pamSSHRelayPort=PORT
    
    IF "%~1" == "" ECHO No server name specified
    IF "%~1" == "" EXIT /b
    
    SET "usernameUpper=%USERNAME%"
    
    CALL :toUpper usernameUpper
    
    REM Get unique file name
    :uniqLoop
    SET "uniqueFileName=%tmp%\putty~%RANDOM%.tmp"
    IF EXIST "%uniqueFileName%" GOTO :uniqLoop
    
    ECHO root@%1 >%uniqueFileName%
    putty -ssh -t -P %pamSSHRelayPort% %usernameUpper%@%pamSSHRelayServer%^
     -m %uniqueFileName%
    DEL %uniqueFileName%
    EXIT /b
    
    REM Functions
    :toUpper str -- converts lowercase character to uppercase
    ::           -- str [in,out] - valref of string variable to be converted
    :$created 20060101 :$changed 20080219 :$categories StringManipulation
    :$source https://www.dostips.com
    IF NOT DEFINED %~1 EXIT /b
    FOR %%a IN ("a=A" "b=B" "c=C" "d=D" "e=E" "f=F" "g=G" "h=H" "i=I"
                "j=J" "k=K" "l=L" "m=M" "n=N" "o=O" "p=P" "q=Q" "r=R"
                "s=S" "t=T" "u=U" "v=V" "w=W" "x=X" "y=Y" "z=Z") do (
        CALL SET %~1=%%%~1:%%~a%%
    )
    EXIT /b
    
     

    Last edit: Albert Chin-A-Young 2018-08-21
  • Paul

    Paul - 2018-08-21

    Have you tried just:
    cmd://H:\pamssh.bat {BASE:RMVSCM}

    cheers, Paul

     
    • Albert Chin-A-Young

      Yes. I did that initially. I get the cmd window and then the Putty window. Both windows remain open until Putty terminates.

       
  • wellread1

    wellread1 - 2018-08-21

    When you run a batch file, the console window is going to stay open until the job is finished. There is nothing KeePass can do about that.

     
  • Dominik Reichl

    Dominik Reichl - 2018-08-21

    The /C command line option tells cmd.exe to execute the command that follows and terminate afterwards. It doesn't hide the cmd.exe window.

    PowerShell scripts and commands can more easily be executed invisibly (by running PowerShell.exe with the -WindowStyle Hidden command line parameter); maybe you could convert your batch file to a PowerShell script or run your batch file using PowerShell.

    Another solution would be to use the {CMD:...} placeholder (which can run applications with a hidden window, see [1] for details) together with running a GUI dummy executable (like consent.exe), e.g.
    cmd://consent.exe {CMD:!"H:\pamssh.bat" {BASE:RMVSCM}!W=0,WS=H!}
    (that's a bit of a hack; the PowerShell way is cleaner).

    Best regards,
    Dominik

    [1] https://keepass.info/help/base/placeholders.html#cmd

     

    Last edit: Dominik Reichl 2018-08-21
    • Albert Chin-A-Young

      Ok, thanks.

       
    • Albert Chin-A-Young

      I modified my URL handler to:

      cmd://powershell.exe -WindowStyle Hidden "H:\pamssh.bat" {BASE:RMVSCM}
      

      A cmd window appears (to run powershell) but then disappears and then Putty is launched. Wish the cmd window never appeared but that's probably the best that can be achieved with trying to execute a .bat file. Might try to rewrite in .vbs to eliminate this window all-together. Thanks everyone for the help.

       
  • Paul

    Paul - 2018-08-22

    Here's a PowerShell version for you.
    I've not tested the whole thing together but the parts are all OK. Comment the test command and un-comment the real command when you've tested it.

    cheers, Paul

    # PS variables are local by default
    # check command line argument
    if (-Not ($Args[0])) {Break}
    
    # set required values
    $pamSSHRelayServer = SERVERNAME
    $pamSSHRelayPort = PORT
    $usernameUpper = "$env:USERNAME".ToUpper()
    
    # create a random file name; Get-Random -Maximum 99999 -minimum 1000
    do {$uniqueFileName = $env:tmp + "\putty~" + (Get-Random -Maximum 99999 -minimum 1000) + ".tmp"} While (Test-Path "$uniqueFileName")
    
    # create command file
    Write-Output "root@" + $Args[0] | Add-Content $uniqueFileName
    
    # test command. comment out these 2 lines after testing
    Write-Output "putty -ssh -t -P $pamSSHRelayPort $usernameUpper@$pamSSHRelayServer^  -m $uniqueFileName"
    pause
    
    # run puTTY
    ##& putty -ssh -t -P $pamSSHRelayPort $usernameUpper@$pamSSHRelayServer^  -m $uniqueFileName
    
    #clean up
    DEL $uniqueFileName
    
     
    • Albert Chin-A-Young

      Wow! Thanks. Seems simpler than the vbscript version I wrote yesterday::

      Dim userName
      Dim fso, tmp, absTmpPath
      Dim objArgs, destServer
      Dim objShell
      
      Const pamSSHRelayServer = SERVERNAME
      Const pamSSHRelayPort = PORT
      
      ' Class for temporary file. Contains folder and name of temporary
      ' file so we can remove once PuTTY terminates.
      Class TmpFile
        public Folder
        public Name
        public fh
      End Class
      
      ' Function to create temporary file and return TmpFile class. File
      ' object not returned because we cannot remove the file based on
      ' the file object. Rather, we need the full path to the temporary
      ' file.
      Function CreateTempFile
        Dim tmp
        Const tmpFolderType = 2
      
        Set tmp = new TmpFile
        Set tmp.Folder = fso.GetSpecialFolder (tmpFolderType)
        tmp.Name = fso.GetTempName
        Set tmp.fh = tmp.Folder.CreateTextFile (tmp.Name)
        Set CreateTempFile = tmp
      End Function
      
      Set fso = CreateObject ("Scripting.FileSystemObject")
      
      ' Only allowable argument is server name to ssh to. Error
      ' otherwise and display usage informatiopn.
      Set objArgs = WScript.Arguments
      If objArgs.Count <> 1 Then
        MsgBox "No server name specified" & vbCrLf & vbCrLf & _
          WScript.ScriptName & ": " & WScript.ScriptName & " <server name>"
        WScript.Quit
      End If
      destServer = objArgs (0)
      
      ' Take username from login session
      userName = UCase (CreateObject ("WScript.Network").UserName)
      
      Set tmp = CreateTempFile
      tmp.fh.WriteLine "root@" & destServer
      tmp.fh.Close
      absTmpPath = fso.BuildPath (tmp.Folder, tmp.Name)
      
      Set fso = CreateObject ("Scripting.FileSystemObject")
      Dim strPath
      
      Set objShell = CreateObject ("WScript.shell")
      strPath = "putty -ssh -t "
      strPath = strPath + "-P " & pamSSHRelayPort & " "
      strPath = strPath + userName & "@" & pamSSHRelayServer & " "
      strPath = strPath + "-m " & absTmpPath
      objShell.Run strPath
      
      ' Wait for process to finish before removing temp file by
      ' scanning list of processes for one with temp file on the
      ' command line. Continue looping until process exits. When
      ' Putty is invoked, control is returned to this script so
      ' need to loop until Putty terminates.
      Dim objWMIService
      Dim proc, procs
      Dim puttyIsDone
      
      Set objWMIService = GetObject ("winmgmts:\\.\root\cimv2")
      
      puttyIsDone = False
      Do While (Not puttyIsDone)
        ' Check every second if Putty still running
        WScript.Sleep (1000)
      
        Set procs = objWMIService.ExecQuery(_
          "Select * from Win32_Process",,48)
      
        puttyIsDone = True
        For Each proc in procs
          If InStr (proc.CommandLine, absTmpPath) > 0 Then
            puttyIsDone = False
            Exit For
          End If
        Next
      Loop
      
      ' Remove tmp file after Putty terminates
      fso.DeleteFile (absTmpPath)
      
       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.