ฉันจะหาเส้นทางของโปรแกรม“ Python.exe” ที่ใช้โดย ArcMap ได้อย่างไร


16

ฉันกำลังทำงานกับ Add-in ของ ArcMap ใน C # จากรหัส C # ฉันได้เรียกใช้งานสคริปต์ Python ตอนนี้เพื่อเรียกใช้สคริปต์เหล่านี้ฉันมีเส้นทางหลามแบบตายตัว แต่นี่ไม่ใช่พกพา ดังนั้นฉันต้องการได้รับเส้นทางของการปฏิบัติการ Python จากรหัสและใช้งาน

คำถาม:

ฉันจะได้รับเส้นทางของการปฏิบัติการของ Python ที่ใช้โดย ArcMap จากรหัส C # ได้อย่างไร?

แก้ไข:

จากคำแนะนำของคุณตอนนี้ฉันใช้ "สภาพแวดล้อมของเส้นทาง" เพื่อรับเส้นทาง Python

//get python path from environtment variable
string GetPythonPath()
{
    IDictionary environmentVariables = Environment.GetEnvironmentVariables();
    string pathVariable = environmentVariables["Path"] as string;
    if (pathVariable != null)
    {
        string[] allPaths = pathVariable.Split(';');
        foreach (var path in allPaths)
        {
            string pythonPathFromEnv = path + "\\python.exe";
            if (File.Exists(pythonPathFromEnv))
                return pythonPathFromEnv;
        }
    }
}

แต่มีปัญหา:

เมื่อติดตั้งงูหลามรุ่นต่าง ๆ ในเครื่องของฉันไม่มีการรับประกันว่า "python.exe" ที่ฉันใช้คือ ArcGIS ก็ใช้เช่นกัน

ฉันไม่ซาบซึ้งที่ใช้เครื่องมืออื่นเพื่อรับเส้นทาง"python.exe" ดังนั้นฉันคิดว่าถ้ามีวิธีที่จะได้รับเส้นทางจากคีย์รีจิสทรี สำหรับรีจิสทรี"ArcGIS10.0"ดูเหมือนว่า: ป้อนคำอธิบายรูปภาพที่นี่

และสำหรับสิ่งนั้นฉันกำลังคิดเกี่ยวกับวิธีต่อไปนี้เพื่อให้ได้เส้นทาง:

//get python path from registry key
string GetPythonPath()
{
    const string regKey = "Python";
    string pythonPath = null;
    try
    {
        RegistryKey registryKey = Registry.LocalMachine;
        RegistryKey subKey = registryKey.OpenSubKey("SOFTWARE");
        if (subKey == null)
            return null;

        RegistryKey esriKey = subKey.OpenSubKey("ESRI");
        if (esriKey == null)
            return null;

        string[] subkeyNames = esriKey.GetSubKeyNames();//get all keys under "ESRI" key
        int index = -1;
     /*"Python" key contains arcgis version no in its name. So, the key name may be 
     varied version to version. For ArcGIS10.0, key name is: "Python10.0". So, from
     here I can get ArcGIS version also*/
        for (int i = 0; i < subkeyNames.Length; i++)
        {
            if (subkeyNames[i].Contains("Python"))
            {
                index = i;
                break;
            }
        }
        if(index < 0)
            return null;
        RegistryKey pythonKey = esriKey.OpenSubKey(subkeyNames[index]);

        string arcgisVersion = subkeyNames[index].Remove(0, 6); //remove "python" and get the version
        var pythonValue = pythonKey.GetValue("Python") as string;
        if (pythonValue != "True")//I guessed the true value for python says python is installed with ArcGIS.
            return;

        var pythonDirectory = pythonKey.GetValue("PythonDir") as string;
        if (pythonDirectory != null && Directory.Exists(pythonDirectory))
        {
            string pythonPathFromReg = pythonDirectory + "ArcGIS" + arcgisVersion + "\\python.exe";
            if (File.Exists(pythonPathFromReg))
                pythonPath = pythonPathFromReg;
        }  
    }
    catch (Exception e)
    {
        MessageBox.Show(e + "\r\nReading registry " + regKey.ToUpper());
        pythonPath = null;
    }
    return pythonPath ;
}

แต่ก่อนที่จะใช้ขั้นตอนที่สองฉันต้องแน่ใจเกี่ยวกับการคาดเดาของฉัน คาดเดาคือ:

  1. "จริง" ที่เกี่ยวข้องกับหลามหมายถึงงูใหญ่ถูกติดตั้งกับ ArcGIS
  2. ArcGIS 10.0 และรีจิสตรีคีย์ของเวอร์ชั่นที่สูงกว่าจะถูกเขียนในกระบวนการเดียวกัน

