Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > MS SQL Server > Доступ к файлам из внешних программ - SQL Server


Автор: Alex870 29.3.2016, 09:16
Доброго времени суток всем.
Столкнулся с такой проблемой:
В хранимке загружается Excel в таблицу, но перед этим надо его немного поправить.
Для этого решил написать скрипт на vbs. Проверил, из командной строки скрипт работает, а вот внутри процедуры:


SQL
DECLARE @query VARCHAR(255) = 'cscript c:\myscript.vbs c:\myexcel.xlsx'
 
EXEC xp_cmdshell @query 
 


Выдает ошибку, что не может получить доступ к файлу c:\myexcel.xlsx.

Решил, что это особенности работы cscript, написал программку на delphi, делающую то же самое.
Ситуация сохраняется, из командной строки программка отрабатывает, а из хранимки - не может получить доступ к файлу excel.
Что может быть?
Всё запускается под админом сервера. 

Автор: Akina 29.3.2016, 10:06
Цитата(Alex870 @  29.3.2016,  10:16 Найти цитируемый пост)
Всё запускается под админом сервера.

Что, и процесс MS SQL Server тоже? можно, я буду сомневаться?

Поправь просто права доступа к файлу, дай для группы аутентифицированных пользователей (или для группы "Все") доступ на хотя бы чтение файла (ну и содержимого каталога есссно).

Для проверки - запусти из того же скрипта командный процессор и посмотри, от имени какой учётки он работает.

Автор: Alex870 29.3.2016, 13:10
Цитата

Что, и процесс MS SQL Server тоже? можно, я буду сомневаться?

Конечно можно smile. Процесс sqlservr.exe запущен от имени админа. Он (админ) имеет доступ ко всем файлам.
Но!... 
Я могу приведенным выше способом обратиться к любому файлу на сервере. Могу его (файл) удалить например:

SQL
DECLARE @query VARCHAR(255) = 'del /q c:\myexcel.xlsx'
 
EXEC xp_cmdshell @query 


А вот если я вызываю какую-то внешнюю программу, например cscript, которая в свою очередь пытается открыть какой-то файл, то у неё доступа к файлу уже нет.
При этом сама программа (или скрипт) запускаются.

С cmd.exe проверил. Сделал его запуск из скрипта. Cmd.exe запустился под админом. На папку доступ "Всем" тоже не помог. Думаю здесь дело в настройках именно самого MS SQL.
Я пробовал аналогичную операцию сделать на 3-х разных серверах, естественно файлы там клал в разные каталоги. Везде результат одинаковый.

Автор: Alex870 29.3.2016, 13:28
Попробуйте пожалуйста у себя.
Сделайте вот такой простейший скрипт. Он заполняет в первой строке Excel первые сорок ячеек значениями.

Код

dim fPath,objExcel,objWorkBook,Sheet,i

fPath=WScript.Arguments.itm(0)

set objExcel=CreateObject("Excel.Application")
set objWorkBook=objExcel.Workbooks.Open(fPath)
set Sheet=objExcel.WorkBooks(1)

for i= 1 to 40
objExcel.ActiveSheet.Cells(1,i) = "F"&i
next

objExcel.DisplayAlerts = False
objExcel.ActiveWorkBook.SaveAs fPath
objExcel.DisplayAlerts = True
objExcel.Quit


Кладем его например в c:\1\script.vbs (куда доступ есть всем)
Туда же кладем файл c:\1\excel.xlsx

Пробуем из командной строки - всё должно работать, в excel.xlsx в первой строке появляются значения.
А теперь пробуем вот это с сервера:

SQL
DECLARE @query VARCHAR(255) = 'cscript c:\1\script.vbs c:\1\excel.xlsx'
 
EXEC xp_cmdshell @query


Если у кого-то это отработает -напишите пожалуйста.
В смысле SQL запрос пройдет без ошибок, но вернет он информацию о том, что не удалось получить доступ к файлу c:\1\excel.xlsx

Автор: Akina 29.3.2016, 13:30
Цитата(Alex870 @  29.3.2016,  14:10 Найти цитируемый пост)
если я вызываю какую-то внешнюю программу, например cscript, которая в свою очередь пытается открыть какой-то файл, то у неё доступа к файлу уже нет.

Тэк-с... постарайтесь получить более полную информацию об ошибке - хотя бы её расширенный код. Совсем хорошо, если запустите icacls и получите сведения об эффективных правах на нужный файл.


Автор: Alex870 29.3.2016, 14:08
Да никакого кода нет. Запрос в MS SQL выполняется без ошибок.
Но, как результат, выводит сообщение "Приложению MS Excel не удалось получить доступ к файлу (и имя файла)"
Попробуйте у себя запустить скрипт из моего предыдущего поста, Вы сами всё увидите.

