AutoHotKey_Lで、標準出力を得たい……。

 以前見つけた関数だと上手く動かないことがあったのでフォーラム検索したら、もっと新しいやつを見つけた。見つけたんだが、標準出力が多いと文字化けすることが発覚。ReadFileでバイト単位で取得したデータをそのままデコードしてるせいだと思うが、AHKで文字列でないデータを操作とか苦行の予感がするので、Fileオブジェクトで文字単位で取得してごまかした。
 文字化けはなくなったが、本当にこれで問題ないのかは解らん。

; https://autohotkey.com/board/topic/54559-stdin/#entry687172

  MsgBox % sOutput := StdoutToVar_CreateProcess("tasklist /s " A_ComputerName)

StdoutToVar_CreateProcess(psCmd, psInput="", psEncoding:="CP0", psDir:="", ByRef pnExitCode:=0) {
  
  DllCall("CreatePipe", PtrP, hStdInRd, PtrP, hStdInWr, Ptr, 0, UInt, 0)
  DllCall("CreatePipe", PtrP, hStdOutRd, PtrP, hStdOutWr, Ptr, 0, UInt, 0)
  DllCall("SetHandleInformation", Ptr, hStdInRd, Uint, 1, Uint, 1)
  DllCall("SetHandleInformation", Ptr, hStdOutWr, UInt, 1, UInt, 1)
  
   VarSetCapacity(pi, (A_PtrSize == 4) ? 16 : 24, 0)
  siSz := VarSetCapacity(si, (A_PtrSize == 4) ? 68 : 104, 0)
  NumPut(siSz, si, 0, "UInt")
  NumPut(0x100, si, (A_PtrSize == 4) ? 44 : 60, "UInt")
  NumPut(hStdInRd, si, (A_PtrSize == 4) ? 56 : 80, "Ptr")
  NumPut(hStdOutWr, si, (A_PtrSize == 4) ? 60 : 88, "Ptr")
  NumPut(hStdOutWr, si, (A_PtrSize == 4) ? 64 : 96, "Ptr")
  
  If (!DllCall("CreateProcess", Ptr, 0, Ptr, &psCmd, Ptr, 0, Ptr, 0, Int, True, UInt, 0x08000000
   , Ptr, 0, Ptr, psDir ? &psDir : 0, Ptr, &si, Ptr, &pi))
   return
   , DllCall("CloseHandle", Ptr, hStdOutWr)
   , DllCall("CloseHandle", Ptr, hStdOutRd)
   , DllCall("CloseHandle", Ptr, hStdInRd)
  
  DllCall("CloseHandle", Ptr, hStdOutWr ) ; The write pipe must be closed before reading the stdout.
  
  if (psInput != "")
   FileOpen(hStdInWr, "h", psEncoding).Write(psInput)
   DllCall("CloseHandle", "Ptr", hStdInWr)
  
  
; ################################################################################
  
  
  StdOutBuf := FileOpen(hStdOutRd, "h", psEncoding)
  StrBuf := 1
  while StrLen(StrBuf) {
   StrBuf := StdOutBuf.Read(2047)
   sOutPut .= StrBuf
  }
  
  
; ################################################################################
  
  
  DllCall("GetExitCodeProcess", Ptr, NumGet(pi, 0), UIntP, pnExitCode)
  DllCall("CloseHandle", Ptr, NumGet(pi, 0) )
  DllCall("CloseHandle", Ptr, NumGet(pi, A_PtrSize) )
  DllCall("CloseHandle", Ptr, hStdOutRd )
return sOutput
}


[PR]
by LordNoesis | 2016-02-09 20:00 | テクノロジ | Trackback | Comments(0)

AutoHotKey_Lで、標準出力を得る方法。

 新しいの

 AHKでCUIアプリの吐く標準出力を得る方法が分からんかったので調べたらフォーラムにあったのでメモ。

 日本語環境用にラスト1行だけ書き換えた。

; http://www.autohotkey.com/board/topic/15455-stdouttovar/page-8#entry540600

