2016-12-05 24 views
1

パラメータとして渡されたコマンドを実行するCLRストアドプロシージャを作成しました。これはCLRストアドプロシージャのコードです。 SQL Serverでアセンブリを「安全でない」として登録し、そこからストアドプロシージャを作成しました。CLRコマンドを実行するストアドプロシージャ

[SqlProcedure] 
public static int ExecuteCommand(string cmd) 
{ 
    int success = 0; 

    try 
    { 
     EventLog.WriteEntry("MyAppName", "Starting execution " + cmd + " Username: " + System.Security.Principal.WindowsIdentity.GetCurrent().Name + " OR " + Environment.UserName, EventLogEntryType.Information); 

     Process p = new Process(); 
     p.StartInfo = new ProcessStartInfo() { FileName = "cmd.exe", Arguments = cmd, WindowStyle = ProcessWindowStyle.Hidden}; 
     p.Start(); 
    } 
    catch (Exception ex) 
    { 
     EventLog.WriteEntry("MyAppName", "Executed command : " + cmd + " with error : " + ex.Message, EventLogEntryType.Error); 
     success = 1; 
    } 

    return success; 
} 

このコードでは、イベントビューアに書き込んで、ユーザ名NT AUTHORITY\SYSTEMを出力します。その後、cmd.exeを起動しますが、渡されたコマンド(例:mkdir)は実行されず、cmd.exeは実行状態のままです。タスクマネージャでは、ストアドプロシージャの実行ごとに複数のインスタンスcmd.exeが表示されますが、usernameカラムには値はありません。 SQL Serverサービスはローカルシステムアカウントで実行されています。

ここで何が問題になりますか?それがパーミッションに関連している場合、ストアドプロシージャを呼び出すユーザのコンテキストの下でCLRストアドプロシージャを実行する方法はありますか?

答えて

1

権限が問題では、あなたは間違いなく間違ってcmd.exeのを呼び出しているように見えるかもしれませんが。あなたは単にそれを呼び出す場合:

cmd.exe mkdir folder_name 

そして、あなたが見ている行動になるだろう、すなわち、フォルダが作成されないとプロセスが終了せずに続けます。

あなたが提供するコマンドとし、終了を実行するためにCMD指示/Cコマンドラインスイッチを使用して実行するようにコマンドを渡しcmd.exeのを呼び出す必要があります。したがって、以下を呼び出してください:

cmd.exe /C mkdir folder_name 

期待どおり動作します。だから、おそらくあなたが使用する必要があります。

Arguments = "/C " + cmd 

また、あなたは別の「WindowStyleが」および/またはその他のProcessStartInfo財産を必要とするかもしれない可能性があります。上記がうまくいかない場合、私はこれを動作させるために私が過去に使ったことを確認します。

P.S.パラメータにはSql*タイプを使用し、SQLCLRメソッドには値を返す必要があります。したがって、stringSqlInt32の代わりにの代わりにSqlStringを使用してください。 Sql*タイプのすべてには、予想される.NETネイティブタイプを返す.Valueプロパティがあります。したがって、次のように使用します。

Arguments = "/C " + cmd.Value 
+1

ありがとうございました。それは私にとって不思議なように働いた。 – Mahesh

0

偽装の問題やその欠如のような音がします。明示的に指示しない限り、SQL CLRはトークン(資格情報)を他のアプリケーションに転送しません。

[SqlProcedure] 
public static int ExecuteCommand(string cmd) 
{ 
    int success = 0; 
    Impersonate impersonatedUser = new Impersonate(); 
    try 
    { 
     EventLog.WriteEntry("MyAppName", "Starting execution " + cmd + " Username: " + System.Security.Principal.WindowsIdentity.GetCurrent().Name + " OR " + Environment.UserName, EventLogEntryType.Information); 
     Process p = new Process(); 
     p.StartInfo = new ProcessStartInfo() { FileName = "cmd.exe", Arguments = cmd, WindowStyle = ProcessWindowStyle.Hidden }; 
     p.Start(); 

    } 
    catch (Exception ex) 
    { 
     EventLog.WriteEntry("MyAppName", "Executed command : " + cmd + " with error : " + ex.Message, EventLogEntryType.Error); 
     success = 1; 
    } 
    finally 
    { 
     impersonatedUser.Undo(); 
    } 
    return success; 
} 

次のような行がいくつかあることに注意してください。

これは、ストアドプロシージャを実行しているユーザーを偽装するようにSQLに指示します。これは、SQL認証は実際にはWindowsユーザーではないので、SQL認証では失敗します。

finally 
{ 
    impersonatedUser.Undo(); 
} 

偽装は何に関係なくを元に戻すようになりますそれはそうfinallyブロックでこれを入れて、他の問題につながることができ偽装を元に戻すために失敗した場合。ここで

はそれについてもう少し言う主題上のMicrosoftの記事です:

https://msdn.microsoft.com/en-us/library/ms345105.aspx

関連する問題