Невозможно ссылаться на пути UNC при использовании wscript.shell из сценария ASP? - PullRequest
4 голосов
/ 19 июля 2010

У меня проблема с выполнением команды из командной строки через сценарий ASP с использованием объекта wscript.shell.

Вот мой код:

inPath = server.mappath("/connect/dev_f_fusion3/video/6EA63679C27E48538D79F7C7295201CF/6EA63679C27E48538D79F7C7295201CF.mov")
outPath = server.mappath("/connect/dev_f_fusion3/video/6EA63679C27E48538D79F7C7295201CF\6EA63679C27E48538D79F7C7295201CF.flv"
outPath = "\\webdev2\SVC\streams\dev_f_fusion3\6EA63679C27E48538D79F7C7295201CF.flv"

dim cmd
dim wshell
dim wffm

cmd = """C:\Program Files\ffmpeg\ffmpeg.exe"" -i """ & inPath & """ -ar ""22050"" -ab ""32"" -f ""flv"" -s ""320x240"" """ & outPath & """"
set wshell  = server.createobject("wscript.shell")
set wffm = wshell.exec(cmd)

set wffm = nothing
set wshell = nothing

Как вы можетевидите, я определил переменную outPath дважды в качестве примера, чтобы вы мне помогли.С первым присваиванием outPath объект wscript.shell выполняется просто отлично, однако со вторым присваиванием outPath он завершается неудачно, и я полагаю, что он как-то связан с путем UNC, который я указал как outPath.

Разрешено ли объекту wscript.shell доступ к UNC-путям?Если да, то где я могу изменить его, чтобы он им позволил?

Спасибо за помощь!

Ответы [ 3 ]

2 голосов
/ 26 июля 2010

Похоже, здесь есть два потенциальных источника проблемы: 1. вопросы, связанные с запуском нового процесса и доступом этого процесса к общему ресурсу UNC 2. вопросы, связанные с разрешениями, независимо от того, используется ли новый процесс для доступа к общему ресурсу UNC

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

<%
dim filesys, filetxt
Const ForReading = 1, ForWriting = 2, ForAppending = 8 
Set filesys = CreateObject("Scripting.FileSystemObject")
Set filetxt = filesys.OpenTextFile("\\webdev2\SVC\streams\dev_f_fusion3\testfile.txt", ForReading, True) 
Response.Write (filetxt.ReadAll())
filetxt.Close 
%> 

Если это не поможет, значит, ваша проблема, вероятно, относительно проста: ваш сайт не имеет доступа к удаленному ресурсу. Чтобы исправить это, проще всего было бы использовать анонимную аутентификацию и выбрать анонимного пользователя с доступом к общему ресурсу. Вот учебник , объясняющий, как это сделать. Обязательно отключите встроенную аутентификацию Windows, как рекомендует учебник!

Также убедитесь, что вы очень осторожны с тем, как вы обрабатываете и избегаете пользовательского ввода, который преобразуется в ваш путь EXE, поскольку вы действительно не хотите, чтобы злонамеренный посетитель мог запускать произвольный код в вашей сети! В идеале, вы никогда не должны создавать какую-либо часть исполняемого пути или аргументов командной строки непосредственно на основе пользовательского ввода, но только косвенно (например, использовать пользовательский ввод для поиска известного безопасного имени файла в БД, а затем использовать этот результат БД на вашем пути).

Существуют и другие способы (кроме анонимной авторизации под пользователем домена), чтобы включить удаленный доступ, включая делегирование, использование базовой аутентификации через HTTPS и т. Д. Дайте мне знать, если вы не можете использовать анонимную аутентификацию, и я могу поможет вам найти правильную альтернативу.

Однако, если описанный выше тест доступа к файлу завершится успешно, ваша проблема усложняется - это означает, что код, работающий внутри процесса IIS, имеет правильный доступ, но порожденный процесс не наследует возможность доступа к удаленным ресурсам.

ОБНОВЛЕНИЕ: согласно вашему комментарию, приведенному ниже, вы обнаружили, что проблема в том, что порожденный процесс запущен с неверной учетной записью пользователя. Это можно исправить, вызвав некоторые интерфейсы Win32 API напрямую, и есть также решения .NET, но если вы не чувствуете себя комфортно за пределами VBScript, это может быть больше, чем вы захотите принять прямо сейчас.

Можете ли вы скопировать файл с удаленного компьютера во временный файл на локальном компьютере, затем запустить FFMPEG.EXE, затем (если вам нужно) сохранить изменения на удаленном сервере и, наконец, удалить временный файл?

Если вы сможете это сделать, это позволит избежать проблемы, описанной в этом потоке, упростит обнаружение других проблем (например, сбой сети) внутри кода ASP, а не скрыт внутри FFMPEG.EXE, и может даже повысить производительность. в зависимости от того, насколько эффективно FFMPEG.EXE обрабатывает удаленный доступ к файлам.

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

<%
dim filesys, filetxt
Const ForReading = 1, ForWriting = 2, ForAppending = 8 
Set filesys = CreateObject("Scripting.FileSystemObject")

Const TemporaryFolder = 2
Dim tfolder, tname, tfile
Set tfolder = fso.GetSpecialFolder(TemporaryFolder)
tname = tFolder & "/" & fso.GetTempName

Dim remoteFilename
remoteFilename = "\\webdev2\SVC\streams\dev_f_fusion3\testfile.txt"

Const OverwriteExisting = True
filesys.CopyFile  remoteFilename, tName, OverwriteExisting    
%> 

Я считаю, что этот подход с локальным копированием обеспечит вам максимальную надежность и, вероятно, лучшую производительность, поскольку копирование целых файлов по сетевому соединению обычно выполняется быстрее, чем чтение одного блока за раз. Кроме того, ваша обработка ошибок и отладка будут проще, если наиболее вероятные сбои операций (сетевой доступ к файлам) происходят внутри вашего кода, а не чьего-либо другого.

Но если вы уверены, что вызов вашего EXE-файла с UNC-доступом необходим, вам лучше всего создать COM-компонент с использованием C ++, C # или VB, который заменит Wsh.Shell в качестве средства запуска процесса. Я бы рекомендовал создавать компонент с использованием языка .NET вместо собственного C ++, потому что вызовы будут намного проще. Если вы делаете это в .NET, вы захотите использовать класс System.Diagnostics.Process для запуска вашего процесса, используя класс ProcessStartInfo, чтобы указать имя пользователя / пароль для использования ,

Вы также можете попробовать создать соединение, используя WNetAddConnection2, а затем запустить свой процесс, используя CreateProcess или аналогичный Win32 API (или его аналог .NET), но вам может потребоваться поигратьсянайти правильные параметры для использования.

Другими словами, это нетривиально сложная задача для создания этой оболочки.Ваша лучшая ставка, вероятно, ваш текущий обходной путь.

1 голос
/ 23 июля 2010

Было бы полезно, если бы вы опубликовали конкретную ошибку, которую вы получаете. Какой тип аутентификации используется для этого запроса? Если вы используете анонимный доступ, то вам нужно использовать доменного пользователя или пользователя или использовать локальную учетную запись с тем же именем пользователя и паролем на целевом сервере.

...