Автор: Akina 29.3.2016, 14:34
Цитата(Alex870 @  29.3.2016,  15:08 Найти цитируемый пост)
выводит сообщение "Приложению MS Excel не удалось получить доступ к файлу (и имя файла)"

КТО выводит это сообщение? Cscript? Значит, отлаживайте скрипт. Дробите цепочки, выводите всё в дебаг-инфо (хоть msgbox-ами). Код поправьте (строка 6, например - нет у Excel.Application коллекции Workbook, есть коллекция Workbooks). В итоге ошибка должна быть максимально точно локализована. Как минимум.

Цитата(Alex870 @  29.3.2016,  15:08 Найти цитируемый пост)
Попробуйте у себя запустить

Ну нет у меня сейчас в доступе MS SQL, на котором я бы мог это проделать.

Автор: Alex870 29.3.2016, 15:23
Цитата

КТО выводит это сообщение? Cscript? Значит, отлаживайте скрипт. Дробите цепочки, выводите всё в дебаг-инфо (хоть msgbox-ами). Код поправьте (строка 6, например - нет у Excel.Application коллекции Workbook, есть коллекция Workbooks). В итоге ошибка должна быть максимально точно локализована. Как минимум.

Это сообщение выводит скрипт, запущенный xp_cmdshell. Если скрипт запустить из командной строки он работает отлично. На счет ошибки в коде - виноват, я здесь (на форуме) его набирал вручную, а не копировал свой, т.к. не могу его перенести с сервера на машину, имеющую доступ в инет. Как же мне точно локализовать ошибку, если скрип рабочий (100%) и ошибку я вижу, но при запуске его из под xp_cmdshell, а уж как в нем локализовать - не знаю. Вообще думал, что xp_cmdshell запускается под тем пользователем, под которым запущен SQL сервер. Это же подтвердил эксперимент с cmd.exe, который Вы мне посоветовали. Однако запуск другой программы это одно, а доступ на запись к файлам - другое.

Автор: Akina 29.3.2016, 15:41
Цитата(Alex870 @  29.3.2016,  16:23 Найти цитируемый пост)
как в нем локализовать - не знаю

Раздробить скрипт на неделимые куски, и разбавить выводом отладочной информации.
Например, начало скрипта может выглядеть так:

Код

dim fPath,objExcel,objWorkBook,Sheet,i

fPath=WScript.Arguments.item(0)
    WScript.Echo "fPath = "; fPath

set objExcel=CreateObject("Excel.Application")
    WScript.Echo "Excel.Application создан"

' set objWorkBook=objExcel.Workbooks.Open(fPath)
set objWorkBook=objExcel.Workbooks
    WScript.Echo "Коллекция Workbooks получена"
set objWorkBook=objWorkBook.Open(fPath)
    WScript.Echo "Книга "; fPath; " открыта"

set Sheet=objExcel.WorkBooks(1)
    WScript.Echo "Получена книга "; Sheet.Name
...

и так далее... и смотрим, что сыплется в консолю.

Добавлено через 1 минуту и 52 секунды
Кстати, мне вот не нравится обращение к книге по номеру в коллекции. Особенно с учётом того, что ссылка на неё УЖЕ есть в переменной objWorkBook.

Автор: Alex870 29.3.2016, 16:05
Попробовал, до set objWorkBook=objWorkBook.Open(fPath) всё отрабатывает корректно (в MS SQL). после скрипт выдает ошибку которую описывал 2 поста назад. В смысле запрос exce... выводит таблицу отчета о работе внешнего модуля, в которой указано, что Excel не смог получить доступ к файлу и написано имя и путь к файлу xlsx

Автор: Akina 29.3.2016, 16:18
Цитата(Alex870 @  29.3.2016,  17:05 Найти цитируемый пост)
после скрипт выдает ошибку

То есть к ошибке приводит попытка выполнить оператор
Код

set objWorkBook=objWorkBook.Open(fPath)

И сообщение выдаётся именно cscript-ом...
При этом - процесс EXCEL.Application запущен? проверь... влепи в скрипте минутную паузу перед этой строкой и посмотри дерево процессов.

Автор: Alex870 29.3.2016, 16:33
Поставил паузу. В процессах появляются cmd.exe и Excel.exe запущенные под администраторской учеткой.

Автор: Alex870 30.3.2016, 16:33
Проблему решил!!!
Вот описание её решения:
https://social.msdn.microsoft.com/Forums/en-US/b81a3c4e-62db-488b-af06-44421818ef91/excel-2007-automation-on-top-of-a-windows-server-2008-x64

Ну кто бы мог догадаться до такого!!!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)