โปรดช่วยฉันให้ได้คำอธิบายเกี่ยวกับการเดาของฉัน


5
คุณได้พิจารณาการสร้างเครื่องมือสคริปต์และดำเนินการจาก ArcObjectsหรือไม่?
blah238

3
คุณไม่เพียงตั้งค่าตัวแปรสภาพแวดล้อม PATH เป็น ArcGIS Python exe เป็นข้อกำหนดในการติดตั้งสำหรับ Add-In ของคุณหรือไม่?
Chad Cooper

ทั้งหมดกล่าวว่าความคิดของ @ ChadCooper จะต้องเป็นวิธีที่ดีที่สุด แทนที่จะพยายามทำงานย้อนหลังให้ตั้งค่าเพียงครั้งเดียวและตลอดเวลาที่ติดตั้ง
elrobis

@ elrobis: ฉันรู้ว่าการตั้งค่าเส้นทางในสภาพแวดล้อมของเส้นทางเป็นวิธีที่ดี แต่ฉันอยากรู้ว่ามีวิธีใดในการค้นหาไพ ธ อนและทำทุกอย่างโดยไม่ขัดจังหวะผู้ใช้
Emi

@ blah238 ขอบคุณสำหรับคำแนะนำของคุณ ฉันไม่เคยทำงานกับเครื่องมือสคริปต์ ฉันอาจจะต้องเรียนรู้เกี่ยวกับมัน
Emi

คำตอบ:


2

ฉันใช้ตัวอย่างรหัสที่สองของคุณทำให้มันทำงานได้ทั้งระบบปฏิบัติการ 64 และ 32 บิตและทำให้มันง่ายขึ้นเล็กน้อย ทำงานได้ดีสำหรับฉันที่ 10.1 บน Windows 7 64 บิต แต่แน่นอนว่าคุณควรทดสอบบนสภาพแวดล้อมที่เป็นไปได้มากที่สุดและเพิ่มการตรวจสอบการเขียนโปรแกรมเชิงป้องกันที่คุณคิดว่าจำเป็น

หลังจากทดสอบการติดตั้ง ArcGIS Desktop 10.1 โดยไม่ต้องใช้ Python ฉันพบว่ามันไม่รวมคีย์ย่อย Python10.x ให้ค่า "Python" จริง / เท็จเพียงอย่างเดียว (ยังไม่แน่ใจว่าสิ่งนั้นมีไว้เพื่อติดต่อฝ่ายสนับสนุน ESRI ถ้าคุณต้อง ทราบ).

string GetPythonPath()
{
    string pythonPath = null;
    var localmachineKey = Registry.LocalMachine;
    // Check whether we are on a 64-bit OS by checking for the Wow6432Node key (32-bit version of the Software registry key)
    var softwareKey = localmachineKey.OpenSubKey(@"SOFTWARE\Wow6432Node"); // This is the correct key for 64-bit OS's
    if (softwareKey == null) {
        softwareKey = localmachineKey.OpenSubKey("SOFTWARE"); // This is the correct key for 32-bit OS's
    }
    var esriKey = softwareKey.OpenSubKey("ESRI");
    var realVersion = (string)esriKey.OpenSubKey("ArcGIS").GetValue("RealVersion"); // Get the "real", canonical version of ArcGIS
    var shortVersion = String.Join(".", realVersion.Split('.').Take(2).ToArray()); // Get just the Major.Minor part of the version number, e.g. 10.1
    var pythonKey = esriKey.OpenSubKey("Python" + shortVersion); // Open the Python10.x sub-key
    if (pythonKey == null) {
        throw new InvalidOperationException("Python not installed with ArcGIS!");
    }
    var pythonDirectory = (string)pythonKey.GetValue("PythonDir");
    if (Directory.Exists(pythonDirectory))
    {
        // Build path to python.exe
        string pythonPathFromReg = Path.Combine(Path.Combine(pythonDirectory, "ArcGIS" + shortVersion), "python.exe");
        if (File.Exists(pythonPathFromReg)) {
            pythonPath = pythonPathFromReg;
        }
    }
    return pythonPath;
}

บนเครื่องเดสก์ท็ 10.1 C:\Python27\ArcGIS10.1\python.exeกับงูหลามผลตอบแทนนี้ บนเครื่องเดสก์ท็อป 10.1 ที่ไม่มี Python สิ่งนี้จะเพิ่ม InvalidOperationException เนื่องจากไม่มีคีย์ Python10.x

