当前位置:  开发笔记 > 编程语言 > 正文

如何在Vista(.NET)中运行NOT raise

如何解决《如何在Vista(.NET)中运行NOTraise》经验,为你挑选了2个好方法。

我有一个应用程序,我必须以管理员身份运行.

该应用程序的一小部分是使用Process.Start启动其他应用程序

启动的应用程序也将作为管理员运行,但我宁愿看到它们作为"普通"用户运行.

我该如何做到这一点?

/约翰/



1> Ian Boyd..:

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/Invoke声明:

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace PInvoke
{
   public class WinSafer
   {
      /// 
      /// The SaferCreateLevel function opens a SAFER_LEVEL_HANDLE.
      /// 
      /// The scope of the level to be created.
      /// The level of the handle to be opened.
      /// Must be SaferOpenFlags.Open
      /// The returned SAFER_LEVEL_HANDLE. When you have finished using the handle, release it by calling the SaferCloseLevel function.
      /// This parameter is reserved for future use. IntPtr.Zero
      /// 
      [DllImport("advapi32", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
      public static extern bool SaferCreateLevel(SaferLevelScope scopeId, SaferLevel levelId, SaferOpen openFlags,
            out IntPtr levelHandle, IntPtr reserved);

      /// 
      /// The SaferComputeTokenFromLevel function restricts a token using restrictions specified by a SAFER_LEVEL_HANDLE.
      /// 
      /// 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.
      /// 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.
      /// The resulting restricted token.
      /// Specifies the behavior of the method.
      /// Reserved for future use. This parameter should be set to IntPtr.EmptyParam.
      /// 
      [DllImport("advapi32", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
      public static extern bool SaferComputeTokenFromLevel(IntPtr levelHandle, IntPtr inAccessToken,
            out IntPtr outAccessToken, SaferTokenBehaviour flags, IntPtr lpReserved);

      /// 
      /// The SaferCloseLevel function closes a SAFER_LEVEL_HANDLE that was opened by using the SaferIdentifyLevel function or the SaferCreateLevel function.
      /// The SAFER_LEVEL_HANDLE to be closed.
      /// TRUE if the function succeeds; otherwise, FALSE. For extended error information, call GetLastWin32Error.
      [DllImport("advapi32", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
      public static extern bool SaferCloseLevel(IntPtr levelHandle);
   } //class WinSafer

   /// 
   /// Specifies the behaviour of the SaferComputeTokenFromLevel method
   /// 
   public enum SaferTokenBehaviour : uint
   {
      /// 
      Default = 0x0,
      /// If the OutAccessToken parameter is not more restrictive than the InAccessToken parameter, the OutAccessToken parameter returns NULL.
      NullIfEqual = 0x1,
      /// 
      CompareOnly = 0x2,
      /// 
      MakeInert = 0x4,
      /// 
      WantFlags = 0x8
   }

   /// 
   /// The level of the handle to be opened.
   /// 
   public enum SaferLevel : uint
   {
      /// Software will not run, regardless of the user rights of the user.
      Disallowed = 0,
      /// 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.
      Untrusted = 0x1000,
      /// Software cannot access certain resources, such as cryptographic keys and credentials, regardless of the user rights of the user.
      Constrained = 0x10000,
      /// 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.
      NormalUser = 0x20000,
      /// Software user rights are determined by the user rights of the user.
      FullyTrusted = 0x40000
   }

   /// 
   /// The scope of the level to be created.
   /// 
   public enum SaferLevelScope : uint
   {
      /// The created level is scoped by computer.
      Machine = 1,
      /// The created level is scoped by user.
      User = 2
   }

   public enum SaferOpen : uint
   {
      Open = 1
   }
} //namespace PInvoke


IIRC,如果父进程为高IL,则使用更安全令牌启动的进程仍会运行@High IL,因此您可能在令牌中有拒绝管理员SID,但它不是正常的用户令牌
我还想包含一个指向更好方法的链接:“ [常见问题解答:如何从桌面应用程序中以桌面用户身份启动程序?](http://blogs.msdn.com/b/aaron_margosis/archive/2009 / 06/06 / faq-如何从高架app.aspx中作为桌面用户启动程序?)。上面我的SAFER代码中的常见错误是错误的假设,即提升后的应用程序像我一样运行。获取正在运行的应用程序的凭据,““将其关闭” *”,然后以同一用户但“标准”身份启动该应用程序是不正确的。
Raymond Chen [关于同一主题](http://blogs.msdn.com/b/oldnewthing/archive/2013/11/18/10468726.aspx).

2> Greg Dean..:

来自:http://go.microsoft.com/fwlink/?LinkId = 81232

一个经常被问到的问题是如何从提升的进程中启动未提升的应用程序,或者更重要的是,如何在我升级后使用未提升的令牌启动进程.由于没有直接的方法可以做到这一点,通常可以通过将原始应用程序作为标准用户启动并仅提升应用程序中需要管理权限的那些部分来避免这种情况.这样,始终存在一个非提升的进程,可用于以当前登录的桌面用户身份启动其他应用程序.但是,有时候,升级的进程需要让另一个应用程序无法运行.这可以通过在Windows Vista中使用任务计划程序来完成.

以下是如何安排未升级过程的示例(同样来自同一链接)

//---------------------------------------------------------------------
//  This file is part of the Microsoft .NET Framework SDK Code Samples.
// 
//  Copyright (C) Microsoft Corporation.  All rights reserved.
// 
//This source code is intended only as a supplement to Microsoft
//Development Tools and/or on-line documentation.  See these other
//materials for detailed information regarding Microsoft code samples.
// 
//THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
//KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//PARTICULAR PURPOSE.
//---------------------------------------------------------------------

/****************************************************************************
* Main.cpp - Sample application for Task Scheduler V2 COMAPI                * Component: Task Scheduler                          
* Copyright (c) 2002 - 2003, Microsoft Corporation 
* This sample creates a task to that launches as the currently logged on deskup user. The task launches as soon as it is registered.                                                             *
****************************************************************************/
#include "stdafx.h"
#include 
#include 
#include 
#include 
#include 
//Include Task header files - Included in Windows Vista Beta-2 SDK from MSDN
#include 
#include 
#include 
#include 

using namespace std;

#define CLEANUP \
pRootFolder->Release();\
        pTask->Release();\
        CoUninitialize();

HRESULT CreateMyTask(LPCWSTR, wstring);

void __cdecl wmain(int argc, wchar_t** argv)
{
wstring wstrExecutablePath;
WCHAR taskName[20];
HRESULT result;

if( argc < 2 )
{
printf("\nUsage: LaunchApp yourapp.exe" );
return;
}

// Pick random number for task name
srand((unsigned int) time(NULL));
wsprintf((LPWSTR)taskName, L"Launch %d", rand());

wstrExecutablePath = argv[1];

result = CreateMyTask(taskName, wstrExecutablePath);
printf("\nReturn status:%d\n", result);

}
HRESULT CreateMyTask(LPCWSTR wszTaskName, wstring wstrExecutablePath)
{
    //  ------------------------------------------------------
    //  Initialize COM.
TASK_STATE taskState;
int i;
    HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    if( FAILED(hr) )
    {
        printf("\nCoInitializeEx failed: %x", hr );
        return 1;
    }

    //  Set general COM security levels.
    hr = CoInitializeSecurity(
        NULL,
        -1,
        NULL,
        NULL,
        RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
        RPC_C_IMP_LEVEL_IMPERSONATE,
        NULL,
        0,
        NULL);

    if( FAILED(hr) )
    {
        printf("\nCoInitializeSecurity failed: %x", hr );
        CoUninitialize();
        return 1;
    }

    //  ------------------------------------------------------
    //  Create an instance of the Task Service. 
    ITaskService *pService = NULL;
    hr = CoCreateInstance( CLSID_TaskScheduler,
                           NULL,
                           CLSCTX_INPROC_SERVER,
                           IID_ITaskService,
                           (void**)&pService );  
    if (FAILED(hr))
    {
        printf("Failed to CoCreate an instance of the TaskService class: %x", hr);
        CoUninitialize();
        return 1;
    }

    //  Connect to the task service.
    hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
    if( FAILED(hr) )
    {
        printf("ITaskService::Connect failed: %x", hr );
        pService->Release();
        CoUninitialize();
        return 1;
    }

    //  ------------------------------------------------------
    //  Get the pointer to the root task folder.  This folder will hold the
    //  new task that is registered.
    ITaskFolder *pRootFolder = NULL;
    hr = pService->GetFolder( _bstr_t( L"\\") , &pRootFolder );
    if( FAILED(hr) )
    {
        printf("Cannot get Root Folder pointer: %x", hr );
        pService->Release();
        CoUninitialize();
        return 1;
    }

    //  Check if the same task already exists. If the same task exists, remove it.
    hr = pRootFolder->DeleteTask( _bstr_t( wszTaskName), 0  );

    //  Create the task builder object to create the task.
    ITaskDefinition *pTask = NULL;
    hr = pService->NewTask( 0, &pTask );

    pService->Release();  // COM clean up.  Pointer is no longer used.
    if (FAILED(hr))
    {
        printf("Failed to CoCreate an instance of the TaskService class: %x", hr);
        pRootFolder->Release();
        CoUninitialize();
        return 1;
    }


    //  ------------------------------------------------------
    //  Get the trigger collection to insert the registration trigger.
    ITriggerCollection *pTriggerCollection = NULL;
    hr = pTask->get_Triggers( &pTriggerCollection );
    if( FAILED(hr) )
    {
        printf("\nCannot get trigger collection: %x", hr );
  CLEANUP
        return 1;
    }

    //  Add the registration trigger to the task.
    ITrigger *pTrigger = NULL;

    hr = pTriggerCollection->Create( TASK_TRIGGER_REGISTRATION, &pTrigger );     
    pTriggerCollection->Release();  // COM clean up.  Pointer is no longer used.
    if( FAILED(hr) )
    {
        printf("\nCannot add registration trigger to the Task %x", hr );
        CLEANUP
        return 1;
    }
    pTrigger->Release();

    //  ------------------------------------------------------
    //  Add an Action to the task.     
    IExecAction *pExecAction = NULL;
    IActionCollection *pActionCollection = NULL;

    //  Get the task action collection pointer.
    hr = pTask->get_Actions( &pActionCollection );
    if( FAILED(hr) )
    {
        printf("\nCannot get Task collection pointer: %x", hr );
        CLEANUP
        return 1;
    }

    //  Create the action, specifying that it is an executable action.
    IAction *pAction = NULL;
    hr = pActionCollection->Create( TASK_ACTION_EXEC, &pAction );
    pActionCollection->Release();  // COM clean up.  Pointer is no longer used.
    if( FAILED(hr) )
    {
        printf("\npActionCollection->Create failed: %x", hr );
        CLEANUP
        return 1;
    }

    hr = pAction->QueryInterface( IID_IExecAction, (void**) &pExecAction );
    pAction->Release();
    if( FAILED(hr) )
    {
        printf("\npAction->QueryInterface failed: %x", hr );
        CLEANUP
        return 1;
    }

    //  Set the path of the executable to the user supplied executable.
   hr = pExecAction->put_Path( _bstr_t( wstrExecutablePath.c_str() ) );  

    if( FAILED(hr) )
    {
        printf("\nCannot set path of executable: %x", hr );
        pExecAction->Release();
        CLEANUP
        return 1;
    }
    hr = pExecAction->put_Arguments( _bstr_t( L"" ) );  

   if( FAILED(hr) )
    {
        printf("\nCannot set arguments of executable: %x", hr );
        pExecAction->Release();
        CLEANUP
        return 1;
    }

    //  ------------------------------------------------------
    //  Save the task in the root folder.
    IRegisteredTask *pRegisteredTask = NULL;
    hr = pRootFolder->RegisterTaskDefinition(
            _bstr_t( wszTaskName ),
            pTask,
      TASK_CREATE, 
_variant_t(_bstr_t( L"S-1-5-32-545")),//Well Known SID for \\Builtin\Users group
_variant_t(), 
TASK_LOGON_GROUP,
            _variant_t(L""),
            &pRegisteredTask);
    if( FAILED(hr) )
    {
        printf("\nError saving the Task : %x", hr );
        CLEANUP
        return 1;
    }
    printf("\n Success! Task successfully registered. " );
    for (i=0; i<100; i++)//give 10 seconds for the task to start
{
pRegisteredTask->get_State(&taskState);
if (taskState == TASK_STATE_RUNNING)
{
printf("\nTask is running\n");
break;
}
Sleep(100);
}
if (i>= 100) printf("Task didn't start\n");

    //Delete the task when done
    hr = pRootFolder->DeleteTask(
            _bstr_t( wszTaskName ),
            NULL);
    if( FAILED(hr) )
    {
        printf("\nError deleting the Task : %x", hr );
        CLEANUP
        return 1;
    }

    printf("\n Success! Task successfully deleted. " );

//  Clean up.
    CLEANUP
    CoUninitialize();
    return 0;
}


告诉杰夫阿特伍德
推荐阅读
落单鸟人
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有