Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows 使用IShellDispatch2->;ShellExecute用于从提升进程启动非提升进程_Windows_Winapi_Uac - Fatal编程技术网

Windows 使用IShellDispatch2->;ShellExecute用于从提升进程启动非提升进程

Windows 使用IShellDispatch2->;ShellExecute用于从提升进程启动非提升进程,windows,winapi,uac,Windows,Winapi,Uac,我有以下代码(主要部分取自MS SDK v7.1示例代码,它演示了如何从提升的进程启动非提升的进程)- 提升和非提升过程将在(无监督的)服务器上启动,因此用户交互是不可能的(当然,配置部分除外,如果需要的话) 问题是,通过IShellDispatch2->ShellExecute启动的非提升进程仍然处于提升状态(预期为非提升状态)。 这是通过使用IsUserAnAdmin()API确认的。 你知道为什么通过ShellExecute()创建的进程仍然拥有提升的权限吗 一些更相关的细节:在我的机器上

我有以下代码(主要部分取自MS SDK v7.1示例代码,它演示了如何从提升的进程启动非提升的进程)- 提升和非提升过程将在(无监督的)服务器上启动,因此用户交互是不可能的(当然,配置部分除外,如果需要的话)

问题是,通过IShellDispatch2->ShellExecute启动的非提升进程仍然处于提升状态(预期为非提升状态)。 这是通过使用IsUserAnAdmin()API确认的。 你知道为什么通过ShellExecute()创建的进程仍然拥有提升的权限吗

一些更相关的细节:在我的机器上UAC被禁用。 基于VS 2013的应用程序表现为: ) (如果有助于解决此问题,可以使用/MANIFEST:no linker标志禁用显化)。 我使用VS2013在Windows7x64上编译它

#include <shlwapi.h>
#include <shlobj.h>
#include <comutil.h>
#pragma comment(lib, "shlwapi.lib")

// link with (at least) OleAut32.lib shlwapi.lib comsupp.lib shell32.lib uuid.lib
// sorry for the bad formatting 

int main(void)
{
std::wstring processName(L"myapp.exe"), processParams(L"-myAppParam");
LPWSTR processNamePtr = const_cast<LPWSTR>(processName.c_str());
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(hr))
{
  IShellView *psv;
  HRESULT hr = GetShellViewForDesktop(IID_PPV_ARGS(&psv));
  if (SUCCEEDED(hr))
  {
    IShellDispatch2 *psd;
    hr = GetShellDispatchFromView(psv, IID_PPV_ARGS(&psd));
    if (SUCCEEDED(hr))
    {
      BSTR bstrProcessName = SysAllocString(processNamePtr);
      hr = bstrProcessName ? S_OK : E_OUTOFMEMORY;
      if (SUCCEEDED(hr))
      {
        VARIANT vtEmpty = {}; // VT_EMPTY

        LPWSTR processParamsPtr = const_cast<LPWSTR>(processParams.c_str());
        _bstr_t bstrProcessParams(processParamsPtr);
        VARIANT varParams;
        varParams.vt = VT_BSTR;
        varParams.bstrVal = bstrProcessParams;

        char processDir[MAX_PATH + 1];
        ::GetCurrentDirectory(MAX_PATH, processDir);
        _bstr_t bstrProcessDir(processDir);
        VARIANT varProcessDir;
        varProcessDir.vt = VT_BSTR;
        varProcessDir.bstrVal = bstrProcessDir;

        _bstr_t bstrOperation("open");
        VARIANT varOperation;
        varOperation.vt = VT_BSTR;
        varOperation.bstrVal = bstrOperation;

        hr = psd->ShellExecute(bstrProcessName, 
          varParams, // reinterpret_cast<_variant_t&>(bstrProcessParams), 
          varProcessDir,
          varOperation,
          vtEmpty);
        SysFreeString(bstrProcessName);
        SysFreeString(bstrProcessParams);
      }
      psd->Release();
    }
    psv->Release();
  }

  CoUninitialize();
}

} // main()

// use the shell view for the desktop using the shell windows automation to find the
// desktop web browser and then grabs its view
//
// returns:
//      IShellView, IFolderView and related interfaces

HRESULT GetShellViewForDesktop(REFIID riid, void **ppv)
{
  *ppv = NULL;

  IShellWindows *psw;
  HRESULT hr = CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&psw));
  if (SUCCEEDED(hr))
  {
    HWND hwnd;
    IDispatch* pdisp;
    VARIANT vEmpty = {}; // VT_EMPTY
    if (S_OK == psw->FindWindowSW(&vEmpty, &vEmpty, SWC_DESKTOP, (long*)&hwnd,    SWFO_NEEDDISPATCH, &pdisp))
    {
      IShellBrowser *psb;
      hr = IUnknown_QueryService(pdisp, SID_STopLevelBrowser, IID_PPV_ARGS(&psb));
      if (SUCCEEDED(hr))
      {
        IShellView *psv;
        hr = psb->QueryActiveShellView(&psv);
    if (SUCCEEDED(hr))
    {
      hr = psv->QueryInterface(riid, ppv);
      psv->Release();
    }
    psb->Release();
  }
  pdisp->Release();
}
else
{
  hr = E_FAIL;
}
psw->Release();
}
return hr;
} // GetShellViewForDesktop()

// From a shell view object gets its automation interface and from that gets the shell
// application object that implements IShellDispatch2 and related interfaces.

