none
ダブルクォートを含むパスワードを設定したログインに失敗します RRS feed

  • 質問

  • Windows Server 2008 + SQL Server 2008 Enterprise Edition を使っています。

    Management Studio から以下のログインを作成しました。

    ログイン名: USER1

    パスワード: PASS 123!"#      ※ PASS の後に半角スペースを入れています

    # Management Studio を使ってログインできることは確認しました。

     

    その後、コマンドプロンプトを起動し、sqlcmd を使ってログインしようと思い

    sqlcmd -S . -U USER1 -P "PASS 123!""#" -d MyDatabase -q "SELECT * FROM emp"

    としたところ、ログインに失敗しました。

    パスワードに含めているダブルクォートのエスケープシーケンスに原因があると考え、

    \" のエスケープも試してみましたが、効果ありませんでした。

     

    WScript.Shell でも同様の文字列を生成(+ダブルクォートのエスケープ)を試してみましたが

    コマンドプロンプトと同様、ログインエラーがでてしまいました。

     

    そこで、お知恵をお貸し願いたいのは、コマンドプロンプト、および WScript (VBScript) から

    sqlcmd を呼び出して、ダブルクォートを含むパスフレーズを持つログインの方法です。

     

    あまり、この類のことで問題になっていないようなので…実は簡単に解決できることなのかも

    しれませんが…是非、対処方法を教えてください。よろしくお願いします。

     

    PowerShell では、バッククォートでエスケープすることでログインできるんですけどねぇ

     

     

    2010年8月19日 15:20

回答

  • 以下の方法でログインできました。コマンドプロンプトより

    set SQLCMDPASSWORD=PASS 123!"#
    sqlcmd -U USER1

    http://msdn.microsoft.com/ja-jp/library/ms162773.aspx
    には
    「SQLCMDPASSWORD 環境変数を使用して、現在のセッションに既定のパスワードを設定できます。」
    と記述があります。この方法で直接pオプションに指定することの代替策にしてはいかがでしょうか。
    なお、環境変数を実際確認してみると

    echo %SQLCMDPASSWORD%
    PASS 123!"#

    と出力されています。

     

    2010年8月19日 16:15
    モデレータ
  • Option Explicit
    
    Const cServer = "(local)"
    Const cUser = "USER1"
    Const cPassword = "PASS 123!""#"
    Const cSqlCmd = "C:\Program Files\Microsoft SQL Server\100\Tools\Binn\SQLCMD.EXE"
    
    Dim oShell, oEnv, oExec, input
    
    Set oShell = CreateObject("WScript.Shell")
    Set oEnv = oShell.Environment("Process")
    
    oEnv("SQLCMDSERVER") = cServer
    oEnv("SQLCMDUSER") = cUser
    oEnv("SQLCMDPASSWORD") = cPassword
    
    Set oExec = oShell.Exec(cSqlCmd & " -Q ""SELECT @@VERSION""")
    
    Do While True
      If Not oExec.StdOut.AtEndOfStream Then
        WScript.Echo(oExec.StdOut.ReadAll())
      End If
      If oExec.Status = 1 Then Exit Do
      WScript.Sleep(100)
    Loop
    

    Please mark the thread as Answered when an answer resolves your problem. 回答が得られたら、もらった回答の [回答済み] ボタンをクリックしてスレッドを回答済みにしましょう
    2010年8月19日 19:02

