我有一个应用程序,我必须以管理员身份运行。
该应用程序的一小部分是使用Process.Start启动其他应用程序
启动的应用程序也将作为管理员运行,但我宁愿看到它们作为“普通”用户运行。
我该如何做到这一点?
/约翰/
WinSafer API允许一个进程作为有限的,普通的或升级的用户启动。
样品用法:
CreateSaferProcess(@"calc.exe","",SaferLevel.normalUser);
源代码:
//http://odetocode.com/Blogs/scott/archive/2004/10/28/602.aspx
public static void CreateSaferProcess(String fileName,String arguments,SaferLevel saferLevel)
{
IntPtr saferLevelHandle = IntPtr.Zero;
//Create a SaferLevel handle to match what was requested
if (!WinSafer.SaferCreateLevel(
SaferLevelScope.User,saferLevel,SaferOpen.Open,out saferLevelHandle,IntPtr.Zero))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
try
{
//Generate the access token to use,based on the safer level handle.
IntPtr hToken = IntPtr.Zero;
if (!WinSafer.SaferComputetokenFromLevel(
saferLevelHandle,// SAFER Level handle
IntPtr.Zero,// NULL is current thread token.
out hToken,// Target token
SaferTokenBehavIoUr.Default,// No flags
IntPtr.Zero)) // Reserved
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
try
{
//Now that we have a security token,we can lauch the process
//using the standard CreateProcessAsUser API
STARTUPINFO si = new STARTUPINFO();
si.cb = Marshal.SizeOf(si);
si.lpDesktop = String.Empty;
PROCESS_informatION pi = new PROCESS_informatION();
// Spin up the new process
Boolean bResult = Windows.CreateProcessAsUser(
hToken,fileName,arguments,IntPtr.Zero,//process attributes
IntPtr.Zero,//thread attributes
false,//inherit handles
0,//CREATE_NEW_CONSOLE
IntPtr.Zero,//environment
null,//current directory
ref si,//startup info
out pi); //process info
if (!bResult)
throw new Win32Exception(Marshal.GetLastWin32Error());
if (pi.hProcess != IntPtr.Zero)
Windows.CloseHandle(pi.hProcess);
if (pi.hThread != IntPtr.Zero)
Windows.CloseHandle(pi.hThread);
}
finally
{
if (hToken != IntPtr.Zero)
Windows.CloseHandle(hToken);
}
}
finally
{
WinSafer.SaferCloseLevel(saferLevelHandle);
}
}
P /调用声明:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace PInvoke
{
public class WinSafer
{
/// <summary>
/// The SaferCreateLevel function opens a SAFER_LEVEL_HANDLE.
/// </summary>
/// <param name="scopeId">The scope of the level to be created.</param>
/// <param name="levelId">The level of the handle to be opened.</param>
/// <param name="openFlags">Must be SaferOpenFlags.Open</param>
/// <param name="levelHandle">The returned SAFER_LEVEL_HANDLE. When you have finished using the handle,release it by calling the SaferCloseLevel function.</param>
/// <param name="reserved">This parameter is reserved for future use. IntPtr.Zero</param>
/// <returns></returns>
[DllImport("advapi32",SetLastError = true,CallingConvention = CallingConvention.StdCall)]
public static extern bool SaferCreateLevel(SaferLevelScope scopeId,SaferLevel levelId,SaferOpen openFlags,out IntPtr levelHandle,IntPtr reserved);
/// <summary>
/// The SaferComputetokenFromLevel function restricts a token using restrictions specified by a SAFER_LEVEL_HANDLE.
/// </summary>
/// <param name="levelHandle">SAFER_LEVEL_HANDLE that contains the restrictions to place on the input token. Do not pass handles with a LevelId of SAFER_LEVELID_FULLYTRUSTED or SAFER_LEVELID_disALLOWED to this function. This is because SAFER_LEVELID_FULLYTRUSTED is unrestricted and SAFER_LEVELID_disALLOWED does not contain a token.</param>
/// <param name="inAccesstoken">Token to be restricted. If this parameter is NULL,the token of the current thread will be used. If the current thread does not contain a token,the token of the current process is used.</param>
/// <param name="outAccesstoken">The resulting restricted token.</param>
/// <param name="flags">Specifies the behavior of the method.</param>
/// <param name="lpReserved">Reserved for future use. This parameter should be set to IntPtr.EmptyParam.</param>
/// <returns></returns>
[DllImport("advapi32",CallingConvention = CallingConvention.StdCall)]
public static extern bool SaferComputetokenFromLevel(IntPtr levelHandle,IntPtr inAccesstoken,out IntPtr outAccesstoken,SaferTokenBehavIoUr flags,IntPtr lpReserved);
/// <summary>
/// The SaferCloseLevel function closes a SAFER_LEVEL_HANDLE that was opened by using the SaferIdentifyLevel function or the SaferCreateLevel function.</summary>
/// <param name="levelHandle">The SAFER_LEVEL_HANDLE to be closed.</param>
/// <returns>TRUE if the function succeeds; otherwise,FALSE. For extended error information,call GetLastWin32Error.</returns>
[DllImport("advapi32",CallingConvention = CallingConvention.StdCall)]
public static extern bool SaferCloseLevel(IntPtr levelHandle);
} //class WinSafer
/// <summary>
/// Specifies the behavIoUr of the SaferComputetokenFromLevel method
/// </summary>
public enum SaferTokenBehavIoUr : uint
{
/// <summary></summary>
Default = 0x0,/// <summary>If the OutAccesstoken parameter is not more restrictive than the InAccesstoken parameter,the OutAccesstoken parameter returns NULL.</summary>
NullIfEqual = 0x1,/// <summary></summary>
CompareOnly = 0x2,/// <summary></summary>
MakeInert = 0x4,/// <summary></summary>
WantFlags = 0x8
}
/// <summary>
/// The level of the handle to be opened.
/// </summary>
public enum SaferLevel : uint
{
/// <summary>Software will not run,regardless of the user rights of the user.</summary>
disallowed = 0,/// <summary>Allows programs to execute with access only to resources granted to open well-kNown groups,blocking access to Administrator and Power User privileges and personally granted rights.</summary>
Untrusted = 0x1000,/// <summary>Software cannot access certain resources,such as cryptographic keys and credentials,regardless of the user rights of the user.</summary>
Constrained = 0x10000,/// <summary>Allows programs to execute as a user that does not have Administrator or Power User user rights. Software can access resources accessible by normal users.</summary>
normalUser = 0x20000,/// <summary>Software user rights are determined by the user rights of the user.</summary>
FullyTrusted = 0x40000
}
/// <summary>
/// The scope of the level to be created.
/// </summary>
public enum SaferLevelScope : uint
{
/// <summary>The created level is scoped by computer.</summary>
Machine = 1,/// <summary>The created level is scoped by user.</summary>
User = 2
}
public enum SaferOpen : uint
{
Open = 1
}
} //namespace PInvoke