如何从提升的进程中调用未提升的进程
How to call an unelevated process from an elevated process
我看过相关社区posts*
在提升的 Excel 中(Excel 必须 运行 提升),VBA 打开 MS Word。 MS Word VBA 重新启动之前禁用的 OneDrive。问题已提升 Excel 导致 Word 被提升,从而导致调用 OneDrive 提升,从而导致 OneDrive 抛出错误。因此,我希望 Excel 以未提升的方式打开 Word。代码如下。
- 64 位 Win 10 专业版 21H1 19043.1526
- 32 位 Office 365 安装的桌面应用程序
- OneDrive 个人(非企业)
- UAC 已禁用
*P.S.
我阅读了所有社区 posts,还有 37 个结果,当我搜索我的问题的变体时出现,但我找不到任何适用的,可能是因为我的情况是 VBA 或者我没有受过足够的教育,无法理解如何将其他答案转化为我需要的答案。我尝试过,但我是 100% 自学的,复制了一些我不完全理解的代码,例如下面 social.msdn 的 Hans Vogelaar 的代码。
这是ExcelVBA
Sub Open_Word_DocM()
'Credit: Hans Vogelaar https://social.msdn.microsoft.com/Forums/en-US/29265e5f-8df9-4cab-8984-1afb9b110d2f/in-excel-use-vba-to-check-if-a-word-document-is-open?forum=isvvba
Dim Wd As Object
Dim InstrDoc As Object
Dim f As Boolean
Const strpath = "C:\Users\ssttr\OneDrive\Documents\Testing\ReStartOneDrive.docm"
On Error Resume Next
9990100:
Set InstrDoc = GetObject(strpath)
If InstrDoc Is Nothing Then
Set Wd = GetObject(, "Word.Application")
If Wd Is Nothing Then
Set Wd = CreateObject("Word.Application")
If Wd Is Nothing Then
Call ErrorLog
If mErr = 4 Then
GoTo 9990100
End If
End If
f = True
End If
9990200:
Set InstrDoc = Wd.Documents.Open(strpath)
If InstrDoc Is Nothing Then
Call ErrorLog
If mErr = 4 Then
GoTo 9990200
End If
If f Then
Wd.Quit
End If
Exit Sub
End If
Wd.Visible = True
Else
With InstrDoc.Parent
.Visible = True
.Activate
End With
End If
End Sub
这是 Word .docm VBA
Sub Restart_OneDrive()
Dim shell
Set shell = CreateObject("wscript.shell")
shell.Run """C:\Users\ssttr\OneDrive\Documents\Investing\Automation\Static Inputs\OneDrive Restart.bat"""
'batch file contents: start %LOCALAPPDATA%\Microsoft\OneDrive\OneDrive.exe /background
End Sub
这是 OneDrive 错误
OneDrive 无法 运行 使用完全管理员权限
请在没有管理员权限的情况下重新启动 OneDrive。
FWIW 1
SysInternals Process Explorer 显示 Word 的父级为 svchost.exe:
FWIW 2
我一直禁用 UAC。
FWIW 3
我通过以下方式为所有用户调用 Excel 作为管理员:属性 > 兼容性选项卡 > 更改所有用户的设置按钮 > 以管理员身份启用 运行 此程序:
关注论坛?
这个问题的更详细版本是 post2021 年 12 月 How to Restart OneDrive via VBA When Running Excel Elevated. I think it was TLDR bc I received no responses. A couple months ago, an earlier, different approach to this problem was at Start OneDrive Under Full Admin Rights。 post,也是 TLDR,确实收到了一个响应,我尝试过但无法成功实施的响应。如果有一条论坛规则(我找不到)反对 post 不止一次讨论类似的主题,那么请删除过于冗长的规则并请留下这个。谢谢。
简而言之:从资源管理器调用 OneDrive(它有一个在这种情况下很有用的限制;它只调用 exe 作为 non-admin)然后摆脱不需要的文件资源管理器 window.
这有点麻烦,但确实有效。
更改 MS Word VBA(以及相关的批处理文件,如 VBA 评论中所述)如下(我没有再次将其编辑为我最初发布的简化版本):
'The #-prefixed Declarations are used to enable the Windows API Sleep function (since Word does not allow Excel's Application.Wait method)
'VBA 7 replaces the VBA code base in Office 2007 and earlier versions. VBA 7 is available in both the 32-bit and 64-bit versions of Office. It provides two conditional compilation constants:
'VBA7 - Helps ensure the backward compatibility of your code by testing whether your application is using VBA 7 or the previous version of VBA.
'Win64 Tests whether code is running as 32-bit or 64-bit.
'per https://www.myonlinetraininghub.com/pausing-or-delaying-vba-using-wait-sleep-or-a-loop
#If VBA7 And Win64 Then
' For 64bit version of Excel
Public Declare PtrSafe Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As LongPtr)
#Else
' For 32bit version of Excel
Public Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long)
#End If
Sub Restart_OneDrive()
'Restarts OneDrive via batch file command.
'Then closes the unwanted Explorer.exe window after a 5000 [ms] sleep.
'NOTE: this method is necessary to solve the problem of invoking OneDrive
'(which will not run with elevated privileges) from elevated Word
'(elevated bc called from elevated Excel (elevated bc this is the only way
'Excel PID functions can control VLIA).
'https://www.myonlinetraininghub.com/pausing-or-delaying-vba-using-wait-sleep-or-a-loop
'https://docs.microsoft.com/en-us/previous-versions/office/developer/office-2010/ee691831(v=office.14)?redirectedfrom=MSDN
Dim shellt
Set shellt = CreateObject("wscript.shell")
shellt.Run """C:\Users\ssttr\OneDrive\Documents\Automation\Static Inputs\OneDrive Restart.bat"""
'batch file contents: explorer %LOCALAPPDATA%\Microsoft\OneDrive\OneDrive.exe
Dim waitOnReturn As Boolean: waitOnReturn = True 'Waits for shell to finish before returning to VBA
Sleep 5000 'in milliseconds (ref Declarations)
'Now kill the unwanted File Explorer window
'Note that in order to not kill all Explorer.exe windows, TaskKill's syntax requires:
'(1) each explorer window open in a separate process
'View > Folder Options > View Tab > enable Display the full path in the titlebar
'(2) the full path in title bar has been enabled in Folder view
'View > Folder Options > View Tab > enable Launch folder windows in a separate process
'^per https://superuser.com/questions/1263315/how-to-close-a-particular-opened-folder-using-cmd-or-batch-file
Call shell("taskkill /fi ""IMAGENAME eq explorer.exe"" /fi ""windowtitle eq OneDrive - Personal""")
waitOnReturn = True 'Waits for shell to finish before returning to VBA
End Sub
我看过相关社区posts*
在提升的 Excel 中(Excel 必须 运行 提升),VBA 打开 MS Word。 MS Word VBA 重新启动之前禁用的 OneDrive。问题已提升 Excel 导致 Word 被提升,从而导致调用 OneDrive 提升,从而导致 OneDrive 抛出错误。因此,我希望 Excel 以未提升的方式打开 Word。代码如下。
- 64 位 Win 10 专业版 21H1 19043.1526
- 32 位 Office 365 安装的桌面应用程序
- OneDrive 个人(非企业)
- UAC 已禁用
*P.S.
我阅读了所有社区 posts,还有 37 个结果,当我搜索我的问题的变体时出现,但我找不到任何适用的,可能是因为我的情况是 VBA 或者我没有受过足够的教育,无法理解如何将其他答案转化为我需要的答案。我尝试过,但我是 100% 自学的,复制了一些我不完全理解的代码,例如下面 social.msdn 的 Hans Vogelaar 的代码。
这是ExcelVBA
Sub Open_Word_DocM()
'Credit: Hans Vogelaar https://social.msdn.microsoft.com/Forums/en-US/29265e5f-8df9-4cab-8984-1afb9b110d2f/in-excel-use-vba-to-check-if-a-word-document-is-open?forum=isvvba
Dim Wd As Object
Dim InstrDoc As Object
Dim f As Boolean
Const strpath = "C:\Users\ssttr\OneDrive\Documents\Testing\ReStartOneDrive.docm"
On Error Resume Next
9990100:
Set InstrDoc = GetObject(strpath)
If InstrDoc Is Nothing Then
Set Wd = GetObject(, "Word.Application")
If Wd Is Nothing Then
Set Wd = CreateObject("Word.Application")
If Wd Is Nothing Then
Call ErrorLog
If mErr = 4 Then
GoTo 9990100
End If
End If
f = True
End If
9990200:
Set InstrDoc = Wd.Documents.Open(strpath)
If InstrDoc Is Nothing Then
Call ErrorLog
If mErr = 4 Then
GoTo 9990200
End If
If f Then
Wd.Quit
End If
Exit Sub
End If
Wd.Visible = True
Else
With InstrDoc.Parent
.Visible = True
.Activate
End With
End If
End Sub
这是 Word .docm VBA
Sub Restart_OneDrive()
Dim shell
Set shell = CreateObject("wscript.shell")
shell.Run """C:\Users\ssttr\OneDrive\Documents\Investing\Automation\Static Inputs\OneDrive Restart.bat"""
'batch file contents: start %LOCALAPPDATA%\Microsoft\OneDrive\OneDrive.exe /background
End Sub
这是 OneDrive 错误
OneDrive 无法 运行 使用完全管理员权限
请在没有管理员权限的情况下重新启动 OneDrive。
FWIW 1
SysInternals Process Explorer 显示 Word 的父级为 svchost.exe:
FWIW 2
我一直禁用 UAC。
FWIW 3
我通过以下方式为所有用户调用 Excel 作为管理员:属性 > 兼容性选项卡 > 更改所有用户的设置按钮 > 以管理员身份启用 运行 此程序:
关注论坛?
这个问题的更详细版本是 post2021 年 12 月 How to Restart OneDrive via VBA When Running Excel Elevated. I think it was TLDR bc I received no responses. A couple months ago, an earlier, different approach to this problem was at Start OneDrive Under Full Admin Rights。 post,也是 TLDR,确实收到了一个响应,我尝试过但无法成功实施的响应。如果有一条论坛规则(我找不到)反对 post 不止一次讨论类似的主题,那么请删除过于冗长的规则并请留下这个。谢谢。
简而言之:从资源管理器调用 OneDrive(它有一个在这种情况下很有用的限制;它只调用 exe 作为 non-admin)然后摆脱不需要的文件资源管理器 window.
这有点麻烦,但确实有效。
更改 MS Word VBA(以及相关的批处理文件,如 VBA 评论中所述)如下(我没有再次将其编辑为我最初发布的简化版本):
'The #-prefixed Declarations are used to enable the Windows API Sleep function (since Word does not allow Excel's Application.Wait method)
'VBA 7 replaces the VBA code base in Office 2007 and earlier versions. VBA 7 is available in both the 32-bit and 64-bit versions of Office. It provides two conditional compilation constants:
'VBA7 - Helps ensure the backward compatibility of your code by testing whether your application is using VBA 7 or the previous version of VBA.
'Win64 Tests whether code is running as 32-bit or 64-bit.
'per https://www.myonlinetraininghub.com/pausing-or-delaying-vba-using-wait-sleep-or-a-loop
#If VBA7 And Win64 Then
' For 64bit version of Excel
Public Declare PtrSafe Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As LongPtr)
#Else
' For 32bit version of Excel
Public Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long)
#End If
Sub Restart_OneDrive()
'Restarts OneDrive via batch file command.
'Then closes the unwanted Explorer.exe window after a 5000 [ms] sleep.
'NOTE: this method is necessary to solve the problem of invoking OneDrive
'(which will not run with elevated privileges) from elevated Word
'(elevated bc called from elevated Excel (elevated bc this is the only way
'Excel PID functions can control VLIA).
'https://www.myonlinetraininghub.com/pausing-or-delaying-vba-using-wait-sleep-or-a-loop
'https://docs.microsoft.com/en-us/previous-versions/office/developer/office-2010/ee691831(v=office.14)?redirectedfrom=MSDN
Dim shellt
Set shellt = CreateObject("wscript.shell")
shellt.Run """C:\Users\ssttr\OneDrive\Documents\Automation\Static Inputs\OneDrive Restart.bat"""
'batch file contents: explorer %LOCALAPPDATA%\Microsoft\OneDrive\OneDrive.exe
Dim waitOnReturn As Boolean: waitOnReturn = True 'Waits for shell to finish before returning to VBA
Sleep 5000 'in milliseconds (ref Declarations)
'Now kill the unwanted File Explorer window
'Note that in order to not kill all Explorer.exe windows, TaskKill's syntax requires:
'(1) each explorer window open in a separate process
'View > Folder Options > View Tab > enable Display the full path in the titlebar
'(2) the full path in title bar has been enabled in Folder view
'View > Folder Options > View Tab > enable Launch folder windows in a separate process
'^per https://superuser.com/questions/1263315/how-to-close-a-particular-opened-folder-using-cmd-or-batch-file
Call shell("taskkill /fi ""IMAGENAME eq explorer.exe"" /fi ""windowtitle eq OneDrive - Personal""")
waitOnReturn = True 'Waits for shell to finish before returning to VBA
End Sub