2011-01-21 21 views
7

Necesito un código que agregará el icono de derechos de administrador a los botones de comando y mostrará el mensaje cuando se haga clic en dichos botones. ¿Cómo puedo hacer esto en VB6? Algunas acciones requieren derechos de administrador porque reemplazan archivos y cosas donde Windows Vista/7 no permite que el programa tenga acceso normal a los archivos.¿Cómo integro el UAC en mi programa VB6?

Respuesta

7

Aquí hay un ejemplo VB6 de ShellExecuteEx que le permitirá ejecutar opcionalmente cualquier proceso con permisos de administrador. Puede colocar esto en un módulo o clase.

Option Explicit 

Private Const SEE_MASK_DEFAULT = &H0 

Public Enum EShellShowConstants 
     essSW_HIDE = 0 
     essSW_SHOWNORMAL = 1 
     essSW_SHOWMINIMIZED = 2 
     essSW_MAXIMIZE = 3 
     essSW_SHOWMAXIMIZED = 3 
     essSW_SHOWNOACTIVATE = 4 
     essSW_SHOW = 5 
     essSW_MINIMIZE = 6 
     essSW_SHOWMINNOACTIVE = 7 
     essSW_SHOWNA = 8 
     essSW_RESTORE = 9 
     essSW_SHOWDEFAULT = 10 
End Enum 

Private Type SHELLEXECUTEINFO 
     cbSize  As Long 
     fMask   As Long 
     hwnd   As Long 
     lpVerb  As String 
     lpFile  As String 
     lpParameters As String 
     lpDirectory As String 
     nShow   As Long 
     hInstApp  As Long 
     lpIDList  As Long  'Optional 
     lpClass  As String 'Optional 
     hkeyClass  As Long  'Optional 
     dwHotKey  As Long  'Optional 
     hIcon   As Long  'Optional 
     hProcess  As Long  'Optional 
End Type 

Private Declare Function ShellExecuteEx Lib "shell32.dll" Alias "ShellExecuteExA" (lpSEI As SHELLEXECUTEINFO) As Long 

Public Function ExecuteProcess(ByVal FilePath As String, ByVal hWndOwner As Long, ShellShowType As EShellShowConstants, Optional EXEParameters As String = "", Optional LaunchElevated As Boolean = False) As Boolean 
    Dim SEI As SHELLEXECUTEINFO 

    On Error GoTo Err 

    'Fill the SEI structure 
    With SEI 
     .cbSize = Len(SEI)     ' Bytes of the structure 
     .fMask = SEE_MASK_DEFAULT   ' Check MSDN for more info on Mask 
     .lpFile = FilePath     ' Program Path 
     .nShow = ShellShowType    ' How the program will be displayed 
     .lpDirectory = PathGetFolder(FilePath) 
     .lpParameters = EXEParameters  ' Each parameter must be separated by space. If the lpFile member specifies a document file, lpParameters should be NULL. 
     .hwnd = hWndOwner     ' Owner window handle 

     ' Determine launch type (would recommend checking for Vista or greater here also) 
     If LaunchElevated = True Then ' And m_OpSys.IsVistaOrGreater = True 
      .lpVerb = "runas" 
     Else 
      .lpVerb = "Open" 
     End If 
    End With 

    ExecuteProcess = ShellExecuteEx(SEI) ' Execute the program, return success or failure 

    Exit Function 
Err: 
    ' TODO: Log Error 
    ExecuteProcess = False 
End Function 

