Win 7/UAC让我发疯.
在我的C++应用程序中,我需要运行一个需要在Windows 7上提升的可执行文件.我想解决这个问题并等待它继续完成.最简单的方法是什么?
我通常会通过这种方式执行此类操作CreateProcess()
,但对于需要提升的可执行文件,它会失败.
我尝试使用cmd.exe /c ...
直通CreateProcess
,它可以工作,但弹出一个丑陋的cmd终端窗口.
我正在阅读,这ShellExecute()
将允许提升,但使用时等待exe完成似乎并不容易ShellExecute()
.像system()
工作一样简单吗?
非常感谢任何其他想法!
在Windows平台上使用NDK构建静态库时出现错误:
process_begin: CreateProcess( "PATH"\android-ndk-r8b\toolchains\arm-linux-androideabi-4.6\prebuilt\windows\bin\arm-linux-androideabi-ar.exe, "some other commands" ) failed.
make (e=87): The parameter is incorrect.
make: *** [obj/local/armeabi-v7a/staticlib.a] Error 87
make: *** Waiting for unfinished jobs....
Run Code Online (Sandbox Code Playgroud)
所有源文件都已成功构建,并且在撰写目标文件时会发生此错误.
在Ubuntu中构建此项目时,我不会收到此错误,它只发生在Windows上.
我想我发现了这个问题:CreateProcess Win API函数的第二个参数lpCommandLine的最大长度为32,768个字符.但在我的情况下,它超过32,768个字符.
我怎么能解决这个问题?
您好我有以下代码,但它没有按预期工作,无法弄清楚问题是什么.
基本上,我正在执行一个进程(一个.NET进程)并传递它的命令行参数,它由CreateProcess()成功执行但CreateProcess()没有传递命令行参数
我在这做错了什么?
int main(int argc, char* argv[])
{
PROCESS_INFORMATION ProcessInfo; //This is what we get as an [out] parameter
STARTUPINFO StartupInfo; //This is an [in] parameter
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
StartupInfo.cb = sizeof StartupInfo ; //Only compulsory field
LPTSTR cmdArgs = "name@example.com";
if(CreateProcess("D:\\email\\smtp.exe", cmdArgs,
NULL,NULL,FALSE,0,NULL,
NULL,&StartupInfo,&ProcessInfo))
{
WaitForSingleObject(ProcessInfo.hProcess,INFINITE);
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
printf("Yohoo!");
}
else
{
printf("The process could not be started...");
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编辑:嘿,还有一件事,如果我这样通过我cmdArgs
:
// a space as the first character
LPTSTR cmdArgs = " name@example.com";
Run Code Online (Sandbox Code Playgroud)
然后我得到错误,然后CreateProcess返回 …
我很好奇是否有办法在新进程中执行静态.DLL方法而不必为它创建.EXE?
AFAIK,本机Win32/64 DLL无法实现..NET DLL程序集怎么样?
更新:我忘了提到我主要感兴趣的是以编程方式执行此操作(来自C#代码,具体而言).
谢谢!
结论:虽然没有人"敢"拼出来,但答案似乎都倾向于"不".需要通过一种传统方式(EXE,PowerShell等)启动进程,然后说服进程加载DLL并执行其中的代码.我想我错误地希望托管的DLL能够提供更多功能.
再次感谢所有插话的人!
我已经坚持了几个小时,直到我终于成功了.已有链接指向我正确的方向:
但我认为这个问题的简单概述可以帮助某人:).
您这样做AssignProcessToJobObject
并且失败并显示"拒绝访问",但仅当您在调试器中运行时才会失败.为什么是这样?
我创建了一个使用过程CreateProcess()
.这是代码:
STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
result = CreateProcess("C:\\AP\\DatabaseBase\\dbntsrv.exe", NULL, NULL, NULL, FALSE, 0, NULL, "C:\\ADP\\SQLBase", &si, &pi)
Run Code Online (Sandbox Code Playgroud)
如何获取此特定过程的Handle和processId?并最终用它来关闭这个过程?
谢谢.
该CreateProcess的文档状态(我的粗体强调):
lpEnvironment [in,optional]
[...]如果lpEnvironment指向的环境块包含Unicode字符,请确保dwCreationFlags包含CREATE_UNICODE_ENVIRONMENT.如果此参数为NULL并且父进程的环境块包含Unicode字符,则还必须确保dwCreationFlags包含CREATE_UNICODE_ENVIRONMENT.
MSDN是错误的并且夸大了旗帜的含义还是真正的要求?
我见过的代码从未设置过标志并且似乎有效,但我的偏执部分想要100%遵守MSDN所说的内容.这样说,我不确定你真的可以遵循MSDN的规则而不会走极端.
当lpEnvironment为NULL时,必须设置(或不设置)CREATE_UNICODE_ENVIRONMENT会让我觉得很荒谬:
如果我没有传递环境块,那么CreateProcess必须获取块本身.在那种情况下,它比我更了解块的类型.
我怎么知道块实际上是否包含Unicode字符?
我是否希望获得该块并检查当前代码页之外的字符?(我假设这是MSDN在"Unicode字符"中的含义.)
如果我必须获取env-block,那么我不妨在lpEnvionment中传递它而不是NULL,那么为什么甚至允许NULL呢?
必须获取和检查env-block似乎是CreateProcess的每个调用者的疯狂要求; 它肯定是API本身应该处理的东西.
当它说"父进程"它甚至意味着我的进程,即将成为新的父进程,还是它意味着我的进程的父进程?我最初阅读MSDN让我觉得我必须以某种方式判断启动我的进程的CreateProcess调用是否已经传递了ANSI或Unicode环境块,但情况肯定不是这样.
我假设,在基于NT的操作系统上,所有进程都有一个Unicode env块,如果在创建进程时需要从ANSI转换,并且进程不会挂起到按原样传递给CreateProcess的任何数据块.
(也许这整个事情是Win9x时代的一个遗留问题,那时操作系统本身不是Unicode?虽然如此,我看不出应用程序代码如何能够比操作系统本身更好地做出决策,也不知道为什么应该这样做预计会.)
除了从不设置标志的代码,我已经看到了代码,如果在编译时定义UNICODE,它总是设置它.当需求在运行时env块中的内容以及代码可能在加载到外部进程的DLL中时,这没有任何意义.
env块是进程范围的,因此在编译时定义的UNICODE似乎无关紧要.
如果只是我调用CreateProcessA或CreateProcessW,那么当该块为NULL时,该标志应该是隐式的,所以这也没有意义.
在我自己的代码中,我决定避免这个问题并始终获取环境块的Unicode副本(通过GetEnvironmentStringsW),始终将其传递给CreateProcess并始终设置CREATE_UNICODE_ENVIRONMENT.根据MSDN的说法,这是我能看到100%正确的唯一方法.
当然,我正在做的事情是多余的.CreateProcess不可能是那个傻瓜,可以吗?
另一方面,这是我们正在讨论的CreateProcess.它不是设计最好的API,还有许多其他陷阱(在我的脑海中):
因此,或许假设它表现得聪明或者可能会为来电者处理琐事是不正确的......
我不知道是否从我自己的代码中删除偏执垃圾或将其添加到我看到的所有其他代码中.哎呀.:-)
增加18/Nov/2010:
当env-block为NULL时,看起来这个标志似乎无关紧要,至少在Windows 2000到Windows 7中都是如此.请参阅下面的测试.
显然,这并不能确定该标志在将来的操作系统中总是无关紧要,但我真的看不出它是怎么回事.
假设我们有祖父母创建了即将创建Child的Parent:
如果操作系统始终将父级的env-block存储为Unicode - 如果祖父项传递ANSI块,则在父级创建期间将其转换为ANSI - 那么当父传递NULL块时,CreateProcess会出错以便注意该标志.CreateProcess必须知道Child将继承的块将始终是Unicode.
或者,OS可以完全按照祖父母的方式存储父级的env-block.(这似乎不太可能,但它是可能的.)在这种情况下,Parent无法检测祖父母传递的块类型.同样,CreateProcess必须知道块的类型并忽略该标志.
这是我今天早上写的一个测试,它以不同的方式启动子进程,并使子进程报告为env-var(为简洁起见,只是"OS"变量):
wchar_t *szApp = L"C:\\Windows\\system32\\cmd.exe";
wchar_t *szArgs = L"\"C:\\Windows\\system32\\cmd.exe\" /C set OS";
STARTUPINFOW si = {0};
si.cb = sizeof(si);
PROCESS_INFORMATION pi = {0};
// For brevity, this …
Run Code Online (Sandbox Code Playgroud) 问:我有一个Windows服务,它产生了很多子进程.似乎有一些限制,大约100,这个过程无法启动.CreateProcess()调用带有pid返回,但是然后该过程无法实现.如果我将服务器作为控制台应用程序运行,则此限制将消失.另外,如果我设置了DETACHED_PROCESS标志,则此限制会增加一倍以上.但是,如果我设置DETACHED_PROCESS并调用CreateProcesssWithLogonW(),我会失败.
我的目标是在程序中执行外部可执行文件.首先,我使用了system()
函数,但我不希望向用户看到控制台.所以,我搜索了一下,找到了CreateProcess()
功能.但是,当我尝试将参数传递给它时,我不知道为什么,它失败了.我从MSDN中获取了这段代码,并稍作改动:
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
void _tmain( int argc, TCHAR *argv[] )
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
/*
if( argc != 2 )
{
printf("Usage: %s [cmdline]\n", argv[0]);
return;
}
*/
// Start the child process.
if( !CreateProcess( NULL, // No module name (use command line)
L"c:\\users\\e\\desktop\\mspaint.exe", // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, …
Run Code Online (Sandbox Code Playgroud) createprocess ×10
winapi ×7
c++ ×6
windows ×3
c ×2
shellexecute ×2
uac ×2
.net ×1
android-ndk ×1
assemblies ×1
mfc ×1
unicode ×1
visual-c++ ×1