หวังว่าสิ่งนี้จะช่วยคุณในทุกสิ่งที่คุณพยายามทำให้สำเร็จซึ่งก็คือ - น่าอัศจรรย์ - ยังไม่ชัดเจนสำหรับฉัน


7

แทนที่จะค้นหา Python ที่สามารถเรียกใช้งานได้หัวข้อวิธีใช้นี้จะแนะนำให้ทำการ shelling cmd.exeและรันpython.exeโดยไม่ต้องระบุตำแหน่ง อย่างไรก็ตามโปรดทราบว่าสิ่งนี้ควรใช้งานได้เนื่องจากตัวติดตั้ง ArcGIS Desktop ติดตั้ง (แก้ไข: ทดสอบล่าสุดที่ 10.1 ไม่ได้)ขึ้นอยู่กับพา ธ ที่จะpython.exeเพิ่มลงในPATHตัวแปรสภาพแวดล้อมของผู้ใช้

อีกวิธีหนึ่งคือการสร้างเครื่องมือสคริปต์และดำเนินการได้จาก ArcObjects

หากคุณจริงๆหลังจากที่เส้นทางไปยังรุ่น ArcGIS ของpython.exeโดยการขยายตัวของ ArcObjects เครื่องหมาย + วิธีการเครื่องมือสคริปต์คุณสามารถสร้างเครื่องมือสคริปต์ Python sys.exec_prefixที่มีการส่งออกเพียงอย่างเดียวคือค่าของ นี่คือเส้นทางของโฟลเดอร์ที่มีรุ่น ArcGIS C:\Python27\ArcGIS10.1ของงูใหญ่เช่น

หมายเหตุด้านข้าง : sys.executableคืนค่าพา ธ ไปArcMap.exeและไม่ใช่python.exeเมื่อเรียกใช้ระหว่างดำเนินการซึ่งเป็นสาเหตุที่ฉันไม่แนะนำให้ใช้ตัวแปรนั้น

เรียกใช้เครื่องมือสคริปต์จาก ArcObjects และรับผลลัพธ์จากIGeoProcessorResultวัตถุที่ส่งคืน

อัปเดต:นี่คือตัวอย่างโครงการ ArcMap Add-in (VS2010, .NET 3.5) ที่ใช้เครื่องมือสคริปต์ที่บรรจุภายใน Add-in ที่แสดงเส้นทางไปยังpython.exeArcMap ที่ใช้โดย: http://wfurl.com/cbd5091

มันเป็นเพียงปุ่มที่คุณคลิกและมันจะเปิดกล่องข้อความขึ้นพร้อมกับเส้นทาง:

ปุ่ม MessageBox

รหัสที่น่าสนใจ:

  • สคริปต์ Python:

    import sys
    import os
    import arcpy
    
    def getPythonPath():
        pydir = sys.exec_prefix
        pyexe = os.path.join(pydir, "python.exe")
        if os.path.exists(pyexe):
            return pyexe
        else:
            raise RuntimeError("No python.exe found in {0}".format(pydir))
    
    if __name__ == "__main__":
        pyexe = getPythonPath()
        arcpy.AddMessage("Python Path: {0}".format(pyexe))
        arcpy.SetParameterAsText(0, pyexe)
  • ฟังก์ชั่น C #:

    public string GetPythonPath()
    {
        // Build the path to the PythonPathToolbox
        string toolboxPath = Path.Combine(Path.GetDirectoryName(this.GetType().Assembly.Location), "PythonPath.tbx");
    
        // Initialize the geoprocessor.
        IGeoProcessor2 gp = new ESRI.ArcGIS.Geoprocessing.GeoProcessorClass();
    
        // Add the PythonPath toolbox.
        gp.AddToolbox(toolboxPath);
    
        // Need an empty array even though we have no input parameters
        IVariantArray parameters = new VarArrayClass();
    
        // Execute the model tool by name.
        var result = gp.Execute("GetPythonPath", parameters, null);
        return result.GetOutput(0).GetAsText();
    }