すべての返信

  • 以下の方法でログインできました。コマンドプロンプトより

    set SQLCMDPASSWORD=PASS 123!"#
    sqlcmd -U USER1

    http://msdn.microsoft.com/ja-jp/library/ms162773.aspx
    には
    「SQLCMDPASSWORD 環境変数を使用して、現在のセッションに既定のパスワードを設定できます。」
    と記述があります。この方法で直接pオプションに指定することの代替策にしてはいかがでしょうか。
    なお、環境変数を実際確認してみると

    echo %SQLCMDPASSWORD%
    PASS 123!"#

    と出力されています。

     

    2010年8月19日 16:15
    モデレータ
  • Dim a
    a = "a""b"
    WScript.Echo(a)
    WScript.Echo(Len(a))

    二重引用符 エスケープ vbscript で検索するといろいろヒットします。


    Please mark the thread as Answered when an answer resolves your problem. 回答が得られたら、もらった回答の [回答済み] ボタンをクリックしてスレッドを回答済みにしましょう
    2010年8月19日 18:11
  • Option Explicit
    
    Const cServer = "(local)"
    Const cUser = "USER1"
    Const cPassword = "PASS 123!""#"
    Const cSqlCmd = "C:\Program Files\Microsoft SQL Server\100\Tools\Binn\SQLCMD.EXE"
    
    Dim oShell, oEnv, oExec, input
    
    Set oShell = CreateObject("WScript.Shell")
    Set oEnv = oShell.Environment("Process")
    
    oEnv("SQLCMDSERVER") = cServer
    oEnv("SQLCMDUSER") = cUser
    oEnv("SQLCMDPASSWORD") = cPassword
    
    Set oExec = oShell.Exec(cSqlCmd & " -Q ""SELECT @@VERSION""")
    
    Do While True
      If Not oExec.StdOut.AtEndOfStream Then
        WScript.Echo(oExec.StdOut.ReadAll())
      End If
      If oExec.Status = 1 Then Exit Do
      WScript.Sleep(100)
    Loop
    

    Please mark the thread as Answered when an answer resolves your problem. 回答が得られたら、もらった回答の [回答済み] ボタンをクリックしてスレッドを回答済みにしましょう
    2010年8月19日 19:02
  • > PowerShell では、バッククォートでエスケープすることでログインできるんですけどねぇ

    本当に?  具体的にどんな記述をしていますか? PASS` 123!`"# では無理ですよね?

    PowerShell ではエスケープを ` で行いますが、CMD ではエスケープは ^ で行います。ただし、PowerShell では " が意味ある文字なのでエスケープを行いますが、CMD では " は意味のない文字なのでエスケープの必要がありません。コマンドラインからのアプリケーション起動では、引数はすべて1本の文字列で与えられ、各アプリケーションが処理をします。ダブルクオートを特別扱いしているのはコマンドラインではなく、それを受け取ったアプリケーションです。つまり、PowerShell で動く記述があるなら、それと同じ文字列がわたるように書けば、CScript からでも CMD からでも一緒のはずです。

    問題になっているのは、「スペース と ダブルクオート が共に含まれるパラメータ」だと思います。スペースがなければ、前述のとおり CMD なら特にエスケープは不要で -P PASS123!"# でよく、スペースだけなら -P "PASS 123" などとすればよいはずです。

    sqlcmd は、おそらく VC++ の標準のコマンドラインパーサを使用しているので、コマンドライン引数としてスペースとダブルクオートが含まれるパラメータを扱えないのではないか?と思います。(回避策は、既に書かれているように環境変数を利用したり、外部ファイルに記録するなどになると思います)

    2010年8月20日 3:34
  • 空白だけ: -P "Pass word"
    二重引用符:-P pass"word
    まじっている場合:-P "PASS 123!"#
    こういうパスワードでも可能です。 -P "PASS 123 !"#
    ☆しまりがないんですな。これがorz

    最後が空白で終わっている場合、二重引用符と空白の組み合わせでのログイン方法は知りません。
    あと、経験則で知っているだけで、特にこういう書き方をすると指示している資料は知りません。

    注:接続ができる、というだけであって、自分でコマンドを叩くときには良いかもしれませんが、バッチ化するときは、ElanLilacさんとM_Lewisさんが紹介している方法をご使用ください。
    #奇妙に感じる構文は使わないに越したことがありません^^;

    • 編集済み ChukiMVP 2010年8月20日 6:22 注意書き追加
    2010年8月20日 4:44
  • K.Takaoka さん、コメントありがとうございます。

    $pass = "PASS 123!`"#"

    Invoke-Sqlcmd -ServerInstance "Localhost" -User "USER1" -Password "$pass" -Database ...

     

    といった感じで、PowerShell では、ダブルクォートのみエスケープしています。

    半角スペースを、エスケープしなければ、K.Takaoka さんの環境でもログインできると思います。

     

    本題の sqlcmd は、K.Takaoka さんも仰っているように、環境変数で回避することができました。

     

     

    2010年8月20日 9:50

  • Elan Lilac さん、コメントありがとございます。

    私のつたない文章で、質問の意図が正しく伝わるかどうか心配でしたが、
    行間を読み取っていただいて、期待以上の回答をいただけたこと、
    うれしく思っています。

    sqlcmd 用の環境変数を使う方法で、実装をおこなったところ、
    ログインのパスフレーズに関係なく、SQL Server への接続が
    可能となり、期待した結果が得られるようになりました。

    丁寧な回答をいただいて、本当にありがとうございました。


    ちなみに… bcp ユーティリティは、sqlcmd のようにはいきませんよね?
    2010年8月20日 9:53
  • M_Lewis さん、コメントありがとうございます。

    WScript では、ダブルクォートを重ねてエスケープするのですね。

    もう少し、コードを見直してみます。

     

    2010年8月20日 9:55
  • Chuki さん、コメントありがとうございます。

    環境変数に設定すると、データベースに接続できることが確認できましたので

    無難な方法で、実装してみます。

    環境変数があるってことは、きっと…こういう場合に使えってことなのかな…と

    思っています。また、いろいろ教えてください。

     

    2010年8月20日 9:58
  • >環境変数があるってことは、きっと…こういう場合に使えってことなのかな…と

    まさにその通りだと思います^^

    >半角スペースを、エスケープしなければ、K.Takaoka さんの環境でもログインできると思います。

    K.Takaoka さんの返信は、PowerShell上でsqlcmdを実行したときについての言及だと思います。
    私の環境でも、PowerShell上からsqlcmdでのログインは無理でした。
    #PowerShell向けに作られたInvoke-Sqlcmd コマンドでは可能でした。

    2010年8月20日 10:15