在Shell中执行命令并等待进程结束可以使用/bin/sh -c
命令,并在命令后加上&& echo Success || echo Failure
来检查命令是否成功执行。
以下是一个使用ShellExecuteEx
函数的例子,该函数在Windows中可以用来启动一个进程并等待其结束:
cpp#include <windows.h>
#include <shellapi.h>
#include <iostream>
int main() {
SHELLEXECUTEINFO ShExecInfo = {0};
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpFile = L"cmd.exe";
ShExecInfo.lpParameters = L"/c dir && echo Success || echo Failure";
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_HIDE;
ShExecInfo.hInstApp = NULL;
BOOL result = ShellExecuteEx(&ShExecInfo);
if( result ) {
// 等待进程结束
WaitForSingleObject(ShExecInfo.hProcess, INFINITE);
DWORD dwExitCode;
if(GetExitCodeProcess(ShExecInfo.hProcess, &dwExitCode)) {
std::cout << "Process exit code: " << dwExitCode << std::endl;
}
else {
std::cerr << "Cannot get exit code of the process." << std::endl;
}
// 关闭进程句柄
CloseHandle(ShExecInfo.hProcess);
}
return 0;
}
在这个例子中,SEE_MASK_NOCLOSEPROCESS
标志被设置,这样我们可以在ShellExecuteEx
调用之后获取进程句柄。然后使用WaitForSingleObject
函数等待进程结束。
请注意,这个代码是在Windows环境下编译的,并且需要包含适当的头文件和链接必要的库。在Linux环境下,你可以使用system
函数或者popen
和pclose
函数来执行Shell命令,并通过它们的返回值检查命令执行的成功与否。
用VB6代码实现
在 VB6 (Visual Basic 6.0) 中,你可以使用 Shell
函数来执行一个外部命令,并使用 WaitForSingleObject
函数来等待进程结束。然而,VB6 并没有内置的 WaitForSingleObject
函数,因为那是 Windows API 的一部分。为了在 VB6 中使用这个功能,你需要调用 Windows API。以下是一个示例,展示了如何在 VB6 中执行一个外部命令并等待它完成:
首先,你需要定义一些 Windows API 函数。在 VB6 的代码编辑器中,选择“项目”菜单,然后选择“添加模块”。在模块中添加以下声明:
vbDeclare Function CreateProcess Lib "kernel32" Alias "CreateProcessA" (
ByVal lpApplicationName As String,
lpCommandLine As String,
lpProcessAttributes As Long,
lpThreadAttributes As Long,
ByVal bInheritHandles As Long,
ByVal dwCreationFlags As Long,
lpEnvironment As Long,
lpCurrentDirectory As String,
lpStartupInfo As STARTUPINFO,
lpProcessInformation As PROCESS_INFORMATION) As Long
Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Type SECURITY_ATTRIBUTES
nLength As Long
lpSecurityDescriptor As Long
bInheritHandle As Long
End Type
Type STARTUPINFO
cb As Long
lpReserved As String
lpDesktop As String
lpTitle As String
dwX As Long
dwY As Long
dwXSize As Long
dwYSize As Long
dwXCountChars As Long
dwYCountChars As Long
dwFillAttribute As Long
dwFlags As Long
wShowWindow As Integer
cbReserved2 As Integer
lpReserved2 As Long
hStdInput As Long
hStdOutput As Long
hStdError As Long
End Type
Type PROCESS_INFORMATION
hProcess As Long
hThread As Long
dwProcessId As Long
dwThreadId As Long
End Type
Const INFINITE = -1
Const SYNCHRONIZE = &H100000
Const CREATE_NO_WINDOW = &H8000000
然后,你可以创建一个函数来执行命令并等待其完成:
vbFunction ExecuteAndWait(ByVal CommandLine As String) As Boolean
Dim sa As SECURITY_ATTRIBUTES
Dim si As STARTUPINFO
Dim pi As PROCESS_INFORMATION
Dim Result As Long
Dim ExitCode As Long
' 初始化结构
sa.nLength = Len(sa)
sa.lpSecurityDescriptor = 0
sa.bInheritHandle = True
si.cb = Len(si)
si.wShowWindow = 0 ' 隐藏窗口
si.hStdInput = 0
si.hStdOutput = 0
si.hStdError = 0
' 创建进程
Result = CreateProcess(vbNullString, CommandLine, ByVal 0&, ByVal 0&, True, CREATE_NO_WINDOW, ByVal 0&, vbNullString, si, pi)
If Result <> 0 Then
' 等待进程结束
Result = WaitForSingleObject(pi.hProcess, INFINITE)
' 获取退出代码
GetExitCodeProcess pi.hProcess, ExitCode
' 关闭句柄
CloseHandle pi.hProcess
CloseHandle pi.hThread
' 根据退出代码返回结果
ExecuteAndWait = (ExitCode = 0)
Else
' 创建进程失败
ExecuteAndWait = False
End If
End Function
现在你可以调用 ExecuteAndWait
函数来执行一个命令,并等待它完成:
vbSub Main()
Dim CommandLine As String
Dim Success As Boolean
' 设置要执行的命令
CommandLine = "cmd.exe /c dir" ' 示例命令,你可以替换为其他命令
' 执行命令并等待完成
Success = ExecuteAndWait(CommandLine)
' 显示结果
If Success Then
MsgBox "命令执行成功"
Else
MsgBox "命令执行失败"
End If
End Sub
请注意,CreateProcess
函数的 lpCommandLine
参数应该是包含完整命令行的字符串,包括任何必要的参数和路径。在上面的例子中,我使用了 cmd.exe /c dir
作为示例命令,它会启动命令提示符并执行 dir
命令。你可以
VB6 ShellExecuteEx,如何添加RUNAS参数
在 VB6 中使用 ShellExecuteEx
函数时,如果你想要以管理员权限运行程序,你需要设置 lpVerb
成员为 "runas"
。这将尝试以提升的权限执行指定的程序。请注意,runas
动词在 Windows Vista 及更高版本中可用,并且用户可能会看到一个 UAC(用户帐户控制)提示来确认权限提升。
以下是如何在 VB6 中使用 ShellExecuteEx
函数并添加 RUNAS
参数的示例:
vbDeclare Function ShellExecuteEx Lib "shell32.dll" Alias "ShellExecuteExA" (lpExecInfo As SHELLEXECUTEINFO) As Long
Type SHELLEXECUTEINFO
cbSize As Long
fMask As Long
hwnd As Long
lpVerb As String
lpFile As String
lpParameters As String
lpDirectory As String
nShow As Long
hInstApp As Long
lpIDList As Long
lpClass As String
hkeyClass As Long
dwHotKey As Long
hIcon As Long
hProcess As Long
End Type
Const SEE_MASK_NOCLOSEPROCESS = &H40
Sub RunAsAdmin()
Dim sei As SHELLEXECUTEINFO
Dim Result As Long
' 初始化SHELLEXECUTEINFO结构
sei.cbSize = Len(sei)
sei.fMask = SEE_MASK_NOCLOSEPROCESS
sei.hwnd = Me.hwnd ' 使用当前窗体的句柄
sei.lpVerb = "runas" ' 使用RUNAS动词
sei.lpFile = "C:\path\to\your\program.exe" ' 要执行的程序路径
sei.lpParameters = "" ' 程序参数,如果需要的话
sei.lpDirectory = "" ' 初始目录,如果需要的话
sei.nShow = SW_SHOWNORMAL ' 显示方式
' 执行ShellExecuteEx
Result = ShellExecuteEx(sei)
' 检查是否成功执行
If Result > 32 Then
' 进程句柄在sei.hProcess中,如果需要的话可以使用它
' 例如,你可以使用WaitForSingleObject来等待进程结束
' ...
' 关闭进程句柄(如果不再需要)
CloseHandle sei.hProcess
Else
MsgBox "无法以管理员权限运行程序。"
End If
End Sub
在这个例子中,lpVerb
被设置为 "runas"
,这将尝试以管理员权限运行指定的 lpFile
。如果成功,ShellExecuteEx
会返回一个大于 32 的值,并且 hProcess
成员会被填充,以便你可以后续操作进程(例如等待它结束)。如果 ShellExecuteEx
返回一个小于或等于 32 的值,那么调用就失败了。
请注意,由于 UAC 的限制,不是所有的程序都可以或应该使用 runas
动词来运行。而且,如果用户拒绝提升权限请求,程序将不会以管理员权限运行。
12:12
VB6用ShellExecuteEx如何以非管理员权限运行EXE
在 VB6 中使用 ShellExecuteEx
函数来以非管理员权限运行一个 .exe
文件实际上是一个有点误导的概念,因为 ShellExecuteEx
本身并不直接控制权限级别。当你使用 ShellExecuteEx
时,它会按照调用它的应用程序的权限级别来执行指定的文件。如果 VB6 应用程序以管理员权限运行,那么 ShellExecuteEx
也将尝试以相同的权限级别执行文件。
如果你想确保以非管理员权限运行一个 .exe
文件,你需要确保你的 VB6 应用程序本身不是以管理员权限运行的。这通常意味着你需要以标准用户身份登录到 Windows,或者确保你的应用程序的快捷方式或启动配置没有设置为“以管理员身份运行”。
不过,如果你确实需要以编程方式降低权限级别(尽管这通常不是一个推荐的做法,因为它可能导致权限不足的问题),你可能需要创建一个辅助进程,该进程以较低的权限级别运行,并通过某种形式的进程间通信(如命名管道、套接字或共享内存)与你的主应用程序通信。
但是,在大多数情况下,你应该尽量避免需要降低权限级别的情况。相反,你应该设计你的应用程序以便它可以在标准用户权限下运行,或者提供适当的用户界面来提示用户以管理员身份运行特定的操作(如果确实需要)。
如果你只是想确保你的 VB6 应用程序不以管理员身份运行,你可以检查它的快捷方式属性或启动配置,确保没有设置“以管理员身份运行”选项。另外,确保你的应用程序的清单文件(如果存在)没有请求更高的执行级别。
如果你仍然需要在 VB6 中使用 ShellExecuteEx
并确保以非管理员权限运行,你可能需要创建一个单独的、权限较低的服务或应用程序来执行这项任务,并通过某种机制与你的 VB6 应用程序进行通信。但请注意,这样做可能会引入额外的复杂性和安全风险。