#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Icon=office365.ico #AutoIt3Wrapper_UseX64=y #AutoIt3Wrapper_Res_Comment=Learning Tree Office 365 Sign In #AutoIt3Wrapper_Res_Description=Sign in to office 365 accounts #AutoIt3Wrapper_Res_Fileversion=3.1.0.0 #AutoIt3Wrapper_Res_LegalCopyright=Learning Tree International #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include #include #include #include #include #include ;NOTES ON VARIOUS OPTIONS ;Can set alternative login name for students in Metadata with login=xxxxxx. Separate the fields with pipe ;Can also set new password in userdata with password=xxxxxx. Again separate the fields with pipe ;MUST RUN AS REGULAR USER FROM SCHEDULED TASK MANAGER, NOT HIGHEST PRIVILEDGES ;Developed by Robin Johnston 2021 ;V3.0 - Conversion to Cloudshare ;V3.1 - Updated Edge driver Global $version = StringLeft(FileGetVersion(@ScriptFullPath),3) Global $o365url = "https://www.office.com/" Global $edgeVersion = StringLeft(FileGetVersion("C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe"),10) Global $webDriverVersion = StringLeft(FileGetVersion(@ScriptDir & "\msedgedriver.exe"),10) ConsoleWrite ("Edge vesion: " & $edgeVersion & @CRLF) ConsoleWrite ("Webdriver version: " & $webDriverVersion & @CRLF) AutoItSetOption("SendKeyDelay",10) AutoItSetOption("SendKeyDownDelay",10) AutoItSetOption("WinTitleMatchMode",2) FileChangeDir(@ScriptDir) ;Make sure we have correct file path ;Edge params Global $sDesiredCapabilities, $sSession, $sElement Global $force = False Global $LogFile = "O365SignIn.log" If StringInStr($cmdlineraw, "/f") Or StringInStr($cmdlineraw, ".au3") Then ;allow a forced update FileDelete(@ScriptDir & '\' & $LogFile) RegDelete("HKCU\Software\O365SignIn","ClassId") $force = True WriteLog("Forced restart, log cleared, registry emptied") EndIf If StringInStr($cmdlineraw, "/d") Then ;perform a debug browser check WriteLog("Performing browser sync check...") ;kill all Edge instances While ProcessExists("msedge.exe") ProcessClose("msedge.exe") WEnd ;_WD_Option("errormsgbox", (@Compiled = 1)) ;_WD_Option("OutputDebug", (@Compiled = 1)) $sDesiredCapabilities = SetupEdge(False) If @error <> $_WD_ERROR_Success Then MsgBox(0,"O365SignIn Error V" & $version,"Could not download and verify the Edge Web Driver") WriteLog("Could not download and verify the Edge Web Driver") Exit EndIf _WD_Startup() If @error <> $_WD_ERROR_Success Then MsgBox(0,"O365SignIn Error V" & $version,"Could not correctly startup the web driver" & @CRLF & @ScriptDir) WriteLog("Could not correctly startup the web driver") Exit EndIf $sSession = _WD_CreateSession($sDesiredCapabilities) If @error <> $_WD_ERROR_Success Then $msg = MsgBox(0,"O365SignIn Error V" & $version,"Could not correctly launch the Web Browser") WriteLog("Could not correctly launch the Web Browser") Exit EndIF _WD_Window($sSession, 'Maximize') _WD_Navigate($sSession, $o365url) If @error <> $_WD_ERROR_Success Then MsgBox(0,"O365SignIn Error V" & $version,"Could not launch Edge Startup Page Window") WriteLog("Could not launch Edge Startup Page Window") Exit EndIf MsgBox(0,"O365SignIn Error V" & $version,"Edge Startup seemed to work as expected" & @CR & @CR & "Edge browser version: " & $edgeVersion & @CR & "WebDriver version: " & $webDriverVersion) WriteLog("Edge Startup seemed to work as expected" & @CR & @CR & "Edge Startup seemed to work as expected" & @CR & @CR & "Edge browser version: " & $edgeVersion & @CR & "WebDriver version: " & $webDriverVersion) Exit EndIf ;All these set in registry by the installer Global $PBI=RegRead("HKLM\Software\O365SignIn","PowerBI") Global $CRED=RegRead("HKLM\Software\O365SignIn","DisplayCreds") Global $PASS=RegRead("HKLM\Software\O365SignIn","Password") Global $APPS=RegRead("HKLM\Software\O365SignIn","AppSignIn") If (@YEAR & @MON & @MDAY) - StringTrimRight(FileGetTime($LogFile,0,1),6) > 0 Then FileDelete($LogFile) EndIf Global $hLogFile = FileOpen(@ScriptDir & '\' & $LogFile, 1) WriteLog("", 1) Global $classId, $seqnum, $hostname, $vmNum, $passwd, $password, $login ;Only run once If Not _Singleton(@ScriptName) Then If $cmdline[0] > 0 Then If $cmdline[1] = "stop" or StringRight($cmdline[1],1) = "s" Then ;DO nothing.... Else WriteLog("Already running.") Exit EndIf EndIf EndIf HotKeySet("{Esc}", "Terminate") WriteLog("Edge Browser version: " & $edgeVersion) WriteLog("Edge Webdriver version: " & $webDriverVersion) ;10-30 second sleep if /b called on startup (scheduled task) If StringInStr($cmdlineraw, "/b") Then Sleep(10000 + Random(1,20000,1)) $backoff=1000+Random(1,1000,1) Do local $metadata=InetRead("https://metadata.cloudshare.com/api/v3/unauthenticated/metadata") ;If @error set here, then metadata is bad - backoff, retry a few times, then reboot to see if that fixes it If @error Then Sleep($backoff) $backoff = $backoff * 2 EndIf If $backoff > 16000 Then ;Have we been here before? If RegRead("HKCU\Software\O365SignIn","Backoff") == "ONCE" Then ;Already done this once - so throw up error and quit RegDelete("HKCU\Software\O365SignIn","Backoff") WriteLog("Quitting because no VM metadata discovered") MsgBox(0,"O365SignIn Error V" & $version,"Unable to pull the Cloudshare metadata" & @CR & @CR & "Check the Network Config and if this error persists, fully powercycle the whole environment") Exit Else RegWrite("HKCU\Software\O365SignIn","Backoff", "REG_SZ", "ONCE") WriteLog("Rebooting to see if we can pickup metadata on second boot") Shutdown(6) ;Reboot if taking too long EndIf EndIf Until Not @error ;got some metadata $metadata = BinaryToString($metadata) WriteLog("Cloudshare Metadata: " & $metadata) Local $jsonObj = Json_Decode($metadata) WriteLog("Cloudshare Metadata: " & @CRLF & Json_Encode($jsonObj, $JSON_PRETTY_PRINT, " ", "\n", "\n", "") & @CRLF) ConsoleWrite("Full Metadata: " & @CRLF & Json_Encode($jsonObj, $JSON_PRETTY_PRINT, " ", "\n", "\n", "") & @CRLF) If Json_ObjExists($jsonObj, "custom-properties") Then Local $custObj = Json_ObjGet($jsonObj, "custom-properties") ConsoleWrite("Custom Properties: " & @CRLF & Json_Encode($custObj, $JSON_PRETTY_PRINT, " ", "\n", "\n", "") & @CRLF) Else ;Bail because no custom properties ProgressOff() WriteLog("No Custom Properties found in the metadata, Exiting") MsgBox(0,"O365SignIn Info V" & $version,"This course requires the o365 custom properties to be defined" & @CR & @CR & "You will need to redeploy the course and set them up as you do so, or sign in to o365 manually!") Exit EndIf ;First up, check to see if any o365 user params If Not Json_ObjExists($custObj,"o365email") Then ;Bail because no o365 within custom properties ProgressOff() WriteLog("No o365 Properties found in the metadata, Exiting") MsgBox(0,"O365SignIn Info V" & $version,"This course requires the o365 custom properties to be defined" & @CR & @CR & "You will need to redeploy the course and set them up as you do so, or sign in to o365 manually!") Exit EndIf ;Now lets pull the various properties - may vary depending upon when CS implements user props on Instructor Local $email = Json_ObjGet($custObj, "o365email") If IsKeyword($email) Then ;User props not implemented on Instructor VM so pull from env-name Local $envName = Json_ObjGet($jsonObj,"env-name") If StringInStr($envName,"Instructor") Then ;We are definitely on Instructor machine so proceed Local $aMatch = StringRegExp($envName, "\b([A-Za-z0-9]{1,5})-([A-Za-z0-9]{1,10})\b", 3) If @error Then ;Might be instructor VM but not a valid deployment - bail ProgressOff() WriteLog("Could not extract sequence number on instructor VM, Exiting") MsgBox(0,"O365SignIn Info V" & $version,"This course requires a valid sequence number" & @CR & @CR & "You will need to redeploy the course using latest deployment tool, or sign in to o365 manually!") Exit Else Local $seqNum = $aMatch[1] ;only supports tenent with @seqNum.onmicrosoft.com Local $vmNum = 0 ; All instructors get 0 Local $email = "admin@" & $seqNum & ".onmicrosoft.com" Local $passwd = "" EndIf EndIf Else ;Regular student VM, have custom properties, use them Local $studReg = Json_ObjGet($custObj, "studRegNum") Local $passwd = Json_ObjGet($custObj, "o365psswd") Local $email = Json_ObjGet($custObj, "o365email") ;Local $seqNum = StringLeft(Json_ObjGet($custObj, "studRegNum"),8) ;this won't work on instructor and don't need it? Local $seqNum = StringLeft($studReg,8) Local $vmNum = Json_ObjGet($custObj, "studNum") EndIf Local $classId = Json_ObjGet($jsonObj,"class-id") WriteLog("Cloudshare ClassId is " & $classId) ConsoleWrite("Cloudshare ClassId is " & $classId & @CRLF) WriteLog("Detected sequence number is " & $seqNum) ConsoleWrite("Detected sequence number is " & $seqNum & @CRLF) WriteLog("Detected VM instance number is " & $vmNum) ConsoleWrite("Detected VM instance number is " & $vmNum & @CRLF) WriteLog("Detected O365 password is " & $passwd) ConsoleWrite("Detected O365 password is " & $passwd & @CRLF) WriteLog("Detected O365 email is " & $email) ConsoleWrite("Detected O365 email is " & $email & @CRLF) ;check params once just incase bad data If $classId="" Or $email="" Then ProgressOff() WriteLog("No ClassId/o365 Email discovered, Exiting") MsgBox(0,"O365SignIn Info V" & $version,"This course requires the use of a Microsoft Office365 tenant" & @CR & @CR & "You will need to create one or have access to an existing one before you can proceed with the course exercises") Exit EndIf If $classId=RegRead("HKCU\Software\O365SignIn","ClassId") Then ;This system has already been processed so just quit WriteLog("ClassId " & $classId & " has already been processed, Exiting...") Exit EndIf ProgressOn("O365SignIn Info V" & $version,"O365SignIn progress","Aquired Cloudshare userdata",Default,@DesktopHeight/4) Sleep(4000) ProgressSet(25,"Got seq: " & $seqnum & " on host: " & $vmNum ) Sleep(2000) ;Use email from userdata if specified, otherwise create it based on sequence no and machine instance If Not StringInStr($email,"@") Then ;Email NOT set in userdata so create one $email="student" & $vmNum & "@" & $seqnum & ".onmicrosoft.com" EndIf If $passwd <> "" Then ;If password set in userdata, it takes priority $password=$passwd ElseIf $PASS <> "" Then ;else if password pulled from registry via install tool, use it $password=$PASS Else ;otherwise use default one $password="Pa55word" EndIf ClipPut($password) ClipPut($email) ;Output to txt file on desktop for student info if selected during install If StringInStr($CRED,"True") Then $sFilename= @DesktopDir & "\Tenant Login Info.txt" $hFilehandle = FileOpen($sFileName, $FO_OVERWRITE) FileWrite($hFilehandle, "Use this email address and password to sign into the Office365 tenant used on this course" & @CRLF & @CRLF) ;FileWrite($hFilehandle, "The Office 365 trial tenant is usually available for 4 weeks after creation so you may be able to access it for 2 or 3 weeks after class" & @CRLF & @CRLF) FileWrite($hFilehandle, "Class tenant Email: " & $email & @CRLF) FileWrite($hFilehandle, "Class tenant Password: " & $password & @CRLF) FileClose($hFilehandle) WriteLog("User credential file created on desktop") Else WriteLog("User credential file wss not created") EndIf ProgressOff() If $vmNum=0 Then ;Admin - do a timed msgbox that defaults to admin or force to student1 if set on installer ;instructor WriteLog("Setting to admin account") ;$msg=MsgBox(35+262144,"O365SignIn Config V" & $version, "Select YES if you want to sign in as admin" & @CR & "NO if you wish to sign in as " & StringSplit($email,"@")[1] & " instead" & @CR & "or CANCEL if you wish to disable O365SignIn permanently") $msg=MsgBox(33+262144,"O365SignIn Config V" & $version, "Select OK if you want to sign in as admin" & @CR & "or CANCEL if you wish to disable O365SignIn permanently") If $msg=2 Then ;Add ConfigID to registry to stop rerunning script RegWrite("HKCU\Software\O365SignIn","ClassId", "REG_SZ", $classId) Exit ; Quit on cancel EndIf Else ;NOT admin - do a timed msgbox WriteLog("Setting to regular student") $msg=MsgBox(1+262144,"O365SignIn Config V" & $version, "Select OK to proceed with O365 SignIn" & @CR & "(will auto-signin after 30 seconds)" & @CR & "or CANCEL if you wish to exit O365SignIn",30) If $msg=2 Then RegWrite("HKCU\Software\O365SignIn","ClassId", "REG_SZ", $classId) Exit ; Quit on cancel EndIf EndIf ProgressOn("O365SignIn Info V" & $version,"O365SignIn progress","",Default,@DesktopHeight/4) WriteLog("User email will be: " & $email & " with password: " & $password) ProgressSet(50,"Email: " & $email) ;Output to txt file on desktop for student info if selected during install If StringInStr($CRED,"True") Then $sFilename= @DesktopDir & "\Tenant Login Info.txt" $hFilehandle = FileOpen($sFileName, $FO_OVERWRITE) FileWrite($hFilehandle, "Use this email address and password to sign into the Office365 tenant used on this course" & @CRLF & @CRLF) ;FileWrite($hFilehandle, "The Office 365 trial tenant is usually available for 4 weeks after creation so you may be able to access it for 2 or 3 weeks after class" & @CRLF & @CRLF) FileWrite($hFilehandle, "Class tenant Email: " & $email & @CRLF) FileWrite($hFilehandle, "Class tenant Password: " & $password & @CRLF) FileClose($hFilehandle) WriteLog("User credential file recreated on desktop") EndIf Sleep(2000) $_WD_DEBUG = 0 WriteLog("PBI Desktop set to " & $PBI) ClipPut($email) ;Just incase it got changed ;kill all Edge instances $count = 0 While ProcessExists("msedge.exe") And $count < 30 ProcessClose("msedge.exe") $count += 1 WEnd _WD_Option("errormsgbox", (@Compiled = 1)) _WD_Option("OutputDebug", (@Compiled = 1)) $sDesiredCapabilities = SetupEdge(False) ;SetupChrome() If @error <> $_WD_ERROR_Success Then ProgressOff() MsgBox(0,"O365SignIn Error V" & $version,"Could not download and verify the Edge Web Driver") WriteLog("Could not download and verify the Edge Web Driver") If @Compiled Then RegWrite("HKCU\Software\O365SignIn","ClassId", "REG_SZ", $classId) Exit EndIf If Not FileExists($_WD_DRIVER) Then ;No webdriver found - $_WD_DRIVER is just the filename, no path so uses current path - path comes from launch method so can vary - need correct path to exe here!!! MsgBox(0,"O365SignIn Error V" & $version,"The webdriver is missing. Unable to continue" & @CR & $_WD_DRIVER) WriteLog("The webdriver is missing. Unable to continue") EndIf ;MsgBox(0, "Done","Chrome/Edge Webdriver should be in place") ;startup Edge web driver - hidden console if _WD_Debug=0 ;$_WD_Debug=1 _WD_Startup() If @error <> $_WD_ERROR_Success Then ProgressOff() MsgBox(0,"O365SignIn Error V" & $version,"Could not correctly startup the web driver" & @CRLF & @ScriptDir) WriteLog("Could not correctly startup the web driver") Exit EndIf $sSession = _WD_CreateSession($sDesiredCapabilities) If @error <> $_WD_ERROR_Success Then ProgressOff() $msg = MsgBox(4+262144,"O365SignIn Error V" & $version,"Could not correctly launch the Web Browser" & @CR & "Should we try a reboot to see if browser updated...",60) WriteLog("Could not correctly launch the Web Browser - shall we try a reboot") If $msg=6 Then Shutdown(6) Exit EndIF _WD_Window($sSession, 'Maximize') _WD_Navigate($sSession, $o365url) If @error <> $_WD_ERROR_Success Then ProgressOff() MsgBox(0,"O365SignIn Error V" & $version,"Could not launch Edge Startup Page Window") WriteLog("Could not launch Edge Startup Page Window") Exit EndIf ProgressSet(50,"Edge driver and browser started") ;Slow things down so that it definitely works Sleep(2000) If WinExists("Restore pages","") Then WinClose("Restore pages","") ;Use the DOM to enter username and password quickly - all the below do the same - looking for tag with txt, id or class info ;$sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "//a[@id='hero-banner-sign-in-to-office-365-link']") $sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "//a[contains(text(),'Sign in')]") If @error = $_WD_ERROR_Success Then ;$sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "//a[@class='hero__button hero__button--primary']") $sValue = _WD_ElementAction($sSession, $sElement, 'click') ;Set the usename value _WD_LoadWait($sSession, 5000) If WinExists("Restore pages","") Then WinClose("Restore pages","") Sleep(2000) ;May already have an account here, so try checking for that screen before proceeding $sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "//div[@id='otherTileText']") If @error = $_WD_ERROR_Success Then ;click on other account button ;$sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "//div[@id='otherTile']") _WD_ElementActionEx($sSession, $sElement, "click") _WD_LoadWait($sSession, 5000) EndIf $sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "//input[@id='i0116']") ;_WD_ElementAction($sSession, $sElement, 'clear') $sValue = _WD_ElementAction($sSession, $sElement, 'value', $email) If _WD_ElementAction($sSession, $sElement, 'property', 'value') <> $email Then _WD_ElementAction($sSession, $sElement, 'clear') Sleep(1000) $sValue = _WD_ElementAction($sSession, $sElement, 'value', $email) EndIf $sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "//input[@id='idSIButton9']") _WD_ElementActionEx($sSession, $sElement, "doubleclick") ;detect invalid username and quit if one found _WD_LoadWait($sSession, 5000) Sleep(2000) ;detect invalid username and quit if one found - txt changed 02/22 $sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "//div[@id='usernameError']") If @error = $_WD_ERROR_Success Then ProgressOff() MsgBox(0,"O365SignIn Error V" & $version,"User email not found, unable to proceed" & @CR & "Check sequence numbers, capatalization and tenant") WriteLog("Username not found, unable to proceed") Exit EndIf ;Set the password value $sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "//input[@id='i0118']") $sValue = _WD_ElementAction($sSession, $sElement, 'value', $password) ;Force bad password ;$sValue = _WD_ElementAction($sSession, $sElement, 'value', "WRONGONE") If _WD_ElementAction($sSession, $sElement, 'property', 'value') <> $password Then _WD_ElementAction($sSession, $sElement, 'clear') Sleep(1000) $sValue = _WD_ElementAction($sSession, $sElement, 'value', $password) EndIf $sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "//input[@id='idSIButton9']") _WD_ElementActionEx($sSession, $sElement, "doubleclick") ;Possible 14 days page here so may wish to add ;$sSearch = "/html[@id='ng-app']/body[@id='home']/div[@class='main main_white ng-scope']/section[@id='content']/div[@class='container']/div[@class='row'][2]/div[@class='col-md-12']/ul[@class='list-group']/li[@class='list_row ng-scope'][" & $i & "]/a[@class='list-group-item list-group-item-info dropdown-header']" ;_WD_WaitElement($sSession,$_WD_LOCATOR_ByXPath,$sSearch) ;works ;$sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, $sSearch);works ;_WD_HighlightElement($sSession, $sElement,2);works _WD_LoadWait($sSession, 5000) Sleep(2000) ;detect bad password and quit if one found - txt changed 02/22 $sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "//div[@id='passwordError']") If @error = $_WD_ERROR_Success Then ProgressOff() MsgBox(0,"O365SignIn Error V" & $version,"Incorrect password found, unable to proceed" & @CR & "Check your tenant is correctly setup") WriteLog("Bad password found, unable to proceed") Exit EndIf $sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "//div[contains(text(),'Help us protect your account')]") If @error = $_WD_ERROR_Success Then ;_WD_HighlightElement($sSession, $sElement,2);works $sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "//a[contains(text(),'Skip for now')]") _WD_ElementActionEx($sSession, $sElement, "doubleclick") _WD_LoadWait($sSession, 2000) Sleep(2000) EndIf ;Save the password If WinExists("Save password","") Then WinActivate("Save password","") Sleep(1000) ;Send("{Left}") ;Sleep(500) Send("{Enter}") Sleep(2000) EndIf ;Save the password $sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "//input[@id='idSIButton9']") _WD_ElementActionEx($sSession, $sElement, "doubleclick") ;Send("{Enter}") Else ;detect blocked device and quit if one found $sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "//div[@id='messagePromptTitle']") If @error = $_WD_ERROR_Success Then ProgressOff() MsgBox(0,"O365SignIn Error V" & $version,"Device blocked error found, unable to proceed" & @CR & "Check your tenant is correctly setup") WriteLog("Device blocked error, unable to proceed") Exit EndIf ProgressSet(50,"O365 is already signed in. Continuing...") WriteLog("O365 seemed to be already signed in - No Sign In button") EndIf Sleep(10000) _WD_DeleteSession($sSession) _WD_Shutdown() WriteLog("Exited Edge browser") If StringInStr($email,"admin") Then _URLCreateShortcut("https://admin.microsoft.com/adminportal", "Office 365 Administration") WriteLog("Created an Admin Desktop Link for O365") EndIf If StringInStr($PBI,"True") Then ;Try and sigin in to power BI Desktop ProgressSet(50,"O365 is now signed in. Starting PBI Desktop") If ProcessExists("PBIDesktop.exe") Then ProcessClose("PBIDesktop.exe") If FileExists("C:\Program Files\Microsoft Power BI Desktop\bin\PBIDesktop.exe") Then ;Run it.... ShellExecute("C:\Program Files\Microsoft Power BI Desktop\bin\PBIDesktop.exe") ElseIf FileExists("C:\Program Files (x86)\Microsoft Power BI Desktop\bin\PBIDesktop.exe") Then ShellExecute("C:\Program Files (x86)\Microsoft Power BI Desktop\bin\PBIDesktop.exe") Else ProgressSet(60,"PBI Desktop not found, skipping sign on") WriteLog("Could not find PBI Desktop EXE file") Sleep(5000) MsgBox(0,"O365SignIn Error V" & $version,"Unable to find the PowerBI executable" & @CR & @CR & "Check that PowerBI Desktop is not installed from the Microsoft store",60) Exit EndIf WinWait("Untitled - Power BI Desktop","",120) ;give it 120 seconds to fire up ;Look for opening dialog - this is now not there in latest 2024 versions so shortened the timeout WinWait("Start","",10) ;give it 10 seconds to fire up If WinExists("Start") Then Sleep(5000) WinClose("Start") EndIf If WinExists("Untitled - Power BI Desktop") Then WinSetState("Untitled - Power BI Desktop","",@SW_MAXIMIZE) ;WinActivate("Untitled - Power BI Desktop","") WriteLog("Power BI Desktop has started") Sleep(5000) MouseClick("right",@DesktopWidth/2,15) Sleep(500) Send("{TAB}") Sleep(500) Send("{Enter}") ;At this point enter email window should appear - lets verify that!!! WinWait("Enter your email address","",5) If Not WinExists("Enter your email address","") Then ;something went wrong so lets try and redo this a different way MouseClick("right",24,15) ;right mouse click on save button Sleep(1000) Send("+{TAB}") ; Reverse Tab to focus sign in option Sleep(500) Send("{Enter}") ; At this point enter email window should appear - lets verify that again!!! WinWait("Enter your email address","",5) If Not WinExists("Enter your email address","") Then ProgressSet(60,"PBI Desktop not behaving, skipping sign on") WriteLog("Could not sign in to PBI Desktop") Sleep(5000) Exit EndIf EndIf Sleep(4000) Send($email) Sleep(500) Send("{Enter}") ;New Microsoft or Work account screen (down arrow then enter to clear) ;Reducing timeout here from 120 to 30 to speed up new version that does not have title bar so does not detect WinWait("Sign in","",30) ; Give the account type screen a couple of minutes to appear If WinExists("Sign in","") Then Sleep(5000) Send("{DOWN}") Sleep(1000) Send("{TAB}") Sleep(1000) Send("{DOWN}") Sleep(1000) Send("{Enter}") Sleep(2000) EndIf ;Now get a crappy untitled signin window and have to reenter email address ;WinWait("","",30) ;don't wait too long because no window name to wait for Sleep(4000) Send($email) Sleep(500) Send("{Enter}") ;WinWait("Sign in to your account","",120) ; Give the logon account screen a couple of minutes to appear Sleep(4000) ;Send("{TAB}") ;Sleep(1000) ;Send("{Enter}") ;Sleep(2000) Send($password,1) Sleep(1000) Send("{Enter}") Sleep(2000) If StringInStr($APPS,"True") Then ;After password, get various new screens with no window names - just enter/enter to sign in to all apps Send("{Enter}") Sleep(1000) Send("{Enter}") Sleep(2000) Else ;After password, get various new screens with no window names - just shift-tab then enter on first Send("+{TAB}") ; Reverse Tab to focus sign in on this app only option (no delay) Sleep(1000) Send("{Enter}") Sleep(2000) EndIf ;Enter again to close dialog - deleted so can see result ;Send("{Enter}") ;Sleep(2000) ;If Edge opens up here then PBI account does not exist so use it to flag up not signed in account WinWait("Microsoft Fabric free","",10) If WinExists("Microsoft Fabric free") Then ProgressOff() WinClose("Untitled - Power BI Desktop","") WinClose("Enter your email","") WinClose("Microsoft Fabric free","") MsgBox(0,"O365SignIn Error V" & $version,"Could not complete signing into PBI Desktop" & @CR & "Check your tenant has enough accounts for PBI") WriteLog("Could not complete signing into PBI Desktop - No account???") Exit EndIf WriteLog("Should have signed into PBI Desktop") ;shut it down ;WinClose("Untitled - Power BI Desktop","") ;Sleep(1000) ;If WinExists("Untitled - Power BI Desktop") Then Send("{Enter}") ;save on exit window on screen so close it Else ProgressSet(60,"PBI Desktop not found, skipping sign on") WriteLog("Could not find PBI Desktop EXE file") Sleep(5000) EndIf EndIf ProgressSet(100,"O365 Sign In should now be complete. Exiting...") Sleep(30000) ;Job done so update registry to prevent rerun RegWrite("HKCU\Software\O365SignIn","classId", "REG_SZ", $classId) Exit Func _URLCreateShortcut($sUrl, $sName, $sFldr = @DesktopDir) $sFldr = StringRegExpReplace($sFldr, "\\+\z", "") & "\" If NOT FileExists($sFldr) Then Return SetError(1) $sName = StringReplace($sName, ".url", "") & ".url" Local $Ini = $sFldr & $sName, $iSec = "InternetShortcut" $sUrl = StringRegExpReplace($sUrl, "^.*?:/+", "") IniWrite($Ini, $iSec, "URL", $sURL) IniWrite($Ini, $iSec, "IDList", "") IniWrite($Ini, $iSec, "IconFile", "") IniWrite($Ini, $iSec, "IconIndex", "1") EndFunc Func Terminate() HotKeySet("{Esc}") WriteLog("Escape pressed, exiting") Exit EndFunc ;==>TERMINATE Func SetupEdge($bHeadless) ;_WD_Option('Driver', @ScriptDir & '\msedgedriver.exe') _WD_Option('Driver', 'msedgedriver.exe') ;Needs full path so that scheduled task can find it Local $iPort = _WD_GetFreePort(9515, 9600) If @error Then Return SetError(@error, @extended, 0) ;Block Update for now ProcessClose("msedgedriver.exe") If StringInStr(@ScriptFullPath,"C:\") Then _WD_UpdateDriver('MSEdge', @ScriptDir, True, False) ;_WD_UpdateDriver('MSEdge', Default, True, Default) _WD_Option('Port', $iPort) _WD_Option('DriverParams', '--port=' & $iPort & ' --verbose --log-path="' & @ScriptDir & '\msedge.log"') _WD_CapabilitiesStartup() _WD_CapabilitiesAdd('alwaysMatch', 'msedge') _WD_CapabilitiesAdd('excludeSwitches', 'enable-automation') _WD_CapabilitiesAdd('args', 'user-data-dir', 'C:\\Users\\' & @UserName & '\\AppData\\Local\\Microsoft\\Edge\\User Data') ;_WD_CapabilitiesDump(@ScriptLineNumber) ; dump current Capabilities setting to console - only for testing in this demo ;If $bHeadless Then _WD_CapabilitiesAdd('args', '--headless') ;_WD_CapabilitiesDump(@ScriptLineNumber) ; dump current Capabilities setting to console - only for testing in this demo Local $sCapabilities = _WD_CapabilitiesGet() Return $sCapabilities EndFunc ;==>SetupEdge