سؤال

أرغب في الاستعلام عن خدمة البحث في نظام التشغيل Windows Vista مباشرة (أو غير مباشر) من Java.

أعلم أنه من الممكن الاستعلام باستخدام بروتوكول Search-MS: ولكني أود أن أستهلك النتيجة داخل التطبيق.

لقد وجدت معلومات جيدة في ويندوز بحث API. ولكن لا شيء يرتبط جافا.

وأود أن موضحة كما قبلت الإجابة التي توفر معلومات مفيدة ونهائية حول كيفية تحقيق هذا.

شكرا لك مقدما.

تعديل

هل لدى أي شخص عينة يعقوب، قبل أن أتمكن من وضع علامة على هذا كما هو مقبول؟ :)

هل كانت مفيدة؟

المحلول

قد ترغب في إلقاء نظرة على أحد تقنيات تكامل Java-Com. لقد عملت شخصيا مع يعقوب (جافا كوم جسر):

التي كانت مرهقة إلى حد ما (اعتقد عمل حصريا مع انعكاس)، ولكن حصلت على الوظيفة من أجلي (إثبات سريع للمفهوم، والوصول إلى MapPoint من داخل Java).

هذه التكنولوجيا الأخرى الوحيدة التي أدركها هي جووين، لكن ليس لدي أي تجربة شخصية معها:

التحديث 04/26/2009:فقط من أجل هيك، أجريت المزيد من البحث في بحث Microsoft Windows، ووجدت طريقة سهلة للتكامل معها باستخدام OLE DB. إليك بعض الكود الذي كتبته كدليل على المفهوم:

public static void main(String[] args) {
    DispatchPtr connection = null;
    DispatchPtr results = null;
    try {
        Ole32.CoInitialize();
        connection = new DispatchPtr("ADODB.Connection");
        connection.invoke("Open",
            "Provider=Search.CollatorDSO;" +
            "Extended Properties='Application=Windows';");
        results = (DispatchPtr)connection.invoke("Execute",
            "select System.Title, System.Comment, System.ItemName, System.ItemUrl, System.FileExtension, System.ItemDate, System.MimeType " +
            "from SystemIndex " +
            "where contains('Foo')");
        int count = 0;
        while(!((Boolean)results.get("EOF")).booleanValue()) {
            ++ count;
            DispatchPtr fields = (DispatchPtr)results.get("Fields");
            int numFields = ((Integer)fields.get("Count")).intValue();

            for (int i = 0; i < numFields; ++ i) {
                DispatchPtr item =
                    (DispatchPtr)fields.get("Item", new Integer(i));
                System.out.println(
                    item.get("Name") + ": " + item.get("Value"));
            }
            System.out.println();
            results.invoke("MoveNext");
        }
        System.out.println("\nCount:" + count);
    } catch (COMException e) {
        e.printStackTrace();
    } finally {
        try {
            results.invoke("Close");
        } catch (COMException e) {
            e.printStackTrace();
        }
        try {
            connection.invoke("Close");
        } catch (COMException e) {
            e.printStackTrace();
        }
        try {
            Ole32.CoUninitialize();
        } catch (COMException e) {
            e.printStackTrace();
        }
    }
}

لتجميع هذا، ستحتاج إلى التأكد من أن Jawin Jar في Classpath الخاص بك، وأن jawin.dll موجود في طريقك (أو Java.Library.Path الخاصية). يقوم هذا الرمز ببساطة بتفتح اتصال ADO بفهرس بحث سطح مكتب Windows المحلي، واستفسارات للمستندات مع الكلمة الأساسية "foo"، وطباعة عدد قليل من الخصائص الرئيسية على المستندات الناتجة.

اسمحوا لي أن أعرف إذا كان لديك أي أسئلة، أو احتاجني لتوضيح أي شيء.

التحديث 04/27/2009:حاولت تنفيذ نفس الشيء في يعقوب كذلك، وسوف أفعل بعض المعايير لمقارنة اختلافات الأداء بين الاثنين. قد أفعل شيئا خاطئا في يعقوب، لكن يبدو أنه يستخدم باستمرار ذاكرة 10X أخرى. سأعمل على تنفيذ JCOM و COM4J أيضا، إذا كان لدي بعض الوقت، وحاول معرفة بعض عمليات التراجع التي أعتقد أنها بسبب نقص سلامة الخيط في مكان ما. قد أحاول حتى حل يستند إلى JNI. أتوقع أن يتم ذلك مع كل شيء في 6-8 أسابيع.

التحديث 04/28/2009:هذا مجرد تحديث لأولئك الذين كانوا متابعين والفضولين. اتضح أنه لا توجد مشكلات خيوط، أحتاج إلى إغلاق موارد قاعدة البيانات الخاصة بي بشكل صريح، حيث من المفترض أن تكون اتصالات OLE DB مجمعة على مستوى نظام التشغيل (ربما أغلقت الاتصالات على أي حال ...). لا أعتقد أنني سأكون أي تحديثات أخرى لهذا. اسمحوا لي أن أعرف ما إذا كان أي شخص يعمل في أي مشاكل مع هذا.

تحديث 05/01/2009:وأضاف مثال جاكوب حسب طلب أوسكار. يمر هذا بالتسلسل نفسه بالضبط من المكالمات من منظور كوم، فقط باستخدام يعقوب. في حين أن يعقوب صحيح يعمل بشكل فعال بكثير في الآونة الأخيرة، إلا أنني لاحظت أيضا أنها خنزير ذاكرة تماما (يستخدم 10X أكبر قدر ممكن من الذاكرة كإصدار Jawin)

