首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在Windows 10上从提升管理员上下文启动非提升管理员进程?

如何在Windows 10上从提升管理员上下文启动非提升管理员进程?
EN

Stack Overflow用户
提问于 2016-06-21 15:04:36
回答 3查看 3.9K关注 0票数 5

是否有一种从提升的管理员进程创建正常管理员进程(而不是提升)的简单方法?我正在使用Windows 10 pro。现在的情况是,我正在尝试制作某种部署工具。该工具将在提升的管理员上下文中运行,以便将文件写入"Program“(并访问其他特权资源)。但是其中一个步骤是调用外部程序。当使用更高的管理员权限创建程序时,该程序似乎有一些奇怪的问题。我们必须在非提升的管理员上下文中启动它。我在MSDN博客中尝试了这种方法,https://blogs.msdn.microsoft.com/winsdk/2010/05/31/dealing-with-administrator-and-standard-users-context根本不起作用。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-06-21 18:07:47

解决办法有点复杂。也许您不能通过获取一种访问令牌并将其传递给createprocesswithtoken,从而直接从提升管理员转到非提升管理员,但您可以向另一个方向走得更远。您可以从提升的管理员转到具有更高权限的系统帐户。根据系统帐户特权,您应该能够在非提升级别的管理员上下文中启动进程。使用关键字“模拟”搜索可以给你很多例子。那么如何从提升的管理员到系统呢?您只能编写系统服务,并在提升的管理员上下文下创建/启动服务。

票数 0
EN

Stack Overflow用户

发布于 2017-05-03 19:35:50

下面是我的雷蒙德·陈密码版本,它通过C++异常添加错误处理。

首先,我们声明了一些帮助函数,用于从std::system_error抛出HRESULT异常,将GUID转换为string,将RAII包装器转换为COM初始化。

代码语言:javascript
运行
复制
#include <windows.h>
#include <shldisp.h>
#include <shlobj.h>
#include <exdisp.h>
#include <atlbase.h>
#include <stdlib.h>
#include <iostream>
#include <system_error>

template< typename T >
void ThrowIfFailed( HRESULT hr, T&& msg )
{
    if( FAILED( hr ) )
        throw std::system_error{ hr, std::system_category(), std::forward<T>( msg ) };
}

template< typename ResultT = std::string >
ResultT to_string( REFIID riid )
{
    LPOLESTR pstr = nullptr;
    if( SUCCEEDED( ::StringFromCLSID( riid, &pstr ) ) ) 
    {
        // Use iterator arguments to cast from wchar_t to char if element type of ResultT is char.
        ResultT result{ pstr, pstr + wcslen( pstr ) };
        ::CoTaskMemFree( pstr ); pstr = nullptr;
        return result;
    }
    return {};
}

struct ComInit
{
    ComInit() { ThrowIfFailed( ::CoInitialize( nullptr ), "Could not initialize COM" ); }
    ~ComInit() { ::CoUninitialize(); }
    ComInit( ComInit const& ) = delete;
    ComInit& operator=( ComInit const& ) = delete;
};

接下来是执行实际工作的函数。这与雷米·莱博的回答中的代码基本相同,但增加了错误处理(以及我的个人格式化风格)。

代码语言:javascript
运行
复制
void FindDesktopFolderView( REFIID riid, void **ppv )
{
    CComPtr<IShellWindows> spShellWindows;
    ThrowIfFailed( 
        spShellWindows.CoCreateInstance( CLSID_ShellWindows ),
        "Could not create instance of IShellWindows" );

    CComVariant vtLoc{ CSIDL_DESKTOP };
    CComVariant vtEmpty;
    long lhwnd = 0;
    CComPtr<IDispatch> spdisp;
    ThrowIfFailed( 
        spShellWindows->FindWindowSW(
            &vtLoc, &vtEmpty, SWC_DESKTOP, &lhwnd, SWFO_NEEDDISPATCH, &spdisp ),
        "Could not find desktop shell window" );

    CComQIPtr<IServiceProvider> spProv{ spdisp };
    if( ! spProv )
        ThrowIfFailed( E_NOINTERFACE, "Could not query interface IServiceProvider" );

    CComPtr<IShellBrowser> spBrowser;
    ThrowIfFailed( 
        spProv->QueryService( SID_STopLevelBrowser, IID_PPV_ARGS(&spBrowser) ),
        "Could not query service IShellBrowser" );

    CComPtr<IShellView> spView;
    ThrowIfFailed( 
        spBrowser->QueryActiveShellView( &spView ),
        "Could not query active IShellView" );

    ThrowIfFailed( 
        spView->QueryInterface( riid, ppv ),
        "Could not query interface " + to_string( riid ) + " from IShellView" );
}

void GetDesktopAutomationObject( REFIID riid, void **ppv )
{
    CComPtr<IShellView> spsv;
    FindDesktopFolderView( IID_PPV_ARGS(&spsv) );

    CComPtr<IDispatch> spdispView;
    ThrowIfFailed( 
        spsv->GetItemObject( SVGIO_BACKGROUND, IID_PPV_ARGS(&spdispView) ),
        "Could not get item object SVGIO_BACKGROUND from IShellView" );
    ThrowIfFailed( 
        spdispView->QueryInterface( riid, ppv ),
        "Could not query interface " + to_string( riid ) + " from ShellFolderView" );
}

