別アカウントでプロセスを起動する方法

Cc440886.download(ja-jp,MSDN.10).gif サンプル コードのダウンロード (vbmigtips_Process.msi, 478 KB)

制限付きアカウントのユーザーでログインされた環境でも、一時的に管理者権限でアプリケーションを起動したい場合などがあると思います。その場合、別アカウントでアプリケーションを起動することができます。そこで今回は、図1 のような別のアカウントでプロセスを起動するアプリケーションを作成する方法について紹介します。

 Cc440886.Process_fig01(ja-jp,MSDN.10).jpg
 図1

別のアカウントでプロセスを起動する場合、Win32API の CreateProcessWithLogonW 関数を使用します。 CreateProcessWithLogonW 関数は、新しいプロセスとそのプライマリスレッドを作成し、指定したユーザー、ドメイン、パスワードのセキュリティコンテキストで、指定した実行可能なファイルを実行します。CreateProcessWithLogonW 関数を利用するためには、CreateProcessWithLogonW 関数と、プロセスハンドルとスレッドハンドルが不要になったときに破棄する CloseHandle 関数の定義を宣言します。
実装コードは以下のとおりです。

<DllImport("Advapi32.dll")> _
Public Shared Function CreateProcessWithLogonW( _
<MarshalAs(UnmanagedType.LPWStr)> ByVal lpUsername As String, _
<MarshalAs(UnmanagedType.LPWStr)> ByVal lpDomain As String, _
<MarshalAs(UnmanagedType.LPWStr)> ByVal lpPassword As String, _
ByVal dwLogonFlags As Integer, _
<MarshalAs(UnmanagedType.LPWStr)> ByVal lpApplicationName As String, _
<MarshalAs(UnmanagedType.LPWStr)> ByVal lpCommandLine As String, _
ByVal lpCreationFlags As Integer, _
ByVal lpEnvironment As IntPtr, _
<MarshalAs(UnmanagedType.LPWStr)> ByVal lpCurrentDirectory As String, _
ByRef lpStartupInfo As STARTUPINFO, _
ByRef lpProcessInfo As PROCESS_INFORMATION) As Boolean
End Function

<DllImport("kernel32.dll")> _
Public Shared Function CloseHandle( _
ByVal hObject As Long) As Long
End Function

リスト1

ウィンドウステーション、デスクトップ、標準ハンドル、メインウィンドウの表示に関する属性 STARTUPINFO 構造体と、プロセスとプライマリスレッド情報を格納する PROCESS_INFORMATION 構造体を宣言します。

Private Const LOGON_WITH_PROFILE = &H1&
Private Const CREATE_DEFAULT_ERROR_MODE = &H4000000
Private Const CREATE_NEW_CONSOLE = &H10&
Private Const CREATE_NEW_PROCESS_GROUP = &H200&
Private Const CREATE_SEPARATE_WOW_VDM = &H800&
Private Const CREATE_SUSPENDED = &H4&
Private Const CREATE_UNICODE_ENVIRONMENT = &H400&

Public Structure STARTUPINFO
Dim cb As Integer
<MarshalAs(UnmanagedType.LPTStr)> _
Dim lpReserved As String
<MarshalAs(UnmanagedType.LPTStr)> _
Dim lpDesktop As String
<MarshalAs(UnmanagedType.LPTStr)> _
Dim lpTitle As String
Dim dwX As Integer
Dim dwY As Integer
Dim dwXSize As Integer
Dim dwYSize As Integer
Dim dwXCountChars As Integer
Dim dwYCountChars As Integer
Dim dwFillAttribute As Integer
Dim dwFlags As Integer
Dim wShowWindow As Short
Dim cbReserved2 As Short
Dim lpReserved2 As Integer
Dim hStdInput As Integer
Dim hStdOutput As Integer
Dim hStdError As Integer
End Structure

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

リスト2

次に、リスト1 で定義の宣言を行った CreateProcessWithLogonW 関数を呼び出す方法は以下のとおりです。

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim processInfo As PROCESS_INFORMATION
Dim startupInfo As STARTUPINFO = New STARTUPINFO
Dim userName As String = txtUserName.Text
Dim domain As String = txtDomain.Text
Dim password As String = txtPassword.Text
Dim commandLine As String = txtCommandLine.Text

startupInfo.cb = System.Runtime.InteropServices.Marshal.SizeOf(startupInfo)
startupInfo.lpTitle = Nothing
startupInfo.dwYCountChars = 50

Dim retval As Boolean = CreateProcessWithLogonW(userName, domain, password, _
LOGON_WITH_PROFILE, Nothing, commandLine, _
CREATE_DEFAULT_ERROR_MODE Or CREATE_NEW_CONSOLE Or CREATE_NEW_PROCESS_GROUP, _
IntPtr.Zero, Nothing, startupInfo, processInfo)

If retval = True Then
CloseHandle(processInfo.hProcess)
CloseHandle(processInfo.hThread)
End If
End Sub

リスト3

上記 (リスト3) の「Dim retval As Boolean = CreateProcessWithLogonW(userName, domain, password, LOGON_WITH_PROFILE, Nothing, commandLine, CREATE_DEFAULT_ERROR_MODE Or CREATE_NEW_CONSOLE Or CREATE_NEW_PROCESS_GROUP, IntPtr.Zero, Nothing, startupInfo, processInfo)」で新しいプロセスとプライマリスレッドを作成し、指定したセキュリティコンテキストで、notepad.exe (メモ帳) を実行します。そして「CloseHandle(processInfo.hProcess)」では CreateProcessWithLogonW 関数で設定した PROCESS_INFORMATION 構造体に格納されたスレッドハンドルを破棄し、「CloseHandle(processInfo.hThread)」でプロセスハンドルを破棄します。
上記を実装し、ユーザー名、ドメイン、パスワード、アプリケーションをそれぞれ指定し (図1)、[起動] ボタンをクリックします。すると、指定したユーザーでアプリケーションが起動します。図1 の場合、ユーザー名”abcd”で notepad.exe (メモ帳) が起動します。起動結果は、Windows タスク マネージャ の [プロセス] にて確認が可能です (図2)。

 Cc440886.Process_fig02(ja-jp,MSDN.10).jpg
 図2