1 votes

Ouvrir un navigateur (par défaut) à partir d'un travail en arrière-plan dans une méthode de classe Powershell ?

Scénario

Deux approches différentes qui ouvrent toutes deux une url dans un navigateur cessent de fonctionner lorsque je les place dans un job dans powershell, mais cessent de fonctionner si je les place dans une méthode d'une classe/objet. J'ai vérifié que l'objet dans le job est exécuté correctement car il exécute également une commande de copie dont je peux voir le résultat apparaître.

Code

Il s'agit du code de travail sans qu'il soit placé dans un objet :

# 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

Et pour être complet, voici le code qui n'ouvre pas l'url intégrée dans l'objet :

# 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

Pregunta

Pourquoi le code intégré dans un objet méthode n'ouvre-t-il pas un navigateur ?

Solution

La solution à mon problème xy est de mettre le code d'ouverture du site web en dehors de l'objet, mais j'aimerais mieux comprendre pourquoi powershell se comporte de cette façon (ou découvrir que j'ai fait une erreur que je n'ai pas encore vue).

1voto

a.t. Points 333

Powershell n'empêche pas l'ouverture de navigateurs à l'intérieur d'une méthode, d'une classe ou d'un travail. J'avais supposé, à tort et avec une confiance excessive, qu'aucun autre changement ne se produirait lors du passage de l'exécution normale à l'exécution d'un travail.

En ajoutant les lignes :

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

J'ai débogué manuellement le code et déterminé la commande suivante pour déterminer que le chemin actuel est défini différemment à l'intérieur d'un travail et en dehors d'un travail :

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

En déterminant le chemin courant avant un travail, et en le passant à un travail comme argument, vous pouvez obtenir le chemin courant correct à l'intérieur d'un travail (Le chemin dans lequel se trouve le script powershell qui a généré le travail, c'est-à-dire).

Le code de travail était :

$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

Vous pouvez ouvrir un navigateur à l'intérieur d'une méthode, d'une classe ou d'un travail dans powershell.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X