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\v 242.
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 \n The 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 )))
0 commit comments