This directory contains headless Chrome wrapper Java helper class and example based on ldaume/headless-chrome
The project has been stale for some time, then tested with Chrome 101 (64 bit) running on Windows 10 VM. To detect the headless run, an environment variable WINDOWS_NO_DISPLAY is set by the launcher script which itself is run by Windowws Scheduled Task with one minute delay after the reboot event.
the log of the headless run ( from the logfile).
running by app
checking display
setting WINDOWS_NO_DISPLAY to true
1
setting WINDOWS_NO_DISPLAY to true
WINDOWS_NO_DISPLAY=true
Downloaded from central: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-resources-plugin/2.6/maven-resources-plugin-2.6.pom (8.1 kB at 8.7 kB/s)
Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-plugins/23/maven-plugins-23.pom
Progress (1): 2.7/9.2 kB
Progress (1): 5.5/9.2 kB
Progress (1): 8.2/9.2 kB
Progress (1): 9.2 kB
...
[INFO] Scanning for projects...
...
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running software.MinimalTest
Observed environment keys: [PATH, PROCESSOR_LEVEL, SYSTEMDRIVE, M2, ALLUSERSPROFILE, JAVA_OPTS, PROCESSOR_ARCHITECTURE, DRIVERDATA, MAVEN_HOME, PROGRAMFILES, PSMODULEPATH, PROGRAMDATA, USERNAME, WDIR, GROOVY_VERSION, PATHEXT, GRADLE_VERSION, LOG, PROCESSOR_ARCHITEW6432, CLASSWORLDS_JAR, MAVEN_VERSION, TOOL_HOME, WINDOWS_NO_DISPLAY, WINDIR, PROCESSOR_IDENTIFIER, M2_HOME, IVY_VERSION, PUBLIC, IVY_HOME, LOCALAPPDATA, COMMONPROGRAMFILES(X86), USERDOMAIN, JAVA_HOME, PROMPT, PROGRAMFILES(X86), ERROR_CODE, EXEC_DIR, GRADLE_HOME, MAVEN_OPTS, ANT_HOME, GROOVY_HOME, =C:, APPDATA, JAVA_TOOL_OPTIONS, PROGRAMW6432, SYSTEMROOT, JAVA_VERSION, MAVEN_CMD_LINE_ARGS, OS, COMMONPROGRAMW6432, COMPUTERNAME, COMMONPROGRAMFILES, COMSPEC, JAVACMD, MAVEN_PROJECTBASEDIR, PROCESSOR_REVISION, CLASSWORLDS_LAUNCHER, TEMP, USERPROFILE, ANT_VERSION, TMP, PHANTOMJS_HOME, NUMBER_OF_PROCESSORS, JVMCONFIG]
Checking environment JAVA_OPTS: -Xms256m -Xmx512m
Checking environment MAVEN_OPTS: -Xms256m -Xmx512m
Checking environment JAVA_TOOL_OPTIONS: -DWINDOWS_NO_DISPLAY=true
Detected WINDOWS_NO_DISPLAY
Detected WINDOWS_NO_DISPLAY environment or property
Detected WINDOWS_NO_DISPLAY in JAVA_TOOL_OPTIONS
Switching to headless
Tests run: 3, Failures: 0, Errors: 0, Skipped: 1, Time elapsed: 24.27 sec
Picked up JAVA_TOOL_OPTIONS: -DWINDOWS_NO_DISPLAY=true
Results :
Tests run: 3, Failures: 0, Errors: 0, Skipped: 1
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 38.452 s
[INFO] Finished at: 2022-06-10T01:30:21+03:00
[INFO] ------------------------------------------------------------------------
Done. NOTE: - the maven dependencies will be downloaded into the user profile in the first run
If the scheduled task is configured to run under NT AUTHORIRY\SYSTEM account
the jars will go into c:\Windows\SysWOW64\config\systemprofile\.m2\repository for 32 bit task on 64 bit system and into
c:\Windows\System32\config\systemprofile\.m2\repository otherwise.
The log from the call of the launcher interactively:
client.cmd
running by app
checking display
setting WINDOWS_NO_DISPLAY to true
0
clearing WINDOWS_NO_DISPLAY to true
[INFO] Scanning for projects...
...
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running software.MinimalTest
checking environment: [PATH, USERDOMAIN_ROAMINGPROFILE, PROCESSOR_LEVEL, SYSTEMDRIVE, M2, SESSIONNAME, ALLUSERSPROFILE, JAVA_OPTS, PROCESSOR_ARCHITECTURE, DRIVERDATA, MAVEN_HOME, PROGRAMFILES, PSMODULEPATH, PROGRAMDATA, USERNAME, WDIR, GROOVY_VERSION, PATHEXT, GRADLE_VERSION, LOG, PROCESSOR_ARCHITEW6432, CLASSWORLDS_JAR, MAVEN_VERSION, TOOL_HOME, WINDIR, HOMEPATH, PROCESSOR_IDENTIFIER, M2_HOME, IVY_VERSION, PUBLIC, IVY_HOME, =::, =EXITCODE, LOCALAPPDATA, COMMONPROGRAMFILES(X86), USERDOMAIN, LOGONSERVER, JAVA_HOME, PROMPT, PROGRAMFILES(X86), ERROR_CODE, EXEC_DIR, GRADLE_HOME, MAVEN_OPTS, ANT_HOME, GROOVY_HOME, =C:, APPDATA, PROGRAMW6432, SYSTEMROOT, JAVA_VERSION, MAVEN_CMD_LINE_ARGS, OS, COMMONPROGRAMW6432, COMPUTERNAME, COMMONPROGRAMFILES, COMSPEC, JAVACMD, MAVEN_PROJECTBASEDIR, PROCESSOR_REVISION, CLASSWORLDS_LAUNCHER, RUBYOPT, TEMP, HOMEDRIVE, USERPROFILE, ANT_VERSION, TMP, PHANTOMJS_HOME, NUMBER_OF_PROCESSORS, JVMCONFIG]
Switching to / staying visible
Switching to / staying visible
Winlogon, the GINA, and network providers are the parts of the interactive logon model. The interactive logon procedure is normally controlled by Winlogon, MSGina.dll, and network providers. To change the interactive logon procedure, MSGina.dll can be replaced with a customized GINA DLL.
GINA is a replaceable dynamically linked library that is loaded early in the boot process in the context of Winlogon
The Windows shell, as it is known today, is an evolution of what began with Windows 95, released in 1995. It is intimately identified with File Explorer, a Windows component that can browse the whole shell namespace.
The headless_detector.cmd script used in this project is checking if the shell process is running by the account that runs the detector script:
tasklist.exe /FI "USERNAME eq %USERNAME%" /FI "IMAGENAME EQ explorer.exe"when the output shows the process:
Image Name PID Session Name Session# Mem Usage
========================= ======== ================ =========== ============
explorer.exe 3912 Console 1 143,648 K
the environment variable WINDOWS_NO_DISPLAY is cleared. Otherwise it is set. There are two alternative ways to do it in Powershell. One requires elevation:
$processname = 'explorer'
get-process -name $processname -includeusername
Get-Process : The 'IncludeUserName' parameter requires elevated user rights.
Try running the command again in a session that has been opened with elevated user rights (that is, Run as Administrator).the other uses performs p/invoke into advapi32.dll and contains substantial amount of inline C# code (see headless_detector.ps1 script).
The password for the account can be specified in one of two ways. For computers running one of the Windows Server 2003 or Windows XP operating systems, the password should be stored as a secret using the LsaStorePrivateData function. For details, see Protecting the Automatic Logon Password. The other way to store the password plaintext in the Registry.
If no DefaultPassword string is specified, Windows automatically changes the value of the AutoAdminLogon key from 1 (true) to 0 (false), disabling the AutoAdminLogon feature.
The SAS (Secure Attention Sequence) in Reactos and CSRSS (Client Server Runtime Subsystem) in Windows are similar roles sas.c
static BOOL
StartUserShell(
IN OUT PWLSESSION Session)static BOOL GetRegistrySettings(PGINA_CONTEXT pgContext) {
rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", 0, KEY_QUERY_VALUE, &hKey);
rc = ReadRegSzValue(hKey, L"AutoAdminLogon", &lpAutoAdminLogon);
if (rc == ERROR_SUCCESS)
if (wcscmp(lpAutoAdminLogon, L"1") == 0)
pgContext->bAutoAdminLogon = TRUE;if (pgContext->bAutoAdminLogon) {
if (pgContext->bIgnoreShiftOverride || (GetKeyState(VK_SHIFT) >= 0)) {
/* Don't display the window, we want to do an automatic logon */
pgContext->pWlxFuncs->WlxSasNotify(pgContext->hWlx, WLX_SAS_TYPE_CTRL_ALT_DEL);214794369
The process hosting the driver for this device has been terminated. (Exception from HRESULT: 0x8007050B)
these tasks launch hub
hub4.cmdnode
node4.cmd
and test
client.cmd
Note: only tested with Selenium standalone 4.0 this far - unknown if works with downlevel Selenium 3.x
for the sake of passing all options through selenium hub pipeline:
ChromeOptions options = new ChromeOptions();
options.setBinary(osName.equals("windows") ? (new File(
(System.getenv().containsKey("PROCESSOR_ARCHITECTURE")
&& System.getenv("PROCESSOR_ARCHITECTURE").matches("(?:AMD64)")) ?
"C:/Program Files (x86)/Google/Chrome/Application/chrome.exe" : "C:/Program Files/Google/Chrome/Application/chrome.exe")) .getAbsolutePath() : "/usr/bin/chromium-browser" /* "/usr/bin/google-chrome" */ );
if (headless) {
for (String optionAgrument : (new String[] { "headless", "--window-size=1200x800", "disable-gpu" })) {
options.addArguments(optionAgrument);
}
driver = new RemoteWebDriver(new URL("http://localhost:4444"), options);the legacy invocation
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
capabilities.setCapability("headless", true);
capabilities.setCapability("platform", "WINDOWS");
capabilities.setCapability("version", "latest");
driver = new RemoteWebDriver(new URL("https://localhost:4444/wd/hub"), capabilities);was not found to work (more testing is pending)
The error with Selenium Server 3.x called with options:
software.MinimalTest: Unable to create new remote session.
Caused by: org.openqa.selenium.SessionNotCreatedException:
Unable to create new remote session. desired capabilities =
Capabilities [{goog:chromeOptions={args=[headless, --window-size=1200x800, disable-gpu], extensions=[],
binary=C:\Program Files\Google\Chrome\Application\chrome.exe}, browserName=chrome}],
required capabilities = Capabilities [{}]
the error with Selenium Server 3.x called with capabilities:
org.openqa.selenium.remote.UnreachableBrowserException:
Could not start a new session.
Possible causes are invalid address of the remote server or browser start-up failure.
along with that error, the hub console logs the attempt:
04:58:58.274 INFO - Got a request to create a new session: Capabilities [{headless=true, browserName=chrome, version=latest, platform=WINDOWS}]
while if in foreground
06:10:43.595 INFO [LocalDistributor.newSession] - Session request received by the distributor:
[Capabilities {browserName: chrome, goog:chromeOptions: {args: [headless], extensions: []}}]
06:10:43.595 INFO [LocalDistributor.newSession] - Unable to find slot for request 22073277-e9a3-4701-a62d-15d597cfc43f. May retry: Capabilities {browserName: chrome, goog:chromeOptions: {args: [headless], extensions: []}}6:10:43.595 INFO [LocalDistributor$NewSessionRunnable.handleNewSessionRequest] - Retrying
- getting started with headless Chrome
- in russian, Javascript port
- minimal project
- tips regarding reducing additioan lattency because of chomedriver (in Russian)
- Selenium JsonWire Protocol
- Chrome Devkit Protocol
- article on how to get process owner
- known SID list
- blog on headless switch - does not cover
RemoteWebDriver - https://www.browserstack.com/guide/selenium-grid-4-tutorial - the 'headless' option is ifnored







