Vista (.NET)에서 실행되지 않는 방법
-
10-07-2019 - |
문제
관리자로 실행 해야하는 응용 프로그램이 있습니다.
해당 응용 프로그램의 한 부분은 Process.Start를 사용하여 다른 응용 프로그램을 시작하는 것입니다.
시작된 응용 프로그램은 관리자로도 실행되지만 '일반'사용자로 실행되는 것을 볼 수 있습니다.
어떻게 달성합니까?
/johan/
해결책
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", 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
다른 팁
에서: http://go.microsoft.com/fwlink/?linkid=81232
자주 묻는 질문은 고가 프로세스에서 유발되지 않은 응용 프로그램을 시작하는 방법, 또는 더 근본적으로 고가가 실행되면 Un-Exevated 토큰을 사용하여 프로세스를 시작하는 방법입니다. 이를 수행하는 직접적인 방법이 없기 때문에 원래 응용 프로그램을 표준 사용자로 시작하고 관리 권한이 필요한 응용 프로그램의 일부만 높이면 상황을 피할 수 있습니다. 이러한 방식으로 현재 데스크탑 사용자에 기록 된 추가 응용 프로그램을 시작하는 데 사용할 수있는 비 유전 프로세스가 항상 있습니다. 그러나 때로는 고가 프로세스가 다른 응용 프로그램을 실행하지 않아야합니다. 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 <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;
}
나는 같은 요구 사항을 가지고 있었고 Windows에서 작업 스케줄러 서비스를 사용하는 솔루션을 찾았습니다.
따라서 먼저 추가하십시오 그만큼 Task Scheduler Managed Wrapper
프로젝트에 라이브러리 이 코드를 사용하여 작업을 작성하고 제한된 사용자로 실행하도록 구성하십시오 (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);
}