none
Ajuda para mover um arquivo - diferentes resultados executando no prompt de comando e no Powershell ISE RRS feed

  • Pergunta

  • Bom dia a todos!

    Estou com um problema na execução de um script powershell. Ja busquei em varios foruns, varias solucoes alternativas mas ainda nao consegui.
    O script importa dados de planilhas excel para um banco de dados SQLServer. O problema ocorre quando ao abrir uma planilha excel e apos algumas verificações necessárias para o cliente (ex nome da aba diferente do que tem que vir) tentamos mover a planilha com outro nome para um outro diretorio de erro. So que o powershell retorna o erro de que nao se pode mover pois o arquivo esta em uso. Fiz algumas alterações e em uma delas ocorreu algo estranho, que, no Powershell ISE, o processo roda ok e consegue mover a planilha, mas executando pelo prompt de comando, nao consegue mover a planilha.
    No script antes de tentar mover a planilha, faço um loop e so saio do loop para mover o arquivo qdo retorna true. Funcao abaixo:

    try {
        $sw = new-object system.io.streamwriter $filePath
        $sw.close()
        Write-Host "teste true"
        return $true
    }
    catch
    {
        Write-Host "teste false"
        return $false
    }


    Como falei, ao executar pelo powershell ise, de primeira ele me retorna "teste true" e consegue mover o arquivo.
    Ao executar pelo prompt, ele fica em loop infinito, retornando somente "teste false".

    Obrigado!


    • Editado Fábio JrModerator quinta-feira, 27 de dezembro de 2012 15:44 Formatação do código
    quinta-feira, 27 de dezembro de 2012 13:00

Respostas

  • Consegui resolver da seguinte maneira, fiz um loop, pois depois de uns 2 minutos, dependendo do tamanho da planilha, ele fecha a planilha. O LimitTime é para que não passe de uma hora, pois o processo roda a noite então da pra esperar este tempo para tentar mover corretamente a planilha.

    Obrigado pela ajuda!!!

        $test = $false
        $StartTime = (Get-Date)
        $LimitTime = (Get-Date)
        $LimitTime = $LimitTime.AddHours(1)
        while (($test -eq $false) -and ($StartTime -le $LimitTime)) {
           $StartTime = (Get-Date)
           try {
               $ErrorActionPreference = "Stop"; #Make all errors terminating
               Move-Item $file $newFile -force
               $test = $true
           } catch {
               $test = $false
               Start-Sleep -s 5
           } finally {
              $ErrorActionPreference = "Continue"; #Reset the error action pref to default
           }
        }

    • Marcado como Resposta Mateus Mollo sexta-feira, 11 de janeiro de 2013 13:13
    sexta-feira, 11 de janeiro de 2013 13:13

