Запуск макроса доступа в Powershell
Я пытаюсь запустить макрос Access 2010 в PowerShell (v4.0 Windows 8.1) с помощью кода ниже:
$Access = New-Object -com Access.Application
$Access.OpenCurrentDatabase("SomePath", $False, "Password")
$Access.Run("SomeProc")
$Access.CloseCurrentDatabase()
$Access.Quit()
[System.Runtime.InteropServices.Marshal]::ReleaseComObject($Access)
Remove-Variable Access
Я получаю сообщение об ошибке на строке $Access.Run("SomeProc")
, что не хватает указанных параметров:
Экземпляр, вызывающий "Запуск" с аргументом "1": "Недопустимое количество параметров. (Исключение от HRESULT: 0x8002000E (DISP_E_BADPARAMCOUNT))"
Процедура SomeProc
не требует никаких параметров.
Я прочитал статью msdn о методе запуска и требуется только один параметр.
Я также пробовал это обходное решение, которое также не работало по несвязанной причине.
Кто-нибудь знает, что может быть причиной ошибки и как заставить этот метод работать?
Ответы
Ответ 1
Это проблема с драйвером, когда библиотеки OLEDB загружаются неправильно.
Я смог точно воспроизвести вашу ошибку, и мне удалось обойти это, открыв Powershell из вашей папки SysWow вместо System32.
Попробуйте открыть эту версию Powershell (вам придется снова запустить set-executionpolicy) и посмотреть, выполнит ли она ваш script.
% SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe
Полезная ссылка: https://social.msdn.microsoft.com/Forums/en-US/4500877f-0031-426e-869d-bda33d9fe254/microsoftaceoledb120-provider-cannot-be-found-it-may-not-be-properly-installed?forum=adodotnetdataproviders
Ответ 2
Подпись С# выглядит примерно так:
public object Run(string Procedure, ref object Arg1, ... ref object Arg30) ...
Это означает, что COM необязательные аргументы Arg не являются необязательными в .NET, потому что они явно отмечены как [ref]. Вам необходимо предоставить все 32 аргумента, даже если вы их не используете.
Предполагая, что у вас есть следующий код VBA:
Public Sub Greeting(ByVal strName As String)
MsgBox ("Hello, " & strName & "!"), vbInformation, "Greetings"
End Sub
Вы можете использовать его так:
$Access = New-Object -com Access.Application
$Access.OpenCurrentDatabase("Database1.accdb")
$runArgs = @([System.Reflection.Missing]::Value) * 31
$runArgs[0] = "Greeting" #Method Name
$runArgs[1] = "Jeno" #First Arg
$Access.GetType().GetMethod("Run").Invoke($Access, $runArgs)
В вашем случае это будет:
$runArgs = @([System.Reflection.Missing]::Value) * 31
$runArgs[0] = "SomeProc"
$Access.GetType().GetMethod("Run").Invoke($Access, $runArgs)
Я бы, вероятно, попытался добавить помощника к объекту доступа:
Add-Member -InputObject $Access -MemberType ScriptMethod -Name "Run2" -Value {
$runArgs = @([System.Reflection.Missing]::Value) * 31
for($i = 0; $i -lt $args.Length; $i++){ $runArgs[$i] = $args[$i] }
$this.GetType().GetMethod("Run").Invoke($this, $runArgs)
}
Затем вы можете использовать Run2, как и ожидалось:
$Access.Run2("Greeting", "Jeno")
$Access.Run2("SomeProc")