void ShellExecuteFromExplorer(
    PCWSTR pszFile,
    PCWSTR pszParameters = nullptr,
    PCWSTR pszDirectory  = nullptr,
    PCWSTR pszOperation  = nullptr,
    int nShowCmd         = SW_SHOWNORMAL)
{
    CComPtr<IShellFolderViewDual> spFolderView;
    GetDesktopAutomationObject( IID_PPV_ARGS(&spFolderView) );

    CComPtr<IDispatch> spdispShell;
    ThrowIfFailed( 
        spFolderView->get_Application( &spdispShell ),
        "Could not get application object from IShellFolderViewDual" );

    CComQIPtr<IShellDispatch2> spdispShell2{ spdispShell };
    if( !spdispShell2 )
        ThrowIfFailed( E_NOINTERFACE, "Could not query interface IShellDispatch2" );

    ThrowIfFailed( 
        spdispShell2->ShellExecute(
            CComBSTR{ pszFile },
            CComVariant{ pszParameters ? pszParameters : L"" },
            CComVariant{ pszDirectory ? pszDirectory : L"" },
            CComVariant{ pszOperation ? pszOperation : L"" },
            CComVariant{ nShowCmd } ),
        "ShellExecute failed" );
}

使用示例:

代码语言:javascript
运行
复制
int main()
{
    try
    {
        ComInit init;
        ShellExecuteFromExplorer( L"http://www.stackoverflow.com" );
    }
    catch( std::system_error& e )
    {
        std::cout << "ERROR: " << e.what() << "\n"
            << "Error code: " << e.code() << std::endl;
    }
}

附加注释:

在使用此方法时,您可能会注意到,已启动应用程序的窗口并不总是到达前台,特别是当它已经在运行时。我的解决方法是在调用AllowSetForegroundWindow( ASFW_ANY )之前调用ShellExecuteFromExplorer(),以使进程能够将自己带到前台(我们不能指定进程ID,因为我们不知道将提前启动的进程)。

票数 2
EN

Stack Overflow用户

发布于 2018-12-15 16:25:34

这是Raymond方法,有错误处理,没有不幸的异常。

代码语言:javascript
运行
复制
#include <atlbase.h>
#include <Shlobj.h>

HRESULT FindDesktopFolderView(REFIID riid, void **ppv)
{
HRESULT hr;
CComPtr<IShellWindows> spShellWindows;
hr = spShellWindows.CoCreateInstance(CLSID_ShellWindows);
if(FAILED(hr))
    return hr;

CComVariant vtLoc { 0 };    // 0 = CSIDL_DESKTOP
CComVariant vtEmpty;
long lhwnd = 0;
CComPtr<IDispatch> spdisp;
hr = spShellWindows->FindWindowSW(&vtLoc, &vtEmpty, SWC_DESKTOP, &lhwnd, SWFO_NEEDDISPATCH, &spdisp);
if(FAILED(hr))
    return hr;

CComQIPtr<IServiceProvider> spProv{ spdisp };
if(!spProv)
    return E_NOINTERFACE;

CComPtr<IShellBrowser> spBrowser;
hr = spProv->QueryService(SID_STopLevelBrowser, IID_PPV_ARGS(&spBrowser));
if(FAILED(hr))
    return hr;

CComPtr<IShellView> spView;
hr = spBrowser->QueryActiveShellView(&spView);
if(FAILED(hr))
    return hr;

return spView->QueryInterface(riid, ppv);
}


HRESULT GetDesktopAutomationObject(REFIID riid, void **ppv)
{
HRESULT hr;
CComPtr<IShellView> spsv;
hr = FindDesktopFolderView(IID_PPV_ARGS(&spsv));
if(FAILED(hr))
    return hr;
if(!spsv)
    return E_NOINTERFACE;

CComPtr<IDispatch> spdispView;
hr = spsv->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARGS(&spdispView));
if(FAILED(hr))
    return hr;

return spdispView->QueryInterface(riid, ppv);
}


HRESULT ShellExecuteFromExplorer(PCWSTR pszFile, PCWSTR pszParameters, PCWSTR pszDirectory, PCWSTR pszOperation, int nShowCmd)
{
HRESULT hr;
CComPtr<IShellFolderViewDual> spFolderView;
hr = GetDesktopAutomationObject(IID_PPV_ARGS(&spFolderView));
if(FAILED(hr))
    return hr;

CComPtr<IDispatch> spdispShell;
hr = spFolderView->get_Application(&spdispShell);
if(FAILED(hr))
    return hr;

CComQIPtr<IShellDispatch2> spdispShell2{ spdispShell };
if(!spdispShell2)
    return E_NOINTERFACE;

// without this, the launched app is not moved to the foreground
AllowSetForegroundWindow(ASFW_ANY);

return spdispShell2->ShellExecute(
        CComBSTR{ pszFile },
        CComVariant{ pszParameters ? pszParameters : L"" },
        CComVariant{ pszDirectory ? pszDirectory : L"" },
        CComVariant{ pszOperation ? pszOperation : L"" },
        CComVariant{ nShowCmd } );
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37948064

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档