JavaまたはJava Native Accessを使用してローカルで開いているMS Wordドキュメントのテキストを読み取る方法

アルナブダッシュ:

ローカルで開いているMSWord文書のテキストを読むという問題の声明があります。私が理解していることは、次のアプローチを使用すると、ドキュメントのパスが与えられれば、ドキュメント内の任意の操作を実行できます。

https://github.com/java-native-access/jna/blob/master/contrib/msoffice/src/com/sun/jna/platform/win32/COM/util/office/Wordautomation_KB_313193_Mod.java

しかし、私の場合、ローカルに開かれたwordオブジェクトへのハンドル(WinDef.HWND)があります。そして、そこからローカルパスを取得できません私が試しているコードを指定しましたが、私が探しているものを達成できません。上記の解決策をどのようにして達成できるかをポインタで教えてください。

WINWORD.EXEのパスは次のとおりです。そしてSystem.out.println("File Path: "+desktop.getFilePath());


import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.DesktopWindow;
import com.sun.jna.platform.FileUtils;
import com.sun.jna.platform.WindowUtils;
import com.sun.jna.platform.WindowUtils.NativeWindowUtils;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.Kernel32Util;
import com.sun.jna.platform.win32.WinUser;
import com.sun.jna.win32.StdCallLibrary;

import java.util.List;

public class NativeWordpadExtractor {
    public static void main(String ar[]){
        executeNativeCommands();
    }
    public static void executeNativeCommands(){
        NativeExtractor.User32 user32 = NativeExtractor.User32.INSTANCE;
        user32.EnumWindows(new WinUser.WNDENUMPROC() {
            int count = 0;
            @Override
            public boolean callback(WinDef.HWND hWnd, Pointer arg1) {
                byte[] windowText = new byte[512];
                user32.GetWindowTextA(hWnd, windowText, 512);
                String wText = Native.toString(windowText);

                // get rid of this if block if you want all windows regardless of whether
                // or not they have text
                if (wText.isEmpty()) {
                    return true;
                }
                if("SampleTextForScreenScrapping_Word - WordPad".equals(wText)){
                    System.out.println("Got the 'Wordpad'" + hWnd + ", class " + hWnd.getClass() +"getPointer"+ hWnd.getPointer()+ " Text: " + wText);
                    //WinDef.HWND notePadHwnd = user32.FindWindowA("Wordpad",null  );
                    byte[] fileText = new byte[1024];

                    System.out.println("fileText : " + WindowUtils.getWindowTitle(hWnd));
                    List<DesktopWindow> desktops=WindowUtils.getAllWindows(true);
                    // Approach 1) For getting a handle to the Desktop object . I am not able to achieve result with this.
                    for(DesktopWindow desktop:desktops){
                        System.out.println("File Path: "+desktop.getFilePath());
                        System.out.println("Title : "+desktop.getTitle());
                    }
                    System.out.println("fileText : " + WindowUtils.getAllWindows(true));
                    // Approach 2) For getting a handle to the native object .
                    // This is also not working 
                    WinDef.HWND editHwnd = user32.FindWindowExA(hWnd, null, null, null);
                    byte[] lParamStr = new byte[512];
                    WinDef.LRESULT resultBool = user32.SendMessageA(editHwnd, NativeExtractor.User32.WM_GETTEXT, 512, lParamStr);
                    System.out.println("The content of the file is : " + Native.toString(lParamStr));
                    return false;
                }
                System.out.println("Found window with text " + hWnd + ", total " + ++count + " Text: " + wText);
                return true;
            }
        }, null);

    }
    interface User32 extends StdCallLibrary {
        NativeExtractor.User32 INSTANCE = (NativeExtractor.User32) Native.loadLibrary("user32", NativeExtractor.User32.class);
        int WM_SETTEXT = 0x000c;
        int WM_GETTEXT = 0x000D;
        int GetWindowTextA(WinDef.HWND hWnd, byte[] lpString, int nMaxCount);
        boolean EnumWindows(WinUser.WNDENUMPROC lpEnumFunc, Pointer arg);
        WinDef.HWND FindWindowA(String lpClassName, String lpWindowName);
        WinDef.HWND FindWindowExA(WinDef.HWND hwndParent, WinDef.HWND hwndChildAfter, String lpClassName, String lpWindowName);
        WinDef.LRESULT SendMessageA(WinDef.HWND paramHWND, int paramInt, WinDef.WPARAM paramWPARAM, WinDef.LPARAM paramLPARAM);
        WinDef.LRESULT SendMessageA(WinDef.HWND editHwnd, int wmGettext, long l, byte[] lParamStr);
        int GetClassNameA(WinDef.HWND hWnd, byte[] lpString, int maxCount);
    }
}


