C#調用python.exe使用arcpy

背景

環境:ArcGis10.2.2。C#開發程序一直以來以調用Desktop的python環境(32位)來做數據處理分析。但是數據量大時,出現了內存資源不夠的情況。因此決定換成使用64位python環境。

遇到問題

C#通過Process.Start()去調用64位python.exe,在Debug模式下毫無問題,但是直接運行exe就報錯Process finished with exit code -1073741819 (0xC0000005)
指向異常。

分析問題

後來發現是由於arcpy模塊導致的,去掉這個模塊的內容就能運行,import arcpy就運行不起來。既然使用arcpy做數據處理,如果連import arcpy都不行,那還做個屁啊。於是開始尋找程序Debug模式下和Run模式下的區別。

程序中使用ProcessStartInfo類啓動的python.exe的進程,那問題基本就出自這裏了。附上檢測代碼:

var start = new ProcessStartInfo
{
    WorkingDirectory = Environment.CurrentDirectory,
    FileName = sInterpreterPath,
    UseShellExecute = false,
    ErrorDialog = true,
    CreateNoWindow = true,
    RedirectStandardOutput = true,
    RedirectStandardInput = true,
    Arguments = sParam
};
using (Process process = Process.Start(start))
{
    var a = start.Environment;
    var b = a.Keys.ToList();
    b.Sort();
    var sss = "";
    foreach (var it in b)
    {
        sss = $"{sss}\n{it}------->{a[it]}";
    }
    sss = sss.Trim();
    using (StreamReader reader = process.StandardOutput)
    {
        var sResult = "";
        while (!reader.EndOfStream)
        {
            sResult = $"{sResult} \n {reader.ReadLine()}";
        }
        sResult = sResult.Trim();
        MessageBox.Show(sResult);
    }
    MessageBox.Show("ExitCode is " + process.ExitCode);
}

於是就對比了Debug模式下與Run模式下的進程環境變量。
在這裏插入圖片描述
明顯可見兩個環境的__COMPAT_LAYER值就是不一樣的。查了一下__COMPAT_LAYER是版本兼容相關參數,由於我是32位程序調用64位python.exe,因此懷疑是這個參數導致的問題。RunAsAdmin是以管理員運行,而Installer的解釋是安裝工具。

解決問題

上面分析出可能是__COMPAT_LAYER值不同才導致的問題,那麼就能對症下藥了,現在把Run下的值也設置爲RunAsAdmin。加上下例代碼:

start.EnvironmentVariables["__COMPAT_LAYER"] = "RunAsAdmin";
start.Environment["__COMPAT_LAYER"] = "RunAsAdmin";

再次運行,居然成功了。

下面附上C#調用64爲Python.exe處理腳本代碼:

/// <summary>
/// 執行Python腳本
/// </summary>
/// <param name="sScriptPath">腳本路徑</param>
/// <param name="lstParam">參數列表</param>
/// <returns>是否成功</returns>
public bool RunScript(string sScriptPath, List<string> lstParam)
{
    var bResult = false;
    try
    {
        if (!File.Exists(sScriptPath))
            throw new Exception($"文件{sScriptPath}不存在!");

        var sInterpreterPath = @"E:\ArcGIS\Python27\ArcGISx6410.2\python.exe";
        var sParam = $"{sScriptPath}";
        if (null != lstParam && 0 < lstParam.Count)
        {
            var sArgument = "\"" + string.Join("\" \"", lstParam) + "\"";
            sParam = $"\"{sParam}\" {sArgument}";
        }
        var start = new ProcessStartInfo
        {
            WorkingDirectory = Environment.CurrentDirectory,
            FileName = sInterpreterPath,
            UseShellExecute = false,
            ErrorDialog = true,
            CreateNoWindow = true,
            RedirectStandardOutput = true,
            RedirectStandardInput = true,
            Arguments = sParam
        };
        start.EnvironmentVariables["__COMPAT_LAYER"] = "RunAsAdmin";
        start.Environment["__COMPAT_LAYER"] = "RunAsAdmin";
        using (Process process = Process.Start(start))
        {
            using (StreamReader reader = process.StandardOutput)
            {
                var sResult = "";
                while (!reader.EndOfStream)
                {
                    sResult = $"{sResult} \n {reader.ReadLine()}";
                }
                sResult = sResult.Trim();
                MessageBox.Show(sResult);
            }
            MessageBox.Show("ExitCode is " + process.ExitCode);
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
    return bResult;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章