会社行きたくなかったんです。

自由になりたくて会社辞めました

VB.net プログラミング

VB.netで子プロセスの権限を降格させて起動させる方法

投稿日:

管理者権限のアプリケーションから、他のアプリケーションを呼び出すと、呼ばれた側のアプリケーションのプロセスも管理者権限になります。

たまに、管理者権限だとうまく動作しないOCXなどがあるので、子プロセスを通常ユーザーの権限で起動させたい場合があります。
間にバッチファイルを噛ませてやってみましたが、管理者権限で起動してしまうのでダメでした。

スポンサーリンク

以下のページのソースコードを利用して、テストアプリを作ってみました。
https://social.msdn.microsoft.com/Forums/vstudio/en-US/3c9aa0fa-c860-4a26-bde0-4ccf8a3793b3/use-processstart-to-start-an-application-without-administrator-privileges-on-windows-7?forum=vbgeneral

アプリ名は、「RunAsBasicUser」です。

Form1にボタンを2つ配置しました。

「RunAsBasicUser」を管理者として実行します。
管理者特権は「はい」となっています。

Button2をクリックして、Terapadを起動させてみました。
管理者特権は「はい」となっています。

Button1をクリックして、Terapadを起動させてみました。
管理者特権は「いいえ」となっています。

上記ページのほとんどコピペですが、以下がソースコードです。

 

 

Imports System.Runtime.InteropServices

