私はいくつかのWebを検索してきましたが、XP_CMDSHELLから結果を取得する唯一の方法はそれらを一時テーブルに格納することです。本当に簡単な方法はありませんか?
Experts Exchangeから:
いいえ、xp_cmdshellはexeから情報を返しません。実行するためにmasterデータベースにいない場合は、次の構文を使用する必要があります。 master..xp_cmdshell。 masterデータベースでこのプロシージャを実行するためのアクセス許可をユーザーに与える必要があります。それはそれを呼び出したプロセスに情報を返すことができないので、あなたはあなたのexeに情報をそれ自身に挿入させる必要があります。
そして...
@resultはxp_cmdshellからの戻り値のみを取得しますが、テーブルに直接挿入することでコマンドの結果をキャプチャできる場合があります...次のようなもの:
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
xp_cmdshell
からSTDOUT/STDERRフィードバックを取得する簡単な方法はありません。少なくとも1つの代替案がありますが、これほど簡単には分類できません。
コマンドの出力をコマンドの一部としてテキストファイルにリダイレクトし、OPENROWSET
を使用してテキストファイルを読み取ることができます。
ところで、上記のスクリプトに少なくとも1つのエラーがあります。 xp_cmdshell
のドキュメントには、コマンド出力をnvarchar(255)として返すことが記載されています。
また、一時テーブルにはID列が必要です。それ以外の場合、結果が正しい順序で表示されないことがあります。
...
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
これが私がやったことです...私は今日チェックして、あなたの反応を見ました。私は昨日リアルタイムで緊張していたので、確認済みの作業ソリューションであったため、一時テーブルの方向で作業を開始しました。クリップボードとして使用しているだけなので、内部で物事を処理するのと同じくらい簡単に、または簡単に思えたため、一時ファイルを作成しないようにしました。必要に応じて行う1つの変更は、一時テーブル名に一意の番号を追加することです。ただし、これらが同時に処理されることを心配する必要はないと思います(つまり、ストアドプロシージャの2回目の呼び出しで一時テーブルがダンプされる可能性があります) cmdシェルが実行されています)。わかります...
ストアドプロシージャを呼び出し(さらに下を見て)、パスワードを暗号化します。以下のコードは、それで十分なものになるように変更されています。これは基本的にパスワードオフロード/同期ソリューションであるため、実際には手動でパスワードを設定していません。
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
暗号化ストアドプロシージャを次に示します。戻りコードが失敗を示す理由を推測せずにプログラムが正しく実行されることを確認するために、@@ rowsetをチェックする追加のコード(ここにはリストされていません)があります。 1より大きい場合は、問題が発生したことを知っているので、理由を示さずに失敗したことを示すメッセージを作成する代わりに、実際のエラーを(必要に応じて)キャプチャして返すことができます。この方法で現実的にチェックすることは、デバッグや将来のレビューのためにエラーを別のテーブルに記録する場合に役立ちます。このようなエラーをエンドユーザーに送り返さないため、リアルタイムの解釈には役立ちません。
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