Original URL: | https://blogs.msdn.microsoft.com/alejacma/2007/12/20/how-to-call-createprocesswithlogonw-createprocessasuser-in-net/ |
Post name: | How to call CreateProcessWithLogonW & CreateProcessAsUser in .NET |
Original author: | Alejandro Campos Magencio |
Posting date: | 2007-12-20T08:30:00+00:00 |
Hi, welcome back,
Sometimes.NET's System.Diagnostics.Process class and its Start method are not enough for our purposes and we need to call Win32 API directly from .NET (P/Invoke mechanism) to be able to create a process the way we need. Here you have a sample you might find useful. It includes P/Invoke declarations and usage samples of some very famous API: LogonUser, CreateProcessAsUser and CreateProcessWithLogonW.
<SAMPLE>
using System; using System.Collections.Generic; using System.Text;
namespace CreateProcessSample
{
class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine("Test with CreateProcessWithLogonW...");
Win32.LaunchCommand1("\\\\server\\tests\\Batch.cmd", "domain", "user", "password");
Console.WriteLine("Test with CreateProcessAsUser...");
Win32.LaunchCommand2("\\\\server\\tests\\Batch.cmd", "domain", "user", "password");
}
catch (Exception ex)
{
Console.WriteLine("LaunchCommand error: " + ex.Message);
}
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
}
}
//--------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.IO;
namespace CreateProcessSample
{
class Win32
{
#region "CONTS"
const UInt32 INFINITE = 0xFFFFFFFF;
const UInt32 WAIT_FAILED = 0xFFFFFFFF;
#endregion
#region "ENUMS"
[Flags]
public enum LogonType
{
LOGON32_LOGON_INTERACTIVE = 2,
LOGON32_LOGON_NETWORK = 3,
LOGON32_LOGON_BATCH = 4,
LOGON32_LOGON_SERVICE = 5,
LOGON32_LOGON_UNLOCK = 7,
LOGON32_LOGON_NETWORK_CLEARTEXT = 8,
LOGON32_LOGON_NEW_CREDENTIALS = 9
}
[Flags]
public enum LogonProvider
{
LOGON32_PROVIDER_DEFAULT = 0,
LOGON32_PROVIDER_WINNT35,
LOGON32_PROVIDER_WINNT40,
LOGON32_PROVIDER_WINNT50
}
#endregion
#region "STRUCTS"
[StructLayout(LayoutKind.Sequential)]
public struct STARTUPINFO
{
public Int32 cb;
public String lpReserved;
public String lpDesktop;
public String lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public Int32 dwProcessId;
public Int32 dwThreadId;
}
#endregion
#region "FUNCTIONS (P/INVOKE)"
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern Boolean LogonUser
(
String lpszUserName,
String lpszDomain,
String lpszPassword,
LogonType dwLogonType,
LogonProvider dwLogonProvider,
out IntPtr phToken
);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern Boolean CreateProcessAsUser
(
IntPtr hToken,
String lpApplicationName,
String lpCommandLine,
IntPtr lpProcessAttributes,
IntPtr lpThreadAttributes,
Boolean bInheritHandles,
Int32 dwCreationFlags,
IntPtr lpEnvironment,
String lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation
);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern Boolean CreateProcessWithLogonW
(
String lpszUsername,
String lpszDomain,
String lpszPassword,
Int32 dwLogonFlags,
String applicationName,
String commandLine,
Int32 creationFlags,
IntPtr environment,
String currentDirectory,
ref STARTUPINFO sui,
out PROCESS_INFORMATION processInfo
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern UInt32 WaitForSingleObject
(
IntPtr hHandle,
UInt32 dwMilliseconds
);
[DllImport("kernel32", SetLastError=true)]
public static extern Boolean CloseHandle (IntPtr handle);
#endregion
#region "FUNCTIONS"
public static void LaunchCommand1(string strCommand, string strDomain, string strName, string strPassword)
{
// Variables
PROCESS_INFORMATION processInfo = new PROCESS_INFORMATION();
STARTUPINFO startInfo = new STARTUPINFO();
bool bResult = false;
UInt32 uiResultWait = WAIT_FAILED;
try
{
// Create process
startInfo.cb = Marshal.SizeOf(startInfo);
bResult = CreateProcessWithLogonW(
strName,
strDomain,
strPassword,
0,
null,
strCommand,
0,
IntPtr.Zero,
null,
ref startInfo,
out processInfo
);
if (!bResult) { throw new Exception("CreateProcessWithLogonW error #" + Marshal.GetLastWin32Error().ToString()); }
// Wait for process to end
uiResultWait = WaitForSingleObject(processInfo.hProcess, INFINITE);
if (uiResultWait == WAIT_FAILED) { throw new Exception("WaitForSingleObject error #" + Marshal.GetLastWin32Error()); }
}
finally
{
// Close all handles
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
}
}
public static void LaunchCommand2(string strCommand, string strDomain, string strName, string strPassword)
{
// Variables
PROCESS_INFORMATION processInfo = new PROCESS_INFORMATION();
STARTUPINFO startInfo = new STARTUPINFO();
Boolean bResult = false;
IntPtr hToken = IntPtr.Zero;
UInt32 uiResultWait = WAIT_FAILED;
try
{
// Logon user
bResult = Win32.LogonUser(
strName,
strDomain,
strPassword,
Win32.LogonType.LOGON32_LOGON_INTERACTIVE,
Win32.LogonProvider.LOGON32_PROVIDER_DEFAULT,
out hToken
);
if (!bResult) { throw new Exception("Logon error #" + Marshal.GetLastWin32Error()); }
// Create process
startInfo.cb = Marshal.SizeOf(startInfo);
startInfo.lpDesktop = "winsta0\\default";
bResult = Win32.CreateProcessAsUser(
hToken,
null,
strCommand,
IntPtr.Zero,
IntPtr.Zero,
false,
0,
IntPtr.Zero,
null,
ref startInfo,
out processInfo
);
if (!bResult) { throw new Exception("CreateProcessAsUser error #" + Marshal.GetLastWin32Error()); }
// Wait for process to end
uiResultWait = WaitForSingleObject(processInfo.hProcess, INFINITE);
if (uiResultWait == WAIT_FAILED) { throw new Exception("WaitForSingleObject error #" + Marshal.GetLastWin32Error()); }
}
finally
{
// Close all handles
CloseHandle(hToken);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
}
}
#endregion
}
}
</SAMPLE>
I hope this helps.
Cheers,
Alex (Alejandro Campos Magencio)
Comments: