Como as citações / strings funcionam no Powershell?

3

Eu tenho uma linha de comando que funciona no antigo shell de comando do Windows, mas de alguma forma é mal interpretada no Powershell (eu sou relativamente novo no Powershell).

sqlcmd -S .\SQLEXPRESS -i "f:\SQLBackups\ExpressMaint.sql" -v DB="ksuite" -v OPTYPE="DB" -v BACKUPFOLDER="f:\SQLBackups" -v REPORTFOLDER="f:\SQLBackups\Reports" -v DBRETAINUNIT="days" -v DBRETAINVAL="7"

O Powershell parece estar retirando as letras de drive dos argumentos que requerem caminhos. Por exemplo, eu recebo o seguinte quando tento executar o comando acima no Powershell:

Sqlcmd: ':\SQLBackups': Invalid argument. Enter '-?' for help.

Bem, é inválido sem a letra da unidade. Eu tentei variações em duplas citando isto, escapando isto, etc. mas não posso conseguir isto para trabalhar. O que estou perdendo que o Powershell faz diferente?

    
por Casey Wilkins 07.01.2011 / 18:43

3 respostas

0

O processo inicial do Jaykul é como eu faço também. O SQLCMD foi projetado com o cmd.exe em mente e, como resultado, existe algum conflito entre querer ver os caracteres de aspas e o modo como o Powershell os usa (ou não os usa mais ao ponto).

Veja o que você pode usar para uma ligação direta, deve funcionar:

sqlcmd -S .\SQLEXPRESS -i "'""f:\SQLBackups\ExpressMaint.sql'"" -v 'DB="ksuite"' -v 'OPTYPE="DB"' -v 'BACKUPFOLDER="'"'f:\SQLBackups''"" -v 'REPORTFOLDER="'"'f:\SQLBackups\Reports''"" -v 'DBRETAINUNIT="days"' -v 'DBRETAINVAL="7"'
    
por 07.01.2011 / 19:53
3

Para iniciantes, o PowerShell pressupõe que todos os parâmetros são apenas um valor ou um par -name value . Quando você tem aspas no meio do valor, coisas estranhas acontecem ...

Você provavelmente só precisa citar o parâmetro inteiro nesses casos:

sqlcmd -S .\SQLEXPRESS -i "f:\SQLBackups\ExpressMaint.sql" -v 'DB="ksuite"' -v 'OPTYPE="DB"' -v 'BACKUPFOLDER="f:\SQLBackups"' -v 'REPORTFOLDER="f:\SQLBackups\Reports"' -v 'DBRETAINUNIT="days"' -v 'DBRETAINVAL="7"'

No entanto, minha sugestão usual é apenas usar o Start-Process, que pega all os argumentos em uma única string, então você pode fazer:

Start-Process sqlcmd @"
-S .\SQLEXPRESS -i "f:\SQLBackups\ExpressMaint.sql" -v DB="ksuite" -v OPTYPE="DB" -v BACKUPFOLDER="f:\SQLBackups" -v REPORTFOLDER="f:\SQLBackups\Reports" -v DBRETAINUNIT="days" -v DBRETAINVAL="7"
"@ -RedirectStandardOutput f:\SQLBackups\CapturedOutput.log

O -RedirectStandardOutput f:\SQLBackups\CapturedOutput.log na última linha irá apenas capturar stdout para um arquivo no caso de você precisar dele ... se você precisar registrar a saída do erro ou precisar fornecer entrada, você pode redirecioná-los para / de arquivos também.

    
por 07.01.2011 / 19:44
1

Eu não tenho sqlcmd, então não posso comentar como isso está interpretando os parâmetros que estão sendo passados, mas se eu usar a estrutura que você está usando para entregar os parâmetros para um arquivo em lotes que apenas ecoa o comando que invocou o shell cmd ( echo %cmdcmdline% ) mostra que o que está sendo passado como parâmetros é o seguinte:

cmd /c ""C:\Users\Joe\sqlcmd.cmd"  -S .\SQLEXPRESS -i f:\SQLBackups\ExpressMaint.sql -v DB=ksuite -v OPTYPE=DB -v BACKUPFOLDER=f:\SQLBackups -v REPORTFOLDER=f:\SQLBackups\Reports -v DBRETAINUNIT=days -v DBRETAINVAL=7"

O analisador do Sqlcmd provavelmente não faz o mesmo que o Powershell está removendo aspas em torno de alguns dos parâmetros como o local da consulta e a maneira como o parâmetro DB="ksuite" é seriamente alterado.

Uma opção que pode funcionar é apenas agrupar o lote inteiro entre aspas simples para preservar as cadeias duplas internas e esperar que o analisador sqlcmd possa lidar com isso:

sqlcmd '-S .\SQLEXPRESS -i "f:\SQLBackups\ExpressMaint.sql" -v DB="ksuite" -v OPTYPE="DB" -v BACKUPFOLDER="f:\SQLBackups" -v REPORTFOLDER="f:\SQLBackups\Reports" -v DBRETAINUNIT="days" -v DBRETAINVAL="7"'

Isso entregará a lista de parâmetros não modificados para o sqlcmd, mas o fará como um único parâmetro no que diz respeito ao shell e eu ficaria surpreso se funcionasse. É muito mais provável que você tenha sucesso se você citar seletivamente todos os blocos de parâmetros que estão sendo modificados com aspas simples da seguinte forma:

sqlcmd.cmd -S .\SQLEXPRESS -i '"f:\SQLBackups\ExpressMaint.sql"' -v 'DB="ksuite"' -v 'OPTYPE="DB"' -v 'BACKUPFOLDER="f:\SQLBackups"' -v 'REPORTFOLDER="f:\SQLBackups\Reports"' -v 'DBRETAINUNIT="days"' -v 'DBRETAINVAL="7"'

Se isso ainda não funcionar, pode haver outros itens que precisam ser explicitamente ignorados e não apenas evitados alternando entre aspas simples e dupla usando o caractere de backtick que é usado como caractere de escape na análise de cadeias de caracteres do Powershell.

Você pode obter mais informações sobre todos os aspectos de cotação e escape via help about_quoting no PowerShell.

    
por 07.01.2011 / 19:50