atomicshop 2.11.47__py3-none-any.whl → 3.10.5__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.
- atomicshop/__init__.py +1 -1
- atomicshop/{addons/mains → a_mains}/FACT/update_extract.py +3 -2
- atomicshop/a_mains/addons/process_list/compile.cmd +7 -0
- atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.dll +0 -0
- atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.exp +0 -0
- atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.lib +0 -0
- atomicshop/{addons → a_mains/addons}/process_list/process_list.cpp +8 -1
- atomicshop/a_mains/dns_gateway_setting.py +11 -0
- atomicshop/a_mains/get_local_tcp_ports.py +85 -0
- atomicshop/a_mains/github_wrapper.py +11 -0
- atomicshop/a_mains/install_ca_certificate.py +172 -0
- atomicshop/{addons/mains → a_mains}/msi_unpacker.py +3 -1
- atomicshop/a_mains/process_from_port.py +119 -0
- atomicshop/a_mains/set_default_dns_gateway.py +90 -0
- atomicshop/a_mains/update_config_toml.py +38 -0
- atomicshop/appointment_management.py +5 -3
- atomicshop/basics/ansi_escape_codes.py +3 -1
- atomicshop/basics/argparse_template.py +2 -0
- atomicshop/basics/booleans.py +27 -30
- atomicshop/basics/bytes_arrays.py +43 -0
- atomicshop/basics/classes.py +149 -1
- atomicshop/basics/dicts.py +12 -0
- atomicshop/basics/enums.py +2 -2
- atomicshop/basics/exceptions.py +5 -1
- atomicshop/basics/list_of_classes.py +29 -0
- atomicshop/basics/list_of_dicts.py +69 -5
- atomicshop/basics/lists.py +14 -0
- atomicshop/basics/multiprocesses.py +374 -50
- atomicshop/basics/package_module.py +10 -0
- atomicshop/basics/strings.py +160 -7
- atomicshop/basics/threads.py +14 -0
- atomicshop/basics/tracebacks.py +13 -4
- atomicshop/certificates.py +153 -52
- atomicshop/config_init.py +12 -7
- atomicshop/console_user_response.py +7 -14
- atomicshop/consoles.py +9 -0
- atomicshop/datetimes.py +98 -0
- atomicshop/diff_check.py +340 -40
- atomicshop/dns.py +128 -12
- atomicshop/etws/_pywintrace_fix.py +17 -0
- atomicshop/etws/const.py +38 -0
- atomicshop/etws/providers.py +21 -0
- atomicshop/etws/sessions.py +43 -0
- atomicshop/etws/trace.py +168 -0
- atomicshop/etws/traces/trace_dns.py +162 -0
- atomicshop/etws/traces/trace_sysmon_process_creation.py +126 -0
- atomicshop/etws/traces/trace_tcp.py +130 -0
- atomicshop/file_io/csvs.py +222 -24
- atomicshop/file_io/docxs.py +35 -18
- atomicshop/file_io/file_io.py +35 -19
- atomicshop/file_io/jsons.py +49 -0
- atomicshop/file_io/tomls.py +139 -0
- atomicshop/filesystem.py +864 -293
- atomicshop/get_process_list.py +133 -0
- atomicshop/{process_name_cmd.py → get_process_name_cmd_dll.py} +52 -19
- atomicshop/http_parse.py +149 -93
- atomicshop/ip_addresses.py +6 -1
- atomicshop/mitm/centered_settings.py +132 -0
- atomicshop/mitm/config_static.py +207 -0
- atomicshop/mitm/config_toml_editor.py +55 -0
- atomicshop/mitm/connection_thread_worker.py +875 -357
- atomicshop/mitm/engines/__parent/parser___parent.py +4 -17
- atomicshop/mitm/engines/__parent/recorder___parent.py +108 -51
- atomicshop/mitm/engines/__parent/requester___parent.py +116 -0
- atomicshop/mitm/engines/__parent/responder___parent.py +75 -114
- atomicshop/mitm/engines/__reference_general/parser___reference_general.py +10 -7
- atomicshop/mitm/engines/__reference_general/recorder___reference_general.py +5 -5
- atomicshop/mitm/engines/__reference_general/requester___reference_general.py +47 -0
- atomicshop/mitm/engines/__reference_general/responder___reference_general.py +95 -13
- atomicshop/mitm/engines/create_module_template.py +58 -14
- atomicshop/mitm/import_config.py +359 -139
- atomicshop/mitm/initialize_engines.py +160 -74
- atomicshop/mitm/message.py +64 -23
- atomicshop/mitm/mitm_main.py +892 -0
- atomicshop/mitm/recs_files.py +183 -0
- atomicshop/mitm/shared_functions.py +4 -10
- atomicshop/mitm/ssh_tester.py +82 -0
- atomicshop/mitm/statistic_analyzer.py +257 -166
- atomicshop/mitm/statistic_analyzer_helper/analyzer_helper.py +136 -0
- atomicshop/mitm/statistic_analyzer_helper/moving_average_helper.py +525 -0
- atomicshop/monitor/change_monitor.py +96 -120
- atomicshop/monitor/checks/dns.py +139 -70
- atomicshop/monitor/checks/file.py +77 -0
- atomicshop/monitor/checks/network.py +81 -77
- atomicshop/monitor/checks/process_running.py +33 -34
- atomicshop/monitor/checks/url.py +94 -0
- atomicshop/networks.py +671 -0
- atomicshop/on_exit.py +205 -0
- atomicshop/package_mains_processor.py +84 -0
- atomicshop/permissions/permissions.py +22 -0
- atomicshop/permissions/ubuntu_permissions.py +239 -0
- atomicshop/permissions/win_permissions.py +33 -0
- atomicshop/print_api.py +24 -41
- atomicshop/process.py +63 -17
- atomicshop/process_poller/__init__.py +0 -0
- atomicshop/process_poller/pollers/__init__.py +0 -0
- atomicshop/process_poller/pollers/psutil_pywin32wmi_dll.py +95 -0
- atomicshop/process_poller/process_pool.py +207 -0
- atomicshop/process_poller/simple_process_pool.py +311 -0
- atomicshop/process_poller/tracer_base.py +45 -0
- atomicshop/process_poller/tracers/__init__.py +0 -0
- atomicshop/process_poller/tracers/event_log.py +46 -0
- atomicshop/process_poller/tracers/sysmon_etw.py +68 -0
- atomicshop/python_file_patcher.py +1 -1
- atomicshop/python_functions.py +27 -75
- atomicshop/question_answer_engine.py +2 -2
- atomicshop/scheduling.py +24 -5
- atomicshop/sound.py +4 -2
- atomicshop/speech_recognize.py +8 -0
- atomicshop/ssh_remote.py +158 -172
- atomicshop/startup/__init__.py +0 -0
- atomicshop/startup/win/__init__.py +0 -0
- atomicshop/startup/win/startup_folder.py +53 -0
- atomicshop/startup/win/task_scheduler.py +119 -0
- atomicshop/system_resource_monitor.py +61 -46
- atomicshop/system_resources.py +8 -8
- atomicshop/tempfiles.py +1 -2
- atomicshop/timer.py +30 -11
- atomicshop/urls.py +41 -0
- atomicshop/venvs.py +28 -0
- atomicshop/versioning.py +27 -0
- atomicshop/web.py +110 -25
- atomicshop/web_apis/__init__.py +0 -0
- atomicshop/web_apis/google_custom_search.py +44 -0
- atomicshop/web_apis/google_llm.py +188 -0
- atomicshop/websocket_parse.py +450 -0
- atomicshop/wrappers/certauthw/certauth.py +1 -0
- atomicshop/wrappers/cryptographyw.py +29 -8
- atomicshop/wrappers/ctyping/etw_winapi/__init__.py +0 -0
- atomicshop/wrappers/ctyping/etw_winapi/const.py +335 -0
- atomicshop/wrappers/ctyping/etw_winapi/etw_functions.py +393 -0
- atomicshop/wrappers/ctyping/file_details_winapi.py +67 -0
- atomicshop/wrappers/ctyping/msi_windows_installer/cabs.py +2 -1
- atomicshop/wrappers/ctyping/msi_windows_installer/extract_msi_main.py +13 -9
- atomicshop/wrappers/ctyping/msi_windows_installer/tables.py +35 -0
- atomicshop/wrappers/ctyping/setup_device.py +466 -0
- atomicshop/wrappers/ctyping/win_console.py +39 -0
- atomicshop/wrappers/dockerw/dockerw.py +113 -2
- atomicshop/wrappers/elasticsearchw/config_basic.py +0 -12
- atomicshop/wrappers/elasticsearchw/elastic_infra.py +75 -0
- atomicshop/wrappers/elasticsearchw/elasticsearchw.py +2 -20
- atomicshop/wrappers/factw/get_file_data.py +12 -5
- atomicshop/wrappers/factw/install/install_after_restart.py +89 -5
- atomicshop/wrappers/factw/install/pre_install_and_install_before_restart.py +20 -14
- atomicshop/wrappers/factw/postgresql/firmware.py +4 -6
- atomicshop/wrappers/githubw.py +583 -51
- atomicshop/wrappers/loggingw/consts.py +49 -0
- atomicshop/wrappers/loggingw/filters.py +102 -0
- atomicshop/wrappers/loggingw/formatters.py +58 -71
- atomicshop/wrappers/loggingw/handlers.py +459 -40
- atomicshop/wrappers/loggingw/loggers.py +19 -0
- atomicshop/wrappers/loggingw/loggingw.py +1010 -178
- atomicshop/wrappers/loggingw/reading.py +344 -19
- atomicshop/wrappers/mongodbw/__init__.py +0 -0
- atomicshop/wrappers/mongodbw/mongo_infra.py +31 -0
- atomicshop/wrappers/mongodbw/mongodbw.py +1432 -0
- atomicshop/wrappers/netshw.py +271 -0
- atomicshop/wrappers/playwrightw/engine.py +34 -19
- atomicshop/wrappers/playwrightw/infra.py +5 -0
- atomicshop/wrappers/playwrightw/javascript.py +7 -3
- atomicshop/wrappers/playwrightw/keyboard.py +14 -0
- atomicshop/wrappers/playwrightw/scenarios.py +172 -5
- atomicshop/wrappers/playwrightw/waits.py +9 -7
- atomicshop/wrappers/powershell_networking.py +80 -0
- atomicshop/wrappers/psutilw/processes.py +81 -0
- atomicshop/wrappers/psutilw/psutil_networks.py +85 -0
- atomicshop/wrappers/psutilw/psutilw.py +9 -0
- atomicshop/wrappers/pyopensslw.py +9 -2
- atomicshop/wrappers/pywin32w/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/cert_store.py +116 -0
- atomicshop/wrappers/pywin32w/console.py +34 -0
- atomicshop/wrappers/pywin32w/win_event_log/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/win_event_log/fetch.py +174 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribe.py +212 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_create.py +57 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_terminate.py +49 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/schannel_logging.py +97 -0
- atomicshop/wrappers/pywin32w/winshell.py +19 -0
- atomicshop/wrappers/pywin32w/wmis/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/wmis/msft_netipaddress.py +113 -0
- atomicshop/wrappers/pywin32w/wmis/win32_networkadapterconfiguration.py +259 -0
- atomicshop/wrappers/pywin32w/wmis/win32networkadapter.py +112 -0
- atomicshop/wrappers/pywin32w/wmis/wmi_helpers.py +236 -0
- atomicshop/wrappers/socketw/accepter.py +21 -7
- atomicshop/wrappers/socketw/certificator.py +216 -150
- atomicshop/wrappers/socketw/creator.py +190 -50
- atomicshop/wrappers/socketw/dns_server.py +500 -173
- atomicshop/wrappers/socketw/exception_wrapper.py +45 -52
- atomicshop/wrappers/socketw/process_getter.py +86 -0
- atomicshop/wrappers/socketw/receiver.py +144 -102
- atomicshop/wrappers/socketw/sender.py +65 -35
- atomicshop/wrappers/socketw/sni.py +334 -165
- atomicshop/wrappers/socketw/socket_base.py +134 -0
- atomicshop/wrappers/socketw/socket_client.py +137 -95
- atomicshop/wrappers/socketw/socket_server_tester.py +14 -9
- atomicshop/wrappers/socketw/socket_wrapper.py +717 -116
- atomicshop/wrappers/socketw/ssl_base.py +15 -14
- atomicshop/wrappers/socketw/statistics_csv.py +148 -17
- atomicshop/wrappers/sysmonw.py +157 -0
- atomicshop/wrappers/ubuntu_terminal.py +65 -26
- atomicshop/wrappers/win_auditw.py +189 -0
- atomicshop/wrappers/winregw/__init__.py +0 -0
- atomicshop/wrappers/winregw/winreg_installed_software.py +58 -0
- atomicshop/wrappers/winregw/winreg_network.py +232 -0
- {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info}/METADATA +31 -49
- atomicshop-3.10.5.dist-info/RECORD +306 -0
- {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info}/WHEEL +1 -1
- atomicshop/_basics_temp.py +0 -101
- atomicshop/addons/a_setup_scripts/install_psycopg2_ubuntu.sh +0 -3
- atomicshop/addons/a_setup_scripts/install_pywintrace_0.3.cmd +0 -2
- atomicshop/addons/mains/install_docker_rootless_ubuntu.py +0 -11
- atomicshop/addons/mains/install_docker_ubuntu_main_sudo.py +0 -11
- atomicshop/addons/mains/install_elastic_search_and_kibana_ubuntu.py +0 -10
- atomicshop/addons/mains/install_wsl_ubuntu_lts_admin.py +0 -9
- atomicshop/addons/package_setup/CreateWheel.cmd +0 -7
- atomicshop/addons/package_setup/Setup in Edit mode.cmd +0 -6
- atomicshop/addons/package_setup/Setup.cmd +0 -7
- atomicshop/addons/process_list/compile.cmd +0 -2
- atomicshop/addons/process_list/compiled/Win10x64/process_list.dll +0 -0
- atomicshop/addons/process_list/compiled/Win10x64/process_list.exp +0 -0
- atomicshop/addons/process_list/compiled/Win10x64/process_list.lib +0 -0
- atomicshop/archiver/_search_in_zip.py +0 -189
- atomicshop/archiver/archiver.py +0 -34
- atomicshop/archiver/search_in_archive.py +0 -250
- atomicshop/archiver/sevenz_app_w.py +0 -86
- atomicshop/archiver/sevenzs.py +0 -44
- atomicshop/archiver/zips.py +0 -293
- atomicshop/etw/dns_trace.py +0 -118
- atomicshop/etw/etw.py +0 -61
- atomicshop/file_types.py +0 -24
- atomicshop/mitm/engines/create_module_template_example.py +0 -13
- atomicshop/mitm/initialize_mitm_server.py +0 -240
- atomicshop/monitor/checks/hash.py +0 -44
- atomicshop/monitor/checks/hash_checks/file.py +0 -55
- atomicshop/monitor/checks/hash_checks/url.py +0 -62
- atomicshop/pbtkmultifile_argparse.py +0 -88
- atomicshop/permissions.py +0 -110
- atomicshop/process_poller.py +0 -237
- atomicshop/script_as_string_processor.py +0 -38
- atomicshop/ssh_scripts/process_from_ipv4.py +0 -37
- atomicshop/ssh_scripts/process_from_port.py +0 -27
- atomicshop/wrappers/_process_wrapper_curl.py +0 -27
- atomicshop/wrappers/_process_wrapper_tar.py +0 -21
- atomicshop/wrappers/dockerw/install_docker.py +0 -209
- atomicshop/wrappers/elasticsearchw/infrastructure.py +0 -265
- atomicshop/wrappers/elasticsearchw/install_elastic.py +0 -232
- atomicshop/wrappers/ffmpegw.py +0 -125
- atomicshop/wrappers/loggingw/checks.py +0 -20
- atomicshop/wrappers/nodejsw/install_nodejs.py +0 -139
- atomicshop/wrappers/process_wrapper_pbtk.py +0 -16
- atomicshop/wrappers/socketw/base.py +0 -59
- atomicshop/wrappers/socketw/get_process.py +0 -107
- atomicshop/wrappers/wslw.py +0 -191
- atomicshop-2.11.47.dist-info/RECORD +0 -251
- /atomicshop/{addons/mains → a_mains}/FACT/factw_fact_extractor_docker_image_main_sudo.py +0 -0
- /atomicshop/{addons → a_mains/addons}/PlayWrightCodegen.cmd +0 -0
- /atomicshop/{addons → a_mains/addons}/ScriptExecution.cmd +0 -0
- /atomicshop/{addons/mains → a_mains/addons}/inits/init_to_import_all_modules.py +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/ReadMe.txt +0 -0
- /atomicshop/{addons/mains → a_mains}/search_for_hyperlinks_in_docx.py +0 -0
- /atomicshop/{archiver → etws}/__init__.py +0 -0
- /atomicshop/{etw → etws/traces}/__init__.py +0 -0
- /atomicshop/{monitor/checks/hash_checks → mitm/statistic_analyzer_helper}/__init__.py +0 -0
- /atomicshop/{wrappers/nodejsw → permissions}/__init__.py +0 -0
- /atomicshop/wrappers/pywin32w/{wmi_win32process.py → wmis/win32process.py} +0 -0
- {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info/licenses}/LICENSE.txt +0 -0
- {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info}/top_level.txt +0 -0
atomicshop/print_api.py
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import sys
|
|
2
|
+
import logging
|
|
3
|
+
from typing import Any
|
|
2
4
|
|
|
3
|
-
from .basics
|
|
5
|
+
from .basics import ansi_escape_codes
|
|
4
6
|
from .basics import tracebacks
|
|
5
7
|
|
|
6
8
|
|
|
7
|
-
# noinspection PyUnusedLocal,PyIncorrectDocstring
|
|
8
9
|
def print_api(
|
|
9
|
-
message:
|
|
10
|
-
color:
|
|
10
|
+
message: Any,
|
|
11
|
+
color: Any = None,
|
|
11
12
|
print_end: str = '\n',
|
|
12
13
|
rtl: bool = False,
|
|
13
14
|
error_type: bool = False,
|
|
14
|
-
logger:
|
|
15
|
+
logger: logging.Logger = None,
|
|
15
16
|
logger_method: str = 'info',
|
|
16
17
|
stdout: bool = True,
|
|
17
18
|
stderr: bool = True,
|
|
@@ -19,8 +20,6 @@ def print_api(
|
|
|
19
20
|
traceback_string: bool = False,
|
|
20
21
|
oneline: bool = False,
|
|
21
22
|
oneline_end: str = '',
|
|
22
|
-
# raise_exception: bool = True,
|
|
23
|
-
# exit_on_error: bool = False,
|
|
24
23
|
**kwargs: object) -> None:
|
|
25
24
|
"""
|
|
26
25
|
Function of custom api that is responsible for printing messages to console.
|
|
@@ -82,39 +81,37 @@ def print_api(
|
|
|
82
81
|
|
|
83
82
|
# This section takes care of different types of string manipulations for message.
|
|
84
83
|
|
|
85
|
-
# If 'exit_on_error' is set to 'True', we'll add 'exit_message' on new line after 'message'.
|
|
86
|
-
# if error_type and exit_on_error and raise_exception:
|
|
87
|
-
# message = message + '\n' + exit_message
|
|
88
|
-
|
|
89
84
|
# If 'rtl' is set to 'True', we'll add Right-To-Left text conversion to 'message'.
|
|
90
85
|
if rtl:
|
|
91
|
-
# Lazy importing of 'bidi' library. It's not a problem since python caches the library after first import.
|
|
92
|
-
# Off-course, it will be imported from the cache each time this section is triggered.
|
|
93
86
|
# pip install python-bidi
|
|
94
87
|
from bidi.algorithm import get_display
|
|
95
88
|
message = get_display(message)
|
|
96
89
|
|
|
90
|
+
if logger_method == 'error' or logger_method == 'critical':
|
|
91
|
+
error_type = True
|
|
92
|
+
|
|
93
|
+
# If exception was raised and 'stderr=True'.
|
|
94
|
+
if sys.exc_info()[0] is not None and stderr and traceback_string:
|
|
95
|
+
# If 'traceback' is set to 'True', we'll output traceback of exception.
|
|
96
|
+
if traceback_string:
|
|
97
|
+
if message:
|
|
98
|
+
message = f'{message}\n{tracebacks.get_as_string()}{message}'
|
|
99
|
+
else:
|
|
100
|
+
message = tracebacks.get_as_string()
|
|
101
|
+
|
|
102
|
+
color = 'red'
|
|
103
|
+
|
|
97
104
|
# If 'stdcolor' is 'True', the console output will be colored.
|
|
98
105
|
if stdcolor:
|
|
99
106
|
# If 'logger.error' should be outputted to console, and 'color' wasn't selected, then set color to 'yellow'.
|
|
100
107
|
if logger_method == 'error' and not color:
|
|
101
108
|
color = 'yellow'
|
|
102
|
-
error_type = True
|
|
103
109
|
# If 'logger.critical' should be outputted to console, and 'color' wasn't selected, then set color to 'red'.
|
|
104
110
|
elif logger_method == 'critical' and not color:
|
|
105
111
|
color = 'red'
|
|
106
|
-
error_type = True
|
|
107
|
-
|
|
108
|
-
if color:
|
|
109
|
-
message = get_colors_basic_dict(color) + message + ColorsBasic.END
|
|
110
112
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
# If 'traceback' is set to 'True', we'll output traceback of exception.
|
|
114
|
-
if traceback_string:
|
|
115
|
-
message = f'{message} | Exception: {tracebacks.get_as_string()}'
|
|
116
|
-
|
|
117
|
-
color = 'red'
|
|
113
|
+
if color is not None:
|
|
114
|
+
message = ansi_escape_codes.get_colors_basic_dict(color) + message + ansi_escape_codes.ColorsBasic.END
|
|
118
115
|
|
|
119
116
|
# If 'online' is set to 'True', we'll output message as oneline.
|
|
120
117
|
if oneline:
|
|
@@ -129,14 +126,14 @@ def print_api(
|
|
|
129
126
|
if print_end == '\n':
|
|
130
127
|
# Use logger to output message.
|
|
131
128
|
getattr(logger, logger_method)(message)
|
|
129
|
+
else:
|
|
130
|
+
raise ValueError("Logger can't output messages with 'print_end' other than '\\n'.")
|
|
132
131
|
# If logger wasn't passed.
|
|
133
132
|
else:
|
|
134
133
|
# Use print to output the message.
|
|
135
134
|
print(message, end=print_end)
|
|
136
135
|
|
|
137
136
|
# = Main Section with printing cases ===============================================================================
|
|
138
|
-
# exit_message: str = 'Exiting...'
|
|
139
|
-
|
|
140
137
|
# Convert message to string.
|
|
141
138
|
message = str(message)
|
|
142
139
|
|
|
@@ -150,20 +147,6 @@ def print_api(
|
|
|
150
147
|
if error_type:
|
|
151
148
|
print_or_logger()
|
|
152
149
|
|
|
153
|
-
# ==================================
|
|
154
|
-
# This section is responsible for ending the script.
|
|
155
|
-
|
|
156
|
-
# Check if we're inside exception. In this case each of 3 entries in 'sys.exc_info()' tuple will not equal
|
|
157
|
-
# to 'None', so picked only the first one.
|
|
158
|
-
# if sys.exc_info()[0] and not exit_on_error:
|
|
159
|
-
# # If 'raise_exception' is set to 'True', we'll end the script with exception.
|
|
160
|
-
# if pass_exception:
|
|
161
|
-
# pass
|
|
162
|
-
|
|
163
|
-
# If 'exit_on_error' is set to 'True', we'll end the script.
|
|
164
|
-
# if exit_on_error and error_type:
|
|
165
|
-
# sys.exit()
|
|
166
|
-
|
|
167
150
|
|
|
168
151
|
def print_status(
|
|
169
152
|
prefix_string: str,
|
atomicshop/process.py
CHANGED
|
@@ -7,11 +7,16 @@ import shutil
|
|
|
7
7
|
|
|
8
8
|
from .print_api import print_api
|
|
9
9
|
from .inspect_wrapper import get_target_function_default_args_and_combine_with_current
|
|
10
|
-
from .basics
|
|
10
|
+
from .basics import strings
|
|
11
11
|
from .wrappers import ubuntu_terminal
|
|
12
|
+
from .wrappers.psutilw import processes
|
|
12
13
|
|
|
13
14
|
if os.name == 'nt':
|
|
14
|
-
from .
|
|
15
|
+
from . import get_process_list
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class MultipleProcessesFound(Exception):
|
|
19
|
+
pass
|
|
15
20
|
|
|
16
21
|
|
|
17
22
|
def is_command_exists(cmd: str) -> bool:
|
|
@@ -77,7 +82,18 @@ def execute_with_live_output(
|
|
|
77
82
|
:return: Boolean, If execution was successful, return True, if not - False.
|
|
78
83
|
"""
|
|
79
84
|
|
|
80
|
-
|
|
85
|
+
if isinstance(cmd, str):
|
|
86
|
+
shell = True
|
|
87
|
+
elif isinstance(cmd, list):
|
|
88
|
+
shell = False
|
|
89
|
+
else:
|
|
90
|
+
raise TypeError(f'cmd must be a string or list, not {type(cmd)}')
|
|
91
|
+
|
|
92
|
+
if wsl:
|
|
93
|
+
if isinstance(cmd, str):
|
|
94
|
+
cmd = 'wsl ' + cmd
|
|
95
|
+
elif isinstance(cmd, list):
|
|
96
|
+
cmd = ['wsl'] + cmd
|
|
81
97
|
|
|
82
98
|
# Needed imports:
|
|
83
99
|
# from subprocess import Popen, PIPE, STDOUT
|
|
@@ -98,7 +114,7 @@ def execute_with_live_output(
|
|
|
98
114
|
# The buffer size is system-dependent and usually chosen by the underlying implementation to optimize performance.
|
|
99
115
|
# # bufsize=0: This means no buffering.
|
|
100
116
|
# The I/O is unbuffered, and data is written or read from the stream immediately.
|
|
101
|
-
with subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=1, text=True) as process:
|
|
117
|
+
with subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=1, text=True, shell=shell) as process:
|
|
102
118
|
# We'll count the number of lines from 'process.stdout'.
|
|
103
119
|
counter: int = 0
|
|
104
120
|
# And also get list of all the lines.
|
|
@@ -247,44 +263,74 @@ def safe_terminate(popen_process: subprocess.Popen):
|
|
|
247
263
|
popen_process.wait()
|
|
248
264
|
|
|
249
265
|
|
|
250
|
-
def
|
|
266
|
+
def get_running_processes_by_cmdline_pattern(
|
|
267
|
+
pattern: str,
|
|
268
|
+
cmdline_case_insensitive: bool = False,
|
|
269
|
+
first: bool = False,
|
|
270
|
+
prefix_suffix: bool = False
|
|
271
|
+
) -> list:
|
|
251
272
|
"""
|
|
252
273
|
The function matches specified string pattern including wildcards against all the currently running processes'
|
|
253
274
|
command lines.
|
|
254
275
|
|
|
255
276
|
:param pattern: string, the pattern that we will search in the command line list of currently running processes.
|
|
277
|
+
:param cmdline_case_insensitive: boolean,
|
|
278
|
+
True, the pattern and the command line will be matched case-insensitive.
|
|
256
279
|
:param first: boolean, that will set if first pattern match found the iteration will stop, or we will return
|
|
257
280
|
the list of all command lines that contain the pattern.
|
|
258
281
|
:param prefix_suffix: boolean. Check the description in 'match_pattern_against_string' function.
|
|
282
|
+
|
|
283
|
+
:return: list, of command lines that contain the pattern.
|
|
259
284
|
"""
|
|
260
285
|
|
|
261
286
|
# Get the list of all the currently running processes.
|
|
262
|
-
|
|
263
|
-
processes =
|
|
287
|
+
get_process_list_instance = get_process_list.GetProcessList(get_method='psutil', connect_on_init=True)
|
|
288
|
+
processes = get_process_list_instance.get_processes(as_dict=False)
|
|
264
289
|
|
|
265
290
|
# Iterate through all the current process, while fetching executable file 'name' and the command line.
|
|
266
291
|
# Name is always populated, while command line is not.
|
|
267
292
|
matched_cmdlines: list = list()
|
|
268
293
|
for process in processes:
|
|
269
294
|
# Check if command line isn't empty and that string pattern is matched against command line.
|
|
270
|
-
if process['cmdline']
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
295
|
+
if process['cmdline']:
|
|
296
|
+
is_pattern_matched = strings.match_pattern_against_string(
|
|
297
|
+
pattern, process['cmdline'], case_insensitive=cmdline_case_insensitive, prefix_suffix=prefix_suffix)
|
|
298
|
+
if is_pattern_matched:
|
|
299
|
+
matched_cmdlines.append(process)
|
|
300
|
+
# If 'first' was set to 'True' we will stop, since we found the first match.
|
|
301
|
+
if first:
|
|
302
|
+
break
|
|
276
303
|
|
|
277
304
|
return matched_cmdlines
|
|
278
305
|
|
|
279
306
|
|
|
280
|
-
def
|
|
307
|
+
def kill_process_by_filename_pattern(pattern: str):
|
|
308
|
+
running_processes = get_running_processes_by_cmdline_pattern(
|
|
309
|
+
pattern, first=False, prefix_suffix=True, cmdline_case_insensitive=True)
|
|
310
|
+
|
|
311
|
+
processes_found: int = len(running_processes)
|
|
312
|
+
|
|
313
|
+
if processes_found > 1:
|
|
314
|
+
raise MultipleProcessesFound(f"[{processes_found}] processes found with pattern '{pattern}'.")
|
|
315
|
+
elif processes_found == 1:
|
|
316
|
+
processes.kill_process_by_pid(running_processes[0]['pid'])
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def run_powershell_command(
|
|
320
|
+
command: str
|
|
321
|
+
):
|
|
281
322
|
try:
|
|
282
323
|
result = subprocess.run(["powershell", "-Command", command], capture_output=True, text=True, check=True)
|
|
283
|
-
|
|
324
|
+
if result.stdout:
|
|
325
|
+
print_api(result.stdout)
|
|
326
|
+
if result.stderr: # PS can write warnings to stderr even on success
|
|
327
|
+
print_api(result.stderr, color='yellow')
|
|
284
328
|
return result.stdout
|
|
285
329
|
except subprocess.CalledProcessError as e:
|
|
286
|
-
|
|
287
|
-
|
|
330
|
+
# e.stderr and e.stdout are populated because capture_output=True
|
|
331
|
+
msg = (e.stderr or e.stdout or f"PowerShell exited with code {e.returncode}")
|
|
332
|
+
print_api(msg, color='red', error_type=True)
|
|
333
|
+
return msg
|
|
288
334
|
|
|
289
335
|
|
|
290
336
|
"""
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
from typing import Union, Literal
|
|
2
|
+
import threading
|
|
3
|
+
import time
|
|
4
|
+
|
|
5
|
+
from ... import get_process_list
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class PollerPsutilPywin32Dll:
|
|
9
|
+
"""
|
|
10
|
+
The class is responsible for getting the list of opened processes by using mentioned libraries.
|
|
11
|
+
"""
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
interval_seconds: Union[int, float] = 0,
|
|
15
|
+
process_get_method: Literal[
|
|
16
|
+
'poll_psutil',
|
|
17
|
+
'poll_pywin32',
|
|
18
|
+
'poll_process_dll'
|
|
19
|
+
] = 'poll_process_dll',
|
|
20
|
+
process_queue=None
|
|
21
|
+
):
|
|
22
|
+
"""
|
|
23
|
+
:param interval_seconds: works only for pollers, float, how many seconds to wait between each cycle.
|
|
24
|
+
Default is 0, which means that the polling will be as fast as possible.
|
|
25
|
+
|
|
26
|
+
Basically, you want it to be '0' if you want to get the most recent processes.
|
|
27
|
+
Any polling by itself takes time, so if you want to get the most recent processes, you want to do it as fast
|
|
28
|
+
as possible.
|
|
29
|
+
:param process_get_method: str. Default is 'process_dll'. Available:
|
|
30
|
+
'poll_psutil': Poller, Get the list of processes by 'psutil' library. Resource intensive and slow.
|
|
31
|
+
'poll_pywin32': Poller, processes by 'pywin32' library, using WMI. Not resource intensive, but slow.
|
|
32
|
+
'poll_process_dll'. Poller, Not resource intensive and fast. Probably works only in Windows 10 x64.
|
|
33
|
+
'trace_sysmon_etw': Tracer, Get the list of processes with running SysMon by ETW - Event Tracing.
|
|
34
|
+
In this case 'interval_seconds' is irrelevant, since the ETW is real-time.
|
|
35
|
+
Steps we take:
|
|
36
|
+
1. Check if SysMon is Running. If not, check if the executable exists in specified
|
|
37
|
+
location and start it as a service.
|
|
38
|
+
2. Start the "Microsoft-Windows-Sysmon" ETW session.
|
|
39
|
+
3. Take a snapshot of current processes and their CMDs with psutil and store it in a dict.
|
|
40
|
+
4. Each new process creation from ETW updates the dict.
|
|
41
|
+
'trace_event_log': Get the list of processes by subscribing to the Windows Event Log.
|
|
42
|
+
Log Channel: Security, Event ID: 4688.
|
|
43
|
+
We enable the necessary prerequisites in registry and subscribe to the event.
|
|
44
|
+
:param process_queue: Queue. The queue to put the processes in. If None, the processes will not be put in the
|
|
45
|
+
queue.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
self.interval_seconds: Union[int, float] = interval_seconds
|
|
49
|
+
self.process_get_method = process_get_method.replace('poll_', '')
|
|
50
|
+
self.process_queue = process_queue
|
|
51
|
+
|
|
52
|
+
# noinspection PyTypeChecker
|
|
53
|
+
self.poller_instance = get_process_list.GetProcessList(get_method=self.process_get_method)
|
|
54
|
+
|
|
55
|
+
self._processes = {}
|
|
56
|
+
|
|
57
|
+
def start(self):
|
|
58
|
+
"""
|
|
59
|
+
Start the poller.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
thread = threading.Thread(target=self.emit_loop)
|
|
63
|
+
thread.daemon = True
|
|
64
|
+
thread.start()
|
|
65
|
+
|
|
66
|
+
def emit_loop(self):
|
|
67
|
+
"""
|
|
68
|
+
Get the list of processes.
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
self.poller_instance.connect()
|
|
72
|
+
|
|
73
|
+
while True:
|
|
74
|
+
current_processes = self.poller_instance.get_processes(as_dict=True)
|
|
75
|
+
|
|
76
|
+
# Remove Command lines that contains only numbers, since they are useless.
|
|
77
|
+
for pid, process_info in current_processes.items():
|
|
78
|
+
if process_info['cmdline'].isnumeric():
|
|
79
|
+
current_processes[pid]['cmdline'] = str()
|
|
80
|
+
elif process_info['cmdline'] == 'Error':
|
|
81
|
+
current_processes[pid]['cmdline'] = str()
|
|
82
|
+
|
|
83
|
+
# This loop is essential for keeping the command lines.
|
|
84
|
+
# When the process unloads from memory, the last polling will have only pid and executable name, but not
|
|
85
|
+
# the command line. This loop will keep the command line from the previous polling if this happens.
|
|
86
|
+
for pid, process_info in current_processes.items():
|
|
87
|
+
if pid in self._processes:
|
|
88
|
+
if self._processes[pid]['name'] == current_processes[pid]['name']:
|
|
89
|
+
if current_processes[pid]['cmdline'] == '':
|
|
90
|
+
current_processes[pid]['cmdline'] = self._processes[pid]['cmdline']
|
|
91
|
+
self._processes.update(current_processes)
|
|
92
|
+
|
|
93
|
+
self.process_queue.put(self._processes)
|
|
94
|
+
|
|
95
|
+
time.sleep(self.interval_seconds)
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import threading
|
|
2
|
+
import multiprocessing
|
|
3
|
+
import time
|
|
4
|
+
from typing import Literal, Union
|
|
5
|
+
|
|
6
|
+
from .tracers import sysmon_etw, event_log
|
|
7
|
+
from .pollers import psutil_pywin32wmi_dll
|
|
8
|
+
from ..wrappers.pywin32w.win_event_log.subscribes import process_terminate
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
POLLER_SETTINGS_SYSMON_ETW: dict = {
|
|
12
|
+
'etw_session_name': None, # Default will be used, check 'trace_sysmon_process_creation' for details.
|
|
13
|
+
'sysmon_directory': None # Directory, where sysmon.exe is located. Default will be used.
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ProcessPool:
|
|
18
|
+
"""
|
|
19
|
+
The class is responsible for getting processes and storing them in a pool.
|
|
20
|
+
THE POOL OF PROCESSES IS NOT REAL TIME!!!
|
|
21
|
+
There can be several moments delay (less than a second) + you can add delay before pid removal from the pool.
|
|
22
|
+
This is needed only to correlate PIDs to process names and command lines of other events you get on Windows.
|
|
23
|
+
"""
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
operation: Literal['thread', 'process'] = 'thread',
|
|
27
|
+
interval_seconds: Union[int, float] = 0,
|
|
28
|
+
process_get_method: Literal[
|
|
29
|
+
'poll_psutil',
|
|
30
|
+
'poll_pywin32',
|
|
31
|
+
'poll_process_dll',
|
|
32
|
+
'trace_sysmon_etw',
|
|
33
|
+
'trace_event_log'
|
|
34
|
+
] = 'trace_event_log',
|
|
35
|
+
poller_settings: dict = None,
|
|
36
|
+
process_terminator: bool = True,
|
|
37
|
+
wait_before_pid_remove_seconds: float = 5
|
|
38
|
+
):
|
|
39
|
+
"""
|
|
40
|
+
:param operation: str, 'thread' or 'process'. Default is 'process'.
|
|
41
|
+
'process': The polling will be done in a new process.
|
|
42
|
+
'thread': The polling will be done in a new thread.
|
|
43
|
+
|
|
44
|
+
Python is slow, if you are going to use 'thread' all other operations inside this thread will be very slow.
|
|
45
|
+
You can even get exceptions, if you're using process polling for correlations of PIDs and process names.
|
|
46
|
+
It is advised to use the 'process' operation, which will not affect other operations in the thread.
|
|
47
|
+
:param interval_seconds: works only for pollers, float, how many seconds to wait between each cycle.
|
|
48
|
+
Default is 0, which means that the polling will be as fast as possible.
|
|
49
|
+
|
|
50
|
+
Basically, you want it to be '0' if you want to get the most recent processes.
|
|
51
|
+
Any polling by itself takes time, so if you want to get the most recent processes, you want to do it as fast
|
|
52
|
+
as possible.
|
|
53
|
+
:param process_get_method: str. Default is 'process_dll'. Available:
|
|
54
|
+
'poll_psutil': Poller, Get the list of processes by 'psutil' library. Resource intensive and slow.
|
|
55
|
+
'poll_pywin32': Poller, processes by 'pywin32' library, using WMI. Not resource intensive, but slow.
|
|
56
|
+
'poll_process_dll'. Poller, Not resource intensive and fast. Probably works only in Windows 10 x64.
|
|
57
|
+
'trace_sysmon_etw': Tracer, Get the list of processes with running SysMon by ETW - Event Tracing.
|
|
58
|
+
In this case 'interval_seconds' is irrelevant, since the ETW is real-time.
|
|
59
|
+
Steps we take:
|
|
60
|
+
1. Check if SysMon is Running. If not, check if the executable exists in specified
|
|
61
|
+
location and start it as a service.
|
|
62
|
+
2. Start the "Microsoft-Windows-Sysmon" ETW session.
|
|
63
|
+
3. Take a snapshot of current processes and their CMDs with psutil and store it in a dict.
|
|
64
|
+
4. Each new process creation from ETW updates the dict.
|
|
65
|
+
'trace_event_log': Get the list of processes by subscribing to the Windows Event Log.
|
|
66
|
+
Log Channel: Security, Event ID: 4688.
|
|
67
|
+
We enable the necessary prerequisites in registry and subscribe to the event.
|
|
68
|
+
:param poller_settings: dict, settings for the poller method.
|
|
69
|
+
'sysmon_etw': If not set 'POLLER_SETTINGS_SYSMON_ETW' will be used.
|
|
70
|
+
:param process_terminator: bool, if True, process terminator will run in the background and monitor
|
|
71
|
+
the processes for termination. If the process is terminated it will be removed from the pool.
|
|
72
|
+
:param wait_before_pid_remove_seconds: float, how many seconds to wait before the process is removed from
|
|
73
|
+
the pool after process termination event is received for that pid.
|
|
74
|
+
---------------------------------------------
|
|
75
|
+
If there is an exception, ProcessPollerPool.processes will be set to the exception.
|
|
76
|
+
While getting the processes you can use this to execute the exception:
|
|
77
|
+
|
|
78
|
+
processes = ProcessPollerPool.processes
|
|
79
|
+
|
|
80
|
+
if isinstance(processes, BaseException):
|
|
81
|
+
raise processes
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
self.operation: str = operation
|
|
85
|
+
self.interval_seconds: float = interval_seconds
|
|
86
|
+
self.process_get_method = process_get_method
|
|
87
|
+
self.process_terminator: bool = process_terminator
|
|
88
|
+
self.wait_before_pid_remove_seconds: float = wait_before_pid_remove_seconds
|
|
89
|
+
self.poller_settings: dict = poller_settings
|
|
90
|
+
|
|
91
|
+
if self.poller_settings is None:
|
|
92
|
+
if process_get_method == 'sysmon_etw':
|
|
93
|
+
self.poller_settings: dict = POLLER_SETTINGS_SYSMON_ETW
|
|
94
|
+
|
|
95
|
+
# Current process pool.
|
|
96
|
+
self._processes: dict = dict()
|
|
97
|
+
|
|
98
|
+
# The variable is responsible to stop the thread if it is running.
|
|
99
|
+
self._running: bool = False
|
|
100
|
+
|
|
101
|
+
self._process_queue = multiprocessing.Queue()
|
|
102
|
+
self._running_state_queue = multiprocessing.Queue()
|
|
103
|
+
|
|
104
|
+
def start(self):
|
|
105
|
+
if self.operation == 'thread':
|
|
106
|
+
self._start_thread()
|
|
107
|
+
elif self.operation == 'process':
|
|
108
|
+
self._start_process()
|
|
109
|
+
else:
|
|
110
|
+
raise ValueError(f'Invalid operation type [{self.operation}]')
|
|
111
|
+
|
|
112
|
+
thread_get_queue = threading.Thread(target=self._thread_get_queue)
|
|
113
|
+
thread_get_queue.daemon = True
|
|
114
|
+
thread_get_queue.start()
|
|
115
|
+
|
|
116
|
+
if self.process_terminator:
|
|
117
|
+
thread_process_termination = threading.Thread(target=self._thread_process_termination)
|
|
118
|
+
thread_process_termination.daemon = True
|
|
119
|
+
thread_process_termination.start()
|
|
120
|
+
|
|
121
|
+
def stop(self):
|
|
122
|
+
self._running = False
|
|
123
|
+
self._running_state_queue.put(False)
|
|
124
|
+
|
|
125
|
+
def get_processes(self):
|
|
126
|
+
return self._processes
|
|
127
|
+
|
|
128
|
+
def _get_args_for_worker(self):
|
|
129
|
+
return self.process_get_method, self.interval_seconds, self._process_queue, self.poller_settings
|
|
130
|
+
|
|
131
|
+
def _start_thread(self):
|
|
132
|
+
self._running = True
|
|
133
|
+
|
|
134
|
+
thread = threading.Thread(target=_worker, args=(self._get_args_for_worker()))
|
|
135
|
+
thread.daemon = True
|
|
136
|
+
thread.start()
|
|
137
|
+
|
|
138
|
+
def _start_process(self):
|
|
139
|
+
self._running = True
|
|
140
|
+
multiprocessing.Process(target=_worker, args=(self._get_args_for_worker())).start()
|
|
141
|
+
|
|
142
|
+
def _thread_get_queue(self):
|
|
143
|
+
while True:
|
|
144
|
+
self._processes = self._process_queue.get()
|
|
145
|
+
|
|
146
|
+
def _thread_process_termination(self):
|
|
147
|
+
process_terminate_instance = process_terminate.ProcessTerminateSubscriber()
|
|
148
|
+
process_terminate_instance.start()
|
|
149
|
+
|
|
150
|
+
while True:
|
|
151
|
+
termination_event = process_terminate_instance.emit()
|
|
152
|
+
process_id = termination_event['ProcessIdInt']
|
|
153
|
+
|
|
154
|
+
removal_thread = threading.Thread(target=self._remove_pid, args=(process_id,))
|
|
155
|
+
removal_thread.daemon = True
|
|
156
|
+
removal_thread.start()
|
|
157
|
+
|
|
158
|
+
def _remove_pid(self, process_id):
|
|
159
|
+
# We need to wait a bit before we remove the process.
|
|
160
|
+
# This is because termination event can come sooner than the creation and the process
|
|
161
|
+
# is not yet in the pool.
|
|
162
|
+
# This happens mostly when the process is terminated immediately after the creation.
|
|
163
|
+
# Example: ping example.c
|
|
164
|
+
# 'example.c' is not a valid address, so the process is terminated immediately after the creation.
|
|
165
|
+
counter = 0
|
|
166
|
+
while counter < 30:
|
|
167
|
+
if process_id in self._processes:
|
|
168
|
+
break
|
|
169
|
+
counter += 1
|
|
170
|
+
time.sleep(0.1)
|
|
171
|
+
|
|
172
|
+
if counter == 30:
|
|
173
|
+
# print_api(f'Process [{process_id}] not found in the pool.', color='yellow')
|
|
174
|
+
return
|
|
175
|
+
|
|
176
|
+
# time.sleep(1)
|
|
177
|
+
# if process_id not in self._processes:
|
|
178
|
+
# print_api(f'Process [{process_id}] not found in the pool.', color='red')
|
|
179
|
+
# return
|
|
180
|
+
|
|
181
|
+
time.sleep(self.wait_before_pid_remove_seconds)
|
|
182
|
+
_ = self._processes.pop(process_id, None)
|
|
183
|
+
# print_api(f'Process [{process_id}] removed from the pool.', color='yellow')
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def _worker(
|
|
187
|
+
poller_method,
|
|
188
|
+
interval_seconds,
|
|
189
|
+
process_queue,
|
|
190
|
+
poller_settings
|
|
191
|
+
):
|
|
192
|
+
|
|
193
|
+
if poller_method == 'trace_sysmon_etw':
|
|
194
|
+
get_instance = sysmon_etw.TracerSysmonEtw(settings=poller_settings, process_queue=process_queue)
|
|
195
|
+
elif poller_method == 'trace_event_log':
|
|
196
|
+
get_instance = event_log.TracerEventlog(process_queue=process_queue)
|
|
197
|
+
elif 'poll_' in poller_method:
|
|
198
|
+
get_instance = psutil_pywin32wmi_dll.PollerPsutilPywin32Dll(
|
|
199
|
+
interval_seconds=interval_seconds, process_get_method=poller_method, process_queue=process_queue)
|
|
200
|
+
else:
|
|
201
|
+
raise ValueError(f'Invalid poller method [{poller_method}]')
|
|
202
|
+
|
|
203
|
+
# We must initiate the connection inside the thread/process, because it is not thread-safe.
|
|
204
|
+
get_instance.start()
|
|
205
|
+
|
|
206
|
+
while True:
|
|
207
|
+
time.sleep(1)
|