1

はい。複雑。
前提:
FTP 経由で情報を取得する必要がある Access データベースを実行しています。WScriptExec オブジェクトを使用して ftp.exe を実行し、stdOut を読み取って、ディレクトリが作成された日付と時刻を特定します (名前は「d.yymmdd.hhmmss」の形式の日付と時刻であるls d.*ため、サーバーに送信するだけです)。ウィンドウが表示されないようにするか、少なくとも高速に非表示にすることを除いて、コードは機能します。
目的:
ハンドルを見つけて WScriptExec ウィンドウを見つけて操作します (私は本質的に ProcessID を持っていますが、これは明らかに価値がありません)。いいえ、このアプリケーションで .Run を使用してファイルに出力したくない/できません。後でこのようなウィンドウを操作する必要があるかもしれませんが、「この他の方法を使用する」などの回避策なしでそれを行う方法を知りたい.
私が試したこと:
-FindWindow("Console,MSDOS,pretty much any made up class I could think of since I don't know class types", "C:\WINDOWS\system32\ftp.exe, C:\WINDOWS\system32\cmd.exe, ftp.exe, cmd.exe, pretty much every window title you can imagine")これらはすべて、他の引数に vbNullString があります。私が試したすべてに対して0が返されました。
-FindWindowLikeこのリンクから. 私が試したすべてに対して0が返されました。見つかったすべてのウィンドウをポップアップするように変更しましたが、正しいと思われるウィンドウ タイトルが表示されませんでした。したがって、このタイトルは、WScriptExec コマンド プロンプト ウィンドウに表示されるキャプションではないと想定しています。
- GetForegroundWindow. の後でさえ、Access DB ウィンドウを返しますAppActivate objExec.ProcessID

参考までに、WScriptExecオブジェクトの呼び出し方法:(
Set objExec = objShell.Exec("cmd /c ftp -n ftp.server.location")なしでも試しましたがcmd /c、両方とも機能します)

4

2 に答える 2

3

この質問は少し古いかもしれませんが、この回答がまだ役立つ可能性があると思います。(Excel VBA でテスト済み、Access ではテストできませんでした)

usncahillの回答と非常に似ていますが、ウィンドウが読み込まれるのをスリープまたは待機する代わりに、ループを続けてhwndを探し、見つかったらすぐに実行します。

以下のスクリプトは、Exec オブジェクトから ProcessID を取得して、ウィンドウの Hwnd を見つけます。Hwnd を使用すると、ウィンドウの表示状態を設定できます。

Excel 2007 VBA でのテストから、ほとんどの場合、ウィンドウが表示されることさえありません...場合によっては、数ミリ秒間表示されることがありますが、ちらつきや点滅のみが表示されます... 注: を使用すると、より良い結果が得られましたSW_HIDE で行ったよりも SW_MINIMIZE ですが、いじることができます。

「HideWindow」関数の使用方法の例を示すために、TestRoutine Sub を追加しました。「HideWindow」関数は、「GetHwndFromProcess」関数を使用して、ProcessID からウィンドウ hwnd を取得します。

以下をモジュールに配置します...

Option Explicit
'   ShowWindow() Commands
Public Const SW_HIDE = 0
Public Const SW_MINIMIZE = 6
'GetWindow Constants
Public Const GW_CHILD = 5
Public Const GW_HWNDFIRST = 0
Public Const GW_HWNDLAST = 1
Public Const GW_HWNDNEXT = 2
Public Const GW_HWNDPREV = 3
Public Const GW_OWNER = 4
'   API Functions
Public Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
Public Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Public Declare Function GetDesktopWindow Lib "user32" () As Long
Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long


Sub TestRoutine()
    Dim objShell As Object
    Dim oExec As Object
    Dim strResults As String

    Set objShell = CreateObject("WScript.Shell")
    Set oExec = objShell.Exec("CMD /K")
    Call HideWindow(oExec.ProcessID)

    With oExec
        .StdIn.WriteLine "Ping 127.0.0.1"
        .StdIn.WriteLine "ipconfig /all"
        .StdIn.WriteLine "exit"
        Do Until .StdOut.AtEndOfStream
            strResults = strResults & vbCrLf & .StdOut.ReadLine
            DoEvents
        Loop
    End With
    Set oExec = Nothing
    Debug.Print strResults
End Sub


Function HideWindow(iProcessID)
    Dim lngWinHwnd As Long
    Do
        lngWinHwnd = GetHwndFromProcess(CLng(iProcessID))
        DoEvents
    Loop While lngWinHwnd = 0
    HideWindow = ShowWindow(lngWinHwnd, SW_MINIMIZE)
End Function

Function GetHwndFromProcess(p_lngProcessId As Long) As Long
    Dim lngDesktop As Long
    Dim lngChild As Long
    Dim lngChildProcessID As Long
    On Error Resume Next
    lngDesktop = GetDesktopWindow()
    lngChild = GetWindow(lngDesktop, GW_CHILD)
    Do While lngChild <> 0
        Call GetWindowThreadProcessId(lngChild, lngChildProcessID)
        If lngChildProcessID = p_lngProcessId Then
            GetHwndFromProcess = lngChild
            Exit Do
        End If
        lngChild = GetWindow(lngChild, GW_HWNDNEXT)
    Loop
    On Error GoTo 0
End Function

ShowWindow 関数: http://msdn.microsoft.com/en-us/library/windows/desktop/ms633548%28v=vs.85%29.aspx

GetWindow 関数: http://msdn.microsoft.com/en-us/library/windows/desktop/ms633515%28v=vs.85%29.aspx

GetDesktopWindow 関数: http://msdn.microsoft.com/en-us/library/windows/desktop/ms633504%28v=vs.85%29.aspx

GetWindowThreadProcessId 関数: http://msdn.microsoft.com/en-us/library/windows/desktop/ms633522%28v=vs.85%29.aspx

API の仕組みについてさらに詳しい情報が必要な場合は、簡単な Google 検索で大量の情報が得られます。

これが役立つことを願っています...ありがとう。

于 2014-01-09T18:23:30.727 に答える
0

FindWindow("ConsoleWindowClass", vbNullString)ウィンドウをロードできるように十分な遅延が与えられている場合に機能します。

次のコードにより、ユーザーは WScriptExec オブジェクトを非表示にできます。

Public Declare Function ShowWindow Lib "user32" (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Dim objShell As Object, objExec As Object
Dim lngWnd As Long

Set objShell = CreateObject("Wscript.Shell")
Set objExec = objShell.Exec("ftp -n server.location.com")

Pause 0.01
lngWnd = FindWindow("ConsoleWindowClass", vbNullString)
ShowWindow lngWnd, 0
MsgBox lngWnd

wherePauseはプログラムを遅らせるために作成したコードで、値は秒単位です。代わりにWindows APISleepコマンド obvi を使用できます。

このメソッドのテストは、メッセージがポップアップ表示され、コンソール ウィンドウが表示されなくなった場合に成功します。助けてくれた@mehowに感謝します:)

検索で WScriptExec オブジェクト ウィンドウを非表示にしようとしている人をたくさん見てきました。彼らにこの解決策を示すことができれば、少なくとも、長時間の活動のためにウィンドウを非表示にしたい人にとっては役立ちます. この問題に対する本当の答えは、API を使用して手動でコンソール プロセスをロードすることです

于 2013-06-19T11:46:23.870 に答える