Todas as Respostas

  • Enquanto o script está em loop vc consegue mover a planilha pelo windows explorer?

    Se puder coloque o código completo.


    Fábio de Paula Junior

    quinta-feira, 27 de dezembro de 2012 15:46
    Moderador
  • Fabio,
    não, não consigo mover o arquivo quando o powershell é executado pelo prompt do DOS e está no loop de "false"
    Segue o principal do codigo, pois é meio grande devido aos tratamentos dos dados da planilha.

    Function Process-Files { $items = dir $location -filter $filter if($items -eq $null) { Write-Log "No items to process at the time" $script:dbConn.close() exit } # clear stage tables foreach($it in $script:stageTable) { Clear-Stage-Table $it } $backupFile = $true $backupItens = $true foreach($it in $items) { $script:filexl = $location + "\" + $it Write-Log $(Get-Date) + " ------------------------------------------------------------------------" Write-Log "Processing file $script:filexl" try { # Loop for spreadsheets $stg = 0 foreach($sheet in $spreadsheets) { if($sheet -eq $null) { break; } # Retrieve data try { $data = Get-ACEData -FilePath $script:filexl -Worksheet $($sheet+ "$") } catch { Write-Host "It was not possible to retrieve the data from Excel spreadsheet. Impossible to continue." Write-Log "It was not possible to retrieve the data from Excel spreadsheet. Impossible to continue." Write-Log $_ #exit # entra aqui devido a aba da planilha estar com nome diferente do definido $backupItens = $false } if ($backupItens -eq $true) { ........ } else { $backupItens = $true $backupFile = $false continue }

    #apos o continue entra neste ponto
    # Moves the file
    $filename = Backup-Excel $script:filexl


    Esta é a função que move o arquivo Excel

    function Backup-Error-Excel
    {
        param($file)
        
        $filename = $(split-path -leaf $file).split(".")[0]
        $extension = $(split-path -leaf $file).split(".")[1]
        $newFile = $script:ErrorLocation + "\" + $filename + "-" + $(get-date -f "yyyyMMddhhmm") + "." + $extension
    
        if(test-path $newFile) {
            Remove-Item -Force $newFile
        }
    
        $fileStatus = $false
        while ($fileStatus -eq $false)
        {
           $fileStatus = checkFileStatus $file
           $fileStatus
        }
    
        Move-Item $file $newFile -force
    
        #Return
        $newFile
    }



    E esta é a função que verifica se o arquivo esta aberto:

    function checkFileStatus($filePath)
    {
       try {
          $sw = new-object system.io.streamwriter $filePath
          $sw.close()
          return $true
       }
       catch
       {
          Write-Host "teste false"
          return $false
       }
    }

    Obrigado


    • Editado Mateus Mollo quinta-feira, 27 de dezembro de 2012 18:00 formatacao da mensagem
    quinta-feira, 27 de dezembro de 2012 16:28
  • Mateus,

    Ao que parece algum objeto está aberto e utilizando o Excel.

    Será que não falta dar um "close" em algum objeto antes de fazer a cópia.

    Eu desconfio desta linha

    $data = Get-ACEData -FilePath $script:filexl -Worksheet $($sheet+ "$")

    Não sei como fechar, poderia tentar um $data=$null antes de fazer a cópia.


    Fábio de Paula Junior

    quinta-feira, 27 de dezembro de 2012 17:09
    Moderador
  • Pois é Fabio... o problema é como fechar a planilha q esta em aberto. Eu alterei o nome da aba da planilha pra testar o processo e tratamento de erro, e cai neste problema.
    Pesquisei bastante, e encontrei o codido da funcao checkFileStatus:

    function checkFileStatus($filePath)
    {
       try {
          $sw = new-object system.io.streamwriter $filePath
          $sw.close()
          return $true
       }
       catch
       {
          Write-Host "teste false"
          return $false
       }
    }



    Executando o script pelo PowerShell ISE, esta funcao consegue fechar o arquivo!!! Assim, move normalmente o arquivo! O que não consigo entender é pq funciona no powershell ISE mas nao funciona executando o script pelo prompt de comando... ele cai no loop e nao consegue fechar o arquivo.
    Qualquer outra duvida sobre o codigo, me peca q eu explico.
    Agradeco demais sua atencao!!!



    • Editado Mateus Mollo quinta-feira, 27 de dezembro de 2012 18:01 formatacao da mensagem
    quinta-feira, 27 de dezembro de 2012 17:21
  • Faça esta tentativa: mova o código da função  checkFileStatus para o inicio do seu código.

    Fábio de Paula Junior

    quinta-feira, 27 de dezembro de 2012 19:43
    Moderador
  • Fabio, fiz o teste com o $data=$null, mesmo resultado:
    "Move-Item : The process cannot access the file because it is being used by another process."

    E sim, a função já estava no início do script... probleminha chato esse rsrsrs
    Vou continuar pesquisando... tbem nao encontrei um modo de fechar o $data... a tentativa da função deu certo somente executando pelo PowerShell ISE...

    Bom, no aguardo e mais uma vez obrigado pela sua ajuda e atencao!!!

    sexta-feira, 28 de dezembro de 2012 12:04
  • Consegui resolver da seguinte maneira, fiz um loop, pois depois de uns 2 minutos, dependendo do tamanho da planilha, ele fecha a planilha. O LimitTime é para que não passe de uma hora, pois o processo roda a noite então da pra esperar este tempo para tentar mover corretamente a planilha.

    Obrigado pela ajuda!!!

        $test = $false
        $StartTime = (Get-Date)
        $LimitTime = (Get-Date)
        $LimitTime = $LimitTime.AddHours(1)
        while (($test -eq $false) -and ($StartTime -le $LimitTime)) {
           $StartTime = (Get-Date)
           try {
               $ErrorActionPreference = "Stop"; #Make all errors terminating
               Move-Item $file $newFile -force
               $test = $true
           } catch {
               $test = $false
               Start-Sleep -s 5
           } finally {
              $ErrorActionPreference = "Continue"; #Reset the error action pref to default
           }
        }

    • Marcado como Resposta Mateus Mollo sexta-feira, 11 de janeiro de 2013 13:13
    sexta-feira, 11 de janeiro de 2013 13:13