2
แต่เอกสารนี้ไม่ได้บอกว่าโปรแกรมติดตั้ง ArcGIS Desktop ตั้งค่าพา ธ ไปยัง python.exe กับตัวแปรสภาพแวดล้อม PATH ของผู้ใช้ ดังนั้นจึงเป็นไปได้ว่าเส้นทางของงูหลามไม่ได้อยู่ในตัวแปรสภาพแวดล้อมของเส้นทาง จากนั้นจะสร้างข้อผิดพลาด ดังนั้นฉันจะแน่ใจได้อย่างไรว่า python ที่สามารถเรียกใช้งานได้อยู่ในตัวแปรสภาพแวดล้อม PATH ของผู้ใช้
Emi

2
คุณไม่สามารถทำได้เหมือนกับสิ่งต่าง ๆ ในชีวิตและการคำนวณทั้งหมดที่คุณทำได้คือตั้งสมมติฐานและหวังว่าทุกอย่างจะทำงานได้และมีแผนสำรองเมื่อพวกเขาทำไม่ได้ (ให้คำแนะนำเกี่ยวกับการเพิ่มลงในตัวแปรสภาพแวดล้อม PATH) ที่กล่าวว่าหากเป็นการติดตั้งปกติฉันเชื่อว่าตัวติดตั้ง ArcGIS Desktop เพิ่มพา ธ นั้นไปยังตัวแปรสภาพแวดล้อม PATH
blah238

2
ฉันได้เห็นการติดตั้งมากมายที่งูหลามที่ติดตั้ง arcgis ไม่ได้อยู่ในเส้นทาง และจะเกิดอะไรขึ้นถ้ามีสองรุ่นที่ติดตั้งและอันที่ 'ผิด' อยู่ในพา ธ
blindjesse

ฉันเสนอวิธีแก้ไขปัญหาในย่อหน้าที่ 3 ของฉันที่ควรจะค้นหาการติดตั้ง Python ของ ArcGIS โดยไม่คำนึงถึงPATHตัวแปรสภาพแวดล้อม
blah238

@ blah238 ไม่ได้สร้างเครื่องมือสคริปต์ทำให้ Add-in พกพาของฉันน้อยลงหรือทำให้กระบวนการติดตั้ง Add-in ให้กับเครื่องอื่นยาก
Emi

6

คุณจะสามารถเข้าถึงรีจิสตรีได้หรือไม่?

เมื่อติดตั้ง ArcMap มันจะติดตั้ง Python หากไม่พบ ดูเหมือนว่าในรีจิสทรีเพื่อดูว่า Python ได้รับการติดตั้งแล้ว ฉันเชื่อว่าตำแหน่งรีจิสตรีมาตรฐานสำหรับสิ่งนี้คือ: คอมพิวเตอร์ \ HKEY_LOCAL_MACHINE \ SOFTWARE \ PYTHON \ PythonCore \ 2.7 \ InstallPath ด้วยคีย์เริ่มต้นของตำแหน่งพา ธ (2.7 คือ 10.1, 2.6 กำลัง 10.0)

ฉันไม่สามารถคิดเหตุผลได้เมื่อ / ทำไมค่าของคีย์นี้จะไม่ถูกต้อง แต่คุณสามารถไปทางนี้เสมอ: ภายในกลุ่ม Esri \ Desktop ของรีจิสทรีเป็นที่ตั้งของหลาม เป็นเส้นทางที่ง่ายซึ่งคุณจะได้รับจากนั้นสร้างเส้นทางเพิ่มเติมเพื่อให้แน่ใจว่ามี Python.exe ตัวอย่างเช่นคีย์บนเครื่อง 64 บิตจะได้รับการติดตั้งไปที่: คอมพิวเตอร์ \ HKEY_LOCAL_MACHINE \ SOFTWARE \ Wow6432Node \ ESRI \ Python10.1 ด้วยคีย์ PythonDir และค่าพา ธ ที่เกี่ยวข้อง

แต่ฉันชอบ @ blah238 คำตอบ เพียงเปิดพรอมต์จากโปรแกรมของคุณและเรียกใช้ที่นั่น ฉันไม่เห็นเหตุผลที่จะไม่ทำงาน


2
วิธีการนี้มีข้อบกพร่องเช่นกันเนื่องจากอาจมีการติดตั้ง Python หลายแบบและคุณไม่มีวิธีที่ตรงไปตรงมาในการกำหนดแบบเป็นโปรแกรมโดยทางหนึ่งว่า ArcGIS นั้นใช้วิธีใด หากคุณไม่ได้ใช้งานอาร์คปีสิ่งนี้อาจไม่สำคัญ แต่ถึงกระนั้นฉันคิดว่าทางออกที่แข็งแกร่งที่สุดจะเกี่ยวข้องกับรีจิสทรีและตรรกะเล็กน้อย ฉันจะไม่ไปที่นั่นแม้ว่า
blah238

