Назад | Перейти на главную страницу

Как цитаты / строки работают в Powershell?

У меня есть командная строка, которая работает в обычной старой командной оболочке Windows, но каким-то образом неправильно интерпретируется в Powershell (я новичок в 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"

Powershell, похоже, удаляет буквы дисков из аргументов, требующих пути. Например, я получаю следующее, когда пытаюсь запустить указанную выше команду в Powershell:

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

Конечно, он недействителен без буквы диска. Я пробовал варианты двойного цитирования, экранирования и т. Д., Но не могу заставить его работать. Что мне не хватает, что Powershell делает иначе?

Для начала PowerShell предполагает, что все параметры являются либо просто значением, либо -name value пара. Когда в середине значения есть кавычки, происходят странные вещи ...

Скорее всего, в таких случаях вам просто нужно указать весь параметр:

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"'

Однако я обычно предлагаю просто использовать Start-Process, что требует все аргументы в одной строке, поэтому вы можете:

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

В -RedirectStandardOutput f:\SQLBackups\CapturedOutput.log в последней строке просто захватит stdout в файл на случай, если он вам понадобится ... если вам нужно регистрировать вывод ошибки или вводить данные, вы также можете перенаправить их в / из файлов.

У меня нет sqlcmd, поэтому я не могу прокомментировать, как он интерпретирует параметры, которые он передает, но если я использую структуру, которую вы используете для доставки параметров в пакетный файл, который просто повторяет команду, которая вызвала оболочку cmd (echo %cmdcmdline%) показывает, что в качестве параметров передаются следующие параметры:

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"

Синтаксическому анализатору Sqlcmd, вероятно, не нравится то, как Powershell удаляет кавычки вокруг некоторых параметров, таких как местоположение запроса и способ DB = "ksuite" параметр серьезно изменен.

Один из вариантов, который может сработать, - просто заключить всю партию в одинарные кавычки, чтобы сохранить внутренние строки в двойных кавычках, и надеяться, что синтаксический анализатор sqlcmd справится с этим:

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"'

Это доставит немодифицированный список параметров в sqlcmd, но это будет единый параметр для оболочки, и я был бы удивлен, если бы это сработало. У вас гораздо больше шансов на успех, если вы выборочно заключите в одинарные кавычки все блоки параметров, которые изменяются, следующим образом:

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"'

Если это все еще не работает, могут быть другие элементы, которые необходимо явно экранировать, а не просто избегать путем переключения между одинарным и двойным кавычками с помощью символа обратной кавычки, который используется в качестве escape-символа при синтаксическом анализе строки Powershell.

Вы можете получить дополнительную информацию обо всех аспектах цитирования и экранирования через help about_quoting из PowerShell.

Я тоже так делаю старт-процесс Джайкула. SQLCMD был разработан с учетом cmd.exe, и в результате возникает некоторый конфликт между желанием видеть символы кавычек и тем, как 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"'