我在问题上被困了太多天。
直到现在我们在40多个存储过程中使用了xp_cmdshell。现在我们要使用程序集替换此调用。 我创建了一个CLR项目。它看起来像:
using System;
using System.Data;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.IO;
using System.Text;
using Microsoft.SqlServer.Server;
namespace CmdShellBridge
{
public class CmdShell
{
[SqlProcedure]
public static void CmdShellBridgeBCP(string arguments, out String ReturnMessage)
{
processCMD("cmd.exe", arguments, out ReturnMessage);
}
[SqlProcedure]
public static void CmdShellBridgeMD(string arguments, out String ReturnMessage)
{
processCMD("cmd.exe", arguments, out ReturnMessage);
}
[SqlProcedure]
public static void CmdShellBridgeMKDIR(string arguments, out String ReturnMessage)
{
processCMD("cmd.exe", arguments, out ReturnMessage);
}
[SqlProcedure]
public static void CmdShellBridgeBCMSyncImport(string arguments, out String ReturnMessage)
{
processNotCMD("F:\\ThirdParty_Applications\\BCMSync\\BCMSyncImp.exe", arguments, out ReturnMessage);
}
[SqlProcedure]
public static void CmdShellBridgeBCMSyncExport(string arguments, out String ReturnMessage)
{
processNotCMD("F:\\ThirdParty_Applications\\BCMSync\\BCMSyncExp.exe", arguments, out ReturnMessage);
}
[SqlProcedure]
public static void CmdShellBridgeOSQL(string arguments, out String ReturnMessage)
{
processCMD("cmd.exe", arguments, out ReturnMessage);
}
[SqlProcedure]
public static void CmdShellBridgeSQLCMD(string arguments, out String ReturnMessage)
{
processCMD("cmd.exe", arguments, out ReturnMessage);
}
[SqlProcedure]
public static void CmdShellBridgeDIR(string arguments, out String ReturnMessage)
{
processCMD("cmd.exe", arguments, out ReturnMessage);
}
[SqlProcedure]
public static void CmdShellBridgeXCOPY(string arguments, out String ReturnMessage)
{
processCMD("cmd.exe", arguments, out ReturnMessage);
}
[SqlProcedure]
public static void CmdShellBridgeDEL(string arguments, out String ReturnMessage)
{
processCMD("cmd.exe", arguments, out ReturnMessage);
}
[SqlProcedure]
public static void CmdShellBridgeNETUSE(string arguments, out String ReturnMessage)
{
processCMD("cmd.exe", arguments, out ReturnMessage);
}
[SqlProcedure]
public static void CmdShellBridgeMOVE(string arguments, out String ReturnMessage)
{
processCMD("cmd.exe", arguments, out ReturnMessage);
}
[SqlProcedure]
public static void CmdShellBridgeCOPY(string arguments, out String ReturnMessage)
{
processCMD("cmd.exe", arguments, out ReturnMessage);
}
[SqlProcedure]
public static void CmdShellBridgeBLAT(string arguments, out String ReturnMessage)
{
processNotCMD("D:\\EMailer\\blat.exe", arguments, out ReturnMessage);
}
[SqlProcedure]
public static void CmdShellBridgeROBOCOPY(string arguments, out String ReturnMessage)
{
processNotCMD("ROBOCOPY", arguments, out ReturnMessage);
}
[SqlProcedure]
public static void CmdShellBridgeRD(string arguments, out String ReturnMessage)
{
processCMD("cmd.exe", arguments, out ReturnMessage);
}
private static void processCMD(string fileName, string arguments, out String ReturnMessage)
{
try
{
Process proc = new Process();
proc.StartInfo.FileName = fileName;
proc.StartInfo.Arguments = arguments;
proc.StartInfo.UseShellExecute = true;
proc.Start();
proc.WaitForExit();
ReturnMessage = "OK";
}
catch (Exception ex)
{
ReturnMessage = ex.Message;
}
}
private static void processNotCMD(string fileName, string arguments, out String ReturnMessage)
{
try
{
Process proc = new Process();
proc.StartInfo.FileName = fileName;
proc.StartInfo.Arguments = arguments;
proc.Start();
proc.WaitForExit();
ReturnMessage = "OK";
}
catch (Exception ex)
{
ReturnMessage = ex.Message;
}
}
}
}
在存储过程中,我们使用此过程,如下例所示:
set @execcommand = ' \c bcp ' + @CSSdbname+'.BankCardtrxGPEtemp in '+@importdir + @Kfilename +' -c -S'+@CSSserver+' -r \n -T -C 1250 -e '+@importdir+'bcp.error -m 1000 >NUL'
declare @sResult nvarchar(max)
exec dbo.CmdShellBridgeBCP @execcommand, @sResult OUTPUT
如果我尝试执行此操作,结果为“OK”,但事实上没有什么是正常的,因为使用的bcp命令不会导入任何内容。 如果我尝试使用一些dos命令,例如dir,del,mkdir,结果也是如此。 结果还可以,但事实上并没有执行任何事情。
我的程序集权限集设置为Unrestricted。 也许问题是我必须在我的命令中使用网络共享文件夹? 当我使用mkdir和本地文件夹时,它可以正常工作。
但在共享文件夹中,我拥有完全权限。