ตรรกะจะต้องเริ่มต้นด้วยรุ่นใหม่ล่าสุด 2.7 และทำงานย้อนหลัง หลักสูตรนี้อาจล้มเหลวหากคุณติดตั้ง Python เวอร์ชันใหม่จากนั้นไปและติดตั้ง ArcGIS เวอร์ชันเก่าซึ่งจะติดตั้ง Python เวอร์ชันที่เก่ากว่า ดังนั้นใช่ฉันเห็นด้วยมีศักยภาพนี้ แต่ก็ไม่น่าจะเป็นไปได้ (หรือคุณสามารถสร้างการค้นหาของ arc10.1 = py2.7, arc10.0 = py26 ... ฯลฯ เพื่อให้แน่ใจ 100%) ดังที่ฉันได้กล่าววิธีที่ดีที่สุดอาจจะแค่ใช้คำสั่งพรอมต์
KHibma

@KHibma ฉันค้นหาผ่านรีจิสตรี แต่ฉันคิดว่ามันน่ารำคาญจริง ๆ ถ้าฉันดูคีย์ "PYTHON" ในเครื่องของฉันมีรุ่นไพ ธ อนสองตัวติดตั้งอยู่และจะส่งคืนทั้งคู่ ฉันคิดว่ามันเป็นความคิดที่ดีในการค้นหาคีย์ "ESRI" และหากมีคีย์ย่อย "Python" ที่มีค่าจริงฉันสามารถใช้คีย์ย่อยของ "PythonDir" ได้ มันทำงานได้ในกรณีของฉัน :)
อีเอ็มไอ

นี่เป็นวิธีที่ผิดในการค้นหาเส้นทางของหลามในรีจิสตรีผ่านคีย์ "ESRI" หรือไม่? หรือมีโอกาสใด ๆ ที่วิธีที่ ESRI ใช้ในการสร้างคีย์และค่าต่างๆในรีจิสตรีสามารถเปลี่ยนแปลงได้และโค้ดอาจไม่สามารถอ่านได้
Emi

เมื่อฉันพูดว่า "ค้นหา" รีจิสทรีฉันหมายถึงใช้เส้นทางจริงที่ฉันให้ไว้ข้างต้น ถ้าไม่มีใครรู้ดีกว่าตำแหน่งรีจิสตรีคีย์เหล่านี้ (ในรีจิสตรี) จะไม่เปลี่ยนจากเครื่องเป็นเครื่อง ดังนั้นคุณเพียงแค่ฮาร์ดโค้ดพา ธ เพื่อดูว่ามีกุญแจอยู่ที่นั่นหรือ
เปล่า

5

[แก้ไข]ในขณะที่การดำเนินการsetโปรแกรม (หลงออกด้านล่าง) ทำในสิ่งที่ฉันต้องการก็สามารถประสบความสำเร็จได้ง่ายขึ้นและมีรหัสทำความสะอาดโดยใช้Environment.GetEnvironmentVariables ()

ทางเลือกหนึ่งคือการสแกนสภาพแวดล้อมตัวแปรทั้งหมดในระบบและพยายามที่จะพิสูจน์สิ่งต่อไปนี้:

1) ค่าตัวแปรสภาพแวดล้อมเป็นไดเรกทอรีหรือไม่ (และถ้าเป็นเช่นนั้น .. )

2) ไดเรกทอรีนั้นมีpython.exe?

ผมสามารถที่จะทำเช่นนี้โปรแกรมโดยการดำเนินการsetคำสั่งผ่าน .Net กระบวนการ API setคำสั่งเมื่อนำมาใช้โดยไม่ต้องพารามิเตอร์กลับทั้งหมดตัวแปรสภาพแวดล้อมในการใช้งานโดยระบบ ดังนั้นผมจึงสามารถ parase แล้วจัดระเบียบผล STDOUT ที่ปล่อยออกมาจากsetและหน้าจอให้พวกเขาเห็นว่าอะไรใด ๆ (และฉันหมายถึงอะไร ) python.exeพร้อมใช้งานผ่านระบบทรัพยากรธรรมชาติและสิ่งแวดล้อมในท้ายที่สุดชี้ไปที่

จากหน้านี้พูดถึงsetคำสั่ง:

พิมพ์ SET โดยไม่มีพารามิเตอร์เพื่อแสดงตัวแปรสภาพแวดล้อมปัจจุบันทั้งหมด

เพื่อแสดงให้เห็นว่าฉันเขียนการผสมผสานของวิธีการ (และคลาสผู้ช่วย ) ที่ทำสิ่งที่ฉันพูดถึงข้างต้น สิ่งเหล่านี้สามารถปรับให้เหมาะสมและพวกเขาสามารถใช้กระสุนพิสูจน์อักษร (ลอง .. จับได้ ฯลฯ ) แต่ถ้าคอมพิวเตอร์มีตัวแปรสภาพแวดล้อมใด ๆ ชี้ไปที่python.exeวิธีการนี้ควรหามัน! ฉันไม่สนใจถ้า var ที่เรียกว่าPATH, ABBRACADABBRAหรืออะไรก็ตาม .. ถ้ามันชี้ไปpython.exeนี้ควรพบว่ามัน

// C#, you'll need these using statements:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;

นี่termsคืออาร์เรย์ของสตริงที่คุณส่งผ่านไปยังรูทีนเพื่อค้นหาในชื่อของตัวแปรสภาพแวดล้อมหรือnค่าของมัน(เช่นPATHสามารถมีค่าได้หลายค่า แต่ vars อื่น ๆ ส่วนใหญ่จะมีเพียงค่าเดียว) ตรวจสอบให้แน่ใจว่าสตริงทั้งหมดtermsมีค่ามากขึ้น!

(เมื่อฉันทดสอบสิ่งนี้ฉันใช้ "PYTHON" ซึ่งพบได้C:\Python27\python.exeในระบบที่บ้านของฉัน แต่คุณสามารถขยายได้อย่างง่ายดายเพื่อรวมสตริง [] ของคำศัพท์หากคุณต้องการตรวจสอบเส้นทางของpython.exeผู้สมัครที่กลับมาเพิ่มเติม ตัวอย่างเพื่อดูว่าพวกเขาอยู่ในถัง ArcGIS ฯลฯ )

// Top-level method that organizes everything below..
private void scrapeEnvironmentVariables(string[] terms)
{
    // !! ValueObject !! This is a Helper Class, find it at the bottom..
    List<ValueObject> voList = buildListOfEnvironmentObjects();

    foreach (ValueObject vo in voList)
    {
        bool candidateFound = ObjectMatchesSearchTerms(vo, terms);

        if (candidateFound)
        {    
            string exeCandidate = "";
            foreach (string unlikelyPath in vo.values)
            {
                if (Directory.Exists(unlikelyPath))
                {
                    string unlikelyExe = unlikelyPath + "\\python.exe";
                    if(File.Exists(unlikelyExe))
                        exeCandidate = unlikelyExe;
                }

                if (exeCandidate != "")
                {
                    break;
                    // At this point, exeCandidate is a fully-qualified
                    // path to python.exe..
                }
            }

            // If you only want the first hit, break here..
            // As-is, the code will look for even more matches.
            //if (breakOnFirstHit)
            //    break;
        }
    }
}


// Execute Environment.GetEnvironmentVariables() and organize the 
// key..value pairs into 1:n ValueObjects (see Helper Class below).
private List<ValueObject> buildListOfEnvironmentObjects()
{
    // Return a List of 1:n key..value objects.
    List<ValueObject> voList = new List<ValueObject>();

    IDictionary variableDictionary = Environment.GetEnvironmentVariables();
    foreach (DictionaryEntry entry in variableDictionary)
    {
        // Explode multi-values into a List of values (n).
        List<string> values = new List<string>();
        string[] rawValues = ((string)entry.Value).Split(';');
        foreach (string value in rawValues)
            if (value != "") values.Add(value.ToUpper());

        ValueObject valueObject = new ValueObject();
        valueObject.key = ((string)entry.Key).ToUpper();
        valueObject.values = values.ToArray();

        voList.Add(valueObject);
    }
    return voList;
}


// Compare the key and any value(s) in a ValueObject with all the
// terms submitted to the top-level method. If **ALL** the terms
// match (against any combination of key..value), it returns true.
private bool ObjectMatchesSearchTerms(ValueObject vo, string[] terms)
{
    int matchCount = 0;

    foreach (string term in terms)
    {
        if (vo.key.Contains(term))              // screen the key
            matchCount++;

        foreach (string value in vo.values)     // screen N values
        {
            if (value.Contains(term))
                matchCount++;
        }
    }

    // Test against >= because it's possible the match count could
    // exceed the terms length, like if a match occurred in both the
    // key and the value(s). So >= avoids omiting that possibility.
    return (matchCount >= terms.Length) ? true : false;
}    