Private Function PathGetFolder(psPath As String) As String 
    On Error Resume Next 
    Dim lPos As Long 
    lPos = InStrRev(psPath, "\") 
    PathGetFolder = Left$(psPath, lPos - 1) 
End Function 
+0

¿Cómo agrego el icono de escudo al botón? – WindozeNT

+0

No importa, encontré BCM_SETSHEILD para VB6. ¿Cómo obtengo el aviso para realizar una acción en lugar de iniciar el programa? ¿Como dónde dice "Windows necesita tu permiso para continuar" en lugar de "Un programa no identificado quiere acceder a tu computadora"? ¿Y cuál es la sintaxis para ejecutar? – WindozeNT

+0

Ejemplo de registro de error: abra Para salida como archivo libre – WindozeNT

1

Primero, tome el código que se ejecuta cuando alguien hace clic en el botón y póngalo en un exe por separado. Cambie su código de clic de botón para iniciar el exe con ShellExecute. Segundo, compila manifiestos externos para cada nuevo exe y haz que especifique requireAdministrator. En tercer lugar, envíe a sus botones el mensaje BCM_SETSHIELD (probablemente tendrá que buscar el valor numérico de la ID del mensaje) para que el escudo aparezca en ellos.

+0

Me gustaría sugerir, en lugar de crear un exe por separado, el lanzamiento de una segunda instancia de la aplicación con un argumento de línea de comando que indica que solo desea realizar esta tarea específica, luego salir. –

+0

El problema con la segunda instancia de ti es el manifiesto. Desea que la segunda instancia sea elevada y la primera no lo sea. La misma aplicación significa el mismo manifiesto, por lo que no funcionará. –

+1

Kate, puede usar ShellExecuteEx y pasarle una estructura SHELLEXECUTEINFO que tenga .lpFile como la ruta de la aplicación y .lpVerb = "runas". Eso lanzará la aplicación existente con privilegios de administrador. –

4

Los ejemplos de código realmente se pueden ejecutar, pero aquí hay uno trivial que muestra el enfoque de "segunda instancia de mí".

El programa cuenta con un módulo de arranque estático con algunas funciones públicas, incluyendo una "operación elevada" manipulador, y una forma con sólo un CommandButton en él:

Module1.bas

Option Explicit 

Private Const BCM_SETSHIELD As Long = &H160C& 

Private Declare Sub InitCommonControls Lib "comctl32"() 

Private Declare Function IsUserAnAdmin Lib "shell32"() As Long 

Private Declare Function SendMessage Lib "user32" _ 
    Alias "SendMessageA" (_ 
    ByVal hWnd As Long, _ 
    ByVal wMsg As Long, _ 
    ByVal wParam As Long, _ 
    ByRef lParam As Any) As Long 

Private Declare Function ShellExecute Lib "shell32" _ 
    Alias "ShellExecuteA" (_ 
    ByVal hWnd As Long, _ 
    ByVal lpOperation As String, _ 
    ByVal lpFile As String, _ 
    ByVal lpParameters As String, _ 
    ByVal lpDirectory As String, _ 
    ByVal nShowCmd As VbAppWinStyle) As Long 

Private mblnIsElevated As Boolean 

Public Function IsElevated() As Boolean 
    IsElevated = mblnIsElevated 
End Function 

Public Sub OperationRequiringElevation(ByRef Params As Variant) 
    MsgBox "Insert logic here for: " & vbNewLine _ 
     & Join(Params, vbNewLine) 
End Sub 

Public Sub RequestOperation(_ 
    ByVal hWnd As Long, _ 
    ByVal Focus As VbAppWinStyle, _ 
    ByRef Params As Variant) 

    ShellExecute hWnd, "runas", App.EXEName & ".exe", _ 
       Join(Params, " "), CurDir$(), Focus 
End Sub 

Public Sub SetShield(ByVal hWnd As Long) 
    SendMessage hWnd, BCM_SETSHIELD, 0&, 1& 
End Sub 

Private Sub Main() 
    If Len(Command$()) > 0 Then 
     'Assume we've been run elevated to execute an operation 
     'specified as a set of space-delimited strings. 
     OperationRequiringElevation Split(Command$(), " ") 
    Else 
     mblnIsElevated = IsUserAnAdmin() 
     InitCommonControls 
     Form1.Show 
    End If 
End Sub 

Form1. frm

Option Explicit 

Private Sub Command1_Click() 
    Dim Params As Variant 

    Params = Array("ReplaceFile", "abc", "123") 
    If IsElevated() Then 
     OperationRequiringElevation Params 
    Else 
     RequestOperation hWnd, vbHide, Params 
    End If 
End Sub 

Private Sub Form_Load() 
    If Not IsElevated() Then 
     SetShield Command1.hWnd 
    End If 
End Sub 

la aplicación cuenta con un simple manifiesto "asInvoker" seleccionando el montaje de controles comunes 6,0.

+1

+1 por mencionar IsUserAnAdmin() – CSharper

1


  1. Mover todo el código que requiere la elevación en los procesos externos.
  2. Envíe sus botones al mensaje BCM_SETSHIELD para agregar el icono del escudo.
  3. Incrustar manifiestos en esos procesos, indicando a Windows que requieren elevación. Vea abajo.



Con el fin de forzar Vista y superior para ejecutar un exe VB6 como administrador en la UAC, debe incrustar un manifiesto XML como un recurso dentro de ella. Los pasos siguen;

  1. Crea el archivo de manifiesto. Llámalo "YourProgram.exe.manifest", debería contener lo siguiente. La línea importante es el "requestedExecutionLevel". Cambie los atributos para que coincida con su exe.

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>> 
    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
        <assemblyIdentity 
        version="1.0.0.0" 
        processorArchitecture="X86" 
        name="YourProgram" 
        type="win32" 
        > 
        <description>application description</description> 
        <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> 
        <security 
         <requestedPrivileges> 
         <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/> 
         </requestedPrivileges> 
        </security> 
        </trustInfo> 
    </assembly> 
    
  2. Crear un archivo llamado "YourProgram.exe.manifest.rc". Debe contener lo siguiente.

    # definen CREATEPROCESS_MANIFEST_RESOURCE_ID 1
    # definen RT_MANIFEST 24 CREATEPROCESS_MANIFEST_RESOURCE_ID
    RT_MANIFEST

  3. compilar su recurso mediante rc.exe "YourProgram.exe.manifest". Se encuentra por defecto en C: \ Archivos de programa \ Microsoft Visual Studio \ COMMON \ MSDev98 \ Bin. Esto creará un archivo llamado YourProgram.exe.manifest.RES. La sintaxis es;

    rc /r YourProgram.exe.manifest.rc

  4. Agregue el archivo .RES a su proyecto. Haga esto usando el Add-In del editor de recursos en VB6. El icono en la barra de herramientas se ve como bloques verdes. Si no tiene el ícono, asegúrese de que esté habilitado en el administrador de complementos. Si no está en el administrador de complementos, necesita regsvr32 en C: \ Archivos de programa \ Microsoft Visual Studio \ VB98 \ Wizards \ Resedit.dll. Una vez que haya abierto el editor de recursos, haga clic en abrir y seleccione su archivo .RES.

  5. Recopila tu proyecto.

  6. Para comprobar que el manifiesto está incrustado correctamente, puede utilizar una herramienta llamada InspectExe. En el explorador, vaya a las propiedades del archivo ejecutable y, si el manifiesto está incrustado, debe tener una pestaña de manifiesto (los ensamblados .Net también tendrán esta pestaña de manifiesto).

  7. Pruebe ejecutar su programa en Vista o posterior. Si el UAC está habilitado, debería aparecer el mensaje de inmediato.

+0

Estoy usando Visual Basic 6 Portable, por lo que solo es IDE. – WindozeNT

+2

No hay una "Edición portátil": está utilizando un software robado. – Bob77

+0

No necesita estos giros RC.EXE para incrustar un manifiesto de aplicación.Simplemente cree su archivo de manifiesto como texto ANSI (lo suficientemente cerca de UTF-8 normalmente), asegúrese de que esté acolchado a un múltiplo de 4 bytes, luego agréguelo como un recurso personalizado utilizando el editor de recursos IDE y establezca su tipo en # 24 y Id a # 1 y Guardar. – Bob77

Cuestiones relacionadas