HRESULT GetShellDispatchFromView(IShellView *psv, REFIID riid, void **ppv)
{
  *ppv = NULL;

 IDispatch *pdispBackground;
 HRESULT hr = psv->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARGS(&pdispBackground));
 if (SUCCEEDED(hr))
 {
   IShellFolderViewDual *psfvd;
   hr = pdispBackground->QueryInterface(IID_PPV_ARGS(&psfvd));
   if (SUCCEEDED(hr))
   {
     IDispatch *pdisp;
     hr = psfvd->get_Application(&pdisp);
     if (SUCCEEDED(hr))
     {
       hr = pdisp->QueryInterface(riid, ppv);
       pdisp->Release();
     }
     psfvd->Release();
   }
   pdispBackground->Release();
}
return hr;
} // GetShellDispatchFromView()
#包括
#包括
#包括
#pragma注释(lib,“shlwapi.lib”)
//链接到(至少)OleAut32.lib shlwapi.lib comsupp.lib shell32.lib uuid.lib
//对不起,格式不好
内部主(空)
{
std::wstring processName(L“myapp.exe”)、processParams(L“-myAppParam”);
LPWSTR processNamePtr=const_cast(processName.c_str());
HRESULT hr=coinitializex(NULL,COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
如果(成功(hr))
{
IShellView*psv;
HRESULT hr=GetShellViewForDesktop(IID_PPV_参数(&psv));
如果(成功(hr))
{
IShellDispatch2*psd;
hr=GetShellDispatchFromView(psv、IID_PPV_参数和psd));
如果(成功(hr))
{
BSTR bstrProcessName=SysAllocString(processNamePtr);
hr=bstrProcessName?S_确定:E_OUTOFMEMORY;
如果(成功(hr))
{
变量vtEmpty={};//VT_EMPTY
LPWSTR processParamsPtr=const_cast(processParams.c_str());
_bstr_t bstrProcessParams(processParamsPtr);
变异变量;
varParams.vt=vtbstr;
varParams.bstrVal=bstrProcessParams;
char processDir[MAX_PATH+1];
::GetCurrentDirectory(最大路径,processDir);
_bstr_t bstrProcessDir(processDir);
变种varProcessDir;
varProcessDir.vt=vt\u BSTR;
varProcessDir.bstrVal=bstrProcessDir;
_bstr_t bstrOperation(“开放”);
变异操作;
varOperation.vt=vt\u BSTR;
varOperation.bstrVal=bstrOperation;
hr=psd->ShellExecute(bstrProcessName,
varParams,//reinterpret_cast(bstrProcessParams),
瓦普斯迪尔,
varOperation,
vt(空);
SysFreeString(bstrProcessName);
SysFreeString(bstrProcessParams);
}
psd->Release();
}
psv->Release();
}
coninitialize();
}
}//main()
//使用shell windows automation为桌面使用shell视图来查找
//桌面web浏览器,然后获取其视图
//
//返回:
//IShellView、IFolderView和相关接口
HRESULT GetShellViewForDesktop(REFIID riid,void**ppv)
{
*ppv=NULL;
IShellWindows*psw;
HRESULT hr=CoCreateInstance(CLSID_外壳窗口,NULL,CLSCTX_本地_服务器,IID_PPV_参数(&psw));
如果(成功(hr))
{
HWND-HWND;
IDispatch*pdisp;
VARIANT vEmpty={};//VT_EMPTY
如果(S_OK==psw->FindWindowSW(&vEmpty,&vEmpty,SWC_桌面,(长*)&hwnd,SWFO_需要调度和pdisp))
{
IShellBrowser*psb;
hr=IUnknown_QueryService(pdisp、SID_STopLevelBrowser、IID_PPV_参数(&psb));
如果(成功(hr))
{
IShellView*psv;
hr=psb->QueryActiveShellView(&psv);
如果(成功(hr))
{
hr=psv->QueryInterface(riid,ppv);
psv->Release();
}
psb->Release();
}
pdisp->Release();
}
其他的
{
hr=E_失败;
}
psw->Release();
}
返回人力资源;
}//GetShellViewForDesktop()
//从shell视图对象获取其自动化接口,并从该接口获取shell
//实现IShellDispatch2和相关接口的应用程序对象。
HRESULT GetShellDispatchFromView(IShellView*psv,REFIID riid,void**ppv)
{
*ppv=NULL;
IDispatch*pdispBackground;
HRESULT hr=psv->GetItemObject(SVGIO_BACKGROUND、IID_PPV_ARGS(&pdispBackground));
如果(成功(hr))
{
IShellFolderViewDual*psfvd;
hr=pdispBackground->QueryInterface(IID_PPV_ARGS(&psfvd));
如果(成功(hr))
{
IDispatch*pdisp;
hr=psfvd->get_应用程序(&pdisp);
如果(成功(hr))
{
hr=pdisp->QueryInterface(riid,ppv);
pdisp->Release();
}
psfvd->Release();
}
pdispBackground->Release();
}
返回人力资源;
}//GetShellDispatchFromView()
在我的机器上,UAC已禁用

这就是你的问题。通过禁用UAC,您可以阻止系统以标准用户身份创建进程。如果登录的用户是管理员,则进程使用完全特权令牌运行

禁用UAC后,运行shell的explorer进程将使用交互用户的完整令牌启动,该令牌似乎是管理员用户的令牌。因此,当shell使用
IShellDispatch2->ShellExecute
启动新进程时,新进程将在相同的用户令牌下运行


您需要启用UAC以允许系统使用标准用户令牌创建流程。启用UAC时,shell的explorer进程将以标准用户身份运行,因此
IShellDispatch2->ShellExecute
将创建以标准用户身份运行的新进程。

谢谢David,我现在启用了UAC。现在的问题是另一个问题,这意味着主进程(将调用ShellExecute())不再提升。我如何始终启动主进程(并且不必弹出UAC确认,因为正如前面提到的,此应用程序将在服务器上运行)。这确实是一个不同的问题,与此问题并不相关。然而,你似乎陷入了困境。您想享受UAC的好处,但不想看到UAC对话框