Visual studio 如何将UAC集成到VB6程序中?

Visual studio 如何将UAC集成到VB6程序中?,visual-studio,vb6,uac,administrator,Visual Studio,Vb6,Uac,Administrator,我需要一些代码,将添加管理员权限图标的命令按钮,并显示提示时,这些按钮被单击。如何在VB6中执行此操作?有些操作需要管理员权限,因为它们会替换Windows Vista/7不允许程序正常访问文件的文件和内容。首先,获取有人单击按钮时运行的代码,并将其放入单独的exe中。更改按钮单击代码以使用ShellExecute启动exe。其次,为每个新的exe构建外部清单,并让它指定requireAdministrator。第三,向按钮发送BCM_SETSHIELD消息(您可能需要查找消息ID的数值)以使屏

我需要一些代码,将添加管理员权限图标的命令按钮,并显示提示时,这些按钮被单击。如何在VB6中执行此操作?有些操作需要管理员权限,因为它们会替换Windows Vista/7不允许程序正常访问文件的文件和内容。

首先,获取有人单击按钮时运行的代码,并将其放入单独的exe中。更改按钮单击代码以使用ShellExecute启动exe。其次,为每个新的exe构建外部清单,并让它指定requireAdministrator。第三,向按钮发送BCM_SETSHIELD消息(您可能需要查找消息ID的数值)以使屏蔽显示在按钮上。

以下是一个VB6 ShellExecuteEx示例,它允许您选择使用管理员权限执行任何进程。您可以将其放入模块或类中

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

代码示例确实可以在上运行,但这里有一个简单的示例显示了“我的第二个实例”方法

该程序有一个启动静态模块,其中包含几个公共函数,包括一个“提升的操作”处理程序,以及一个仅包含一个CommandButton的窗体:

模块1.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
表格1.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
该应用程序有一个简单的“asInvoker”清单,用于选择通用控件6.0程序集。


  • 将所有需要提升的代码移到外部进程中
  • 向按钮发送BCM_SETSHIELD消息以添加屏蔽图标
  • 将清单嵌入到这些进程中,告诉Windows它们需要提升。见下文


  • 为了强制Vista和更高版本在UAC中以管理员身份运行VB6 exe,必须将清单xml作为资源嵌入其中。步骤如下

  • 创建清单文件。将其命名为“YourProgram.exe.manifest”,它应该包含以下内容。重要的一行是“requestedExecutionLevel”。更改中的属性以匹配您的exe

    >
    .   在资源管理器中,转到exe的属性,如果已嵌入清单,则应具有清单选项卡(.Net程序集也将具有此清单选项卡)

  • 尝试在Vista或更高版本上运行您的程序。如果UAC确实启用了,它应该立即给出提示


  • 我只是建议,与其创建单独的exe,不如启动应用程序的第二个实例,并使用命令行参数指示您只想执行此特定任务,然后退出。您的第二个实例的问题是清单。您希望提升第二个实例,而不提升第一个实例。同一个应用程序意味着相同的清单,所以这不起作用。Kate,您可以使用ShellExecuteEx并向其传递一个SHELLEXECUTEINFO结构,该结构的应用程序路径为.lpFile,运行方式为.lpVerb=“runas”。这将以管理员权限启动现有应用程序。但我将如何执行此操作?示例?如何将屏蔽图标添加到按钮?无论如何,我找到了VB6的BCM_设置帮助。如何获得执行操作而不是启动程序的提示。比如说“Windows需要您的许可才能继续”,而不是“一个身份不明的程序想要访问您的计算机”?要运行的语法是什么?错误日志记录示例:openforoutput As freefile要获得不那么可怕的提示,您需要使用代码签名证书对可执行文件进行签名。KSoftware是一家知名可靠的Comodo代码签名证书经销商:@JoeJordan您有singtool实用程序吗?我需要它,但只是EXE,而不是完整的SDK。我使用的是Visual Basic 6 Portable,所以它只是IDE。没有“Portable Edition”-您使用的是被盗软件。您不需要这些RC.EXE旋转来嵌入应用程序清单。只需将清单文件创建为ANSI文本(通常非常接近UTF-8),确保它被填充为4字节的偶数倍,然后使用IDE资源编辑器将其添加为自定义资源,并将其类型设置为#24,Id设置为#1并保存。@WindozeNT如果使用VB6 Portable是您的问题的一部分,那么它应该是问题的一部分。如果VB6 Portable是您的问题的一部分,那么它不是一个有效的问题(鼓励使用非法软件)。要么接受当前(相当优秀)的答案之一,要么结束问题。
    <?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>