1

Scenario

Two different approaches that both open an url in a browser stop work when I put them inside a job in powershell, but stop working if I put them in a method of a class/object. I verified the object in the job is being executed correctly as it also performs a copy command of which I can see the result appear.

Code

This is the working code without it being placed in an object:


# 5. Start job and execute a method of the object
Start-Job -Name ListStuffOnTable -ScriptBlock {
        # attempt 1 opening default browser
        $authUrl = "http://superuser.com"
        Write-Host "visiting url="$authUrl
        (New-Object -com Shell.Application).Open($authUrl)

        # attempt 2 opening internet explorer
        $ie = new-object -com "InternetExplorer.Application"
        $ie.visible = $true
        $ie.navigate("http://superuser.com")
 }
 
 Write-Host "Created job"
 
 # Give the job 10 seconds to create a list of entries.
 Start-Sleep -Milliseconds 10000
 
 Write-Host "Running askSync"
 #Run command that starts an infinite loop untill the browser is opened by the job.
 wsl /home/testlinuxname/maintenance/./askSync.sh
 
 Write-Host "Running stopjob"
 # 6. Stop the job to get the data out.
 Get-Job -Name ListStuffOnTable | Stop-Job
 
 # 7. Verify it exists and functions correctly:
 Write-Host "`n Deleting job"
 
 # 8. Delete the job for correct bookkeeping:
 Get-Job -Name ListStuffOnTable | Remove-Job

And for completeness, this is the code that does not open the url integrated inside the object:


# 5. Start job and execute a method of the object
Start-Job -Name ListStuffOnTable -ScriptBlock {
    # 5.1 first write the class
    class GCalAccess{
       # Properties
       [String] $urlSourcePath  
       [String] $urlDestPath
       [String] $urlFilename
       [String] $absUrlSourceFilePath
       [String] $absUrlDestFilePath
       [HardCoded] $hardCoded
       [String] $authUrl
       [String] $defaultBrowserLocation
       [String] $absUrlWinDestFilePath
       
       # constructor
       GCalAccess([HardCoded] $hardCoded)
       {
          $this.hardCoded = $hardCoded
          Write-Host $this.hardCoded.getWindowsCurrentPath()
          
          # create the source and destination of the file that containts the url (url.txt)
          # it is coppied from inside the wsl to this folder, so that powershell can read it and open the url in browser
          $this.urlSourcePath = "/home/"+"testlinuxname"+"/"+$this.hardCoded.getmaintenanceFolderName()+"/"+$this.hardCoded.getGCalSyncFolderName()+"/"
          $this.urlDestPath = $this.hardCoded.getLinuxCurrentPath()+"/"
          $this.urlFilename = $this.hardCoded.getAuthUrlFilename()
          $this.absUrlSourceFilePath=$this.urlSourcePath+$this.urlFilename
          $this.absUrlDestFilePath=$this.urlDestPath+$this.urlFilename

          $this.absUrlWinDestFilePath = $this.hardCoded.getWindowsCurrentPath()+"/"+$this.urlFilename
          Write-Host "WinPath="$this.absUrlWinDestFilePath

          Write-Host $this.hardCoded.getWindowsCurrentPath()
          Write-Host $this.hardCoded.getLinuxCurrentPath()
          Write-Host "Url source file path = "$this.absUrlSourceFilePath
          Write-Host "Url destination file path = "$this.absUrlDestFilePath
       }
    
       # Infinite loop that Scans the existance of the file
       scanUrlFile(){
          [boolean] $foundUrl = $false
         # first copy the fail, regardless of whether it exists, then check if it is copied:
         while(!$foundUrl)
         {
            $this.copyUrl()
            if (Test-Path $this.absUrlWinDestFilePath -PathType leaf)
            {
               Write-Host "FOUND Url"
               #do some stuff
               $foundUrl = $true
            }
         }
         # exit

         # while(!$this.foundUrl())
         #  {
         #     # sleep 0.3 seconds
         #     Write-Host "Didn't find it yet."
         #     Start-Sleep -Milliseconds 300
         #  }
       }
    
       # Checks whether url file is found in the wsl
       [boolean] foundUrl()
       {
          # create wsl command that checks whether the file exists
          $command = "ls "+$this.absUrlSourceFilePath+" && echo FoundUrlFile"
          Write-Host "Command="+$command
          $output = bash "-c" $command
          
          # evaluate the output of the command to see if it found (null if not found, ends in "FoundUrlFile" if it is found)
          if($output-like "*FoundUrlFile"){
             Write-Host "Output="$output"..."   
             return $true
          }else {
             return $false
          }
       }
    
       # copy the file that contains the url
       copyUrl() {
          # create copy command
          Write-Host "pathSource="$this.absUrlSourceFilePath
          Write-Host "pathDest="$this.absUrlDestFilePath
          [String] $command = "sudo cp "+$this.absUrlSourceFilePath+" `""+$this.absUrlDestFilePath+"`""
          $output = bash "-c" $command
          Write-Host $output
       }

       readUrlFromFile(){
        $windowsUrlFilePath =$this.hardCoded.getWindowsCurrentPath()+"/"+$this.urlFilename
        Write-Host "windowsUrlFilePath="$windowsUrlFilePath
        
        $this.authUrl = Get-Content $windowsUrlFilePath -First 1
     }
       
       # open link to prefered browser
       openUrlInBrowser(){
          Write-Host "visiting url="$this.authUrl
          (New-Object -com Shell.Application).Open($this.authUrl)

          $ie = new-object -com "InternetExplorer.Application"
          $ie.visible = $true
          $ie.navigate("http://www.google.com")
       }
        
    
       # deletes the copied file with the authorization url after use
       cleanUpWindowsUrlFileCopy(){
    
       }
    
       # TODO: CLick >nextnextnext if website allows it.
    
       #############################ASSISTING FUNCTIONS#################
    

    
       # returns the integer index in the url string of the occurence of "$scope"
       [int] findIndexOfKeyword([String] $url){
          return $url.IndexOf("&scope")
       }
    
       
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    class HardCoded {
        # object properties/fields
        [String] $windowsCurrentPath
        [String] $linuxCurrentPath
        
        # create relative folder names
        [String] $maintenanceFolderName = "maintenance"
        [String] $gCalSyncFolderName = "gCal" 
       
        # create hardcoded localHost url for google calendar sync
        [String] $authUrlFilePath = "/home/"+$this.linuxUsername+"/"+$this.getmaintenanceFolderName()+"/"+$this.getGCalSyncFolderName+"/"
        [String] $authUrlFilename = "url.txt"
        
        HardCoded () {
        
            # set current paths
            $this.windowsCurrentPath = $this.getCurrentPath()
            $this.linuxCurrentPath = $this.convertWinPathToLinuxPath($this.windowsCurrentPath)+"/"
        }
    
        # convert Windows path to linux path:
        [String] convertWinPathToLinuxPath([String] $winPath) {
            $linuxPath = (($winPath -replace "\\","/") -replace ":","").Trim("/")
            # convert drive letter to lowercase:
            $linuxPath = $linuxPath.Substring(0,1).ToLower()+$linuxPath.Substring(1)
            $linuxPath = "/mnt/"+$linuxPath
            return $linuxPath
        }
    
        # return linux format of current path
        [String] getCurrentPath() {         
            [String] $winPath = Split-Path -parent $PSCommandPath
            return $winPath
        }
    
        # Getters
        [String] getmaintenanceFolderName() {
           return $this.maintenanceFolderName
        }
        # Getters
        [String] getGCalSyncFolderName() {
           return $this.gCalSyncFolderName
        }
        # Getters
        [String] getAutoInstallTwProjectName() {
           return $this.autoInstallTwProjectName
        }
        # Getters
        [String] getDefaultLocalHostname() {
           return $this.defaultLocalHostname
        }
        # Getters
        [String] getWindowsCurrentPath() {
           return $this.windowsCurrentPath
        }
        # Getters
        [String] getLinuxCurrentPath() {
           return $this.linuxCurrentPath
        }
        # Getters
        [String] getAuthUrlFilePath() {
           return $this.authUrlFilePath
        }
        # Getters
        [String] getAuthUrlFilename() {
           return $this.authUrlFilename
        }
    }
    
    #Create objects that are used
    [HardCoded] $hardCoded = [HardCoded]::new()
    [GCalAccess] $gCalAccess = [GCalAccess]::new($hardCoded)
    
    # Create a background job to scan for url file
    
    # scan for the url file to emerge
    $gCalAccess.scanUrlFile()
    #$gCalAccess.copyUrl()
    $gCalAccess.readUrlFromFile()
    $gCalAccess.openUrlInBrowser()   
 }
 
 Write-Host "Created job"
 
 # Give the job 10 seconds to create a list of entries.
 Start-Sleep -Milliseconds 10000
 
 Write-Host "Running askSync"
 #Run command that displays the url (and indirectly generates the url file)  inside the installer
 wsl /home/testlinuxname/maintenance/./askSync.sh
 
 Write-Host "Running stopjob"
 # 6. Stop the job to get the data out.
 Get-Job -Name ListStuffOnTable | Stop-Job
 
 # 7. Verify it exists and functions correctly:
 Write-Host "`n Deleting job"
 
 # 8. Delete the job for correct bookkeeping:
 Get-Job -Name ListStuffOnTable | Remove-Job

Question

Why does the code integrated in a method object not open a browser?

Solution

The solution to my xy-problem is to put the website opening code outside the object, but I would like to develop a better understanding on why powershell behaves this way (or in find out I made a mistake I did not see yet).

1 Answer 1

1

Powershell does not prevent opening browsers inside a method inside a class inside a job. I had incorrectly and with overconfidence assumed no other changes would happen when switching from normal execution to job-execution.

By adding the lines:

New-Item -Path 'C:/output/logfile.txt' -ItemType File
    Add-Content ('C:/output/logfile.txt') $someVariableThatIWantToPrintToFileFromInsideJob

I manually debugged the code and determined the following command to determine the current path is set different inside a job than not inside a job:

$windowsCurrentPath = Split-Path -parent $PSCommandPath
Write-Host "CurrentPath="$windowsCurrentPath

By determining the current path before a job, and passing it to a job as an argument, you can get the correct current path inside a job (The path in which the powershell script is located, that generated the job, that is).)

The working code was:

$windowsCurrentPath = Split-Path -parent $PSCommandPath
Write-Host "CurrentPath="$windowsCurrentPath

# 5. Start job and execute a method of the object
Start-Job -Name ListStuffOnTable -ScriptBlock {
    # 5.1 first write the class
    class GCalAccess{
       # Properties
       [String] $urlSourcePath  
       [String] $urlDestPath
       [String] $urlFilename
       [String] $absUrlSourceFilePath
       [String] $absUrlDestFilePath
       [HardCoded] $hardCoded
       [String] $authUrl
       [String] $defaultBrowserLocation
       [String] $absUrlWinDestFilePath
       
       # constructor
       GCalAccess([HardCoded] $hardCoded)
       {
          $this.hardCoded = $hardCoded
          Write-Host $this.hardCoded.getWindowsCurrentPath()
          
          # create the source and destination of the file that containts the url (url.txt)
          # it is coppied from inside the wsl to this folder, so that powershell can read it and open the url in browser
          $this.urlSourcePath = "/home/"+"testlinuxname"+"/"+$this.hardCoded.getmaintenanceFolderName()+"/"+$this.hardCoded.getGCalSyncFolderName()+"/"
          $this.urlDestPath = $this.hardCoded.getLinuxCurrentPath()+"/"
          $this.urlFilename = $this.hardCoded.getAuthUrlFilename()
          $this.absUrlSourceFilePath=$this.urlSourcePath+$this.urlFilename
          $this.absUrlDestFilePath=$this.urlDestPath+$this.urlFilename

          $this.absUrlWinDestFilePath = $this.hardCoded.getWindowsCurrentPath()+"/"+$this.urlFilename
          Write-Host "WinPath="$this.absUrlWinDestFilePath

          Write-Host $this.hardCoded.getWindowsCurrentPath()
          Write-Host $this.hardCoded.getLinuxCurrentPath()
          Write-Host "Url source file path = "$this.absUrlSourceFilePath
          Write-Host "Url destination file path = "$this.absUrlDestFilePath
       }
    
       # Infinite loop that Scans the existance of the file
       scanUrlFile(){
          [boolean] $foundUrl = $false
         # first copy the fail, regardless of whether it exists, then check if it is copied:
         while(!$foundUrl)
         {
            $this.copyUrl()
            if (Test-Path $this.absUrlWinDestFilePath -PathType leaf)
            {
               Write-Host "FOUND Url"
               #do some stuff
               $foundUrl = $true
            }
         }
         # exit

         # while(!$this.foundUrl())
         #  {
         #     # sleep 0.3 seconds
         #     Write-Host "Didn't find it yet."
         #     Start-Sleep -Milliseconds 300
         #  }
       }
    
       # Checks whether url file is found in the wsl
       [boolean] foundUrl()
       {
          # create wsl command that checks whether the file exists
          $command = "ls "+$this.absUrlSourceFilePath+" && echo FoundUrlFile"
          Write-Host "Command="+$command
          $output = bash "-c" $command
          
          # evaluate the output of the command to see if it found (null if not found, ends in "FoundUrlFile" if it is found)
          if($output-like "*FoundUrlFile"){
             Write-Host "Output="$output"..."   
             return $true
          }else {
             return $false
          }
       }
    
       # copy the file that contains the url
       copyUrl() {
          # create copy command
          Write-Host "pathSource="$this.absUrlSourceFilePath
          Write-Host "pathDest="$this.absUrlDestFilePath
          [String] $command = "sudo cp "+$this.absUrlSourceFilePath+" `""+$this.absUrlDestFilePath+"`""
          $output = bash "-c" $command
          Write-Host $output
       }

       readUrlFromFile(){
        $windowsUrlFilePath =$this.hardCoded.getWindowsCurrentPath()+"/"+$this.urlFilename
        Write-Host "windowsUrlFilePath="$windowsUrlFilePath
        
        $this.authUrl = Get-Content $windowsUrlFilePath -First 1
     }
       
       # open link to prefered browser
       openUrlInBrowser(){
          Write-Host "visiting url="$this.authUrl
          (New-Object -com Shell.Application).Open($this.authUrl)

          $ie = new-object -com "InternetExplorer.Application"
          $ie.visible = $true
          $ie.navigate("http://www.google.com")
       }
        
    
       # deletes the copied file with the authorization url after use
       cleanUpWindowsUrlFileCopy(){
    
       }
    
       # TODO: CLick >nextnextnext if website allows it.
    
       #############################ASSISTING FUNCTIONS#################
    

    
       # returns the integer index in the url string of the occurence of "$scope"
       [int] findIndexOfKeyword([String] $url){
          return $url.IndexOf("&scope")
       }
    
       
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    class HardCoded {
        # object properties/fields
        [String] $windowsCurrentPath
        [String] $linuxCurrentPath
        
        # create relative folder names
        [String] $maintenanceFolderName = "maintenance"
        [String] $gCalSyncFolderName = "gCal" 
       
        # create hardcoded localHost url for google calendar sync
        [String] $authUrlFilePath = "/home/"+$this.linuxUsername+"/"+$this.getmaintenanceFolderName()+"/"+$this.getGCalSyncFolderName+"/"
        [String] $authUrlFilename = "url.txt"
        
        HardCoded ([String] $incomingCurrentWindowsPath) {
        
            # set current paths
            $this.windowsCurrentPath = $incomingCurrentWindowsPath
            $this.linuxCurrentPath = $this.convertWinPathToLinuxPath($this.windowsCurrentPath)+"/"
        }
    
        # convert Windows path to linux path:
        [String] convertWinPathToLinuxPath([String] $winPath) {
            $linuxPath = (($winPath -replace "\\","/") -replace ":","").Trim("/")
            # convert drive letter to lowercase:
            $linuxPath = $linuxPath.Substring(0,1).ToLower()+$linuxPath.Substring(1)
            $linuxPath = "/mnt/"+$linuxPath
            return $linuxPath
        }
        # Getters
        [String] getmaintenanceFolderName() {
           return $this.maintenanceFolderName
        }
        # Getters
        [String] getGCalSyncFolderName() {
           return $this.gCalSyncFolderName
        }
        # Getters
        [String] getAutoInstallTwProjectName() {
           return $this.autoInstallTwProjectName
        }
        # Getters
        [String] getDefaultLocalHostname() {
           return $this.defaultLocalHostname
        }
        # Getters
        [String] getWindowsCurrentPath() {
           return $this.windowsCurrentPath
        }
        # Getters
        [String] getLinuxCurrentPath() {
           return $this.linuxCurrentPath
        }
        # Getters
        [String] getAuthUrlFilePath() {
           return $this.authUrlFilePath
        }
        # Getters
        [String] getAuthUrlFilename() {
           return $this.authUrlFilename
        }
    }
    
    #Create objects that are used
    $incomingCurrentWindowsPath = $args[0]
    [HardCoded] $hardCoded = [HardCoded]::new($incomingCurrentWindowsPath)
    [GCalAccess] $gCalAccess = [GCalAccess]::new($hardCoded)
    
    # Create a background job to scan for url file
    
    # scan for the url file to emerge
    $gCalAccess.scanUrlFile()
    #$gCalAccess.copyUrl()
    $gCalAccess.readUrlFromFile()
    $gCalAccess.openUrlInBrowser()   
 } -ArgumentList @($windowsCurrentPath)
 
 Write-Host "Created job"
 
 # Give the job 10 seconds to create a list of entries.
 Start-Sleep -Milliseconds 10000
 
 Write-Host "Running askSync"
 #Run command that displays the url (and indirectly generates the url file)  inside the installer
 wsl /home/testlinuxname/maintenance/./askSync.sh
 
 Write-Host "Running stopjob"
 # 6. Stop the job to get the data out.
 Get-Job -Name ListStuffOnTable | Stop-Job
 
 # 7. Verify it exists and functions correctly:
 Write-Host "`n Deleting job"
 
 # 8. Delete the job for correct bookkeeping:
 Get-Job -Name ListStuffOnTable | Remove-Job

Conclusion

You can open a browser inside a method inside a class inside a job in powershell.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .