trucos securecrt script para examples crear commands vbscript savefiledialog common-dialog

vbscript - script - trucos securecrt



¿Cómo puedo usar el diálogo común Guardar como de VBScript? (9)

Me gustaría que mi VBScript muestre el cuadro de diálogo Guardar como de Windows, pero no pude averiguar cómo hacerlo.

Utilizando este código:

Dim sfd Set sfd = CreateObject("UserAccounts.CommonDialog") sfd.ShowOpen

Puedo obtener un cuadro de diálogo Abrir, pero no hay ShowSave método ShowSave para este objeto (como parece que existe para un objeto similar en Visual Basic sin script).

Busqué en StackOverflow y busqué en Google "[vbscript] save dialog" (y con "Windows Script Host"), pero solo encontré hilos sobre el acceso a diálogos comunes desde páginas web y una solución para el diálogo BrowseForFolder y nada acerca de cómo llamar al diálogo Save. .

En realidad, puedo usar el cuadro de diálogo Abrir para mi propósito, ya que todo lo que necesito es un nombre de archivo ... pero como me gustaría guardar algo en la ruta seleccionada, un "Guardar como" en la barra de título del cuadro de diálogo ser mas apropiado


Acabo de crear un shell, lo vinculé a un sitio web de asp, hice que el sitio leyera una etiqueta direccional, en la que cargué la ubicación del archivo, y la página asp abre el cuadro de diálogo del archivo inmediatamente dentro de la ubicación del archivo, con el nombre del archivo también específico. etiquetas direccionales. Una vez guardado, la cáscara desaparece.

Si es una limitación de las etiquetas de dirección del sitio web, es decir (blah.com/temp.aspx?x=0&y=2&z=3)

almacene la información en un db de SQL, o archivos planos, hay un montón de soluciones, pero lo que se dice arriba es cierto. VBS no lo cortará internamente.


Acabo de encontrar una solución en este sitio. Está completamente comentado y funciona bien en Windows 10.

Aquí está el código que devuelve la carpeta como una cadena (probé en tres carpetas de inicio diferentes):

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


Después de buscar las edades, he encontrado jsShell - Componente de Shell en jsware.net. El archivo zip contiene jsShell.dll 176 kB , un vbscript para registrar el archivo jsShell.dll básicamente regsvr32.exe jsShell.dll , scripts de demostración y documentación clara .

La DLL funciona bien en Windows 7 y proporciona varios métodos útiles, incluido el cuadro de diálogo Abrir / Guardar:

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:/")

Cuando no se selecciona ningún archivo, sFileName es una cadena vacía.


El secreto para usar el cuadro de diálogo común de VBScript (o VBA o JScript, para el caso) es que debe tener su licencia instalada en su máquina. Ciertas herramientas de desarrollo, como Visual Basic 6, instalarán la licencia, pero también la instala el Editor de Ayuda HTML de Microsoft (esta es una aplicación bastante antigua). Lo interesante es que si instala y luego desinstala el Editor de Ayuda HTML, deja la Licencia de Diálogo Común en su lugar. Por este motivo, consideraría que la licencia está disponible de forma gratuita, por lo que incluiré la entrada de registro que crea aquí en mi respuesta:

En HKLM/Software/CLASSES/Licenses/4D553650-6ABE-11cf-8ADB-00AA00C00905 , configure la entrada (Default) en gfjmrfkfifkmkfffrlmmgmhmnlulkmfmqkqj .

Una vez que esté en su lugar, puede crear estos diálogos desde un VBScript usando un código como este:

Set objDialog = CreateObject("MSComDlg.CommonDialog")

Para iniciar un cuadro de diálogo para guardar un archivo, use el método ShowSave como en este código:

objDialog.ShowSave

Por supuesto, este objeto tiene un montón de otros métodos y propiedades, y probablemente querrá configurar las propiedades apropiadas antes de iniciar el cuadro de diálogo. Por ejemplo, puede configurar el filtro de archivos para que solo se muestren ciertas extensiones de archivos en el cuadro de diálogo. Hay una buena referencia al control en el sitio de MSDN aquí: http://msdn.microsoft.com/en-us/library/aa259661%28v=vs.60%29.aspx .

Espero que esto ayude. Hazme saber si tienes alguna pregunta.



Si tiene cierto grado de control sobre los sistemas en los que va a implementar esto y puede estar razonablemente seguro de que tienen instalado Visual Studio o la Ayuda HTML de Microsoft, puede usar un código como el siguiente:

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

Además, al adaptar una de las otras respuestas a esta pregunta en el código de VBScript (¡gracias @oddacorn!), Debe agregar esta función si no está razonablemente seguro de que sus usuarios tendrán la Ayuda de VS o HTML. Llame a esta función en el inicio del programa. No te preocupes si ya tienes la llave; En ese caso, esto no tiene efecto. Esto debería funcionar en una cuenta de usuario estándar sin derechos de administrador.

''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

Tenga en cuenta que adapté la función de registro de archivos del "Código fuente de vista" del código de VBScript en el HTML here ; en los navegadores web modernos, parece que el HTML que usan para representar los ejemplos de código no se muestra correctamente (probado en IE 8 y Chrome). Pero, afortunadamente, el código todavía está allí en la fuente de vista.

Encontré una cosa que era fundamental para hacer que esto funcionara en Windows 7 (SP1, totalmente parcheado); debe establecer dialog.MaxFileSize = 256 o obtendrá un error en tiempo de ejecución.

Es decir, el siguiente código falla en Windows 7 SP1, pero probablemente funciona en versiones anteriores de Windows:

Set x = CreateObject("MSComDlg.CommonDialog") x.ShowSave


Definitivamente puedo decir que no hay una solución para mostrar un cuadro de diálogo Guardar como de VBScript en versiones de Windows que no sean XP sin confiar en algunas dependencias externas que debe instalar y registrar. Aparte de la obvia interferencia que esto causa con respecto a una implementación fácil de arrastrar y soltar de su secuencia de comandos, también presenta una gran cantidad de otros problemas relacionados con la seguridad y los permisos, especialmente evitando el UAC en la máquina del cliente para instalar y registrar una dependencia DLL.

Las soluciones que se han propuesto hasta ahora se basan en un archivo DLL que se incluye con Windows XP, invocando el cuadro de diálogo Guardar como desde el panel de control de Cuentas de usuario de Windows XP o instalando una parte del software solo para ello para dejar atrás la DLL de MSComDlg después de que se desinstale, que luego puede usar desde un VBScript. Ninguna de estas soluciones satisface realmente los requisitos anteriores, y ninguna de las respuestas proporcionadas ha considerado siquiera los posibles obstáculos de seguridad que surgirían con sus soluciones propuestas, como mencioné anteriormente.

Y ya que no puede hacer llamadas directamente a la API de Windows (que siempre incluye tan convenientemente un cuadro de diálogo Guardar como) desde VBScript (no solo porque representaría un riesgo de seguridad, sino también debido a la falta de VBScript [falta de ?] escribiendo), eso deja a cualquiera que quiera hacer esto en el frío. Además, la imposibilidad de hacer llamadas a la API también impide el uso de hacks como llamar a SetWindowText para cambiar el título del cuadro de diálogo Abrir, como se sugiere en la pregunta.

Me doy cuenta de que esta no es la respuesta que todos querían. Ni siquiera es la respuesta que estaba esperando. Pero ay, es la respuesta correcta.

Dicho esto, aquí hay un par de soluciones posibles:

  1. Si se está inclinando por aceptar cualquiera de las respuestas ya sugeridas, ya ha decidido introducir una dependencia externa en un archivo DLL para su implementación de VBScript. Una vez que haya dado ese salto, ¿por qué molestarse en "pedir prestado" o secuestrar un DLL de alguna otra fuente? Sólo haz una vez tú mismo. Es trivial envolver las funciones de diálogo comunes nativas proporcionadas por la API de Windows en un DLL ActiveX usando Visual Basic 6, que luego puede ser llamado por su VBScript. Los riesgos son mínimos, ya que se puede esperar que casi todas las versiones modernas de Windows ya tengan instalado el tiempo de ejecución de Visual Basic, y como probablemente ya conoce VBScript, no es una tarea difícil eliminar un código en VB 6. Puede incluir cualquier funcionalidad personalizada que desee y, lo que es más importante, estará en completo control. No tendrá que preocuparse de que los desinstaladores de otras aplicaciones eliminen la DLL que requiere su script, no tendrá que seguir adelante con la instalación y desinstalación de alguna aplicación aleatoria y obsoleta, y no tendrá que cruzar los dedos y esperar. Sabemos, como programadores, que nunca es una buena opción.

    Y sí, recomiendo en realidad envolver las funciones comunes de diálogo expuestas por la API de Windows, en lugar de confiar en el diálogo común OCX ( comdlg32.ocx ) proporcionado por Visual Basic. Tiene su parte de problemas en Windows 7, y no te dará los nuevos y maravillosos diálogos que ahora ofrecen las versiones posteriores de Windows. Un excelente artículo que explica todo lo que necesita saber sobre las API de diálogo de abrir y guardar comunes y cómo usarlas en VB 6 está disponible aquí en VBnet . Por supuesto, si realmente quieres hacer todo lo posible, hay muchas cosas interesantes que puedes hacer con los diálogos comunes, todos documentados (¡con código!) Aquí en VB Accelerator .

  2. Pero ahora que los he convencido a todos para escribir una DLL ActiveX en VB 6 que envuelva la funcionalidad de diálogo común para usar en su VBScript, tengo que hacer la pregunta: ¿Por qué detenerme ahí? Una vez que haya dado el salto para escribir un código en VB 6, ¿por qué no mover todo su código a VB 6? Claro, es un lenguaje "muerto" y todo eso, pero tampoco es que VBScript sea terriblemente activo. Como mencioné anteriormente, la diferencia en la sintaxis es prácticamente nula, y la curva de aprendizaje para un desarrollador de VBScript es tan poco profunda como se podría esperar. Además, obtiene todos los beneficios de un IDE completo, escritura estática, (ligeramente) mejor manejo de errores, bla bla bla. Ah, sí, y poder hacer llamadas directas a las funciones de la API de Windows. El único beneficio real de VBScript es su ubicuidad, pero han pasado años desde que se pudo encontrar una computadora sin el tiempo de ejecución de VB instalado. Sin mencionar que si está escribiendo una aplicación que requiere cuadros de diálogo comunes, probablemente esté participando en un diálogo con sus usuarios: la capacidad de formularios de VB completa podría comenzar a ser útil en ese momento. Pero tal vez la mayor y más importante ventaja de elegir esta ruta es que elimina cualquier necesidad de registrar (o incluir) un DLL "satélite" externo: una aplicación VB 6 simple se ejecutará con solo el EXE en cualquier computadora que tenga el Tiempo de ejecución de VB instalado, que se incluye al menos hasta Windows 7.

  3. Y, por último, en caso de que estés entusiasmado por pasar del VBScript al VB 6 con todas las funciones, me siento obligado a lanzar otra llave en la ecuación: ¿por qué no pasar a un lenguaje como el de VB? .¿RED? Una vez más, hay todo tipo de funciones nuevas ofrecidas en VB.NET gracias a .NET Framework, pero no debería tomar más de unas pocas semanas para que un desarrollador de VB / VBScript decente comience a sentirse cómodo escribiendo aplicaciones en VB.NET . Probablemente no tendrán una comprensión completa de .NET Framework, y ciertamente no habrán desarrollado buenas prácticas de diseño orientadas a objetos, pero al menos se moverán en la dirección correcta. Casi cualquier cosa que pueda hacer en VBScript (o incluso VB 6), puede hacerlo en VB.NET. Y, en general, requiere menos complicaciones que antes, gracias a la inmensa funcionalidad expuesta por .NET Framework. El inconveniente, por supuesto, es que su aplicación ahora requiere la instalación de .NET Framework en la computadora del usuario, lo que no es tan ubicuo como el tiempo de ejecución de VB 6 (aunque es mucho más común ahora que solo unos pocos años). hace).

¿Entonces te oigo decir que esas no eran las soluciones que esperabas escuchar? Sí, yo tampoco. No soy ese tipo que le dice a la gente que deje todo y aprenda un nuevo idioma. Si VBScript continúa trabajando para ti, hazlo . Pero si estás en ese punto en el que empiezas a esforzarte por sus limitaciones, es probable que sea el momento de dar el salto.


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


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