Наиболее эффективно это можно сделать с помощью объектов OLE Automation , работа с которыми осуществляется при помощи:
sp_OACreate, sp_OAGetProperty, sp_OASetProperty, sp_OAMethod, sp_OAGetErrorInfo, sp_OADestroy (подробное описание есть в http://technet.microsoft.com/ru-ru/library/ms203721(sql.90).aspx).
Рабочий пример процедуры (была написана для сохранения zip-архивов, хранящихся в базе):
Код CREATE PROCEDURE dbo.SaveRequestDataAsFile (
@FileName varchar(1024) --имя файла
,@FilePath varchar(1024) --путь файла
,@ReqID --некое условие на таблицу
)
AS
BEGIN
DECLARE
@Stream integer,
@Buffer varbinary(4096),
@Size integer,
@Pos integer,
@BufSize integer,
@FileNameLocal varchar(1024),
@HR integer
if RIGHT(@FilePath, 1)<>'&# 092;' begin set @FilePath=@FilePath+'&# 092;' end
set @FileNameLocal = @FilePath + @FileName
SET @BufSize = 4096
EXEC @HR = sp_OACreate 'ADODB.Stream',@Stream OUT
if @HR<>0
begin
--обработка ошибки создания объекта
EXEC [dbo].[sp_displayoaerrorinfo] @Stream ,@HR
end
EXEC @HR = sp_OASetProperty @Stream,'Type',1 -- binary
EXEC @HR = sp_OASetProperty @Stream,'Mode',3 -- write|read
EXEC @HR = sp_OAMethod @Stream,'Open'
S_elect
@Size = DATALENGTH(SrvRequests.RequestData)
FROM SrvRequests WHERE SrvRequests.RequestID = @ReqID
Set @Pos=0
WHILE @Pos < @Size BEGIN
SET @BufSize = CASE WHEN @Size - @Pos < 4096 THEN @Size - @Pos ELSE 4096 END
S_elect @Buffer = substring(SrvRequests.RequestData ,@Pos+1, @BufSize)
from SrvRequests where SrvRequests.RequestID = @ReqID
EXEC @HR = sp_OAMethod @Stream, 'Write', NULL, @Buffer
SET @Pos = @Pos + @BufSize
END
EXEC @HR = sp_OAMethod @Stream,'SaveToFile',null, @FileNameLocal,2
EXEC @HR = sp_OAMethod @Stream,'Close'
EXEC @HR = sp_OADestroy @Stream
END
Рекомендуется создать еще пару процедур для внятного описания ошибок в случае их возникновения
Код CREATE PROCEDURE sp_hexadecimal
@binvalue varbinary(255),
@hexvalue varchar(255) OUTPUT
AS
DECLARE @charvalue varchar(255)
DECLARE @i int
DECLARE @length int
DECLARE @hexstring char(16)
S_elect @charvalue = '0x'
S_elect @i = 1
S_elect @length = DATALENGTH(@binvalue)
S_elect @hexstring = '0123456789abcdef'
WHILE (@i <= @length)
BEGIN
DECLARE @tempint int
DECLARE @firstint int
DECLARE @secondin t int
S_elect @tempint = CONVERT(int, SUBSTRING(@binvalue,@i,1))
S_elect @firstint = FLOOR(@tempint/16)
S_elect @secondin t = @tempint - (@firstint* 16)
S_elect @charvalue = @charvalue +
SUBSTRING(@hexstring, @firstint+1, 1) +
SUBSTRING(@hexstring, @secondin t+1, 1)
S_elect @i = @i + 1
END
----------------------------------------------------------------------
CREATE PROCEDURE sp_displayoaerrorinfo
@object int,
@hresult int
AS
DECLARE @output varchar(255)
DECLARE @hrhex char(10)
DECLARE @hr int
DECLARE @source varchar(255)
DECLARE @description varchar(255)
PRINT 'OLE Automation Error Information'
EXEC sp_hexadecimal @hresult, @hrhex OUT
S_elect @output = ' HRESULT: ' + @hrhex
PRINT @output
EXEC @hr = sp_OAGetErrorInfo @object, @source OUT, @description OUT
IF @hr = 0
BEGIN
S_elect @output = ' Source: ' + @source
PRINT @output
S_elect @output = ' Description: ' + @description
PRINT @output
END
ELSE
BEGIN
PRINT ' sp_OAGetErrorInfo failed.'
RETURN
END
Код 1C v 8.х Попытка
ЗагрузитьВнешнююКомпоненту("scanopos.dll")
Исключение
Сообщить("Ошибка загрузки внешней компоненты!");
КонецПопытки;
Попытка
// Получить объект компоненты.
Объект = Новый("AddIn .Scanner");
Исключение
Сообщить("Не удалось создать объект внешней компоненты");
КонецПопытки;
Код 1C v 7.x //в качестве аргумента "Значение" в функцию передаётся имя файла внешней компоненты
//функция возвращает "1", если загрузка выполнена успешно, или "0", если внешнюю компоненту загрузить не получилось
Функция гВнешняяКомпонента_Загрузить(Значение) Экспорт
Состояние("Загрузка компоненты: "+Значение);
Если ЗагрузитьВнешнююКомпоненту(Значение)=1 Тогда
Возврат(1);
Иначе
Сообщить("Ошибка при загрузке компоненты: "+Значение,"!");
Возврат(0);
КонецЕсли;
КонецФункции
//этот код можно разместить в локальном модуле, в котором требуется использовать внешнюю компоненту
Если гВнешняяКомпонента_Загрузить("v7plus.dll")=0 Тогда
Возврат;
КонецЕсли;
При загрузке полезно проверять, а есть ли в наличии указанный файл DLL (к сожалению, этого не делает сам движок 1С:Предприятие 7.7).
Код 1C v 7.x имяф="e:\Events\Events.dll";
Если фс.СуществуетФайл(имяф)=0 Тогда
Сообщить("Файл не найден: "+имяф,"!");
КонецЕсли;
Если ЗагрузитьВнешнююКомпоненту(имяф)=0 Тогда
Сообщить("Ошибка загрузки внешней компоненты: "+имяф);
КонецЕсли;
vk=СоздатьОбъект("Addin .Events");