และที่ด้านล่างของชั้นเรียนหลักของฉันฉันรวมHelper Classดังต่อไปนี้:

class ValueObject : Object
{
    public ValueObject() { } // default constructor

    public string key;
    public string[] values;
}

1
สิ่งนี้มีความบอบบางเนื่องจากผู้ใช้สามารถปรับแต่งไดเรกทอรีการติดตั้ง Python ในโปรแกรมติดตั้ง ArcGIS นอกจากนี้ยังมีPYTHONPATHตัวแปรที่ไม่ได้เป็นคนที่คุณต้องการ
blah238

@ blah238 บางครั้งก็เปราะบางคือทั้งหมดที่คุณมี จริง ๆ แล้วฉันประหลาดใจเมื่อเห็นว่า Arc มีสายกับ PYTHONPATH นั่นคือการติดตั้งเริ่มต้น 9.2 อย่างไรก็ตาม OP ได้ถามว่าจะไปยัง ArcGIS python.exe โดยทางโปรแกรมได้อย่างไรและวิธีที่ฉันแนะนำนั้นเปราะบางหรือไม่นั้น
elrobis

ไม่สามารถพูดว่าฉันเข้าใจการลงคะแนนเสียงคำตอบนี้จริงหรือไม่ " ไม่มีประโยชน์ "? มันอาจจะไม่เจ๋งแต่ก็เป็นตัวเลือกแน่นอนอาจจะใช้ได้กับการติดตั้ง Arc ทั่วไปและอย่างน้อยที่สุดมันเพิ่มสิ่งที่เป็นประโยชน์ต่อเธรด - โดยเฉพาะมันแสดงให้เห็นถึงการติดตั้ง Arc เริ่มต้นที่เชื่อมโยงกับไพ ธ exe PATHกับตัวแปรสภาพแวดล้อมอื่นที่ไม่ใช่
elrobis

ขออภัย แต่คุณไม่ถูกต้อง ตัวแปร PYTHONPATH ถูกใช้โดย Pythonเพื่อค้นหาโมดูลไม่ใช่โดย ArcGIS เพื่อค้นหา Python ตรวจสอบลิงค์
blah238

@ blah238 ฉันคิดว่าภาพหน้าจอล้นหลาม / บดบังจุดที่ฉันพยายามทำ (โดยเฉพาะข้อเสนอแนะของฉันไปยัง OP ไม่ได้ตั้งใจที่จะเน้นPYTHONPATHว่าเกิดขึ้นเป็นvar เดียวในระบบนั้นชี้กลับไปpython.exe) อย่างไรก็ตามฉันปรับปรุงคำตอบของฉันที่จะรวมตัวอย่างรหัส C # ทำงานและฉันจะขอบคุณ รู้ว่าคุณยังไม่เห็นด้วยกับวิธีการนี้ ขอขอบคุณ / E
elrobis

4

ฉันต้องการเสนอโซลูชันทางเลือกตามความคิดเห็นของฉันในคำถามด้านบน สำหรับโครงการปัจจุบันฉันกำลังทำสิ่งที่คล้ายกันมาก ฉันมี. NET Add-In นั้นเมื่อผู้ใช้คลิกปุ่มใน ArcMap UI สคริปต์ Python จะทำงาน ฉันได้ตั้งค่าตัวแปรสภาพแวดล้อมของ PATH ให้เป็นข้อกำหนดสำหรับปฏิบัติการของ ArcGIS Python ดังนั้นฉันจึงไม่ต้องกังวลเกี่ยวกับการรวมเส้นทางไปยัง Python exe ในรหัส. NET ของฉัน

ขณะนี้อยู่ระหว่างการพัฒนาผู้ทดสอบกำลังตั้งค่าตัวแปร PATH ด้วยตนเอง แต่ในที่สุดฉันก็จะมีตัวติดตั้ง Windows (exe) ที่สร้างขึ้นเพื่อติดตั้ง Add-In ติดตั้ง Python dependencies และตั้งค่าตัวแปร PATH ที่จำเป็น สำหรับสิ่งนี้ฉันใช้Nullsoft Scriptable Install System (NSIS)ซึ่งเป็นระบบโอเพ่นซอร์สสำหรับการสร้างตัวติดตั้ง Windows นี่คือรหัสบางส่วนที่ฉันทำงานมาจนถึงตอนนี้ซึ่งค่อนข้างหยาบ โดยทั่วไปจะมองหารีจิสทรีเพื่อดูว่ามีตัวแปร PATH ที่น่าสนใจอยู่หรือไม่ จะต้องมีการเรียกใช้ในฐานะผู้ดูแลระบบแน่นอน

