2008-10-13 11 views
17

में उन्नत नहीं किया गया है मेरे पास एक ऐसा एप्लिकेशन है जिसे मुझे व्यवस्थापक के रूप में चलाने के लिए है। कि आवेदन कीVista (.NET)

एक छोटा सा हिस्सा Process.Start

साथ अन्य अनुप्रयोगों शुरू करने के लिए शुरू कर दिया आवेदन भी प्रशासक के रूप में चलाया जाएगा है, लेकिन मैं नहीं बल्कि उन्हें 'सामान्य' उपयोगकर्ता के रूप में चलाने देखना चाहते हैं।

मैं इसे कैसे पूरा करूं?

/जोहान/

+0

नमूना कोड, यहाँ सहित विवरण,: http://blogs.msdn.com/b/aaron_margosis/archive/2009/06/06/faq-how-do-i-start-a-program- as-the-desktop-user-from-an-elevated-app.aspx –

+0

इसके बारे में पूर्ण स्रोत कोड नमूना के साथ कोई अंतिम समाधान? – Kiquenet

+0

स्वीकार्य उत्तर उस समय मेरे लिए काम करता था। – idstam

उत्तर

13

WinSafer एपीआई की अनुमति देने के एक प्रक्रिया है, एक सीमित सामान्य, या भूमि से ऊपर के रूप में शुरू होने की का एक उदाहरण है उपयोगकर्ता।

नमूना उपयोग:

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); 
    } 
} 

पी/आह्वान घोषणाओं:

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", SetLastError = true, 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", SetLastError = true, 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 
+3

आईआईआरसी, एक सुरक्षित टोकन के साथ शुरू की गई प्रक्रिया अभी भी @ उच्च आईएल चलाती है यदि माता-पिता की प्रक्रिया उच्च आईएल थी तो आपको टोकन में व्यवस्थापक एसआईडी से इनकार कर दिया जा सकता है, लेकिन यह सामान्य उपयोगकर्ता टोकन – Anders

+0

नहीं है, मैंने अभी आईई स्टार्टअप पर जासूसी की है। यह CreateProcessAsUserW() का उपयोग कर आईई को फिर से शुरू करता है, इसलिए ... –

+0

RedirectStandardOutput और RedirectStandardError के लिए क्या है? इसके बारे में कोई नमूना? – Kiquenet

6

से: http://go.microsoft.com/fwlink/?LinkId=81232

एक अक्सर प्रश्न पूछा कैसे एक ऊंचा प्रक्रिया से एक गैर-ऊपर उठाया ऐप्स लॉन्च करने की है, या अधिक मौलिक रूप से, कैसे मैं एक शुरू करने के लिए है एक बार जब मैं ऊंचा हो रहा हूं तो मेरे अन-उन्नत टोकन का उपयोग कर प्रक्रिया। के बाद से वहाँ यह करने के लिए कोई सीधा रास्ता है, स्थिति आमतौर पर मानक उपयोगकर्ता के रूप में मूल ऐप्लिकेशन को लॉन्च करने और केवल आवेदन है कि व्यवस्थापकीय अधिकार की आवश्यकता होती है उन लोगों के भाग को ऊपर उठाने से बचा जा सकता। यह तरीका हमेशा एक गैर-उन्नत प्रक्रिया है जिसका उपयोग अतिरिक्त अनुप्रयोगों को लॉन्च करने के लिए किया जा सकता है क्योंकि वर्तमान में डेस्कटॉप उपयोगकर्ता पर लॉग ऑन है। कभी-कभी, एक उन्नत प्रक्रिया को एप्लिकेशन को ऊंचा करने की आवश्यकता होती है। यह विंडोज 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 <windows.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <comdef.h> 
#include <comutil.h> 
//Include Task header files - Included in Windows Vista Beta-2 SDK from MSDN 
#include <taskschd.h> 
#include <conio.h> 
#include <iostream> 
#include <time.h> 

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; 
} 
+1

लिंक किया गया लेख स्थानांतरित हो गया, और अब उस उद्धरण को शामिल नहीं किया गया है। उद्धरण के लिए गुगलिंग मूल लेख पाता है, जो एक ही लेख के "संदर्भ" खंड में नमूना कोड का उल्लेख करता है। अनुमानतः, लेख में कोई कोड नमूना नहीं है। फिर भी स्टैक ओवरफ्लो पर जवाब देने का एक अन्य कारण, उत्तरदाताओं के लिंक नहीं। –

+4

बताएं जेफ एटवुड –

+1

स्थानांतरित आलेख यहां है: http://msdn.microsoft.com/en-us/library/windows/desktop/bb756914.aspx; संदर्भ अनुभाग जिसमें कोड नमूना शामिल है, बाएं हाथ के कॉलम में "यूएसी संदर्भ" लिंक के अंतर्गत पाया जा सकता है। (लेख को कई पृष्ठों में विभाजित किया गया है।) – gpvos

2

मैं था वही आवश्यकता है और मैं विंडोज़ से कार्य शेड्यूलर सेवा का उपयोग करने के लिए समाधान में आया हूं।

तो, पहले the Task Scheduler Managed Wrapperlibrary to your project जोड़ सकते हैं और एक कार्य बनाने के लिए इस कोड का उपयोग, यह कॉन्फ़िगर के रूप में सीमित उपयोगकर्ता (td.Principal.RunLevel = TaskRunLevel.LUA;) को चलाने के लिए, रजिस्टर कार्य, कार्य चलाने के लिए और खत्म करने के बाद, कार्य को हटाने।

// Get the service on the local machine 
using (var ts = new TaskService()) 
{ 
    const string taskName = "foo"; 

    // Create a new task definition and assign properties 
    var td = ts.NewTask(); 
    td.RegistrationInfo.Description = "start foo.exe as limited user"; 

    // Create an action that will launch foo.exe, with argument bar in workingdir C:\\ 
    td.Actions.Add(new ExecAction("C:\\foo.exe", "bar", "C:\\")); 

    td.Settings.Priority = ProcessPriorityClass.Normal; 

    // run with limited token 
    td.Principal.RunLevel = TaskRunLevel.LUA; 

    td.Settings.AllowDemandStart = true; 

    td.Settings.DisallowStartIfOnBatteries = false; 

    td.Settings.StopIfGoingOnBatteries = false; 

    // Register the task in the root folder 
    var ret = ts.RootFolder.RegisterTaskDefinition(taskName, td); 

    var fooTask = ts.FindTask(taskName, true); 
    if (null != fooTask) 
    { 
     if (fooTask.Enabled) 
     { 
      fooTask.Run(); 

      Thread.Sleep(TimeSpan.FromSeconds(1)); 

      // find process and wait for Exit 
      var processlist = Process.GetProcesses(); 

      foreach(var theprocess in processlist) 
      { 
       if (theprocess.ProcessName != "foo") 
        continue; 

       theprocess.WaitForExit(); 
       break; 
      } 
     } 
    } 

    // Remove the task we just created 
    ts.RootFolder.DeleteTask(taskName); 
}