ダニエルウィディス:

あなたがあなたが望むことを達成できるかどうかはよくわかりませんが、私はあなたの質問に答えてあなたが目標に近づくようにできる限りのことをします。

ファイル情報を取得する方法は2つあります。1つはJava / JNAを使用する一般的な方法、もう1つはプロセスのメモリ空間内をピアリングする必要がある方法です。最初の問題を取り上げます。

ウィンドウハンドルを処理するのではなく、後で使いやすいプロセスIDを取得しましょう。それは比較的簡単です:

IntByReference pidPtr = new IntByReference();
com.sun.jna.platform.win32.User32.INSTANCE.GetWindowThreadProcessId(hWnd, pidPtr);
int pid = pidPtr.getValue();

(注目すべきは、おそらくUser32上記の1つを拡張する独自のインターフェースを用意して、1つのクラスを使用するだけで、私が行ったようにJNAバージョンを完全に修飾する必要がないことです。)

PIDで武装した今、パスを取得しようとするいくつかのオプションがあります。

  1. 運が良ければ、ユーザーが([ファイル]> [開く]を使用するのではなく)ファイルを直接開いた場合は、ユーザーが使用したコマンドラインを回復でき、パスが表示される可能性があります。これはWMIクラスから取得できますWin32_ProcessWindowsOperatingSystemクラスの私のプロジェクトOSHI 見つけることができる完全なコードまたはRuntime.getRuntime().exec()コマンドラインWMIバージョンを使用wmic path Win32_Process where ProcessID=1234 get CommandLineして、結果をキャプチャすることができますBufferedReader(または実装のOSHIのExecutingCommandクラス参照してください)。

  2. コマンドラインチェックが失敗した場合は、そのプロセスによって開かれているファイルハンドルを検索できます。これを行う最も簡単な方法は、ハンドルユーティリティをダウンロードして(ただし、すべてのユーザーがこれを行う必要があります)、コマンドラインを実行することhandle -p 1234です。これにより、そのプロセスによって保持されている開いているファイルが一覧表示されます。

  3. ユーザーがHandleをダウンロードすることに依存できない場合は、同じコードを自分で実装してみることができます。これは、を使用した文書化されていないAPI NtQuerySystemInformationです。オペレーティングシステムのすべてのハンドルを反復処理してファイルを確認できるサンプルコードについては、JNAプロジェクトの問題657参照してくださいすでにPIDを知っている場合、pidと一致しSYSTEM_HANDLE sh = info.Handles[i];ない限り、コードの残りの部分をスキップすることで、反復を短縮できsh.ProcessIDます。その問題で述べられているように、リストされているコードはほとんどサポートされておらず危険です。Windowsの将来のバージョンで動作するという保証はありません。

最後に、プロセスメモリで何ができるかを確認できます。PIDで武装すると、プロセスを開いてハンドルを取得できます。

HANDLE pHandle = Kernel32.INSTANCE.OpenProcess(WinNT.PROCESS_QUERY_INFORMATION, false, pid);

次に、EnumProcessModulesを使用してそのモジュールを列挙できますモジュールごとにGetModuleInformationを使用してMODULEINFO構造を取得しますこれは、あなたがあなたの心の内容に探求することができるメモリへのポインタを提供します。もちろん、どのオフセットでどの情報を見つけるかを正確に知るには、探索している実行可能ファイル(Word、ワードパッドなど)のAPIと、適切なバージョンが必要です。また、管理者権限が必要です。この調査は、読者のための演習として残されています。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