Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions Activities/Python/UiPath.Python.Host.Shared/PythonService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,8 @@ internal async void RunServer()
private bool IsWindows()
{
bool isWindows = true;
#if NETCOREAPP
if(!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
isWindows = false;
#endif
return isWindows;
}
private void WaitForPipeDrain(NamedPipeServerStream pipe)
Expand Down
102 changes: 70 additions & 32 deletions Activities/Python/UiPath.Python/EngineProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using UiPath.Python.Impl;
using UiPath.Python.Properties;
using System.Runtime.InteropServices;

namespace UiPath.Python
{
Expand All @@ -14,8 +15,9 @@ namespace UiPath.Python
public static class EngineProvider
{
private const string PythonHomeEnv = "PYTHONHOME";
private const string PythonExe = "python.exe";
private const string PythonLinux = "python";
private static readonly string[] PythonExeWin = ["python.exe", "python3.exe"];
private static readonly string[] PythonLinux = ["python", "python3"];
private static readonly string[] PythonBinFolders = ["", "bin"];
private const string PythonVersionArgument = "--version";

// engines cache
Expand All @@ -31,7 +33,7 @@ public static IEngine Get(Version version, string path, string libraryPath, bool
{
// read path from env variable
path = Environment.GetEnvironmentVariable(PythonHomeEnv);
Trace.TraceInformation($"Found Pyhton path {path}");
Trace.TraceInformation($"Found Python path {path}");
}
if (!version.IsValid())
{
Expand All @@ -43,7 +45,7 @@ public static IEngine Get(Version version, string path, string libraryPath, bool
}

// TODO: target&visible are meaningless when running in-process (at least now), maybe it should be split
if(inProcess)
if (inProcess)
{
if (!_cache.TryGetValue(version, out engine))
{
Expand All @@ -62,37 +64,73 @@ public static IEngine Get(Version version, string path, string libraryPath, bool

public static void Autodetect(string path, out Version version)
{
version = Version.Auto;
Trace.TraceInformation($"Trying to autodetect Python version from path {path}");
var pythonExec = PythonExe;
#if NETCOREAPP
if(!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
pythonExec = PythonLinux;
#endif
string pyExe = Path.GetFullPath(Path.Combine(path, pythonExec));
if (!File.Exists(pyExe))

var exes = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? PythonExeWin : PythonLinux;
var pythonCandidates = PythonBinFolders.SelectMany(folder => exes, Path.Combine).Select(p => Path.Combine(path, p)).Distinct().Select(Path.GetFullPath).ToList();
var existingFiles = pythonCandidates.Where(File.Exists).ToList();

if (existingFiles.Count == 0)
{
throw new FileNotFoundException(Resources.PythonExeNotFoundException, pyExe);
throw new FileNotFoundException(Resources.PythonExeNotFoundException, string.Join(", ", pythonCandidates));
}
Process process = new Process();
process.StartInfo = new ProcessStartInfo()

Dictionary<string, Exception> errors = new Dictionary<string, Exception>();
bool versionDetected = false;

foreach (var python in existingFiles)
{
UseShellExecute = false,
CreateNoWindow = true,
WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden,
FileName = pyExe,
Arguments = PythonVersionArgument,
RedirectStandardError = true,
RedirectStandardOutput = true
};
process.Start();
// Now read the value, parse to int and add 1 (from the original script)
string ver = process.StandardError.ReadToEnd();
if(string.IsNullOrEmpty(ver))
ver = process.StandardOutput.ReadToEnd();
process.WaitForExit();
version = ver.GetVersionFromStr();
Trace.TraceInformation($"Autodetected Python version {version}");
if (Autodetect(python, out version, out Exception ex))
{
versionDetected = true;
break;
}
else
{
errors[python] = ex;
}
}

// if we are here, it means that we found some candidates but all of them failed to be detected, so we throw an aggregate exception with all the details
if (!versionDetected)
{
throw new AggregateException(errors.Where(kv => kv.Value != null).Select(kv => new Exception($"{kv.Key}: {kv.Value.Message}", kv.Value)));
}
}

private static bool Autodetect(string pythonFullPath, out Version version, out Exception exception)
{
version = Version.Auto;
exception = null;
try
{
using Process process = new Process();
process.StartInfo = new ProcessStartInfo()
{
UseShellExecute = false,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
FileName = pythonFullPath,
Arguments = PythonVersionArgument,
RedirectStandardError = true,
RedirectStandardOutput = true
};
process.Start();
process.WaitForExit(3000);
// Now read the value, parse to int and add 1 (from the original script)
string ver = process.StandardError.ReadToEnd();
if (string.IsNullOrEmpty(ver))
ver = process.StandardOutput.ReadToEnd();

version = ver.GetVersionFromStr();
return version != Version.Auto;
}
catch (Exception ex)
{
exception = ex;
return false;
}
}

}
}
2 changes: 0 additions & 2 deletions Activities/Python/UiPath.Python/Impl/Engine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,8 @@ internal Engine(Version version, string path, string libraryPath)
_version = version;
_path = path;
_libraryPath = libraryPath;
#if NETCOREAPP
if(!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
_isWindows = false;
#endif
}

#region IEngine
Expand Down
2 changes: 0 additions & 2 deletions Activities/Python/UiPath.Python/Service/PythonProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,8 @@ private PythonResponse ReadResponse(PythonRequest request, CancellationToken ct)
private bool IsWindows()
{
bool isWindows = true;
#if NETCOREAPP
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
isWindows = false;
#endif
return isWindows;
}
private void WaitForPipeDrain()
Expand Down
2 changes: 0 additions & 2 deletions Activities/Shared/UiPath.Shared.Service/Client/Controller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,8 @@ internal void ForceStop()
private void StartHostService()
{
var isWindows = true;
#if NETCOREAPP
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
isWindows = false;
#endif
string folder = Path.GetDirectoryName(HostLibFile);
var hostLibFullPath = HostLibFile;
if (folder.IsNullOrEmpty())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public void Dispose()

//Prevent process leak in certain error scenarios
Proc?.Kill();
Proc?.Dispose();
Proc = null;
}

Expand Down
Loading