Как я могу использовать общий диалог Сохранить как из VBScript?
Я хотел бы, чтобы мой VBScript отображал диалоговое окно "Сохранить как" в Windows, но я не мог выяснить, как это сделать.
Используя этот код:
Dim sfd
Set sfd = CreateObject("UserAccounts.CommonDialog")
sfd.ShowOpen
Я могу получить диалог открытия, но нет ShowSave
метод для этого объекта (как и для аналогичного объекта в Visual Basic, не являющийся сценарием).
Я искал Stackru и гуглил на "[vbscript] диалоговое окно сохранения" (и с "Windows Script Host"), но я нашел только темы о доступе к общим диалогам с веб-страниц и о решении для BrowseForFolder
диалоговое окно и ничего о вызове диалога сохранения.
На самом деле, я могу использовать диалог "Открыть" для своих целей, потому что все, что мне нужно, это имя файла... но, поскольку я хотел бы сохранить что-то по выбранному пути, "Сохранить как" в строке заголовка диалогового окна будет быть более подходящим
8 ответов
Я могу однозначно сказать, что не существует решения, позволяющего отобразить диалоговое окно "Сохранить как" из VBScript в версиях Windows, отличных от XP, не полагаясь на некоторые внешние зависимости, которые необходимо установить и зарегистрировать самостоятельно. Помимо очевидного вмешательства, которое это вызывает в отношении простого развертывания вашего сценария путем перетаскивания, оно также поднимает целый ряд других проблем, связанных с безопасностью и разрешениями, в частности, обходя UAC на компьютере клиента для установки. и зарегистрировать DLL зависимостей.
Решения, которые были предложены до сих пор, основаны либо на DLL-файле, который так же включается в Windows XP, вызывая диалоговое окно "Сохранить как" из панели управления учетными записями пользователей Windows XP и / или устанавливая часть программного обеспечения только для него. оставить позади MSComDlg
DLL после его удаления можно использовать из VBScript. Ни одно из этих решений действительно не удовлетворяет вышеуказанным требованиям, и ни один из предоставленных ответов даже не рассматривал возможные препятствия безопасности, которые могли бы возникнуть с их предлагаемыми решениями, как я упоминал выше.
И так как вы не можете делать вызовы напрямую в Windows API (который очень удобно включает в себя только такой диалог Сохранить как) из VBScript (не только потому, что это представляет угрозу безопасности, но также из-за слабости VBScript [отсутствие?] печатать), это в значительной степени оставляет любого желающего сделать это на морозе. Кроме того, неспособность совершать вызовы API также исключает использование любых хаков, таких как вызовы. SetWindowText
изменить заголовок диалогового окна Открыть, как предложено в вопросе.
Я понимаю, что это не тот ответ, которого все хотели. Это даже не тот ответ, который я хотел получить. Но, увы, это правильный ответ.
Тем не менее, вот несколько возможных обходных путей:
Если вы склонны принять какой-либо из уже предложенных ответов, вы уже решили ввести внешнюю зависимость от файла DLL в свое развертывание VBScript. После того, как вы совершили этот скачок, зачем беспокоиться о "заимствовании" или хищении DLL из какого-либо другого источника? Просто сделай однажды себя. Это тривиально обернуть встроенные общие диалоговые функции, предоставляемые API-интерфейсом Windows, в библиотеку ActiveX DLL с помощью Visual Basic 6, которая затем может быть вызвана вашим VBScript. Риски минимальны, поскольку можно ожидать, что практически в любой современной версии Windows уже установлена среда выполнения Visual Basic, и, поскольку вы, вероятно, уже знаете VBScript, создание некоторого кода в VB 6 не должно быть очень трудным делом. Вы можете включить любые пользовательские функции, которые вы хотите, и, что наиболее важно, вы будете под полным контролем. Вам не придется беспокоиться об удалении других приложений, удаляющих DLL, которая требуется вашему сценарию, вам не придется возиться с установкой и удалением какого-либо случайного устаревшего приложения, и вам не придется просто скрестить пальцы и надеяться. Мы, программисты, знаем, что это никогда не будет хорошим вариантом.
И да, я рекомендую на самом деле обернуть общие диалоговые функции, предоставляемые Windows API, а не полагаться на общий диалог OCX (
comdlg32.ocx
) предоставляется Visual Basic. У него есть свои проблемы в Windows 7, и он не даст вам великолепных новых диалогов, которые теперь предоставляют более поздние версии Windows. Отличная статья, объясняющая все, что вам нужно знать об API Open and Save Common Dialog и о том, как их использовать в VB 6, доступна здесь, на VBnet. Конечно, если вы действительно хотите сделать все возможное, есть множество интересных вещей, которые вы можете сделать с помощью обычных диалогов, все они документированы (с кодом!) Здесь, на VB Accelerator.Но теперь, когда я убедил вас всех написать ActiveX DLL в VB 6, которая включает в себя функциональность общего диалога для использования в вашем VBScript, я должен задать вопрос: зачем останавливаться на достигнутом? После того, как вы сделали прыжок для написания некоторого кода в VB 6, почему бы не переместить весь ваш код в VB 6? Конечно, это "мертвый" язык и все такое, но VBScript тоже не слишком активен. Как я уже упоминал ранее, разница в синтаксисе практически равна нулю, и кривая обучения для разработчика VBScript примерно такая незначительная, как можно было ожидать. Кроме того, вы получаете все преимущества полной IDE, статической типизации, (немного) лучшей обработки ошибок, бла-бла-бла. Ах да, и возможность совершать прямые вызовы функций Windows API. Единственным реальным преимуществом VBScript является его повсеместное распространение, но прошли годы с тех пор, как вы могли найти компьютер без установленной среды выполнения VB. Не говоря уже о том, что если вы пишете приложение, для которого требуются общие диалоговые окна, вы, вероятно, вступаете в диалог с вашими пользователями: возможность создания форм с полным VB может начать пригодиться в этот момент. Но, пожалуй, самое большое и самое важное преимущество выбора этого пути заключается в том, что вы избавляете от необходимости регистрировать (или включать) внешнюю "спутниковую" DLL - простое приложение VB 6 будет работать только с EXE на любом компьютере, на котором есть VB установлен во время выполнения, который включен по крайней мере через Windows 7.
И, наконец, в случае, если вы очень взволнованы переходом от скромного VBScript к полнофункциональному VB 6, я чувствую себя обязанным добавить еще один ключ в уравнение: почему бы не перейти полностью к языку, подобному VB.СЕТЬ? Опять же, благодаря.NET Framework, в VB.NET предлагаются всевозможные новые функции, но для того, чтобы приличный разработчик VB/VBScript почувствовал себя комфортно при написании приложений на VB.NET, не потребуется более нескольких недель., Вероятно, у них не будет полного понимания.NET Framework, и они, конечно, не разработают хорошие методы объектно-ориентированного проектирования, но, по крайней мере, они будут двигаться в правильном направлении. Почти все, что вы можете сделать в VBScript (или даже VB 6), вы можете сделать в VB.NET. И вообще, это требует еще меньше суеты, чем раньше, благодаря огромной функциональности, предоставляемой.NET Framework. Недостатком, конечно, является то, что вашему приложению теперь требуется установить.NET Framework на компьютер пользователя, что не так широко распространено, как во время выполнения VB 6 (хотя сейчас оно встречается гораздо чаще, чем даже через несколько лет). тому назад).
Я слышал, вы говорили, что это не обходные пути, которые вы надеялись услышать? Да, я тоже. Я не тот парень, который говорит людям бросить все и выучить новый язык. Если VBScript продолжает работать для вас, пойти на это. Но если вы находитесь в той точке, когда вы начинаете напрягаться при ее ограничениях, возможно, пришло время совершить скачок.
Секрет использования общего диалогового окна из VBScript (или VBA или JScript в этом отношении) заключается в том, что на вашем компьютере должна быть установлена его лицензия. Некоторые инструменты разработки, такие как Visual Basic 6, устанавливают лицензию, но также устанавливаются с помощью бесплатного редактора справки Microsoft HTML (это довольно старое приложение). Интересно то, что если вы устанавливаете, а затем удаляете редактор справки HTML, он оставляет лицензию Common Dialog на месте. По этой причине я считаю, что лицензия является свободно доступной, и поэтому в мой ответ будет включена запись реестра, которую он создает здесь:
В HKLM\Software\CLASSES\Licenses\4D553650-6ABE-11cf-8ADB-00AA00C00905
, установить (Default)
вход в gfjmrfkfifkmkfffrlmmgmhmnlulkmfmqkqj
,
Как только это будет сделано, вы можете создать эти диалоги из VBScript, используя такой код:
Set objDialog = CreateObject("MSComDlg.CommonDialog")
Чтобы запустить диалог сохранения файла, используйте метод ShowSave, как в этом коде:
objDialog.ShowSave
Конечно, у этого объекта есть множество других методов и свойств, и вы, вероятно, захотите настроить соответствующие свойства перед запуском диалога. Например, вы можете установить фильтр файлов, чтобы в диалоговом окне отображались только определенные расширения файлов. Хорошая ссылка на элемент управления на сайте MSDN здесь: http://msdn.microsoft.com/en-us/library/aa259661%28v=vs.60%29.aspx.
Надеюсь это поможет. Дайте знать, если у вас появятся вопросы.
Если у вас есть некоторый уровень контроля над системами, на которых вы будете его развертывать, и можете быть достаточно уверены, что на них установлена либо Visual Studio, либо Microsoft HTML Help, вы можете использовать код, подобный следующему:
function filedialog(filt, def, title, save)
set dialog = CreateObject("MSComDlg.CommonDialog")
dialog.MaxFileSize = 256
if filt = "" then
dialog.Filter = "All Files (*.*)|*.*"
else
dialog.Filter = filt
end if
dialog.FilterIndex = 1
dialog.DialogTitle = title
dialog.InitDir = CreateObject("WScript.Shell").SpecialFolders("MyDocuments")
dialog.FileName = ""
if save = true then
dialog.DefaultExt = def
dialog.Flags = &H800 + &H4
discard = dialog.ShowSave()
else
dialog.Flags = &H1000 + &H4 + &H800
discard = dialog.ShowOpen()
end if
filedialog = dialog.FileName
end function
Кроме того, адаптируя один из других ответов на этот вопрос в код VBScript (спасибо @oddacorn!), Вы должны добавить эту функцию, если не уверены, что у ваших пользователей будет VS или HTML Help. Вызовите эту функцию при запуске программы. Не волнуйтесь, если у вас уже есть ключ; в этом случае это не имеет никакого эффекта. Это должно работать на стандартной учетной записи пользователя без прав администратора.
'Make the MSComDlg.CommonDialog class available for use. Required for filedialog function.
function registerComDlg
Set objRegistry = GetObject("winmgmts:\\.\root\default:StdRegProv")
objRegistry.CreateKey &H80000001, "Software\CLASSES\Licenses\4D553650-6ABE-11cf-8ADB-00AA00C00905"
objRegistry.SetStringValue &H80000001, "Software\CLASSES\Licenses\4D553650-6ABE-11cf-8ADB-00AA00C00905", "", "gfjmrfkfifkmkfffrlmmgmhmnlulkmfmqkqj"
end function
Обратите внимание, что я адаптировал функцию filedialog из "View Source" кода VBScript в HTML здесь; в современных веб-браузерах оказывается, что HTML-код, который они используют для визуализации образцов кода, отображается некорректно (протестировано в IE 8 и Chrome). Но, к счастью, код все еще есть в View Source.
Я обнаружил одну вещь, которая имеет решающее значение для работы в Windows 7 (SP1, полностью исправлен); вы должны установить dialog.MaxFileSize = 256
или вы получите ошибку во время выполнения.
То есть следующий код не работает в Windows 7 SP1, но, вероятно, работает в более старых версиях Windows:
Set x = CreateObject("MSComDlg.CommonDialog")
x.ShowSave
После долгих поисков я нашел jsShell - Компонент оболочки на jsware.net. ZIP-файл содержит jsShell.dll
176 кБ, VBScript для регистрации DLL в основном regsvr32.exe jsShell.dll
, демо-сценарии и понятная документация.
DLL хорошо работает в Windows 7 и предоставляет несколько полезных методов, включая диалог открытия / сохранения:
Dim jsS, sFileName
jsS = CreateObject("jsShell.Ops")
' Save as dialog
sFileName = jsS.SaveDlg("<title>", "exe") ' Example: Filter by exe files
sFileName = jsS.SaveDlg("<title>", "") ' Example: No extension filter
' Open dialog
' Example: Filter by exe, initial dir at C:\
sFileName = jsS.OpenDlg("<title>", "exe", "C:\")
Когда файл не выбран, sFileName
пустая строка
На http://blogs.msdn.com/b/gstemp/archive/2004/02/18/75600.aspx описан способ отображения диалога "Сохранить как" из VBScript.
Обратите внимание, что в соответствии с http://www.eggheadcafe.com/software/aspnet/29155097/safrcfiledlg-has-been-deprecated-by-microsoft.aspx SAFRCFileDlg устарела Microsoft.
Private Sub cmdB1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdB1.Click
Dim objExec, strMSHTA, wshShell, SelectFile
SelectFile = ""
' For use in HTAs as well as "plain" VBScript:
strMSHTA = "mshta.exe ""about:" & "<" & "input type=file id=FILE>" _
& "<" & "script>FILE.click();new ActiveXObject('Scripting.FileSystemObject')" _
& ".GetStandardStream(1).WriteLine(FILE.value);close();resizeTo(0,0);" & "<" & "/script>"""
wshShell = CreateObject("WScript.Shell")
objExec = wshShell.Exec(strMSHTA)
SelectFile = objExec.StdOut.ReadLine()
Me.txtT0.Text = SelectFile
objExec = Nothing
wshShell = Nothing
strMSHTA = Nothing
End Sub
Я только что создал оболочку, связал ее с веб-сайтом asp, заставил веб-сайт прочитать метку направления, в которую я загрузил местоположение файла, и страница asp открывает диалоговое окно файла непосредственно в этом месте файла, причем имя файла также указывается через Направленные теги. После сохранения оболочка исчезает.
Если это ограничение тегов директивы сайта, т.е. (blah.com/temp.aspx?x=0&y=2&z=3)
Храните информацию в базе данных SQL или плоских файлах, есть множество обходных путей, но сказанное выше верно. VBS не будет сокращать это внутренне.
Я только что нашел решение на этом сайте, оно полностью прокомментировано и хорошо работает в Windows 10
Вот код, который возвращает папку в виде строки (я пробовал в трех разных папках запуска):
Option Explicit
WScript.Echo BrowseFolder( "C:\Program Files", True )
WScript.Echo BrowseFolder( "My Computer", False )
WScript.Echo BrowseFolder( "", False )
Function BrowseFolder( myStartLocation, blnSimpleDialog )
' This function generates a Browse Folder dialog
' and returns the selected folder as a string.
'
' Arguments:
' myStartLocation [string] start folder for dialog, or "My Computer", or
' empty string to open in "Desktop\My Documents"
' blnSimpleDialog [boolean] if False, an additional text field will be
' displayed where the folder can be selected
' by typing the fully qualified path
'
' Returns: [string] the fully qualified path to the selected folder
'
' Based on the Hey Scripting Guys article
' "How Can I Show Users a Dialog Box That Only Lets Them Select Folders?"
' http://www.microsoft.com/technet/scriptcenter/resources/qanda/jun05/hey0617.mspx
'
' Function written by Rob van der Woude
' http://www.robvanderwoude.com
Const MY_COMPUTER = &H11&
Const WINDOW_HANDLE = 0 ' Must ALWAYS be 0
Dim numOptions, objFolder, objFolderItem
Dim objPath, objShell, strPath, strPrompt
' Set the options for the dialog window
strPrompt = "Select a folder:"
If blnSimpleDialog = True Then
numOptions = 0 ' Simple dialog
Else
numOptions = &H10& ' Additional text field to type folder path
End If
' Create a Windows Shell object
Set objShell = CreateObject( "Shell.Application" )
' If specified, convert "My Computer" to a valid
' path for the Windows Shell's BrowseFolder method
If UCase( myStartLocation ) = "MY COMPUTER" Then
Set objFolder = objShell.Namespace( MY_COMPUTER )
Set objFolderItem = objFolder.Self
strPath = objFolderItem.Path
Else
strPath = myStartLocation
End If
Set objFolder = objShell.BrowseForFolder( WINDOW_HANDLE, strPrompt, _
numOptions, strPath )
' Quit if no folder was selected
If objFolder Is Nothing Then
BrowseFolder = ""
Exit Function
End If
' Retrieve the path of the selected folder
Set objFolderItem = objFolder.Self
objPath = objFolderItem.Path
' Return the path of the selected folder
BrowseFolder = objPath
End Function
Set objDialog = CreateObject( "SAFRCFileDlg.FileSave" )
' Note: If no path is specified, the "current" directory will
' be the one remembered from the last "SAFRCFileDlg.FileOpen"
' or "SAFRCFileDlg.FileSave" dialog!
objDialog.FileName = "test_save.vbs"
' Note: The FileType property is cosmetic only, it doesn't
' automatically append the right file extension!
' So make sure you type the extension yourself!
objDialog.FileType = "VBScript Script"
If objDialog.OpenFileSaveDlg Then
WScript.Echo "objDialog.FileName = " & objDialog.FileName
End If