Search code examples
rubypowershellrakesql-server-2014

Error running Invoke-Sqlcmd from ruby when passing path argument


  def executeSql(sqlFile)
      #exec("powershell $env:gitroot");
      puts "executing file: #{sqlFile}"
      command="powershell Invoke-Sqlcmd -InputFile #{sqlFile} -ServerInstance \"localhost\" -Database \"dbName\" -Verbose"
      command.gsub! '/','\\'
      puts "command: #{command}"
      if($firstRun)
          puts 'inside first run'
          importCommand = `powershell Import-Module \"sqlps\" -DisableNameChecking`
          printf importCommand 
          $firstRun=false
      end
      puts 'made it past first run'
      printf `#{command}`
      puts 'command execution complete'
  end

Error

Invoke-Sqlcmd : A positional parameter cannot be found that accepts argument 'Static'.

When I run this same command in powershell outside of ruby it executes normally. What am I doing wrong?

UPDATE

I found that replacing #{sqlFile} with the hard coded path C:\\test\\test.sql corrects the issue. I tried sqlFile.gsub! '/', '\\\\' and this made no apparent difference (still standard \ windows path).

I also tried

  command="powershell Invoke-Sqlcmd -InputFile #{Shellwords.escape(sqlFile)} -ServerInstance \"localhost\" -Database \"dbName\" -Verbose"

which created

Invoke-Sqlcmd -InputFile C:\\Git\\project\\sql\\db\\01\ -\ Static\ Data\\file.name.here.sql -ServerInstance "localhost" -Database "dbName" -Verbose

I think this would have worked were it not for the 01\ -\ Static\ part in the file path.

UPDATE 2

I found something that works and posted it as an answer. @tadman suggested to use multiple args to system. I tried this and it did not work for me. I'm sure I did something wrong:

 testLocation=File.join("C:/test 1", "test.sql")
   executeSql(testLocation)

  def executeSql(sqlFile)
      system("powershell", "Invoke-Sqlcmd", "-InputFile", "#{sqlFile}", "-ServerInstance", "localhost", "-Database", "dbName", "-Verbose")
  end

Solution

  • The trick is to escape whitespace with backticks to get powershell to behave itself.

      def executeSql(sqlFile)
          sqlFile.gsub! ' ','` '#escape whitespace in path
          command="powershell Invoke-Sqlcmd -InputFile #{sqlFile} -ServerInstance \"localhost\" -Database \"dbName\" -Verbose"
          puts "command: #{command}"
          if($firstRun)
              system("powershell Import-Module sqlps -DisableNameChecking;exit")
              $firstRun=false
          end
          system("#{command}")
      end