xp_cmdshell habilitar enable sql-server stored-procedures xp-cmdshell

sql-server - habilitar - xp_cmdshell sql server



Obtenga resultados de XP_CMDSHELL (2)

He estado buscando en la web y parece que la única forma de obtener los resultados de XP_CMDSHELL es almacenarlos en una tabla temporal. ¿No hay realmente una manera más fácil?

Del intercambio de expertos:

No, xp_cmdshell no devolverá ninguna información del exe. y debe usar la siguiente sintaxis si no está en la base de datos maestra para ejecutarla. master..xp_cmdshell. Deberá dar permiso a su usuario para ejecutar este procedimiento en la base de datos maestra. Deberá hacer que su exe inserte la información en sí mismo porque no puede devolver información al proceso que lo llamó.

Y...

Si bien @result solo obtiene el valor de retorno de xp_cmdshell, es posible que pueda capturar los resultados del comando insertándolo directamente en una tabla ... algo como esto:

ymmv ...

set nocount on declare @filepath varchar(255), @cmd varchar(255), @rc int select @filepath = ''c:/temp/' select @cmd = ''dir '' + @filepath + ''~*.tmp'' create table #output (output varchar(255) null) insert #output exec @rc = master..xp_cmdshell @cmd select * from #output where output is not null drop table #output


No hay una manera más fácil de capturar comentarios STDOUT / STDERR de xp_cmdshell ; hay al menos una alternativa pero no podría clasificarse como más fácil:
Sería posible redirigir la salida del comando a un archivo de texto como parte del comando, luego leer el archivo de texto usando OPENROWSET .

Por cierto, hay al menos un error en el script publicado anteriormente. Los documentos para xp_cmdshell indican que devuelve el resultado del comando como nvarchar (255).
Además, la tabla temporal debe tener una columna de identidad; de lo contrario, es posible que los resultados no se muestren en el orden correcto:

... create table #output (id int identity(1,1), output nvarchar(255) null) insert #output (output) exec @rc = master..xp_cmdshell @cmd select * from #output where output is not null order by id drop table #output


Esto es lo que terminé haciendo ... Hoy volví y vi tu respuesta. Ayer tuve una crisis en tiempo real, así que comencé a trabajar en la dirección de la mesa de trabajo temporal, ya que era una solución de trabajo confirmada. Había elegido evitar crear los archivos temporales ya que me parecía fácil o más fácil de manejar internamente, ya que realmente lo estoy usando como un portapapeles. El único cambio que haré si es necesario es agregar un número único al nombre de la tabla temporal aunque no creo que tenga que preocuparme de que se procesen simultáneamente (lo que significa que una segunda llamada del procedimiento almacenado podría volcar la tabla temporal mientras el shell cmd se está ejecutando). Ya veremos...

Llamo a un procedimiento almacenado (mire más abajo) para encriptar la contraseña: el código a continuación ha sido modificado para que sea autosuficiente. En realidad, no estoy configurando la contraseña manualmente, ya que básicamente se trata de una solución de descarga / sincronización de contraseñas.

DECLARE @password VARCHAR(64) DECLARE @encryptedpass VARCHAR(128); SET @password = ''1234'' BEGIN TRY EXEC pass_encrypt @password, @encryptedpass = @encryptedpass OUTPUT END TRY BEGIN CATCH PRINT ''ERROR'' RETURN END CATCH SELECT @encryptedpass

Aquí está el procedimiento almacenado encriptado: Para verificar y asegurarse de que el programa se ejecuta correctamente sin tener que adivinar por qué el código de retorno indica falla, tengo un código adicional (no listado aquí) que verifica @@ rowset. Si es más de 1, sé que algo salió mal y puedo capturar / devolver el error real (si lo desea) en lugar de solo crear mi propio mensaje que dice que falló sin dar ninguna indicación de por qué. La comprobación realista de esta manera es más útil para la depuración o para registrar el error en otra tabla para su futura revisión, no para la interpretación en tiempo real, ya que no voy a enviar un error como ese al usuario final.

USE [**my_database**] GO SET ANSI_NULLS OFF GO SET QUOTED_IDENTIFIER OFF GO CREATE procedure [dbo].[pass_encrypt] ( @password VARCHAR(64), @encryptedpass VARCHAR(128) OUTPUT ) AS BEGIN DECLARE @command VARCHAR(200) SET @command = **''C:/encrypt_pwd.exe**'' + '' "'' + @password + ''"'' BEGIN IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N''[dbo].[#temppass]'') AND type in (N''U'')) DROP TABLE [dbo].[#temppass] BEGIN TRY CREATE TABLE #temppass(encrypted varchar(1000)) INSERT INTO #temppass execute xp_cmdshell @command IF (@@ROWCOUNT > 1) BEGIN SET @encryptedpass = NULL DROP TABLE #temppass RETURN END ELSE BEGIN SELECT @encryptedpass = encrypted FROM #temppass END --SELECT @encryptedpass END TRY BEGIN CATCH SET @encryptedpass = NULL DROP TABLE #temppass RETURN END CATCH --SELECT encrypted FROM #temppass DROP TABLE #temppass END END