Skip to content

Commit ba730a8

Browse files
Run Speos Labs As Admin (#173)
* RunAsAdmin * RunAsAdmin
1 parent a528870 commit ba730a8

File tree

2 files changed

+286
-7
lines changed

2 files changed

+286
-7
lines changed
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
"""
2+
Requirements: administrative privileges.
3+
-----------------------------------------------------------------------
4+
This module launches with administrator privileges all executables in:
5+
`C:\\Program Files\\ANSYS Inc\\vXXX\\Optical Products\\Viewers`
6+
7+
Many users lack administrative rights, so this module can be executed right after the installation
8+
while the user still has admin rights.
9+
10+
Upon launching each application, the module registers the associated COM server used to call each application,
11+
with the path to each executable appropriately registered.
12+
13+
Class
14+
-----------------------------------------------------------------------
15+
2. **LabsAdmin**
16+
- This class offers methods to open or close one or multiple applications simultaneously.
17+
- By default, if no specific applications are specified, it will launch all applications found.
18+
19+
"""
20+
21+
import subprocess, os, time, sys
22+
# Get the absolute path to the scdm_core directory
23+
current_dir = os.path.dirname(os.path.abspath(__file__))
24+
scdm_core_path = os.path.join(current_dir, '..', 'scdm_core')
25+
# Add the scdm_core path to sys.path if it's not already there
26+
if scdm_core_path not in sys.path:
27+
sys.path.append(scdm_core_path)
28+
# Try importing the function from utils
29+
try:
30+
from utils import find_awp_root
31+
print("get_scdm_install_location imported.")
32+
except ModuleNotFoundError as e:
33+
print(f"Error: {e}")
34+
print(f"sys.path: {sys.path}")
35+
36+
# If pygetwindow is not installed, do it
37+
third_party_package = "pygetwindow"
38+
try:
39+
gw = __import__(third_party_package)
40+
print(f"{third_party_package} is already installed.")
41+
except ImportError:
42+
print(f"{third_party_package} not found. Installing...")
43+
subprocess.check_call([sys.executable, "-m", "pip", "install", third_party_package])
44+
import pygetwindow as gw
45+
46+
47+
import numpy as np
48+
49+
class LabsAdmin:
50+
'''
51+
Class with methods to:
52+
- Run one specific application.
53+
- Kill one specific application.
54+
- Run all applications as admin.
55+
- Kill all applications.
56+
- Run and Kill one application.
57+
- Run and Kill all applications.
58+
'''
59+
60+
def __init__(self, ThreeDigitCode=""):
61+
"""
62+
Initializes the LabsAdmin class with a given ThreeDigitCode or derives it from the installation path.
63+
64+
Parameters
65+
----------
66+
ThreeDigitCode : str, optional
67+
A 3-digit version code (default is an empty string, which causes the code to be derived from the installation path).
68+
Path_Installation_Root: str
69+
Path to Ansys installation, format C:\Program Files\ANSYS Inc\v242.
70+
Uses find_awp_root, imported from utils. If no ThreeDigitCode is given as input, the function will return
71+
the latest installed Ansys installation path.
72+
"""
73+
if not ThreeDigitCode:
74+
self.Path_Installation_Root = find_awp_root(version="")
75+
version_part = self.Path_Installation_Root.split("\\")[-1]
76+
self.ThreeDigitCode = version_part[1:]
77+
else:
78+
self.ThreeDigitCode = ThreeDigitCode
79+
self.Path_Installation_Root = find_awp_root(version=self.ThreeDigitCode)
80+
81+
if not self.Path_Installation_Root:
82+
raise ValueError(f"AWP_ROOT path for version {self.ThreeDigitCode} not found.")
83+
84+
def RunSingleApp(self, exe_name):
85+
"""
86+
Runs a single application as an administrator.
87+
88+
Parameters
89+
----------
90+
exe_name : str
91+
The name of the executable to run.
92+
"""
93+
exe_path = os.path.join(self.Path_Installation_Root, 'Optical Products', 'Viewers', exe_name)
94+
print("Application Executed: " + exe_path)
95+
subprocess.Popen(["powershell", "-Command", f"Start-Process '{exe_path}' -Verb RunAs"])
96+
97+
def RunAll(self):
98+
"""
99+
Runs all applications as administrators.
100+
"""
101+
print("\n\n#### Run all Viewer as admin STARTED: \n")
102+
Dictionary_Labs = self.Applications()
103+
for App in Dictionary_Labs.keys():
104+
self.RunSingleApp(App)
105+
106+
def Applications(self):
107+
"""
108+
Returns a dictionary of applications with the names of the applications to run as key, and the title visible
109+
for each application after running the viewer without input files, as items.
110+
111+
Returns
112+
-------
113+
dict
114+
A dictionary where the keys are executable names and the values are titles.
115+
"""
116+
if len(self.ThreeDigitCode) != 3:
117+
raise ValueError("\n\nThe code must be of 3 characters long to derive the version.")
118+
self.Version = "20" + self.ThreeDigitCode[0] + self.ThreeDigitCode[1] + " R" + self.ThreeDigitCode[2]
119+
self.Labs_Applications = {
120+
"XmpViewer.exe": "Speos " + self.Version + " - Extended map [No Name]",
121+
"VRLab.exe": "Speos " + self.Version + " - Empty view",
122+
"Xm3Viewer.exe": "Speos " + self.Version + " - Virtual 3D Photometric Lab [No file loaded]",
123+
"VisionLabViewer.exe": "Speos " + self.Version + " - Spectral map [No Name]",
124+
"TextureMappingViewer.exe": "Texture Mapping Viewer",
125+
"VMPViewer.exe": "Speos " + self.Version + " - 3D Energy Density Lab [No Name]",
126+
"SimpleScatteringViewer.exe": "Speos " + self.Version + " - Scattering surface [No Name]",
127+
"VPLab.exe": "Speos " + self.Version + " - Photometric Calc",
128+
"SPEOSCore.exe": "Speos Core " + self.Version,
129+
"SpectrumViewer.exe": "Speos " + self.Version + " - Spectrum [No Name]",
130+
"RoughMirrorViewer.exe": "Speos " + self.Version + " - Mirror surface [No Name]",
131+
"FluorescentSurfaceViewer.exe": "Speos " + self.Version + " - Fluorescent surface [No Name]",
132+
"BSDF_BRDF_Anisotropic_Viewer.exe": "Speos " + self.Version + " - Bsdf surface [No Name]",
133+
"PolarizerSurfaceEditor.exe": "Speos " + self.Version + " - Polarizer surface [No Name]",
134+
"RetroReflectingSurfaceViewer.exe": "Speos " + self.Version + " - Retro-reflecting surface [No Name]",
135+
"IESViewer.exe": "Speos " + self.Version + " - Iesna LM-63 []",
136+
"CoatedSurfaceViewer.exe": "Speos " + self.Version + " - Coated surface [No Name]",
137+
"EulumdatViewer.exe": "Speos " + self.Version + " - Eulumdat [No Name]",
138+
"VirtualLightingAnimation.exe": "Virtual Lighting Animation [BETA] " + self.Version,
139+
"AdvancedScatteringViewer.exe": "Speos " + self.Version + " - Scattering surface (Advanced model) [No Name]",
140+
"DoeSurfaceViewer.exe": "Speos " + self.Version + " - Thin lens surface [No Name]",
141+
"GratingSurfaceViewer.exe": "Speos " + self.Version + " - Grating surface [No Name]",
142+
"RayEditor.exe": "Speos " + self.Version + " - [No Name]",
143+
"UserMaterialViewer.exe": "Speos " + self.Version + " - User Material (Advanced Model) [No Name]"
144+
}
145+
return self.Labs_Applications
146+
147+
def KillApp(self, exe_name):
148+
"""
149+
Kills a specific running application.
150+
151+
Parameters
152+
----------
153+
exe_name : str
154+
The name of the executable to kill.
155+
"""
156+
Dictionary_Labs = self.Applications()
157+
open_windows = gw.getAllTitles()
158+
app_opened = False
159+
Expected_title = Dictionary_Labs[exe_name]
160+
while not app_opened:
161+
open_windows = gw.getAllTitles()
162+
for title in open_windows:
163+
if Expected_title in title:
164+
app_opened = True
165+
print("Trying to find: " + exe_name)
166+
subprocess.run(["taskkill", "/f", "/im", exe_name])
167+
break
168+
time.sleep(0.2)
169+
170+
def KillAll(self):
171+
"""
172+
Kills all running applications.
173+
"""
174+
Dictionary_Labs = self.Applications()
175+
print("\n\n#### Kill all process: \n")
176+
for App in Dictionary_Labs.keys():
177+
self.KillApp(App)
178+
179+
def RunAndKillApp(self, exe_name):
180+
"""
181+
Runs and then kills a specific application.
182+
183+
Parameters
184+
----------
185+
exe_name : str
186+
The name of the executable to run and kill.
187+
"""
188+
self.RunSingleApp(exe_name)
189+
self.KillApp(exe_name)
190+
191+
def RunAndKillAll(self):
192+
"""
193+
Runs all applications and then kills all of them.
194+
"""
195+
self.RunAll()
196+
self.KillAll()
197+
198+
# Example usage of LabsAdmin with the new integration
199+
try:
200+
LabsAdmin("242").RunAndKillAll()
201+
except Exception as err:
202+
print("Unexpected error: "+str(err)+", "+str(type(err)))

ansys_optical_automation/scdm_core/utils.py

Lines changed: 84 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,103 @@
44

55
import numpy as np
66

7+
import os
8+
9+
import os
10+
711

8-
def get_scdm_install_location(version):
12+
def find_awp_root(version=""):
13+
"""
14+
Finds the AWP_ROOT path based on the given version.
15+
16+
This function searches the environmental variables for keys containing "AWP_ROOT".
17+
If a specific version is provided, it returns the path for that version.
18+
If no version is provided (i.e., an empty string is passed), it returns the path for the latest version.
19+
20+
Parameters
21+
----------
22+
version : str, optional
23+
The version of AWP_ROOT to search for. If an empty string is passed,
24+
the path for the latest version is returned. Default is an empty string.
25+
26+
Returns
27+
-------
28+
str
29+
The path to the specified AWP_ROOT version if `version` is provided.
30+
If no `version` is specified, it returns the path to the latest AWP_ROOT version.
31+
32+
Raises
33+
------
34+
ValueError
35+
If the specified `version` does not exist or if no AWP_ROOT path is found in the environment variables.
36+
37+
Notes
38+
-----
39+
The function compares the version numbers by splitting the keys containing "AWP_ROOT"
40+
and checking the version number after "AWP_ROOT".
41+
"""
42+
try:
43+
if version:
44+
# If version is specified, return the path for that version
45+
awp_root_path = os.environ.get(f"AWP_ROOT{version}", "")
46+
if not awp_root_path:
47+
raise ValueError(f"AWP_ROOT path for version {version} not found in the environment variables.")
48+
else:
49+
# If no version is specified, find the latest version
50+
last_version = "000"
51+
for key in os.environ:
52+
if "AWP_ROOT" in key and key.split("AWP_ROOT")[1] > last_version:
53+
last_version = key.split("AWP_ROOT")[1]
54+
55+
awp_root_path = os.environ.get(f"AWP_ROOT{last_version}", "")
56+
if not awp_root_path:
57+
raise ValueError("AWP_ROOT path for the latest version not found in the environment variables.")
58+
59+
return awp_root_path
60+
61+
except Exception as e:
62+
raise ValueError(f"An error occurred while finding the AWP_ROOT path: {str(e)}")
63+
64+
65+
print(find_awp_root("242"))
66+
def get_scdm_install_location(version=""):
967
"""
1068
Get the SpaceClaim installation path.
1169
70+
This function retrieves the installation path for SpaceClaim based on the provided version.
71+
It calls the `find_awp_root` function to obtain the AWP_ROOT path for the given version,
72+
and then appends the "scdm" directory to determine the SpaceClaim installation path.
73+
1274
Parameters
1375
----------
14-
version : int
76+
version : str, optional
1577
Version of SpaceClaim in numerical format. For example, ``211`` for 2021 R1.
78+
If an empty string is passed, the function will use the latest version found.
1679
1780
Returns
1881
-------
1982
str
2083
Path of the SpaceClaim installation.
2184
22-
"""
23-
ansys_install_dir = os.environ["AWP_ROOT{}".format(version)]
24-
scdm_install_dir = os.path.join(ansys_install_dir, "scdm")
25-
return scdm_install_dir
26-
85+
Raises
86+
------
87+
ValueError
88+
If the AWP_ROOT path for the specified or latest version cannot be found,
89+
or if there is an issue with accessing the environment variables.
90+
91+
Notes
92+
-----
93+
The `find_awp_root` function is used to retrieve the AWP_ROOT path, and the "scdm" directory
94+
is appended to this path to return the full path to the SpaceClaim installation.
95+
"""
96+
try:
97+
ansys_install_dir = find_awp_root(version=version)
98+
scdm_install_dir = os.path.join(ansys_install_dir, "scdm")
99+
return scdm_install_dir
100+
except ValueError as e:
101+
raise ValueError(f"Error while getting the SpaceClaim installation path: {str(e)}")
102+
103+
print("####",get_scdm_install_location("242"))
27104

28105
def get_speos_core(version):
29106
"""

0 commit comments

Comments
 (0)