@@ -468,6 +468,80 @@ export class LicensingClient {
468468 await this . exec ( [ '--showContext' ] ) ;
469469 }
470470
471+ private async getClientLogSize ( ) : Promise < number > {
472+ try {
473+ const stats = await fs . promises . stat ( LicensingClient . ClientLogPath ( ) ) ;
474+ return stats . size ;
475+ }
476+ catch ( error ) {
477+ if ( ( error as NodeJS . ErrnoException ) . code === 'ENOENT' ) {
478+ return 0 ;
479+ }
480+
481+ throw error ;
482+ }
483+ }
484+
485+ private async waitForLicenseServerConfiguration ( timeoutMs : number = 30_000 , pollIntervalMs : number = 1_000 ) : Promise < void > {
486+ const logPath = LicensingClient . ClientLogPath ( ) ;
487+ const configuredPattern = / F l o a t i n g l i c e n s e s e r v e r U R L i s : \s * (?< url > [ ^ \s ] + ) \s * \( v i a c o n f i g f i l e \) / ;
488+ const notConfiguredPattern = / F l o a t i n g l i c e n s e s e r v e r i s n o t c o n f i g u r e d / ;
489+ const deadline = Date . now ( ) + timeoutMs ;
490+ let offset = await this . getClientLogSize ( ) ;
491+ let remainder = '' ;
492+
493+ while ( Date . now ( ) < deadline ) {
494+ let newChunk = '' ;
495+
496+ try {
497+ const stats = await fs . promises . stat ( logPath ) ;
498+
499+ if ( stats . size > offset ) {
500+ const length = stats . size - offset ;
501+ const handle = await fs . promises . open ( logPath , 'r' ) ;
502+
503+ try {
504+ const buffer = Buffer . alloc ( length ) ;
505+ await handle . read ( buffer , 0 , length , offset ) ;
506+ newChunk = buffer . toString ( 'utf-8' ) ;
507+ offset = stats . size ;
508+ }
509+ finally {
510+ await handle . close ( ) ;
511+ }
512+ }
513+ }
514+ catch ( error ) {
515+ if ( ( error as NodeJS . ErrnoException ) . code !== 'ENOENT' ) {
516+ this . logger . debug ( `Failed to inspect licensing client log: ${ error } ` ) ;
517+ }
518+ }
519+
520+ if ( newChunk . length > 0 ) {
521+ remainder += newChunk ;
522+ const lines = remainder . split ( / \r ? \n / ) ;
523+ remainder = lines . pop ( ) ?? '' ;
524+
525+ for ( const line of lines ) {
526+ const configuredMatch = line . match ( configuredPattern ) ;
527+
528+ if ( configuredMatch && configuredMatch . groups ?. url ) {
529+ this . logger . info ( `License server configured with URL: ${ configuredMatch . groups . url } ` ) ;
530+ return ;
531+ }
532+
533+ if ( notConfiguredPattern . test ( line ) ) {
534+ this . logger . warn ( 'Floating license server is not configured. Waiting for configuration...' ) ;
535+ }
536+ }
537+ }
538+
539+ await new Promise ( ( resolve ) => setTimeout ( resolve , pollIntervalMs ) ) ;
540+ }
541+
542+ throw new Error ( `Timed out waiting for floating license server configuration. Check '${ logPath } ' for details.` ) ;
543+ }
544+
471545 /**
472546 * Activates a Unity license.
473547 * @param options The activation options including license type, services config, serial, username, and password.
@@ -498,6 +572,8 @@ export class LicensingClient {
498572
499573 switch ( options . licenseType ) {
500574 case LicenseType . floating : {
575+ await this . Context ( ) ;
576+ await this . waitForLicenseServerConfiguration ( ) ;
501577 const output = await this . exec ( [ `--acquire-floating` ] , true ) ;
502578 const tokenMatch = output . match ( / w i t h t o k e n : \s * " (?< token > [ \w - ] + ) " / ) ;
503579
0 commit comments