Public Class Form1
    <DllImport("advapi32.dll", SetLastError:=True)>
    Private Shared Function OpenProcessToken(ByVal ProcessHandle As IntPtr, ByVal DesiredAccess As Integer, ByRef TokenHandle As IntPtr) As Boolean
    End Function

    '  <DllImport("advapi32.dll", SetLastError:=True)>
    '  Public Shared Function GetTokenInformation(ByVal TokenHandle As IntPtr, ByVal TokenInformationClass As TOKEN_INFORMATION_CLASS,
    '  ByVal TokenInformation As IntPtr, ByVal TokenInformationLength As System.UInt32,
    '  ByRef ReturnLength As System.UInt32) As Boolean
    '  End Function

    <DllImport("User32.dll", SetLastError:=True)>
    Public Shared Function GetShellWindow() As IntPtr
    End Function

    <DllImport("user32.dll", SetLastError:=True)>
    Private Shared Function GetWindowThreadProcessId(ByVal hwnd As IntPtr,
                          ByRef lpdwProcessId As IntPtr) As Integer
    End Function

    <DllImport("kernel32.dll")>
    Private Shared Function OpenProcess(ByVal dwDesiredAccess As UInteger, <MarshalAs(UnmanagedType.Bool)> ByVal bInheritHandle As Boolean, ByVal dwProcessId As Integer) As IntPtr
    End Function

    <DllImport("advapi32.dll", SetLastError:=True)>
    Private Shared Function DuplicateTokenEx(
    ByVal ExistingTokenHandle As IntPtr,
    ByVal dwDesiredAccess As UInt32,
    ByRef lpThreadAttributes As SECURITY_ATTRIBUTES,
    ByVal ImpersonationLevel As Integer,
    ByVal TokenType As Integer,
    ByRef DuplicateTokenHandle As System.IntPtr) As Boolean
    End Function

    <DllImport("advapi32.dll", SetLastError:=True)>
    Private Shared Function LookupPrivilegeValue(lpSystemName As String,
   lpName As String, ByRef lpLuid As LUID) As Boolean
    End Function

    ' Use this signature if you want the previous state information returned
    <DllImport("advapi32.dll", SetLastError:=True)>
    Private Shared Function AdjustTokenPrivileges(
    ByVal TokenHandle As IntPtr,
    ByVal DisableAllPrivileges As Boolean,
    ByRef NewState As TOKEN_PRIVILEGES,
    ByVal BufferLengthInBytes As Integer,
    ByRef PreviousState As TOKEN_PRIVILEGES,
    ByRef ReturnLengthInBytes As Integer
  ) As Boolean
    End Function

    <DllImport("advapi32", SetLastError:=True, CharSet:=CharSet.Unicode)>
    Public Shared Function CreateProcessWithTokenW(hToken As IntPtr, dwLogonFlags As Integer, lpApplicationName As String, lpCommandLine As String, dwCreationFlags As Integer, lpEnvironment As IntPtr, lpCurrentDirectory As IntPtr, ByRef lpStartupInfo As STARTUPINFO, ByRef lpProcessInformation As PROCESS_INFORMATION) As Boolean
    End Function

    <StructLayout(LayoutKind.Sequential)>
    Structure SECURITY_ATTRIBUTES
        Public nLength As Integer
        Public lpSecurityDescriptor As IntPtr
        Public bInheritHandle As Integer
    End Structure

    Structure TOKEN_PRIVILEGES
        Public PrivilegeCount As Integer
        Public TheLuid As LUID
        Public Attributes As Integer
    End Structure

    Structure LUID
        Public LowPart As UInt32
        Public HighPart As UInt32
    End Structure

    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
    Structure STARTUPINFO
        Public cb As Integer
        Public lpReserved As String
        Public lpDesktop As String
        Public lpTitle As String
        Public dwX As Integer
        Public dwY As Integer
        Public dwXSize As Integer
        Public dwYSize As Integer
        Public dwXCountChars As Integer
        Public dwYCountChars As Integer
        Public dwFillAttribute As Integer
        Public dwFlags As Integer
        Public wShowWindow As Short
        Public cbReserved2 As Short
        Public lpReserved2 As Integer
        Public hStdInput As Integer
        Public hStdOutput As Integer
        Public hStdError As Integer
    End Structure

    Structure PROCESS_INFORMATION
        Public hProcess As IntPtr
        Public hThread As IntPtr
        Public dwProcessId As Integer
        Public dwThreadId As Integer
    End Structure

    Public Const SE_PRIVILEGE_ENABLED = &H2L
    Public Const PROCESS_QUERY_INFORMATION = &H400
    Public Const TOKEN_ASSIGN_PRIMARY = &H1
    Public Const TOKEN_DUPLICATE = &H2
    Public Const TOKEN_IMPERSONATE = &H4
    Public Const TOKEN_QUERY = &H8
    Public Const TOKEN_QUERY_SOURCE = &H10
    Public Const TOKEN_ADJUST_PRIVILEGES = &H20
    Public Const TOKEN_ADJUST_GROUPS = &H40
    Public Const TOKEN_ADJUST_DEFAULT = &H80
    Public Const TOKEN_ADJUST_SESSIONID = &H100
    Public Const SecurityImpersonation = 2
    Public Const TokenPrimary = 1
    Public Const SE_INCREASE_QUOTA_NAME = "SeIncreaseQuotaPrivilege"

    Private Sub RusAsBasicUser(sApplicationPath As String, sCommandLIne As String)

        Dim currentProcess As Process = Process.GetCurrentProcess
        'Enable SeIncreaseQuotaPrivilege in this process.  (This requires administrative privileges.)
        Dim hProcessToken As IntPtr = Nothing
        OpenProcessToken(currentProcess.Handle, TOKEN_ADJUST_PRIVILEGES, hProcessToken)
        Dim tkp As TOKEN_PRIVILEGES
        tkp.PrivilegeCount = 1
        LookupPrivilegeValue(Nothing, SE_INCREASE_QUOTA_NAME, tkp.TheLuid)
        tkp.Attributes = SE_PRIVILEGE_ENABLED

        AdjustTokenPrivileges(hProcessToken, False, tkp, 0, Nothing, Nothing)

        'Get window handle representing the desktop shell.  This might not work if there is no shell window, or when
        'using a custom shell.  Also note that we're assuming that the shell is not running elevated.
        Dim hShellWnd As IntPtr = GetShellWindow()

        'Get the ID of the desktop shell process.
        Dim dwShellPID As IntPtr
        GetWindowThreadProcessId(hShellWnd, dwShellPID)

        'Open the desktop shell process in order to get the process token.
        Dim hShellProcess As IntPtr = OpenProcess(PROCESS_QUERY_INFORMATION, False, dwShellPID)
        Dim hShellProcessToken As IntPtr = Nothing
        Dim hPrimaryToken As IntPtr = Nothing

        'Get the process token of the desktop shell.
        OpenProcessToken(hShellProcess, TOKEN_DUPLICATE, hShellProcessToken)

        'Duplicate the shell's process token to get a primary token.
        Dim dwTokenRights As Integer = TOKEN_QUERY Or TOKEN_ASSIGN_PRIMARY Or TOKEN_DUPLICATE Or TOKEN_ADJUST_DEFAULT Or TOKEN_ADJUST_SESSIONID
        DuplicateTokenEx(hShellProcessToken, dwTokenRights, Nothing, SecurityImpersonation, TokenPrimary, hPrimaryToken)

        Dim si As STARTUPINFO = Nothing
        Dim pi As PROCESS_INFORMATION = Nothing

        si.cb = Marshal.SizeOf(si)
        CreateProcessWithTokenW(hPrimaryToken, 0, sApplicationPath, sCommandLIne, 0, Nothing, Nothing, si, pi)

    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        RusAsBasicUser("C:\Program Files (x86)\TeraPad\Terapad.exe", "")
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        Process.Start("C:\Program Files (x86)\TeraPad\Terapad.exe")
    End Sub
End Class

動作確認は、Windows10で行いました。

-VB.net, プログラミング

Copyright© 自由になりたくて会社辞めました , 2024 AllRights Reserved Powered by AFFINGER4.