MsgBox % sOutput := StdoutToVar_CreateProcess("tasklist /s " A_ComputerName)

StdoutToVar_CreateProcess(sCmd, bStream = False, sDir = "", sInput = "") {
  DllCall("CreatePipe", "UintP", hStdInRd , "UintP", hStdInWr , "Uint", 0, "Uint", 0)
  DllCall("CreatePipe", "UintP", hStdOutRd, "UintP", hStdOutWr, "Uint", 0, "Uint", 0)
  DllCall("SetHandleInformation", "Uint", hStdInRd , "Uint", 1, "Uint", 1)
  DllCall("SetHandleInformation", "Uint", hStdOutWr, "Uint", 1, "Uint", 1)
  VarSetCapacity(pi, 16, 0)
  NumPut(VarSetCapacity(si, 68, 0), si)  ; size of si
  NumPut(0x100 , si, 44)      ; STARTF_USESTDHANDLES
  NumPut(hStdInRd , si, 56)    ; hStdInput
  NumPut(hStdOutWr, si, 60)    ; hStdOutput
  NumPut(hStdOutWr, si, 64)    ; hStdError
  If Not DllCall("CreateProcess", "Uint", 0, "Uint", &sCmd, "Uint", 0, "Uint", 0, "int", True, "Uint", 0x08000000, "Uint", 0, "Uint", sDir ? &sDir : 0, "Uint", &si, "Uint", &pi)  ; bInheritHandles and CREATE_NO_WINDOW
    ExitApp
  DllCall("CloseHandle", "Uint", NumGet(pi,0))
  DllCall("CloseHandle", "Uint", NumGet(pi,4))
  DllCall("CloseHandle", "Uint", hStdOutWr)
  DllCall("CloseHandle", "Uint", hStdInRd)
  If sInput <>
  DllCall("WriteFile", "Uint", hStdInWr, "Uint", &sInput, "Uint", StrLen(sInput), "UintP", nSize, "Uint", 0)
  DllCall("CloseHandle", "Uint", hStdInWr)
  bStream ? (bAlloc:=DllCall("AllocConsole"),hCon:=DllCall("CreateFile","str","CON","Uint",0x40000000,"Uint",bAlloc ? 0 : 3,"Uint",0,"Uint",3,"Uint",0,"Uint",0)) : ""
  VarSetCapacity(sTemp, nTemp:=bStream ? 64-nTrim:=1 : 4095)
  Loop
    If DllCall("ReadFile", "Uint", hStdOutRd, "Uint", &sTemp, "Uint", nTemp, "UintP", nSize:=0, "Uint", 0)&&nSize
    {
      NumPut(0,sTemp,nSize,"Uchar"), VarSetCapacity(sTemp,-1), sOutput.=sTemp
      If bStream&&hCon+1
        Loop
          If RegExMatch(sOutput, "[^\n]*\n", sTrim, nTrim)
            DllCall("WriteFile", "Uint", hCon, "Uint", &sTrim, "Uint", StrLen(sTrim), "UintP", nSize:=0, "Uint", 0)&&nSize ? nTrim+=nSize : ""
          Else Break
    }
    Else Break
  DllCall("CloseHandle", "Uint", hStdOutRd)
  bStream ? (DllCall("Sleep","Uint",1000),hCon+1 ? DllCall("CloseHandle","Uint",hCon) : "",bAlloc ? DllCall("FreeConsole") : "") : ""
  Return StrGet(&sOutput,"CP932")
}

 なんで探してたかって、es.exe(コマンドライン版Everything)をAHKから使いたかったんすよ。これでSearchResult := StdoutToVar_CreateProcess("es.exe 検索文字列")とかやれば超便利。

 例えば、以前書いたパスリストをX-Finderのクリップフォルダに変換するスクリプトと組み合わせるとか? テキスト介せばlist2xf.exeでも同じことできるけど。


[PR]
by lordnoesis | 2014-06-10 20:20 | テクノロジ | Trackback | Comments(0)
ブログトップ | ファンになる