Retired Microsoft Blog disclaimer

This directory is a mirror of retired "Decrypt My World" MSDN blog and is provided as is. All posting authorship and copyrights belong to respective authors.
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)

 


Share this article:

Comments:

Comments are closed.