Did you know that Process.Start always uses the security context of the parent ASP.NET process? I just found this out the hard way; Using Process.Start on "whoami.exe" always returns the ASPNET worker process no matter what I do. Some searching turned up this entry in Scott's blog:
I wantedto run these processes with the identity of the client, but this poses a problem. The Process class in System.Diagnostics canstart a new process, but the process always inherits the security context of the parent process. Even if the ASP.NETthread invoking the Start method is impersonating a client, the Process still starts with the ASP.NET worker process credentials.Enter .NET 2.0, which includes the User, Domain, and Password properties on the ProcessStartInfo type. In .NET 2.0 you can start a process under a different set of credentials.
Way to rub salt in my wounds, Whidbey. This is a very unfortunate limitation of .NET 1.1, as it severely limits what I can do with Process.Start in a web app. Scott helpfully provides a bit of sample C# code that calls the Win32 APIs to simulate a stripped down version of the Whidbey behavior today.
If you aren't calling Process.Start, you may be able to impersonate to get the behavior you want. The MSKB article How to implement impersonation in an ASP.NET application provides some nice, relatively painless workarounds:
If you want to impersonate a user on a thread in ASP.NET, you can use one of the following methods, based on your requirements:Note: You can use the following code to determine what user the thread is executing as:
- Impersonate the IIS authenticated account or user
- Impersonate a specific user for all the requests of an ASP.NET application
- Impersonate the authenticating user in code
- Impersonate a specific user in code
System.Security.Principal.WindowsIdentity.GetCurrent().Name
The last method is the most interesting to me-- it lets you impersonate an arbitrary user on the fly, execute a specific set of code as that user, then revert back to the ASP.NET credentials. Bear in mind that impersonation is a very expensive operation; it's not something you want to do often.
Scott's code assumes we want to impersonate the current user and that we don't have the password. I want to Process.Start as an arbitrary function account using plaintext account and password information. That requires a more masochistic workaround-- calling the newer Win32 API method CreateProcessWithLogonW() directly. The only good sample code I could find was for VB6: How To Start a Process as Another User from Visual Basic. However, I couldn't get this to work in VB.NET.
Even if I could get that API call to work, I still wouldn't have the amenities of the Process class that I need. I want to redirect the standard output and standard error output, then capture them into strings, so I can echo the result of my command line operation to the web page. There's a good example of command line capture behavior on CodeProject. That's for WinForms, but the process is similar for ASP.NET. Well, except for that pesky Process.Start credentials problem.. another reason to look forward to .NET 2.0, I guess.
Sorry to just spam a load of url's at you, but I hope these are of some use in your quest to get CreateProcessWithLogonW working in VB.net:
http://www.dotnet247.com/247reference/msgs/14/73862.aspx
http://www.eggheadcafe.com/ng/microsoft.public.vb.winapi.networks/post3994284.asp
http://weblogs.asp.net/ralfw/archive/2003/11/24/39479.aspx
Cheers,
Andy.
Excellent links particularly the last one. Thank you. Unfortunately, even if I get it to work I can't get the output from the command line execution, which kills this as a solution for me.
Some additional detail. I am using psexec.exe from SysInternals (which requires local admin) and rclient.exe from the Win2k Resource Kit (which doesn't). I can get output from psexec.exe but not from rclient.exe either, so I am basically back where I started.
Jeff Atwood on November 19, 2004 10:12 AMYes indeed, I have a list of about 10 things I can't wait for in 2005!
Scott Allen on November 21, 2004 4:28 AMI'm sure this is too late to help in solving your problems, but a solution I'm using to capture output from the started process is to run it with redirection, ie "procname foo.txt 21 args". Then after getting the Process by it's processId and doing WaitForExit on it, I can read the contents of that file to find out what the output was.
It's a horrible hack, but it works. As long as you have a scratch directory you can use for the temporary files, and you have a solution for the concurrency issues (eg using a different filename for each request).
Stuart Ballard on June 22, 2005 3:54 AMRight-- the filesystem method does work. I am using that in another project with great results. It's just not as elegant as capturing the output directly from the stream...
Jeff Atwood on June 22, 2005 6:36 AM!--Not sure if u've tried these --
System.Diagnostics.Process oProcess = new Process();
oProcess.StartInfo.FileName = "c:\folder1\filename.exe";
oProcess.StartInfo.Arguments = "";
oProcess.StartInfo.UseShellExecute = false;
oProcess.StartInfo.RedirectStandardOutput = true;
oProcess.WaitForExit();
string output = oProcess.StandardOutput.ReadToEnd();
Response.Write("BRBRthe string: " + output);
FCodinera on July 16, 2005 6:29 AMWhich is great, until you need to perform a network operation via the command line in an ASP.NET app. You will *always* get the ASP.NET process credentials, as stated above..
Using Process.Start on "whoami.exe" always returns the ASPNET worker process no matter what I do.
ASPNET is a local machine account. Thus, any network resources that require network credentials (eg DOMAIN\USER) won't work at all.
Jeff Atwood on July 17, 2005 2:23 AMI want register a dll, with regsvr32.exe using System.Diagnostics.Process but to the redirect the error(StandardError) this is empty, though there are errors.Why?
My code
string directorioReg="C:\\Windows\\System32";
System.Diagnostics.Process proc=new System.Diagnostics.Process();
proc.StartInfo.FileName="regsvr32.exe";
proc.StartInfo.WorkingDirectory = directorioReg;
proc.StartInfo.Arguments=" \""+ruta+"\"";//Aadir /s para evitar mensajes
/*Pruebas*/ proc.EnableRaisingEvents = true;
proc.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardInput = false;
proc.StartInfo.UseShellExecute = false;
/*Fin pruebas*/
try
{
proc.Start();
string list_outPut=proc.StandardOutput.ReadToEnd();
string list_errors=proc.StandardError.ReadToEnd();
//list_outPut and list_errors are empty.
proc.WaitForExit();
proc.Close();
}
catch(Exception e){
throw e;
}
I want to call an windows based Exe in client machine using asp.net in a button click is it possible.. If so pls provide the code.
Thanks in advance
Rams
with .Net 2.0 you can't get the standard output of a process that you launch under a different set of credentials.
you can get this output only if you run under current credentials.
we have found a solution for this: run a process under specific credentials, and this process will run another secondary process without any credentials, and so this secondary process will be able to get the standard output.
it's not really elegant, if someone have another ideas/solution ?
Nicolas Dujacquier on November 14, 2005 7:24 AMHere's C# impersonation code, someone else has already given you info on how to redirect stdio. It could have been formatted better but I selectively pulled bits out of a wrapper class I'd written for a project. Please bear in mind that there are security issues here to do with the way that CreateProcessWithLogonW searches for the executable to launch. Refer to https://buildsecurityin.us-cert.gov/portal/article/knowledge/coding_rules/RULE_0029.xml for more info:
const int logonWithProfile = 1;
const int logonTypeNetwork = 3;
const int logonProviderDefault = 0;
ProcessInformation processInfo = new ProcessInformation();
StartupInformation startupInfo = new StartupInformation();
startupInfo.cb = Marshal.SizeOf(typeof(StartupInformation));
startupInfo.reserved = null;
CreateProcessWithLogonW("username", "domain", "password", logonWithProfile, "c:\path\whoami.exe", "c:\path\whoami.exe", 0, IntPtr.Zero, null, ref startupInfo, out processInfo))
if (processInfo.hProcess != IntPtr.Zero) CloseHandle(processInfo.hProcess);
if (processInfo.hThread != IntPtr.Zero) CloseHandle(processInfo.hThread);
///
/// CreateProcessWithLogonW is the unmangaged method used to launch a process under the context of
/// alternative, user provided, credentials. It is called by the managed method CreateProcessAsUser
/// defined earlier in this class. Further information is available on MSDN under
/// CreateProcessWithLogonW (a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/"http://msdn.microsoft.com/library/default.asp?url=/library/en-us//a
/// dllproc/base/createprocesswithlogonw.asp).
///
/// Whether to load a full user profile(param value = 1) or perform a
/// network only (param value = 2) logon.
/// The application to execute (populate either this parameter
/// or the commandLine parameter).
/// The command to execute.
/// Flags that control how the process is created.
///
[DllImport("advapi32.dll", CharSet=CharSet.Unicode, ExactSpelling=true, SetLastError=true)]
static extern bool CreateProcessWithLogonW(
string userName,
string domain,
string password,
int logonFlags,
string applicationPath,
string commandLine,
int creationFlags,
IntPtr environment,
string currentDirectory,
ref StartupInformation startupInformation,
out ProcessInformation processInformation);
/// CloseHandle closes an open object handle.
[DllImport("kernel32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseHandle(IntPtr handle);
///
/// The StartupInformation structure is used to specify the window station, desktop, standard handles
/// and appearance of the main window for the new process. Further information is available on MSDN
/// under STARTUPINFO (a href="http://msdn.microsoft.com/library/en-us/dllproc/base/startupinfo_str.asp)."http://msdn.microsoft.com/library/en-us/dllproc/base/startupinfo_str.asp)./a
///
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
struct StartupInformation
{
internal int cb;
internal string reserved;
internal string desktop;
internal string title;
internal int x;
internal int y;
internal int xSize;
internal int ySize;
internal int xCountChars;
internal int yCountChars;
internal int fillAttribute;
internal int flags;
internal UInt16 showWindow;
internal UInt16 reserved2;
internal byte reserved3;
internal IntPtr stdInput;
internal IntPtr stdOutput;
internal IntPtr stdError;
}
///
/// The ProcessInformation structure contains information about the newly created process and its
/// primary thread.
///
/// hProcess is a handle to the newly created process.
/// hThread is a handle to the primary thread of the newly created process.
[StructLayout(LayoutKind.Sequential)]
struct ProcessInformation
{
internal IntPtr hProcess;
internal IntPtr hThread;
internal int processId;
internal int threadId;
}
Look at full threaded shellicious:
http://www.codinghorror.com/blog/archives/000136.html
Angel - your code isn't working because you're asking for the contents of the StdErr before the process has finished - at that point in time, ReadToEnd probably has nothing to give you. Note that redirecting StdOut and StdErr gives threat of deadlock, so unless you're sure there isn't going to be very much info, you should use threading. There's a good example on microsoft.com somewhere (sorry, I don't have a link to hand).
Rich on December 8, 2005 6:07 AMNicolas D - I've just come across the same thing. I want to launch a 3rdParty exe from my web app and capture the output/error. I'm very familiar with this process having used it a lot in previous versions of dot net, and I've been using streams for years.
I noticed that dot net 2.0 had extra domain\username\password properties so you could launch a process as someone else. I'm trying to use StdOut and StdErr redirection to grab the output of the 3rdparty EXE that I'm running. However, this isn't working, and here's what I've found out so far.
I already knew that all processes have stdin, stdout, stderr. However, processes that are launched by a mouse-click don't get these set up. (I couldn't believe this.) All my experience led me to think that they were there; but just redirected to (if you pardon the Unix expression) "piped to /dev/NULL". For example, go to a command prompt and type "devenv.exe" (in the relevant folder) and it will launch Visual Studio. Type "devenv.exe /?" and the app will write stuff to standard out. Type "devenv.exe /?c:\junk.txt" and nothing appears; because the standard output has been redirected to the 'junk.txt' file.
Similarly, I wrote a trivial C# Windows app, which writes to Console.Out and Console.Error during startup and on button clicks. Launch it from command line with redirection, and all of my messages arrive in the file. However, create a shortcut for the same redirecting command, launch it, and the file doesn't appear. It seems that when you run an app from the command prompt, WinForms fixes your stdin, stdout and stderr, and it all works fine. But if you click on something, it doesn't get the Std streams.
For example, I wrote a trivial console app to wrap launching a process as a different user. I ran this from the command prompt, and it worked fine. So then I wrote a windows app to make use of the console app (which works), and it failed (System.ComponentModel.Win32Exception: The handle is invalid at System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo). Bizarrely (and you won't believe this - I didn't) if you run the windows app from the command line it works!
The problem is caused because when the child process is launched by System.Diagnostics.Process as a different user, it tries to hijack the Std streams of the parent process; but if that was a clicked-on-Gui-app, it doesn't have them, and rather than noticing this and setting them up for you, it crashes. So basically, you have to do it yourself (I don't know how yet, but I've seen a few things around that I'll try.)
Shellicious wraps process launching as the same user - it doesn't use the new feature in dot net 2.0 of being able to launch as a different user, as Nicolas D and myself are trying to do. The code within the .net framework branches depending on whether you've given a user or not. If you supply values to the Domain, UserName and Password properties, you will find that it only works if you launch it from a Command Prompt. If you launch the same program by double-clicking the file (or a shortcut), it will fail with the Win32 invalid handle error mentioned earlier.
Rich on December 12, 2005 9:48 AMIve just re-read my post on the 8th, and noticed that I didn't make it clear that I need to launch the 3rdParty exe as a particular user...
Rich on December 12, 2005 9:58 AMShellicious wraps process launching as the same user
so unless you're sure there isn't going to be very much info, you should use threading. There's a good example on microsoft.com somewhere (sorry, I don't have a link to hand).
Sorry, I wasn't clear. I mentioned Shellicious not because of the user impersonation issue, but because of the multiple threads necessary to capture output and error.
Jeff Atwood on December 12, 2005 12:34 PMusing System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Security.Principal;
using System.Text;
/// summary
/// UserSpecificProcess extends the standard Process object to
/// create new processes under a different user than the calling parent process.
/// Also, the standard output of the child process redirected back to the parent process.
/// This is class is designed to operate inside an ASP.NET web application.
/// The assumption is that the calling thread is operating with an impersonated security token.
/// The this class will change the imperonated security token to a primary token,
/// and call CreateProcessAsUser.
/// A System.Diagnostics.Process object will be returned with appropriate properties set.
/// To use this function, the following security priviliges need to be set for the ASPNET account
/// using the local security policy MMC snap-in. CreateProcessAsUser requirement.
/// "Replace a process level token"/SE_ASSIGNPRIMARYTOKEN_NAME/SeAssignPrimaryTokenPrivilege
/// "Adjust memory quotas for a process"/SE_INCREASE_QUOTA_NAME/SeIncreaseQuotaPrivilege
///
/// This class was designed for .NET 1.1 for operating systems W2k an higher.
/// Any other features or platform support can be implemented by using the .NET reflector and
/// investigating the Process class.
/// /summary
public class UserSpecificProcess : Process
{
[StructLayout(LayoutKind.Sequential)]
public class CreateProcessStartupInfo
{
public int cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public int dwX;
public int dwY;
public int dwXSize;
public int dwYSize;
public int dwXCountChars;
public int dwYCountChars;
public int dwFillAttribute;
public int dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
public CreateProcessStartupInfo()
{
this.cb = Marshal.SizeOf(typeof(CreateProcessStartupInfo));
this.lpReserved = null;
this.lpDesktop = null;
this.lpTitle = null;
this.dwX = 0;
this.dwY = 0;
this.dwXSize = 0;
this.dwYSize = 0;
this.dwXCountChars = 0;
this.dwYCountChars = 0;
this.dwFillAttribute = 0;
this.dwFlags = 0;
this.wShowWindow = 0;
this.cbReserved2 = 0;
this.lpReserved2 = IntPtr.Zero;
this.hStdInput = IntPtr.Zero;
this.hStdOutput = IntPtr.Zero;
this.hStdError = IntPtr.Zero;
}
}
[StructLayout(LayoutKind.Sequential)]
public class CreateProcessProcessInformation
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
public CreateProcessProcessInformation()
{
this.hProcess = IntPtr.Zero;
this.hThread = IntPtr.Zero;
this.dwProcessId = 0;
this.dwThreadId = 0;
}
}
[StructLayout(LayoutKind.Sequential)]
public class SecurityAttributes
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
public SecurityAttributes()
{
this.nLength = Marshal.SizeOf(typeof(SecurityAttributes));
}
}
[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true, ExactSpelling=true)]
public static extern bool CloseHandle(HandleRef handle);
[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool CreateProcess([MarshalAs(UnmanagedType.LPTStr)] string lpApplicationName, StringBuilder lpCommandLine, SecurityAttributes lpProcessAttributes, SecurityAttributes lpThreadAttributes, bool bInheritHandles, int dwCreationFlags, IntPtr lpEnvironment, [MarshalAs(UnmanagedType.LPTStr)] string lpCurrentDirectory, CreateProcessStartupInfo lpStartupInfo, CreateProcessProcessInformation lpProcessInformation);
[DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
public static extern bool CreateProcessAsUserW(IntPtr token, [MarshalAs(UnmanagedType.LPTStr)] string lpApplicationName, [MarshalAs(UnmanagedType.LPTStr)] string lpCommandLine, SecurityAttributes lpProcessAttributes, SecurityAttributes lpThreadAttributes, bool bInheritHandles, int dwCreationFlags, IntPtr lpEnvironment, [MarshalAs(UnmanagedType.LPTStr)] string lpCurrentDirectory, CreateProcessStartupInfo lpStartupInfo, CreateProcessProcessInformation lpProcessInformation);
[DllImport("kernel32.dll", CharSet=CharSet.Ansi, SetLastError=true)]
public static extern IntPtr GetStdHandle(int whichHandle);
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode, SecurityAttributes lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, HandleRef hTemplateFile);
[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern IntPtr CreateNamedPipe(string name, int openMode, int pipeMode, int maxInstances, int outBufSize, int inBufSize, int timeout, SecurityAttributes lpPipeAttributes);
[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern int GetConsoleOutputCP();
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool DuplicateTokenEx(HandleRef hToken, int access, SecurityAttributes tokenAttributes, int impersonationLevel, int tokenType, ref IntPtr hNewToken);
// WinNT.h ACCESS TYPES
const int GENERIC_ALL = 0x10000000;
// WinNT.h enum SECURITY_IMPERSONATION_LEVEL
const int SECURITY_IMPERSONATION = 2;
// WinNT.h TOKEN TYPE
const int TOKEN_PRIMARY = 1;
// WinBase.h
const int STD_INPUT_HANDLE = -10;
const int STD_ERROR_HANDLE = -12;
// WinBase.h STARTUPINFO
const int STARTF_USESTDHANDLES = 0x100;
// Microsoft.Win23.NativeMethods
static IntPtr INVALID_HANDLE_VALUE = (IntPtr) (-1);
public static HandleRef NullHandleRef = new HandleRef(null, IntPtr.Zero);
/// summary
/// Starts the process with the security token of the calling thread.
/// If the security token has a token type of TokenImpersonation,
/// the token will be duplicated to a primary token before calling
/// CreateProcessAsUser.
/// /summary
/// param name="process"The process to start./param
public void StartAsUser()
{
StartAsUser(WindowsIdentity.GetCurrent().Token);
}
/// summary
/// Starts the process with the given security token.
/// If the security token has a token type of TokenImpersonation,
/// the token will be duplicated to a primary token before calling
/// CreateProcessAsUser.
/// /summary
/// param name="process"/param
public void StartAsUser(IntPtr userToken)
{
if (StartInfo.UseShellExecute)
{
throw new InvalidOperationException("can't call this with shell execute");
}
// just assume that the securityToken is of TokenImpersonation and create a primary.
IntPtr primayUserToken = CreatePrimaryToken(userToken);
CreateProcessStartupInfo startupInfo = new CreateProcessStartupInfo();
CreateProcessProcessInformation processInformation = new CreateProcessProcessInformation();
IntPtr stdinHandle;
IntPtr stdoutReadHandle;
IntPtr stdoutWriteHandle = IntPtr.Zero;
IntPtr stderrHandle;
try
{
stdinHandle = GetStdHandle(STD_INPUT_HANDLE);
MyCreatePipe(out stdoutReadHandle, out stdoutWriteHandle, false);
stderrHandle = GetStdHandle(STD_ERROR_HANDLE);
//assign handles to startup info
startupInfo.dwFlags = STARTF_USESTDHANDLES;
startupInfo.hStdInput = stdinHandle;
startupInfo.hStdOutput = stdoutWriteHandle;
startupInfo.hStdError = stderrHandle;
string commandLine = GetCommandLine();
int creationFlags = 0;
IntPtr environment = IntPtr.Zero;
string workingDirectory = GetWorkingDirectory();
// create the process or fail trying.
if (!CreateProcessAsUserW(
primayUserToken,
null,
commandLine,
null,
null,
true,
creationFlags,
environment,
workingDirectory,
startupInfo,
processInformation))
{
throw new Win32Exception();
}
}
finally
{
// close thread handle
if (processInformation.hThread != INVALID_HANDLE_VALUE)
{
CloseHandle(new HandleRef(this, processInformation.hThread));
}
// close client stdout handle
CloseHandle(new HandleRef(this, stdoutWriteHandle));
}
// get reader for standard output from the child
Encoding encoding = Encoding.GetEncoding(GetConsoleOutputCP());
StreamReader standardOutput = new StreamReader(new FileStream(stdoutReadHandle, FileAccess.Read, true, 0x1000, true), encoding);
// set this on the object accordingly.
typeof(Process).InvokeMember("standardOutput",
BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Instance,
null, this, new object[]{standardOutput});
// scream if a process wasn't started instead of returning false.
if (processInformation.hProcess == IntPtr.Zero)
{
throw new Exception("failed to create process");
}
// configure the properties of the Process object correctly
typeof(Process).InvokeMember("SetProcessHandle",
BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance,
null, this, new object[]{processInformation.hProcess});
typeof(Process).InvokeMember("SetProcessId",
BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance,
null, this, new object[]{processInformation.dwProcessId});
}
/// summary
/// Creates a primayToken out of an existing token.
/// /summary
/// param name="userToken"/param
private IntPtr CreatePrimaryToken(IntPtr userToken)
{
SecurityAttributes securityAttributes = new SecurityAttributes();
IntPtr primaryUserToken = IntPtr.Zero;
if (!DuplicateTokenEx(new HandleRef(this, userToken), GENERIC_ALL, securityAttributes, SECURITY_IMPERSONATION, TOKEN_PRIMARY, ref primaryUserToken))
{
throw new Win32Exception();
}
return primaryUserToken;
}
/// summary
/// Gets the appropriate commandLine from the process.
/// /summary
/// param name="process"/param
/// returns/returns
private string GetCommandLine()
{
StringBuilder builder1 = new StringBuilder();
string text1 = StartInfo.FileName.Trim();
string text2 = StartInfo.Arguments;
bool flag1 = text1.StartsWith("\"") text1.EndsWith("\"");
if (!flag1)
{
builder1.Append("\"");
}
builder1.Append(text1);
if (!flag1)
{
builder1.Append("\"");
}
if ((text2 != null) (text2.Length 0))
{
builder1.Append(" ");
builder1.Append(text2);
}
return builder1.ToString();
}
/// summary
/// Gets the working directory or returns null if an empty string was found.
/// /summary
/// returns/returns
private string GetWorkingDirectory()
{
return (StartInfo.WorkingDirectory != string.Empty) ? StartInfo.WorkingDirectory : null;
}
/// summary
/// A clone of Process.CreatePipe. This is only implemented because reflection with
/// out parameters are a pain.
/// Note: This is only finished for w2k and higher machines.
/// /summary
/// param name="parentHandle"/param
/// param name="childHandle"/param
/// param name="parentInputs"Specifies whether the parent will be performing the writes./param
public static void MyCreatePipe(out IntPtr parentHandle, out IntPtr childHandle, bool parentInputs)
{
string pipename = @"\\.\pipe\Global\" + Guid.NewGuid().ToString();
SecurityAttributes attributes2 = new SecurityAttributes();
attributes2.bInheritHandle = false;
parentHandle = CreateNamedPipe(pipename, 0x40000003, 0, 0xff, 0x1000, 0x1000, 0, attributes2);
if (parentHandle == INVALID_HANDLE_VALUE)
{
throw new Win32Exception();
}
SecurityAttributes attributes3 = new SecurityAttributes();
attributes3.bInheritHandle = true;
int num1 = 0x40000000;
if (parentInputs)
{
num1 = -2147483648;
}
childHandle = CreateFile(pipename, num1, 3, attributes3, 3, 0x40000080, NullHandleRef);
if (childHandle == INVALID_HANDLE_VALUE)
{
throw new Win32Exception();
}
}
}
Rich,
I have the same issue with the invalid handle when launching from the GUI. .Net 2.0, setting username and password for ProcessStartInfo.
Did you ever figure out a workaround?
Thanks,
Julie.
I need send 5 param to .exe application.....and receive a value....
How i do this....help
Marco on March 22, 2006 3:00 AMConcerning the "Handle is Invalid" message that Rich and Julie mentioned, try this before starting the process:
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
And to Marco, set p.StartInfo.Arguments to your list of arguments, separated by spaces (perhaps using String.Join).
kurt on November 2, 2006 12:58 PMI keep getting an invalid handle on childHandle = CreateFile(pipename, num1, 3, attributes3, 3, 0x40000080, NullHandleRef);
inside MyCreatePipe() any suggestions. The above suggestion does not change any input parameters. . . hmmm. thanks
see http://wiki.ittoolbox.com/index.php/HOWTO:Fix_%22Binding_handle_is_invalid%22_error_in_Visual_2005
jo on April 26, 2007 6:54 AMYou make it sound like this is a bad thing, to have an asp.net or web service run as the user who logged in. That would present security problems. Say I was a malicious programmer. If I detect that an admin or manager has logged into my system, If the asp.net process could used those credentials, I have free reign to access resources that I plainly should not be accessing.
Credentials are burned once logging into an asp.net page or web service for security reasons. If your application needs to access specific resources, either have internal credentials that have access rights to the specific services/resources you want, or give the local asp.net account access rights and roles.
OmegaMan on August 13, 2007 9:20 AM@tiedyemark on December 22, 2005 06:07 PM:
InvokeMember on SetProcessHandle fails:
Method 'System.Diagnostics.Process.SetProcessHandle' not found.
How should the process handle be set?
ge on October 10, 2007 8:36 AM hi all
I wish to use the win32 api CreateProcessWithLogonW function
in a c++ program, to lunch a remote desktop connection programatically. and send the password programatically without
the password popup window.
I am the client (in windows 2000 professional) remote desktop. using the ocx version of rdp client.
all samples force the developer to use vc.net , I wish not to use the .net or asp or any other compiler except vc6.0 (without this anoing .net package). I know this function is part of .net. but I wish to use it transparently by loading the api function from the dll in c++ program.
can it be done??????
pleas reply to
kovacsio@hotmail.com
a
a on June 27, 2008 2:41 AMHey, first of all, its a good thread.
I want to start an executable (which can't be treated as a service-like application) from within my ASP.Net code, meaning it needs to open a window somehow. (I've tried to install the exe as a service, but that would result in the same). If I run my Webpage with a local server (e.g. visual) it works fine, probably because there is a profile active where to open the window in. If I run it with IIS it does not, allthough I am running the appl. under a different user.
Anyway, all I see is the exe under the right unser in my taskmanager, but the exe doesnt do anything. (emule...in case that helps)
Here is my code:
Process p_exec_EMULE = new Process();
string user = Membership.GetUser().UserName;
string pass = ...;
string dir = @...;
p_exec_EMULE.StartInfo.FileName = dir + emule.exe;
p_exec_EMULE.StartInfo.UseShellExecute = false;
p_exec_EMULE.StartInfo.WorkingDirectory = dir;
p_exec_EMULE.StartInfo.LoadUserProfile = true;
p_exec_EMULE.StartInfo.UserName = user;
p_exec_EMULE.StartInfo.Password = setSecureString(pass);
if (!isRunning(user, emule.exe){
p_exec_EMULE.Start();
As I said, works fine if the webserver runs within a logged on account...but not with IIS...even if User is logged on...
any ideas?
Tom on October 23, 2008 6:53 AMRealy amazing...
suni on November 22, 2008 8:45 AMThis below problem gives head ache for last 4 days. If you can could you please help.
Background:
I have a web service which accept requests from different regions for task. Based on regions ID, the web service submits a request to impersonate the regional service account inside a COM+ object then executes the task. This is what my requirement is. The COM object always runs under US regional service account.
if process is executed by the same user who executes the COM+, all works fine..even process gets started and file is getting executed..etc
If the executer is different from the COM+ users, the process is getting terminated prematurely. If I give the wrong user name or password or workingdirectory or file name exception is thrown out.. but the moment i set all values right.. nothing .. none.. no exception error.. any idea? I checked user permissions.. i even added user into administrative group and provided impersonate a client after authentication rights and allow log on locally on secpol... this code is residing inside a COM+ object and COM+ object is running under another administrative account. I am trying to execute an .exe file
I notice the process being started on process monitor but nothing happens after the process starts.. the command is being closed in seconds.
try
{
SecureString passSecure = new SecureString();
char[] passwordChars = password.ToCharArray();
foreach (char c in passwordChars)
{
passSecure.AppendChar(c);
}
process = new Process();
process.StartInfo.WorkingDirectory = brkWorkingDir.ToString();
process.StartInfo.FileName = brkFileName.ToString();
process.StartInfo.Arguments = argument.ToString();
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.UserName = userName;
process.StartInfo.Password = passSecure;
process.StartInfo.Domain = domain;
process.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
process.StartInfo.LoadUserProfile = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardInput = true;
process.Start();
resultString = process.StandardError.ReadToEnd();
resultString = resultString + process.StandardOutput.ReadToEnd();
resultString = resultString.Replace(', );
}
catch (Win32Exception e2)
{
resultString = loop CMP BB user - Work Order - Exceptional Error: +e2.Message+ +e2.StackTrace+ Native error code is: +e2.NativeErrorCode;
}
finally
{
if (null!=process)
{
process.Dispose();
}
}
Yeaa that is a real pain, I also observed the same as Durairaj:
...after setting all values right.. nothing .. none.. no exception error.. any idea?...
I wonder why no exception is thrown?
great_scandinavian on December 29, 2008 12:47 PMShellicious wraps process launching as the same user - it doesn't use the new feature in dot net 2.0 of being able to launch as a different user, as Nicolas D and myself are trying to do. The code within the .net framework branches depending on whether you've given a user or not. If you supply values to the Domain, UserName and Password properties, you will find that it only works if you launch it from a Command Prompt. If you launch the same program by double-clicking the file (or a shortcut), it will fail with the Win32 invalid handle error mentioned earlier.
http://sadushki.ru/
So there is no solution for ASP.net impersonate???
AD on March 16, 2009 10:55 AMYou make it sound like this is a bad thing, to have an asp.net or web service run as the user who logged in. That would present security problems. Say I was a malicious programmer. If I detect that an admin or manager has logged into my system, If the asp.net process could used those credentials, I have free reign to access resources that I plainly should not be accessing.
http://sudobase.ru
The comments to this entry are closed.
|
|
Traffic Stats |