computer-use-ootb-internal 0.0.170__py3-none-any.whl → 0.0.171__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- computer_use_ootb_internal/app_teachmode.py +7 -14
- computer_use_ootb_internal/guard_service.py +160 -132
- computer_use_ootb_internal/run_teachmode_ootb_args.py +9 -5
- computer_use_ootb_internal/service_manager.py +98 -257
- {computer_use_ootb_internal-0.0.170.dist-info → computer_use_ootb_internal-0.0.171.dist-info}/METADATA +1 -1
- {computer_use_ootb_internal-0.0.170.dist-info → computer_use_ootb_internal-0.0.171.dist-info}/RECORD +8 -9
- computer_use_ootb_internal/launch_ootb_elevated.ps1 +0 -63
- {computer_use_ootb_internal-0.0.170.dist-info → computer_use_ootb_internal-0.0.171.dist-info}/WHEEL +0 -0
- {computer_use_ootb_internal-0.0.170.dist-info → computer_use_ootb_internal-0.0.171.dist-info}/entry_points.txt +0 -0
@@ -552,9 +552,6 @@ def main():
|
|
552
552
|
parser.add_argument("--trace_id", type=str, default="build_scroll_combat", help="Trace ID for the session")
|
553
553
|
parser.add_argument("--api_keys", type=str, default="sk-proj-1234567890", help="API keys")
|
554
554
|
parser.add_argument("--server_url", type=str, default="http://ec2-44-234-43-86.us-west-2.compute.amazonaws.com", help="Server URL for the session")
|
555
|
-
# Add arguments for port override and target user
|
556
|
-
parser.add_argument("-p", "--port", type=int, default=None, help="Specify the port to run the server on, overriding user-based calculation.")
|
557
|
-
parser.add_argument("--target_user", type=str, default=None, help="Specify the target username for port calculation if --port is not given.")
|
558
555
|
|
559
556
|
args = parser.parse_args()
|
560
557
|
|
@@ -571,18 +568,14 @@ def main():
|
|
571
568
|
rate_limiter = RateLimiter(interval_seconds=2) # Re-initialize rate limiter
|
572
569
|
logging.info(f"Shared state initialized for user: {args.user_id}")
|
573
570
|
|
574
|
-
# ---
|
571
|
+
# --- Restore original port calculation logic ---
|
575
572
|
port = 7888 # Default port
|
576
573
|
host = "0.0.0.0" # Listen on all interfaces
|
577
574
|
|
578
|
-
if
|
579
|
-
port = args.port
|
580
|
-
logging.info(f"Using specified port from --port argument: {port}")
|
581
|
-
elif platform.system() == "Windows" and args.target_user is not None:
|
575
|
+
if platform.system() == "Windows":
|
582
576
|
try:
|
583
|
-
|
584
|
-
username
|
585
|
-
logging.info(f"Determining port based on Windows username from --target_user: {username}")
|
577
|
+
username = os.environ["USERNAME"].lower()
|
578
|
+
logging.info(f"Determining port based on Windows username: {username}")
|
586
579
|
if username == "altair":
|
587
580
|
port = 14000
|
588
581
|
elif username.startswith("guest") and username[5:].isdigit():
|
@@ -594,10 +587,10 @@ def main():
|
|
594
587
|
else:
|
595
588
|
logging.info(f"Username '{username}' doesn't match specific rules, using default port {port}.")
|
596
589
|
except Exception as e:
|
597
|
-
logging.error(f"Error determining port from
|
590
|
+
logging.error(f"Error determining port from username: {e}. Using default port {port}.", exc_info=True)
|
598
591
|
else:
|
599
|
-
logging.info(f"
|
600
|
-
# --- End
|
592
|
+
logging.info(f"Not running on Windows, using default port {port}.")
|
593
|
+
# --- End of restored port calculation ---
|
601
594
|
|
602
595
|
logging.info(f"Final Host={host}, Port={port}")
|
603
596
|
|
@@ -23,7 +23,6 @@ import psutil # For process/user info
|
|
23
23
|
from flask import Flask, request, jsonify # For embedded server
|
24
24
|
from waitress import serve # For serving Flask app
|
25
25
|
import json # Needed for status reporting
|
26
|
-
import shutil # Added for shutil.which
|
27
26
|
|
28
27
|
# --- Configuration ---
|
29
28
|
_SERVICE_NAME = "OOTBGuardService"
|
@@ -144,6 +143,7 @@ class GuardService(win32serviceutil.ServiceFramework):
|
|
144
143
|
_svc_name_ = _SERVICE_NAME
|
145
144
|
_svc_display_name_ = _SERVICE_DISPLAY_NAME
|
146
145
|
_svc_description_ = _SERVICE_DESCRIPTION
|
146
|
+
_task_name_prefix = "OOTB_UserLogon_" # Class attribute for task prefix
|
147
147
|
|
148
148
|
# --- Instance Logging Methods ---
|
149
149
|
def log_info(self, msg):
|
@@ -688,29 +688,21 @@ class GuardService(win32serviceutil.ServiceFramework):
|
|
688
688
|
task_created_status = "task_unknown"
|
689
689
|
immediate_start_status = "start_not_attempted"
|
690
690
|
final_status = "failed_unknown"
|
691
|
-
calculated_port = 7888 # Default port
|
692
|
-
|
693
|
-
# --- Calculate Port based on username (mirroring app_teachmode logic) ---
|
694
|
-
try:
|
695
|
-
if user == "altair":
|
696
|
-
calculated_port = 14000
|
697
|
-
elif user.startswith("guest") and user[5:].isdigit():
|
698
|
-
num = int(user[5:])
|
699
|
-
if 1 <= num <= 10:
|
700
|
-
calculated_port = 14000 + num
|
701
|
-
else:
|
702
|
-
self.log_warning(f"Internal trigger: User 'guest{num}' out of range (1-10), using default port {calculated_port} for launch.")
|
703
|
-
# else: use default 7888
|
704
|
-
self.log_info(f"Internal trigger: Calculated port {calculated_port} for user '{user}'.")
|
705
|
-
except Exception as port_calc_e:
|
706
|
-
self.log_error(f"Internal trigger: Error calculating port for user '{user}': {port_calc_e}. Using default port {calculated_port}.")
|
707
|
-
# --- End Port Calculation ---
|
708
|
-
|
709
691
|
|
710
692
|
try:
|
693
|
+
# 1. Ensure scheduled task exists (still useful fallback/persistence)
|
694
|
+
try:
|
695
|
+
task_created = self.create_or_update_logon_task(user)
|
696
|
+
task_created_status = "task_success" if task_created else "task_failed"
|
697
|
+
except Exception as task_err:
|
698
|
+
self.log_error(f"Internal trigger: Exception creating/updating task for {user}: {task_err}", exc_info=True)
|
699
|
+
task_created_status = "task_exception"
|
700
|
+
# Don't necessarily fail the whole operation yet
|
701
|
+
|
711
702
|
# 2. Check if user is active
|
712
703
|
active_sessions = {} # Re-check active sessions specifically for this user
|
713
704
|
session_id = None
|
705
|
+
token = None
|
714
706
|
is_active = False
|
715
707
|
try:
|
716
708
|
sessions = win32ts.WTSEnumerateSessions(win32ts.WTS_CURRENT_SERVER_HANDLE)
|
@@ -731,7 +723,7 @@ class GuardService(win32serviceutil.ServiceFramework):
|
|
731
723
|
if not is_active:
|
732
724
|
self.log_info(f"Internal trigger: User '{user}' is not active. Skipping immediate start.")
|
733
725
|
immediate_start_status = "start_skipped_inactive"
|
734
|
-
final_status =
|
726
|
+
final_status = task_created_status # Status depends only on task creation
|
735
727
|
return final_status # Exit early if inactive
|
736
728
|
|
737
729
|
# 3. Check if already running for this active user
|
@@ -748,100 +740,50 @@ class GuardService(win32serviceutil.ServiceFramework):
|
|
748
740
|
self.log_error(f"Internal trigger: Error checking existing processes for {user}: {e}")
|
749
741
|
# Continue and attempt start despite error?
|
750
742
|
|
751
|
-
# 4. Attempt immediate start
|
752
|
-
immediate_start_status = "
|
753
|
-
self.log_info(f"Internal trigger: User '{user}' is active and not running. Attempting start via
|
754
|
-
|
755
|
-
if not self.target_executable_path:
|
756
|
-
self.log_error("Internal trigger: Cannot start process - target executable path not found.")
|
757
|
-
final_status = "failed_exe_not_found"
|
758
|
-
return final_status
|
759
|
-
|
743
|
+
# 4. Attempt immediate start (User is active and not running)
|
744
|
+
immediate_start_status = "start_attempted"
|
745
|
+
self.log_info(f"Internal trigger: User '{user}' is active and not running. Attempting immediate start via CreateProcessAsUser...")
|
760
746
|
try:
|
761
|
-
# Find helper script path
|
762
|
-
helper_script_path = self._find_helper_script("launch_ootb_elevated.ps1")
|
763
|
-
if not helper_script_path:
|
764
|
-
self.log_error("Internal trigger: Cannot start process - helper script not found.")
|
765
|
-
final_status = "failed_helper_script_not_found"
|
766
|
-
return final_status
|
767
|
-
|
768
|
-
# Get PowerShell executable path
|
769
|
-
powershell_executable = self._find_powershell_executable()
|
770
|
-
if not powershell_executable:
|
771
|
-
self.log_error("Internal trigger: Cannot start process - powershell.exe not found.")
|
772
|
-
final_status = "failed_powershell_not_found"
|
773
|
-
return final_status
|
774
|
-
|
775
|
-
# Prepare arguments for the helper script (paths need quoting if they contain spaces)
|
776
|
-
target_exe_unquoted = self.target_executable_path.strip('"')
|
777
|
-
target_exe_dir = os.path.dirname(target_exe_unquoted) # Use directory of unquoted path
|
778
|
-
|
779
|
-
# Quote paths/args for command line - IMPORTANT: Use double quotes for PowerShell args
|
780
|
-
helper_script_arg = f'"{helper_script_path}"' if " " in helper_script_path else helper_script_path
|
781
|
-
target_exe_arg = f'"{target_exe_unquoted}"' if " " in target_exe_unquoted else target_exe_unquoted
|
782
|
-
working_dir_arg = f'"{target_exe_dir}"' if " " in target_exe_dir else target_exe_dir
|
783
|
-
# Username might need quoting if it contains special characters, double quote should be safe
|
784
|
-
target_user_arg = f'"{user}"'
|
785
|
-
|
786
|
-
# Construct the command line to execute powershell with the helper script and args
|
787
|
-
lpCommandLine = (
|
788
|
-
f'"{powershell_executable}" -NoProfile -ExecutionPolicy Bypass -NoExit '
|
789
|
-
f'-File {helper_script_arg} '
|
790
|
-
f'-TargetExePath {target_exe_arg} '
|
791
|
-
f'-Port {calculated_port} '
|
792
|
-
f'-TargetUser {target_user_arg} '
|
793
|
-
f'-WorkingDirectory {working_dir_arg}'
|
794
|
-
)
|
795
|
-
|
796
|
-
# Use CreateProcessAsUser to launch this command in the user's session
|
797
747
|
token = win32ts.WTSQueryUserToken(session_id)
|
798
748
|
env = win32profile.CreateEnvironmentBlock(token, False)
|
799
749
|
startup = win32process.STARTUPINFO()
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
#
|
806
|
-
|
807
|
-
|
808
|
-
self.log_info(f"Internal trigger: Launching helper script via CreateProcessAsUser:")
|
750
|
+
creation_flags = 0x00000010 # CREATE_NEW_CONSOLE
|
751
|
+
lpApplicationName = None
|
752
|
+
lpCommandLine = f'cmd.exe /K "{self.target_executable_path}"'
|
753
|
+
cwd = os.path.dirname(self.target_executable_path.strip('"')) if os.path.dirname(self.target_executable_path.strip('"')) != '' else None
|
754
|
+
|
755
|
+
# Log details before call
|
756
|
+
self.log_info(f"Internal trigger: Calling CreateProcessAsUser:")
|
809
757
|
self.log_info(f" lpCommandLine: {lpCommandLine}")
|
810
|
-
self.log_info(f" lpCurrentDirectory: {cwd}")
|
758
|
+
self.log_info(f" lpCurrentDirectory: {cwd if cwd else 'Default'}")
|
811
759
|
|
812
|
-
# Execute the command in the user's session
|
813
760
|
hProcess, hThread, dwPid, dwTid = win32process.CreateProcessAsUser(
|
814
761
|
token, lpApplicationName, lpCommandLine, None, None, False,
|
815
762
|
creation_flags, env, cwd, startup
|
816
763
|
)
|
817
|
-
self.log_info(f"Internal trigger: CreateProcessAsUser call for
|
764
|
+
self.log_info(f"Internal trigger: CreateProcessAsUser call succeeded for user '{user}' (PID: {dwPid}). Checking existence...")
|
818
765
|
win32api.CloseHandle(hProcess)
|
819
766
|
win32api.CloseHandle(hThread)
|
820
767
|
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
except Exception as
|
832
|
-
|
833
|
-
|
834
|
-
|
768
|
+
time.sleep(1)
|
769
|
+
if psutil.pid_exists(dwPid):
|
770
|
+
self.log_info(f"Internal trigger: Immediate start succeeded for user '{user}' (PID {dwPid}).")
|
771
|
+
immediate_start_status = "start_success"
|
772
|
+
final_status = "success" # Overall success
|
773
|
+
else:
|
774
|
+
self.log_error(f"Internal trigger: Immediate start failed for user '{user}': Process {dwPid} exited immediately.")
|
775
|
+
immediate_start_status = "start_failed_exited"
|
776
|
+
final_status = "failed_start_exited"
|
777
|
+
|
778
|
+
except Exception as proc_err:
|
779
|
+
self.log_error(f"Internal trigger: Exception during CreateProcessAsUser for user '{user}': {proc_err}", exc_info=True)
|
780
|
+
immediate_start_status = "start_failed_exception"
|
781
|
+
final_status = "failed_start_exception"
|
835
782
|
finally:
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
except: # Ignore errors closing handle
|
841
|
-
pass
|
842
|
-
|
843
|
-
# Combine results (mostly determined by start attempt now)
|
844
|
-
# Status is now primarily determined by the helper script launch attempt
|
783
|
+
if token: win32api.CloseHandle(token)
|
784
|
+
|
785
|
+
# Combine results (though mostly determined by start attempt now)
|
786
|
+
# Example: final_status = f"{task_created_status}_{immediate_start_status}"
|
845
787
|
return final_status
|
846
788
|
|
847
789
|
except Exception as e:
|
@@ -849,47 +791,133 @@ class GuardService(win32serviceutil.ServiceFramework):
|
|
849
791
|
return "failed_trigger_exception"
|
850
792
|
|
851
793
|
|
794
|
+
def create_or_update_logon_task(self, username):
|
795
|
+
"""Creates/updates task to trigger the internal signal script on session connect."""
|
796
|
+
if not self.signal_script_path:
|
797
|
+
self.log_error(f"Cannot create task for {username}: Signal script path is not set.")
|
798
|
+
return False
|
799
|
+
if not sys.executable:
|
800
|
+
self.log_error(f"Cannot create task for {username}: sys.executable is not found.")
|
801
|
+
return False
|
802
|
+
|
803
|
+
# Use the python executable that the service itself is running under
|
804
|
+
python_exe = sys.executable
|
805
|
+
if ' ' in python_exe and not python_exe.startswith('"'):
|
806
|
+
python_exe = f'"{python_exe}"'
|
807
|
+
|
808
|
+
task_name = f"OOTB_UserConnect_{username}"
|
809
|
+
# Action: Run python.exe with the signal script and username argument
|
810
|
+
action_executable = python_exe
|
811
|
+
# Ensure script path is quoted if needed
|
812
|
+
script_arg = self.signal_script_path # Should be quoted already by _find_signal_script
|
813
|
+
# Username might need quoting if it contains spaces, though unlikely
|
814
|
+
user_arg = username # Keep simple for now
|
815
|
+
action_arguments = f'{script_arg} "{user_arg}"' # Pass username as quoted arg
|
816
|
+
safe_action_executable = action_executable.replace("'", "''") # Escape for PS
|
817
|
+
safe_action_arguments = action_arguments.replace("'", "''") # Escape for PS
|
818
|
+
|
819
|
+
# Working directory for the script (likely its own directory)
|
820
|
+
try:
|
821
|
+
script_dir = os.path.dirname(self.signal_script_path.strip('"'))
|
822
|
+
if not script_dir: script_dir = "."
|
823
|
+
safe_working_directory = script_dir.replace("'", "''")
|
824
|
+
working_directory_setting = f"$action.WorkingDirectory = '{safe_working_directory}'"
|
825
|
+
except Exception as e:
|
826
|
+
self.log_error(f"Error determining working directory for signal script task: {e}. WD will not be set.")
|
827
|
+
working_directory_setting = "# Could not set WorkingDirectory"
|
828
|
+
|
829
|
+
# PowerShell command construction
|
830
|
+
ps_command = f"""
|
831
|
+
$taskName = "{task_name}"
|
832
|
+
$principal = New-ScheduledTaskPrincipal -UserId "{username}" -LogonType Interactive
|
833
|
+
|
834
|
+
# Action: Run python signal script
|
835
|
+
$action = New-ScheduledTaskAction -Execute '{safe_action_executable}' -Argument '{safe_action_arguments}'
|
836
|
+
{working_directory_setting}
|
837
|
+
|
838
|
+
# Trigger: On session connect (Event ID 21)
|
839
|
+
$logName = 'Microsoft-Windows-TerminalServices-LocalSessionManager/Operational'
|
840
|
+
$source = 'Microsoft-Windows-TerminalServices-LocalSessionManager'
|
841
|
+
$eventIDs = @(21, 25)
|
842
|
+
$trigger = New-ScheduledTaskTrigger -Event -LogName $logName -Source $source -EventId $eventIDs[0]
|
843
|
+
# Optional Delay: -Delay 'PT15S'
|
844
|
+
# $trigger.Delay = 'PT15S'
|
845
|
+
|
846
|
+
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -ExecutionTimeLimit (New-TimeSpan -Days 9999) -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1)
|
847
|
+
$description = "Triggers OOTB Guard Service for user {username} upon session connect via internal signal." # Updated description
|
848
|
+
|
849
|
+
# Unregister existing task first (force)
|
850
|
+
Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -ErrorAction SilentlyContinue
|
851
|
+
|
852
|
+
# Register the new task
|
853
|
+
Register-ScheduledTask -TaskName $taskName -Principal $principal -Action $action -Trigger $trigger -Settings $settings -Description $description -Force
|
854
|
+
"""
|
855
|
+
self.log_info(f"Attempting to create/update task '{task_name}' for user '{username}' to run signal script.")
|
856
|
+
try:
|
857
|
+
success = self.run_powershell_command(ps_command)
|
858
|
+
if success:
|
859
|
+
self.log_info(f"Successfully ran PowerShell command to create/update task '{task_name}'.")
|
860
|
+
return True
|
861
|
+
else:
|
862
|
+
self.log_error(f"PowerShell command failed to create/update task '{task_name}'. See previous logs.")
|
863
|
+
return False
|
864
|
+
except Exception as e:
|
865
|
+
self.log_error(f"Failed to create/update scheduled task '{task_name}' for user '{username}': {e}", exc_info=True)
|
866
|
+
return False
|
867
|
+
|
868
|
+
def run_powershell_command(self, command, log_output=True):
|
869
|
+
"""Executes a PowerShell command and handles output/errors. Returns True on success."""
|
870
|
+
self.log_info(f"Executing PowerShell: {command}")
|
871
|
+
try:
|
872
|
+
result = subprocess.run(
|
873
|
+
["powershell.exe", "-NoProfile", "-NonInteractive", "-Command", command],
|
874
|
+
capture_output=True, text=True, check=True, encoding='utf-8', errors='ignore'
|
875
|
+
)
|
876
|
+
if log_output and result.stdout:
|
877
|
+
self.log_info(f"PowerShell STDOUT:\n{result.stdout.strip()}")
|
878
|
+
if log_output and result.stderr:
|
879
|
+
# Log stderr as info, as some commands write status here (like unregister task not found)
|
880
|
+
self.log_info(f"PowerShell STDERR:\n{result.stderr.strip()}")
|
881
|
+
return True
|
882
|
+
except FileNotFoundError:
|
883
|
+
self.log_error("'powershell.exe' not found. Cannot manage scheduled tasks.")
|
884
|
+
return False
|
885
|
+
except subprocess.CalledProcessError as e:
|
886
|
+
# Log error but still return False, handled by caller
|
887
|
+
self.log_error(f"PowerShell command failed (Exit Code {e.returncode}):")
|
888
|
+
self.log_error(f" Command: {e.cmd}")
|
889
|
+
if e.stdout: self.log_error(f" STDOUT: {e.stdout.strip()}")
|
890
|
+
if e.stderr: self.log_error(f" STDERR: {e.stderr.strip()}")
|
891
|
+
return False
|
892
|
+
except Exception as e:
|
893
|
+
self.log_error(f"Unexpected error running PowerShell: {e}", exc_info=True)
|
894
|
+
return False
|
895
|
+
|
896
|
+
def remove_logon_task(self, username):
|
897
|
+
"""Removes the logon scheduled task for a user."""
|
898
|
+
task_name = f"{self._task_name_prefix}{username}"
|
899
|
+
safe_task_name = task_name.replace("'", "''")
|
900
|
+
command = f"Unregister-ScheduledTask -TaskName '{safe_task_name}' -Confirm:$false -ErrorAction SilentlyContinue"
|
901
|
+
self.run_powershell_command(command, log_output=False)
|
902
|
+
self.log_info(f"Attempted removal of scheduled task '{task_name}' for user '{username}'.")
|
903
|
+
return True
|
904
|
+
|
852
905
|
def _find_signal_script(self):
|
853
906
|
"""Finds the signal_connection.py script relative to this service file."""
|
854
|
-
return self._find_helper_script("signal_connection.py") # Reuse helper finding logic
|
855
|
-
|
856
|
-
def _find_helper_script(self, script_name):
|
857
|
-
"""Finds a helper script relative to this service file."""
|
858
907
|
try:
|
859
|
-
# Use __file__ which should be reliable when run as a service via pythonservice.exe
|
860
908
|
base_dir = os.path.dirname(os.path.abspath(__file__))
|
861
|
-
script_path = os.path.join(base_dir,
|
909
|
+
script_path = os.path.join(base_dir, "signal_connection.py")
|
862
910
|
if os.path.exists(script_path):
|
863
|
-
self.log_info(f"Found
|
864
|
-
#
|
911
|
+
self.log_info(f"Found signal script at: {script_path}")
|
912
|
+
# Quote if needed?
|
913
|
+
if " " in script_path and not script_path.startswith('"'):
|
914
|
+
return f'"{script_path}"'
|
865
915
|
return script_path
|
866
916
|
else:
|
867
|
-
self.log_error(f"
|
917
|
+
self.log_error(f"Signal script signal_connection.py not found near {base_dir}")
|
868
918
|
return None
|
869
919
|
except Exception as e:
|
870
|
-
self.log_error(f"Error finding
|
871
|
-
return None
|
872
|
-
|
873
|
-
def _find_powershell_executable(self):
|
874
|
-
"""Finds powershell.exe, preferring the system path."""
|
875
|
-
try:
|
876
|
-
# Check System32 first
|
877
|
-
system32_path = os.path.join(os.environ.get('SystemRoot', 'C:\\Windows'), 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe')
|
878
|
-
if os.path.exists(system32_path):
|
879
|
-
self.log_info(f"Found powershell.exe at: {system32_path}")
|
880
|
-
return system32_path
|
881
|
-
else:
|
882
|
-
# Fallback to checking PATH using shutil.which (requires Python 3.3+)
|
883
|
-
# Make sure to import shutil at the top of the file if not already present
|
884
|
-
powershell_path = shutil.which("powershell.exe")
|
885
|
-
if powershell_path:
|
886
|
-
self.log_info(f"Found powershell.exe via PATH: {powershell_path}")
|
887
|
-
return powershell_path
|
888
|
-
else:
|
889
|
-
self.log_error("powershell.exe not found in System32 or PATH.")
|
890
|
-
return None
|
891
|
-
except Exception as e:
|
892
|
-
self.log_error(f"Error finding powershell.exe: {e}")
|
920
|
+
self.log_error(f"Error finding signal script: {e}")
|
893
921
|
return None
|
894
922
|
|
895
923
|
# --- Main Execution Block ---
|
@@ -119,17 +119,21 @@ def simple_teachmode_sampling_loop(
|
|
119
119
|
|
120
120
|
try:
|
121
121
|
step_plan = infer_server_response["generated_plan"]
|
122
|
-
|
123
|
-
|
122
|
+
step_plan_observation = step_plan["observation"]
|
123
|
+
step_plan_reasoning = step_plan["reasoning"]
|
124
|
+
step_plan_info = step_plan["step_info"]
|
124
125
|
step_action = infer_server_response["generated_action"]["content"]
|
125
126
|
step_traj_idx = infer_server_response["current_traj_step"]
|
126
127
|
|
128
|
+
# chat_visable_content = f"{step_plan_observation}{step_plan_reasoning}"
|
129
|
+
|
127
130
|
except Exception as e:
|
128
131
|
print("Error parsing generated_action content:", e)
|
129
132
|
yield {"role": "assistant", "content": "Error parsing response from Marbot Run server. Exiting.", "type": "error"}
|
130
133
|
break
|
131
|
-
|
132
|
-
yield {"role": "assistant", "content":
|
134
|
+
|
135
|
+
yield {"role": "assistant", "content": step_plan_observation, "type": "text"}
|
136
|
+
yield {"role": "assistant", "content": step_plan_reasoning, "type": "text"}
|
133
137
|
|
134
138
|
if step_action.get("action") == "STOP":
|
135
139
|
final_sc, final_sc_path = get_screenshot_external_cmd(selected_screen=selected_screen)
|
@@ -141,7 +145,7 @@ def simple_teachmode_sampling_loop(
|
|
141
145
|
action_history = []
|
142
146
|
break
|
143
147
|
|
144
|
-
action_history.append(f"Executing guidance trajectory step [{step_traj_idx}]: {{Plan: {
|
148
|
+
action_history.append(f"Executing guidance trajectory step [{step_traj_idx}]: {{Plan: {step_plan_info}, Action: {step_action}}}\n")
|
145
149
|
|
146
150
|
for exec_message in executor({"role": "assistant", "content": step_action}):
|
147
151
|
yield exec_message
|
@@ -6,14 +6,11 @@ import subprocess
|
|
6
6
|
import ctypes
|
7
7
|
import platform
|
8
8
|
import time
|
9
|
-
import json
|
10
|
-
import shutil
|
11
9
|
|
12
10
|
# Constants need to match guard_service.py
|
13
11
|
_SERVICE_NAME = "OOTBGuardService"
|
14
12
|
_SERVICE_DISPLAY_NAME = "OOTB Guard Service"
|
15
13
|
_TASK_NAME_PREFIX = "OOTB_UserLogon_" # Must match guard_service.py
|
16
|
-
_SHORTCUT_NAME = "OOTB AutoStart Signal.lnk" # Name for the startup shortcut
|
17
14
|
|
18
15
|
def is_admin():
|
19
16
|
"""Check if the script is running with administrative privileges."""
|
@@ -54,298 +51,142 @@ def get_service_module_path():
|
|
54
51
|
except Exception as fallback_e:
|
55
52
|
raise FileNotFoundError(f"Could not find guard_service.py using inspect ({e}) or sys.prefix ({fallback_e}). Check installation.")
|
56
53
|
|
57
|
-
def _run_command(cmd_list, check_errors=True, capture_output=False, verbose=True):
|
58
|
-
"""Helper to run an external command (like sc.exe)."""
|
59
|
-
if verbose:
|
60
|
-
# Safely join for printing, handle potential non-string elements just in case
|
61
|
-
print(f"Executing command: {' '.join(map(str, cmd_list))}")
|
62
|
-
try:
|
63
|
-
result = subprocess.run(
|
64
|
-
cmd_list,
|
65
|
-
capture_output=capture_output,
|
66
|
-
text=True,
|
67
|
-
check=check_errors,
|
68
|
-
encoding='utf-8',
|
69
|
-
errors='ignore'
|
70
|
-
)
|
71
|
-
if capture_output and verbose:
|
72
|
-
if result.stdout: print(f" CMD STDOUT: {result.stdout.strip()}")
|
73
|
-
if result.stderr: print(f" CMD STDERR: {result.stderr.strip()}")
|
74
|
-
return result if capture_output else (result.returncode == 0)
|
75
|
-
except FileNotFoundError as e:
|
76
|
-
print(f"Error: Command not found during execution: {cmd_list[0]}", file=sys.stderr)
|
77
|
-
print(f" Details: {e}", file=sys.stderr)
|
78
|
-
return None if capture_output else False
|
79
|
-
except subprocess.CalledProcessError as e:
|
80
|
-
# Don't print error if check_errors was False and it failed
|
81
|
-
if check_errors and verbose:
|
82
|
-
print(f"Error executing command {' '.join(map(str, cmd_list))} (Exit Code {e.returncode}).", file=sys.stderr)
|
83
|
-
if e.stdout: print(f"Subprocess STDOUT:", file=sys.stderr); print(e.stdout, file=sys.stderr)
|
84
|
-
if e.stderr: print(f"Subprocess STDERR:", file=sys.stderr); print(e.stderr, file=sys.stderr)
|
85
|
-
return None if capture_output else False
|
86
|
-
except Exception as e:
|
87
|
-
if verbose:
|
88
|
-
print(f"An unexpected error occurred running command: {e}", file=sys.stderr)
|
89
|
-
return None if capture_output else False
|
90
54
|
|
91
|
-
def
|
92
|
-
"""
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
shell = win32com.client.Dispatch("WScript.Shell")
|
98
|
-
# SHGetSpecialFolderPath requires integer CSIDL, Startup=7
|
99
|
-
# Using shell.SpecialFolders is usually easier
|
100
|
-
startup_path = shell.SpecialFolders("Startup")
|
101
|
-
if startup_path and os.path.isdir(startup_path):
|
102
|
-
print(f"Found Startup folder: {startup_path}")
|
103
|
-
return startup_path
|
104
|
-
else:
|
105
|
-
print("Error: Could not resolve Startup folder path via WScript.Shell.", file=sys.stderr)
|
106
|
-
return None
|
107
|
-
except ImportError:
|
108
|
-
print("Error: pywin32com is required to find Startup folder. Cannot manage startup shortcut.", file=sys.stderr)
|
109
|
-
return None
|
110
|
-
except Exception as e:
|
111
|
-
print(f"Error finding Startup folder: {e}", file=sys.stderr)
|
112
|
-
return None
|
55
|
+
def run_service_command(command_args, check_errors=True):
|
56
|
+
"""Runs the guard_service.py script with specified command-line args."""
|
57
|
+
if not is_admin():
|
58
|
+
print("Error: Administrative privileges are required to manage the service.", file=sys.stderr)
|
59
|
+
print("Please run this command from an Administrator Command Prompt or PowerShell.", file=sys.stderr)
|
60
|
+
return False
|
113
61
|
|
114
|
-
def _find_pythonw_executable():
|
115
|
-
"""Finds pythonw.exe in the same directory as sys.executable."""
|
116
62
|
try:
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
print(f"Warning: pythonw.exe not found next to sys.executable ({sys.executable}). Console window might flash on login.", file=sys.stderr)
|
123
|
-
# Fallback to python.exe if pythonw not found
|
124
|
-
return sys.executable
|
125
|
-
except Exception as e:
|
126
|
-
print(f"Error finding pythonw.exe: {e}. Using sys.executable as fallback.", file=sys.stderr)
|
127
|
-
return sys.executable
|
63
|
+
python_exe = sys.executable # Use the same python that's running this script
|
64
|
+
service_script = get_service_module_path()
|
65
|
+
except FileNotFoundError as e:
|
66
|
+
print(f"Error: {e}", file=sys.stderr)
|
67
|
+
return False
|
128
68
|
|
129
|
-
|
130
|
-
""
|
131
|
-
|
132
|
-
|
133
|
-
|
69
|
+
# Quote paths if they contain spaces
|
70
|
+
if " " in python_exe and not python_exe.startswith('"'):
|
71
|
+
python_exe = f'"{python_exe}"'
|
72
|
+
if " " in service_script and not service_script.startswith('"'):
|
73
|
+
service_script = f'"{service_script}"'
|
134
74
|
|
135
|
-
|
136
|
-
|
137
|
-
|
75
|
+
# Construct command using list to avoid shell quoting issues
|
76
|
+
cmd = [sys.executable, get_service_module_path()] + command_args
|
77
|
+
print(f"Executing command: {' '.join(cmd)}")
|
138
78
|
|
139
|
-
shortcut_path = os.path.join(startup_dir, _SHORTCUT_NAME)
|
140
|
-
python_launcher = _find_pythonw_executable()
|
141
|
-
signal_script = None
|
142
79
|
try:
|
143
|
-
#
|
144
|
-
|
145
|
-
|
146
|
-
if
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
80
|
+
# Run the command. Use shell=False with list of args.
|
81
|
+
# Capture output to check for specific errors if needed, but print it too.
|
82
|
+
result = subprocess.run(cmd, capture_output=True, text=True, check=check_errors, encoding='utf-8')
|
83
|
+
if result.stdout:
|
84
|
+
print("Command STDOUT:")
|
85
|
+
print(result.stdout)
|
86
|
+
if result.stderr:
|
87
|
+
print("Command STDERR:")
|
88
|
+
print(result.stderr)
|
89
|
+
print(f"Command {' '.join(command_args)} executed successfully.")
|
90
|
+
return True
|
91
|
+
except FileNotFoundError as e:
|
92
|
+
print(f"Error: Could not find Python executable or service script during execution.", file=sys.stderr)
|
93
|
+
print(f" Details: {e}", file=sys.stderr)
|
94
|
+
return False
|
95
|
+
except subprocess.CalledProcessError as e:
|
96
|
+
print(f"Error executing service command {' '.join(command_args)} (Exit Code {e.returncode}).", file=sys.stderr)
|
97
|
+
if e.stdout:
|
98
|
+
print("Subprocess STDOUT:")
|
99
|
+
print(e.stdout)
|
100
|
+
if e.stderr:
|
101
|
+
print("Subprocess STDERR:")
|
102
|
+
print(e.stderr)
|
151
103
|
return False
|
152
|
-
|
153
|
-
|
154
|
-
target_cmd = f'"{python_launcher}"' # Quote launcher path
|
155
|
-
# Quote script path
|
156
|
-
target_cmd += f' "{signal_script}"'
|
157
|
-
# Username argument - %USERNAME% will be expanded by shell when shortcut runs
|
158
|
-
target_cmd += ' %USERNAME%'
|
159
|
-
|
160
|
-
print(f"Creating Startup shortcut:")
|
161
|
-
print(f" Shortcut : {shortcut_path}")
|
162
|
-
print(f" Target : {target_cmd}")
|
163
|
-
|
164
|
-
# Use PowerShell to create the shortcut
|
165
|
-
# Escape paths and arguments for the PowerShell command string
|
166
|
-
ps_shortcut_path = shortcut_path.replace("'", "''")
|
167
|
-
ps_target_cmd = target_cmd.replace("'", "''")
|
168
|
-
ps_working_dir = os.path.dirname(signal_script).replace("'", "''") # Use script's dir as working dir
|
169
|
-
ps_icon_location = python_launcher.replace("'", "''") # Use python icon
|
170
|
-
|
171
|
-
ps_command = f"""
|
172
|
-
$ws = New-Object -ComObject WScript.Shell
|
173
|
-
$s = $ws.CreateShortcut('{ps_shortcut_path}')
|
174
|
-
$s.TargetPath = '{ps_target_cmd.split()[0]}' # Executable part
|
175
|
-
$s.Arguments = '{ps_target_cmd.split(' ', 1)[1] if ' ' in ps_target_cmd else ''}' # Arguments part
|
176
|
-
$s.WorkingDirectory = '{ps_working_dir}'
|
177
|
-
$s.IconLocation = '{ps_icon_location}'
|
178
|
-
$s.WindowStyle = 7 # Minimized
|
179
|
-
$s.Description = 'Triggers OOTB Guard Service connection check on login'
|
180
|
-
$s.Save()
|
181
|
-
Write-Host 'Shortcut created successfully.'
|
182
|
-
"""
|
183
|
-
|
184
|
-
return _run_command([sys.executable, "-NoProfile", "-NonInteractive", "-Command", ps_command])
|
185
|
-
|
186
|
-
def _remove_startup_shortcut():
|
187
|
-
"""Removes the OOTB startup shortcut if it exists."""
|
188
|
-
if not is_admin(): return False # Need admin to potentially delete
|
189
|
-
startup_dir = _get_startup_folder()
|
190
|
-
if not startup_dir:
|
104
|
+
except Exception as e:
|
105
|
+
print(f"An unexpected error occurred running service command: {e}", file=sys.stderr)
|
191
106
|
return False
|
192
107
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
#
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
print("Shortcut not found, no removal needed.")
|
211
|
-
return True
|
108
|
+
# --- Add cleanup helpers ---
|
109
|
+
def _run_powershell_cleanup_command(command):
|
110
|
+
"""Executes a PowerShell command specifically for cleanup, ignoring most errors."""
|
111
|
+
if platform.system() != "Windows": return True # Skip on non-windows
|
112
|
+
print(f"Executing PowerShell Cleanup: {command}")
|
113
|
+
try:
|
114
|
+
# Use check=False, don't capture output unless needed for debug
|
115
|
+
subprocess.run(
|
116
|
+
["powershell.exe", "-NoProfile", "-NonInteractive", "-Command", command],
|
117
|
+
check=False, # Don't throw error if command fails (e.g., no tasks found)
|
118
|
+
stdout=subprocess.DEVNULL, # Suppress stdout
|
119
|
+
stderr=subprocess.DEVNULL # Suppress stderr
|
120
|
+
)
|
121
|
+
return True # Assume success for cleanup flow
|
122
|
+
except Exception as e:
|
123
|
+
print(f"Warning: PowerShell cleanup command failed: {e}", file=sys.stderr)
|
124
|
+
return False # Indicate potential issue
|
212
125
|
|
213
126
|
def _cleanup_scheduled_tasks():
|
214
|
-
"""Removes all OOTB user logon scheduled tasks
|
215
|
-
print("Attempting
|
127
|
+
"""Removes all OOTB user logon scheduled tasks."""
|
128
|
+
print("Attempting to remove any existing OOTB user logon scheduled tasks...")
|
216
129
|
# Use -like operator and wildcard
|
217
|
-
#
|
130
|
+
# Use try-catch within PowerShell for robustness
|
218
131
|
command = f"""
|
219
132
|
$tasks = Get-ScheduledTask | Where-Object {{ $_.TaskName -like '{_TASK_NAME_PREFIX}*' }}
|
220
133
|
if ($tasks) {{
|
221
|
-
Write-Host "Found $($tasks.Count)
|
134
|
+
Write-Host "Found $($tasks.Count) OOTB logon tasks to remove."
|
222
135
|
$tasks | Unregister-ScheduledTask -Confirm:$false -ErrorAction SilentlyContinue
|
223
|
-
Write-Host "
|
136
|
+
Write-Host "OOTB logon task removal attempted."
|
224
137
|
}} else {{
|
225
|
-
Write-Host "No
|
138
|
+
Write-Host "No OOTB logon tasks found to remove."
|
226
139
|
}}
|
227
140
|
"""
|
228
|
-
|
229
|
-
|
141
|
+
_run_powershell_cleanup_command(command)
|
142
|
+
# --- End cleanup helpers ---
|
230
143
|
|
231
144
|
def install_and_start():
|
232
145
|
"""Installs and starts the Guard Service."""
|
233
146
|
print(f"Attempting to install service: '{_SERVICE_NAME}' ('{_SERVICE_DISPLAY_NAME}')")
|
234
|
-
#
|
235
|
-
|
236
|
-
|
237
|
-
python_exe = sys.executable
|
238
|
-
service_script = get_service_module_path()
|
239
|
-
# Quote paths
|
240
|
-
python_exe_quoted = f'"{python_exe}"' if " " in python_exe else python_exe
|
241
|
-
service_script_quoted = f'"{service_script}"' if " " in service_script else service_script
|
242
|
-
# Use list for subprocess
|
243
|
-
install_cmd = [sys.executable, service_script, '--startup', 'auto', 'install']
|
244
|
-
print(f"Executing registration command: {' '.join(install_cmd)}")
|
245
|
-
# We need to check output/return code carefully
|
246
|
-
result = subprocess.run(install_cmd, capture_output=True, text=True, check=False, encoding='utf-8')
|
247
|
-
if result.stdout: print(f" Registration STDOUT: {result.stdout.strip()}")
|
248
|
-
if result.stderr: print(f" Registration STDERR: {result.stderr.strip()}")
|
249
|
-
# Check common success/already-installed messages or just return code 0?
|
250
|
-
# win32serviceutil often returns 0 even if service exists. Let's assume 0 is okay.
|
251
|
-
if result.returncode == 0:
|
252
|
-
print("Service registration command executed (might indicate success or already installed).")
|
253
|
-
install_success = True
|
254
|
-
else:
|
255
|
-
print(f"Service registration command failed (Exit Code {result.returncode}).", file=sys.stderr)
|
256
|
-
install_success = False
|
257
|
-
|
258
|
-
except FileNotFoundError as e:
|
259
|
-
print(f"Error finding Python or service script for registration: {e}", file=sys.stderr)
|
260
|
-
install_success = False
|
261
|
-
except Exception as e:
|
262
|
-
print(f"Unexpected error during service registration: {e}", file=sys.stderr)
|
263
|
-
install_success = False
|
147
|
+
# Call 'install' command first.
|
148
|
+
# We pass check_errors=True to stop if installation fails fundamentally.
|
149
|
+
install_success = run_service_command(['--startup', 'auto', 'install'], check_errors=True)
|
264
150
|
|
265
151
|
if install_success:
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
start_success =
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
service_running = False
|
277
|
-
if query_result and query_result.stdout:
|
278
|
-
if "RUNNING" in query_result.stdout:
|
279
|
-
service_running = True
|
280
|
-
print(f"Service '{_SERVICE_NAME}' confirmed running.")
|
281
|
-
else:
|
282
|
-
print(f"Service '{_SERVICE_NAME}' status check returned:\n{query_result.stdout.strip()}")
|
152
|
+
# Note: Even if install_success is True, pywin32 might have printed internal errors
|
153
|
+
# like 'service already installed'. We proceed to start anyway in that case.
|
154
|
+
print(f"\nInstallation command finished. Attempting to start service: '{_SERVICE_NAME}' (waiting a few seconds first)")
|
155
|
+
time.sleep(3) # Give SCM time to register the install/update
|
156
|
+
start_success = run_service_command(['start'], check_errors=True)
|
157
|
+
|
158
|
+
if start_success:
|
159
|
+
# Similar caveat: start might succeed according to subprocess, but pywin32 could print internal errors.
|
160
|
+
print(f"\nService '{_SERVICE_NAME}' install command executed and start command executed.")
|
161
|
+
print(f"Please verify service status in 'services.msc' and check logs.")
|
283
162
|
else:
|
284
|
-
|
285
|
-
|
286
|
-
if start_success and service_running:
|
287
|
-
print(f"\nService '{_SERVICE_NAME}' installed/updated and started successfully.")
|
288
|
-
# Step 3: Create startup shortcut only if service started
|
289
|
-
print("Creating startup shortcut...")
|
290
|
-
_create_startup_shortcut()
|
291
|
-
elif start_success and not service_running:
|
292
|
-
print(f"\nService '{_SERVICE_NAME}' installed/updated. 'sc start' command succeeded but service is not in RUNNING state.", file=sys.stderr)
|
293
|
-
print(" Check logs or try starting manually.", file=sys.stderr)
|
294
|
-
else: # start_success was False
|
295
|
-
print(f"\nService '{_SERVICE_NAME}' installed/updated but 'sc start' command failed.", file=sys.stderr)
|
163
|
+
# This path is taken if run_service_command returned False (subprocess error occurred)
|
164
|
+
print(f"\nService '{_SERVICE_NAME}' installed/updated but the 'start' command failed with an error.", file=sys.stderr)
|
296
165
|
print(f" Check output above, service logs ('C:\ProgramData\OOTBGuardService\guard_post_mode.log'), or Windows Event Viewer.", file=sys.stderr)
|
297
166
|
else:
|
298
|
-
# This path is taken if the initial
|
299
|
-
print(f"\nService '{_SERVICE_NAME}'
|
167
|
+
# This path is taken if the initial 'install' command failed critically (subprocess error)
|
168
|
+
print(f"\nService '{_SERVICE_NAME}' installation failed critically. See errors above.", file=sys.stderr)
|
300
169
|
|
301
|
-
def stop_and_remove():
|
302
|
-
"""Stops and removes the Guard Service and associated resources."""
|
303
|
-
print(f"Attempting to remove Startup shortcut...")
|
304
|
-
_remove_startup_shortcut()
|
305
170
|
|
306
|
-
|
171
|
+
def stop_and_remove():
|
172
|
+
"""Stops and removes the Guard Service and associated scheduled tasks."""
|
173
|
+
print(f"Attempting to stop service: '{_SERVICE_NAME}' (will ignore errors if not running)")
|
307
174
|
# Run stop first, ignore errors (check_errors=False)
|
308
|
-
|
309
|
-
|
310
|
-
_run_command(stop_cmd, check_errors=False)
|
311
|
-
time.sleep(3) # Give service time to stop
|
175
|
+
run_service_command(['stop'], check_errors=False)
|
176
|
+
time.sleep(2) # Give service time to stop
|
312
177
|
|
313
|
-
|
314
|
-
|
315
|
-
query_result = _run_command(query_cmd, capture_output=True, check_errors=False, verbose=False)
|
316
|
-
service_exists = True # Assume it exists unless query fails specifically
|
317
|
-
if query_result:
|
318
|
-
if query_result.stderr and ("failed" in query_result.stderr.lower() or "does not exist" in query_result.stderr.lower()):
|
319
|
-
service_exists = False
|
320
|
-
print("Service does not appear to exist before removal attempt.")
|
321
|
-
elif query_result.stdout and "STOPPED" in query_result.stdout:
|
322
|
-
print("Service confirmed stopped.")
|
323
|
-
elif query_result.stdout:
|
324
|
-
print(f"Warning: Service state after stop attempt: {query_result.stdout.strip()}")
|
325
|
-
else:
|
326
|
-
print("Warning: Could not query service state after stop attempt.")
|
327
|
-
|
328
|
-
print(f"\nAttempting to remove service using 'sc delete'...")
|
329
|
-
# remove_success = run_service_command(['remove']) # Check if removal command itself failed
|
330
|
-
delete_cmd = ['sc', 'delete', _SERVICE_NAME]
|
331
|
-
delete_success = _run_command(delete_cmd, check_errors=False) # Ignore error if not found
|
178
|
+
print(f"\nAttempting to remove service: '{_SERVICE_NAME}'")
|
179
|
+
remove_success = run_service_command(['remove']) # Check if removal command itself failed
|
332
180
|
|
333
181
|
# Always attempt task cleanup, even if service removal had issues
|
334
182
|
_cleanup_scheduled_tasks()
|
335
183
|
|
336
|
-
if
|
337
|
-
|
338
|
-
time.sleep(1)
|
339
|
-
query_result_after = _run_command(query_cmd, capture_output=True, check_errors=False, verbose=False)
|
340
|
-
if query_result_after and query_result_after.stderr and ("failed" in query_result_after.stderr.lower() or "does not exist" in query_result_after.stderr.lower()):
|
341
|
-
print(f"\nService '{_SERVICE_NAME}' stopped (if running), removed successfully. Startup shortcut and logon tasks cleanup attempted.")
|
342
|
-
else:
|
343
|
-
print(f"\nService '{_SERVICE_NAME}' stop attempted. 'sc delete' command ran but service might still exist. Please check manually.", file=sys.stderr)
|
344
|
-
print(f" Startup shortcut and logon tasks cleanup attempted.", file=sys.stderr)
|
184
|
+
if remove_success:
|
185
|
+
print(f"\nService '{_SERVICE_NAME}' stopped (if running) and removed successfully. Associated logon tasks cleanup attempted.")
|
345
186
|
else:
|
346
|
-
|
347
|
-
|
348
|
-
print(f"
|
187
|
+
print(f"\nService '{_SERVICE_NAME}' removal command failed.", file=sys.stderr)
|
188
|
+
# Make sure to mention cleanup was still attempted
|
189
|
+
print(f" Associated logon tasks cleanup attempted.", file=sys.stderr)
|
349
190
|
print(f" Ensure the service was stopped first, or check permissions.", file=sys.stderr)
|
350
191
|
|
351
192
|
if __name__ == '__main__':
|
{computer_use_ootb_internal-0.0.170.dist-info → computer_use_ootb_internal-0.0.171.dist-info}/RECORD
RENAMED
@@ -1,12 +1,11 @@
|
|
1
1
|
computer_use_ootb_internal/README.md,sha256=FxpW95lyub2iX73ZDfK6ML7SdEKg060H5I6Grub7li4,31
|
2
2
|
computer_use_ootb_internal/__init__.py,sha256=Nqnn8clbgv-5l0PgxcTOldg8mkMKrFn4TvPL-rYUUGg,1
|
3
|
-
computer_use_ootb_internal/app_teachmode.py,sha256=
|
3
|
+
computer_use_ootb_internal/app_teachmode.py,sha256=MUoMkTXHJL6e6fib459rSlCyOK6AzIrs5XOfKN34-aY,26230
|
4
4
|
computer_use_ootb_internal/dependency_check.py,sha256=y8RMEP6RXQzTgU1MS_1piBLtz4J-Hfn9RjUZg59dyvo,1333
|
5
|
-
computer_use_ootb_internal/guard_service.py,sha256=
|
6
|
-
computer_use_ootb_internal/launch_ootb_elevated.ps1,sha256=_WWVbxOU1Ow8MpOC9GUYV0B-DYEnLGaRCTkT9rNGuYY,2426
|
5
|
+
computer_use_ootb_internal/guard_service.py,sha256=ThF_Y8FcBQseXo6-5hIh_Z4cISkCLLEgjWrR2BIV-C0,50940
|
7
6
|
computer_use_ootb_internal/requirements-lite.txt,sha256=5DAHomz4A_P2BmTIXNkNqkHbnIF0AyZ4_1XAlb1LaYs,290
|
8
|
-
computer_use_ootb_internal/run_teachmode_ootb_args.py,sha256=
|
9
|
-
computer_use_ootb_internal/service_manager.py,sha256=
|
7
|
+
computer_use_ootb_internal/run_teachmode_ootb_args.py,sha256=wou3FkumHHy3XlYlV0orO7zdJfq2ckDLHw5hGtFnieo,8159
|
8
|
+
computer_use_ootb_internal/service_manager.py,sha256=_aFUtvSbovX73PY1QE01RkaqGV6swJaStrOwcg_Df94,9928
|
10
9
|
computer_use_ootb_internal/signal_connection.py,sha256=e6eGByhb2Gx8HHJHrHM3HvchobSUmba1y7-YRB6L59E,1821
|
11
10
|
computer_use_ootb_internal/test_click_0425.py,sha256=uZtP6DsPVRFonKMYlbe9eHmPY6hH5y8xWgr2KxHC8E4,1808
|
12
11
|
computer_use_ootb_internal/computer_use_demo/animation/click_animation.py,sha256=tP1gsayFy-CKk10UlrE9RlexwlHWiHQUe5Ogg4vQvSg,3234
|
@@ -36,7 +35,7 @@ computer_use_ootb_internal/computer_use_demo/tools/run.py,sha256=xhXdnBK1di9muaO
|
|
36
35
|
computer_use_ootb_internal/computer_use_demo/tools/screen_capture.py,sha256=L8qfvtUkPPQGt92N-2Zfw5ZTDBzLsDps39uMnX3_uSA,6857
|
37
36
|
computer_use_ootb_internal/preparation/__init__.py,sha256=AgtGHcBpiTkxJjF0xwcs3yyQ6SyUvhL3G0vD2XO-zJw,63
|
38
37
|
computer_use_ootb_internal/preparation/star_rail_prepare.py,sha256=RAriQxrv55csBNBm0m8CKyd_RW8k1tXx0kdJAcOpYlg,4734
|
39
|
-
computer_use_ootb_internal-0.0.
|
40
|
-
computer_use_ootb_internal-0.0.
|
41
|
-
computer_use_ootb_internal-0.0.
|
42
|
-
computer_use_ootb_internal-0.0.
|
38
|
+
computer_use_ootb_internal-0.0.171.dist-info/METADATA,sha256=c95CauIKJIwTWreTYiPd_j5hLg8EUJIOwNQcU5ymTcw,910
|
39
|
+
computer_use_ootb_internal-0.0.171.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
40
|
+
computer_use_ootb_internal-0.0.171.dist-info/entry_points.txt,sha256=-AbmawU7IRQuDZihgVMVDrFoY4E6rnXYOUB-5vSeBKs,93
|
41
|
+
computer_use_ootb_internal-0.0.171.dist-info/RECORD,,
|
@@ -1,63 +0,0 @@
|
|
1
|
-
# launch_ootb_elevated.ps1
|
2
|
-
param(
|
3
|
-
[Parameter(Mandatory=$true)]
|
4
|
-
[string]$TargetExePath,
|
5
|
-
|
6
|
-
[Parameter(Mandatory=$true)]
|
7
|
-
[string]$Port,
|
8
|
-
|
9
|
-
[Parameter(Mandatory=$true)]
|
10
|
-
[string]$TargetUser,
|
11
|
-
|
12
|
-
[Parameter(Mandatory=$true)]
|
13
|
-
[string]$WorkingDirectory
|
14
|
-
)
|
15
|
-
|
16
|
-
try {
|
17
|
-
Write-Host "--- OOTB Elevation Helper ---"
|
18
|
-
Write-Host "Timestamp: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
|
19
|
-
Write-Host "Received parameters:"
|
20
|
-
Write-Host " Target Exe Path : $TargetExePath"
|
21
|
-
Write-Host " Port : $Port"
|
22
|
-
Write-Host " Target User : $TargetUser"
|
23
|
-
Write-Host " Working Dir : $WorkingDirectory"
|
24
|
-
Write-Host ""
|
25
|
-
|
26
|
-
# Validate paths
|
27
|
-
if (-not (Test-Path -Path $TargetExePath -PathType Leaf)) {
|
28
|
-
throw "Target executable not found at '$TargetExePath'"
|
29
|
-
}
|
30
|
-
if (-not (Test-Path -Path $WorkingDirectory -PathType Container)) {
|
31
|
-
throw "Working directory not found at '$WorkingDirectory'"
|
32
|
-
}
|
33
|
-
|
34
|
-
# Construct the argument list string for the target executable
|
35
|
-
# Ensure target user is single-quoted for the argument parser
|
36
|
-
$argumentList = "--port $Port --target_user '$TargetUser'"
|
37
|
-
|
38
|
-
Write-Host "Constructed ArgumentList for Target Exe: $argumentList"
|
39
|
-
Write-Host "Executing elevated process..."
|
40
|
-
Write-Host "Command: Start-Process -FilePath `$TargetExePath` -ArgumentList `$argumentList` -WorkingDirectory `$WorkingDirectory` -Verb RunAs"
|
41
|
-
Write-Host "--- Waiting for UAC prompt if necessary ---"
|
42
|
-
|
43
|
-
# Execute the command to launch the target exe elevated directly
|
44
|
-
Start-Process -FilePath $TargetExePath -ArgumentList $argumentList -WorkingDirectory $WorkingDirectory -Verb RunAs
|
45
|
-
|
46
|
-
Write-Host "--- OOTB Elevation Helper: Start-Process command executed. ---"
|
47
|
-
# The calling powershell window (started by CreateProcessAsUser with -NoExit) will remain open.
|
48
|
-
|
49
|
-
} catch {
|
50
|
-
Write-Error "--- OOTB Elevation Helper Error ---"
|
51
|
-
Write-Error "Error launching elevated process: $($_.Exception.Message)"
|
52
|
-
Write-Error "Script Parameters:"
|
53
|
-
Write-Error " Target Exe Path : $TargetExePath"
|
54
|
-
Write-Error " Port : $Port"
|
55
|
-
Write-Error " Target User : $TargetUser"
|
56
|
-
Write-Error " Working Dir : $WorkingDirectory"
|
57
|
-
Write-Host "Press Enter to exit..."
|
58
|
-
Read-Host # Keep window open on error
|
59
|
-
Exit 1
|
60
|
-
}
|
61
|
-
|
62
|
-
# Exit gracefully if successful
|
63
|
-
Exit 0
|
{computer_use_ootb_internal-0.0.170.dist-info → computer_use_ootb_internal-0.0.171.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|