include "StrFunc.nsh"
!include "LogicLib.nsh"

/*
  Name: VIESORE_Installer.nsi
  Author: Chad Cooper, CAST
  Date: 7/16/2012
  Purpose: NSIS installer script for .exe creation by NSIS. Installs VIESORE components and sets up environment.
*/

Name "VIESORE"
Caption "VIESORE Installer"
Outfile "VIESOREInstaller.exe"

RequestExecutionLevel admin

# Initialize functions
${StrLoc}
# Initialize user variables
Var path

Section "Set SYSTEM PATH environmental variables"
    ReadRegStr $0 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "Path"
    ${StrLoc} $1 $0 "C:\Python26\ArcGIS10.0" ">"
    ${StrLoc} $2 $0 "C:\Python26\ArcGIS10.0\Scripts" ">"
        ${StrLoc} $3 $0 "C:\Python26\ArcGIS10.0\Lib\site-packages" ">"
        ${StrLoc} $4 $0 "C:\Program Files\e-on software\Vue 10 Infinite\Application" ">"
        # Test to see if env vars exist in current system PATH, if not add them to $path variable
        ${If} $3 == ""
                StrCpy $path "C:\Python26\ArcGIS10.0\Lib\site-packages"
        ${EndIf}
        ${If} $2 == ""
                StrCpy $path "C:\Python26\ArcGIS10.0\Scripts;$path"
        ${EndIf}
        ${If} $1 == ""
                StrCpy $path "C:\Python26\ArcGIS10.0;$path"
        ${EndIf}
        ${If} $4 == ""
                StrCpy $path "C:\Program Files\e-on software\Vue 10 Infinite\Application;$path"
        ${EndIf}
        DetailPrint "$path written to system PATH"
    WriteRegStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "Path" "$0;$path"
    ReadRegStr $5 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "Path"
    DetailPrint "New Path: $5"
SectionEnd

ดังนั้นอีกครั้งสิ่งนี้ไม่พบเส้นทางไปยัง ArcGIS Python exe แต่ช่วยให้คุณสามารถให้ผู้ใช้ของคุณมีอำนาจในการตั้งค่าอย่างถูกต้องและง่ายดาย


+1 ฉันเห็นด้วยกับคำแนะนำนี้อย่างสมบูรณ์ --- ที่ระดับสูงแช้ดพูดว่า"ไม่ทำงานปัญหาย้อนหลังเพื่ออนุมานอินสแตนซ์หลามของอาร์คแทนที่จะใช้โปรแกรมติดตั้งแล้วปล่อยไว้ที่ SysAdmin เพื่อสร้างไพ ธ อนที่ถูกต้อง ตัวอย่าง." @ChadCooper NSIS ให้การควบคุม UI ใด ๆ แก่คุณหรือไม่เพื่อให้คุณสามารถแทนที่เส้นทางเริ่มต้นเหล่านั้นได้หากคุณเลือก? ฉันไม่เห็นว่ามีนัยโดยรหัส แต่ฉันเดิมพันมันอยู่ที่นั่น
elrobis

@elrobis - ฉันคิดว่าคุณสามารถแทนที่ / แก้ไข / เปลี่ยนแปลงรายการที่มีอยู่ได้ - NSIS นั้นสามารถกำหนดค่าได้อย่างมากและสามารถให้คุณสร้างตัวติดตั้งที่ลื่นไหลได้ - คุณเพียงแค่คิดรหัสเพื่อเขียน
Chad Cooper

การสร้างโปรแกรมติดตั้งสำหรับ Add-in ดูเหมือนจะบ้าไปหน่อย นอกจากนี้คุณจะต้องทำการปรับเปลี่ยนอะไรบ้างเพื่อสนับสนุน 10.1, 10.2 เป็นต้นและ 10.0?
blah238

@ blah238 - ใช่มันดูบ้า แต่ผู้ติดตั้งของฉันสำหรับโปรเจ็กต์นี้จะทำอะไรได้อีกมากมายตามที่ได้พูดคุยกัน Add-In ของฉันมีไว้สำหรับ 10.0 อย่างเคร่งครัด ฉันเดา ArcGIS รุ่นต่าง ๆ ที่คุณสามารถตรวจสอบรีจิสทรีเพื่อดูว่ามีการติดตั้งรุ่นใดแล้วดำเนินการตามนั้น
Chad Cooper
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.