public static void main(String[] args) {
    Dispatch connection = null;
    Dispatch results = null;

    try {
        connection = new Dispatch("ADODB.Connection");
        Dispatch.call(connection, "Open",
            "Provider=Search.CollatorDSO;Extended Properties='Application=Windows';");
        results = Dispatch.call(connection, "Execute",
            "select System.Title, System.Comment, System.ItemName, System.ItemUrl, System.FileExtension, System.ItemDate, System.MimeType " +
            "from SystemIndex " +
            "where contains('Foo')").toDispatch();
        int count = 0;
        while(!Dispatch.get(results, "EOF").getBoolean()) {
            ++ count;
            Dispatch fields = Dispatch.get(results, "Fields").toDispatch();
            int numFields = Dispatch.get(fields, "Count").getInt();

            for (int i = 0; i < numFields; ++ i) {
                Dispatch item =
                    Dispatch.call(fields, "Item", new Integer(i)).
                    toDispatch();
                System.out.println(
                    Dispatch.get(item, "Name") + ": " +
                    Dispatch.get(item, "Value"));
            }
            System.out.println();
            Dispatch.call(results, "MoveNext");
        }
    } finally {
        try {
            Dispatch.call(results, "Close");
        } catch (JacobException e) {
            e.printStackTrace();
        }
        try {
            Dispatch.call(connection, "Close");
        } catch (JacobException e) {
            e.printStackTrace();
        }
    }
}

نصائح أخرى

كما أقترح عدد قليل من الوظائف هنا يمكنك الجسر بين Java و .NET أو COM باستخدام أطر تجارية أو مجانية مثل Jacob و Jnbridge و J-Integra وما إلى ذلك. في الواقع كان لدي تجربة مع واحدة من هذه الأطراف الثالثة (واحدة باهظة الثمن :-) ) ويجب أن أقول أنني سأبذل قصارى جهدي لتجنب تكرار هذا الخطأ في المستقبل. والسبب هو أنه ينطوي على العديد من الأشياء "الفودو" التي لا يمكنك تصحيحها حقا، من المعقدة للغاية لفهم ما هي المشكلة عندما تسوء الأمور.

الحل الذي أقترح عليك أن تنفذه هو إنشاء تطبيق .NET بسيط يجعل المكالمات الفعلية ل Windows Search API. بعد القيام بذلك، تحتاج إلى إنشاء قناة اتصال بين هذا المكون ورمز Java الخاص بك. يمكن القيام بذلك بطرق مختلفة، على سبيل المثال من خلال المراسلة إلى DB صغير سيسحب تطبيقك بشكل دوري. أو تسجيل هذا المكون على الجهاز IIS (إذا كان موجودا) وفضح واجهة برمجة تطبيقات WS بسيطة للتواصل معها.

أعلم أنه قد يبدو مرهقا مرهقا ولكن المزايا الواضحة هي: أ) يمكنك التواصل مع واجهة برمجة تطبيقات Windows بحث باستخدام اللغة التي تفهمها (.NET أو COM)، B) يمكنك التحكم في جميع مسارات التطبيق.

أي سبب لماذا لا يمكنك فقط استخدام Runtime.exec() للاستعلام عن طريق search-ms وقراءة BufferedReader مع نتيجة الأمر؟ علي سبيل المثال:

public class ExecTest {
    public static void main(String[] args) throws IOException {
        Process result = Runtime.getRuntime().exec("search-ms:query=microsoft&");

        BufferedReader output = new BufferedReader(new InputStreamReader(result.getInputStream()));
        StringBuffer outputSB = new StringBuffer(40000);
        String s = null;

        while ((s = output.readLine()) != null) {
            outputSB.append(s + "\n");
            System.out.println(s);
        }

        String result = output.toString();
    }
}

هناك العديد من المكتبات هناك لاستدعاء كائنات COM من Java، بعضها مفتوحة (لكن منحنى التعلم أعلى) بعض المصدر مغلقة ولديه منحنى تعليمي أسرع. مثال مصادر مغلقة هو إزكوم. وبعد يميل التجاريون إلى التركيز على استدعاء جافا من النوافذ أيضا، وهو شيء لم أره في OpenSource.

في قضيتك، ما أقترح عليك القيام به هو الدعوة في فئة .NET الخاصة بك (أعتقد أن استخدام C # كما هو الأقرب إلى Java دون الدخول في J # مثيرة للجدل)، والتركيز على جعل قابلية التشغيل البيني مع .NET DLL وبعد وبهذه الطريقة تصبح برمجة Windows أسهل، والواجهة بين Windows و Java هي أبسط.

إذا كنت تبحث عن كيفية استخدام مكتبة Java COM، فإن MSDN هو المكان الخطأ. لكن MSDN سيساعدك على كتابة ما تحتاجه من داخل .NET، ثم انظر إلى برامج تعليم مكتبة COM حول استدعاء الطريق أو طريقتين تحتاجه من كائنات .NET الخاصة بك.

تعديل:

بالنظر إلى النقاش في الإجابات حول استخدام خدمة ويب، يمكنك (وربما سيكون لديك حظ أفضل) قم بإنشاء تطبيق .NET صغير يستدعي خادم ويب Java المضمن بدلا من محاولة جعل .NET لديك خدمة الويب المضمنة، ولديها جافا يكون المستهلك للدعوة. للحصول على خادم ويب مضمن، أظهر بحثي Winstone لتكون جيدا. ليس أصغر، ولكنه أكثر مرونة.

الطريق للحصول على ذلك للعمل هو إطلاق تطبيق .NET من Java، ويحصل على تطبيق .NET استدعاء خدمة الويب على جهاز مؤقت أو حلقة لمعرفة ما إذا كان هناك طلب، وإذا كان هناك، فإنه ترسل الإجابة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top