none
Zugriff auf existierendes COM-Objekt RRS feed

  • Frage

  • Moin, moin!

    Ich bin Anfänger in der Powershell-Programmierung und versuche, aus einem Powershell-Script  auf eine laufende Microsoft-Access-Anwendung zuzugreifen.
    Alle Beispiele, die sich auf das Powershell-comobject beziehen, legen aber mit New einen neuen Prozess an.

    Das hier habe ich schon versucht, der Teil unter  "MSACCESS.EXE ist aktiv"  funktioniert aber nicht:

    $proc = Get-Process | Where-Object {$_.ProcessName -eq "MSACCESS"}

    if ($proc -imatch "MSACCESS")
        {
        Write-Host "MSACCESS.EXE ist aktiv"
        $ShellApp = New-Object -ComObject Shell.Application
        $Fenster = $ShellApp.Windows() | Where-Object { $_.LocationName -eq "Kabelüberwachung" }
        $FensterDOM = $Fenster.Application
        Write-Host "Ende!"  

        }
    else
        {
        Write-Host 'MSACCESS.EXE ist nicht aktiv - wird gestartet'
        $start = "`"C:\Program Files\Microsoft Office\Office14\msaccess.exe`" X:\MDB\Entw2010\Kabelueberwachung\Kabelueberwachung.accdb /cmd `"Cmd=K_S|IDX=11`""
        & "C:\Program Files\Microsoft Office\Office14\msaccess.exe" X:\MDB\Entw2010\Kabelueberwachung\Kabelueberwachung.accdb /cmd "Cmd=K_S|IDX=11"
        #$start = "Test"
        Write-Host $start
        #invoke-Command $start
        }
    read-host

    Vielen Dank schon mal!

        
    Dienstag, 28. Mai 2013 12:35

Antworten

  • Hallo Ingo!

    Da Where-Object nicht das schnellste ist, sollte man in der PowerShell immer die Filter der Cmdlets benutzen bevor man zu Where-object greift!
    Immer so weit rechts wie möglich Filtern!

    Get-Process –Name 'MSAccess'

    Ich hatte dir schon den Hinweis mit dem MainWindowTitle gegeben.
    Anhand des MainWindowTitle des Prozesses, kannst du feststellen ob du den richtigen Prozess vor dir hast!

    Prozesse einfach Killen ist nicht sehr elegant! Ebenso gehen ungesicherte Daten verloren!
    Ich würde den User mit einem Hinweisfenster bitten Access zu schließen!
    Dann kann er nochmal auf deinen Link klicken um die DB neu zu öffnen!

    Alternativ kannst du Access Ordentlich schließen!
    Die CloseMainWindow() Methode von dem Prozess Objekt, hat dieselbe Wirkung, als wenn der User die App von selbst schließt.
    Es wird nach dem abspeichern gefragt!
    Dies ist nicht so Brutal!

    Get-Process –Name 'MSAccess' | ForEach-Object {
        If($_.MainWindowTitle –like "* Kabelueberwachung*") {
            # mach was hier
            # Poupfenster oder $_. CloseMainWindow()
        }
    }


    Please click “Mark as Answer” if my post answers your question and click “Vote As Helpful” if my Post helps you.
    Bitte markiere hilfreiche Beiträge von mir als “Als Hilfreich bewerten” und Beiträge die deine Frage ganz oder teilweise beantwortet haben als “Als Antwort markieren”.
    My PowerShell Blog http://www.admin-source.info
    [string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '
    German ? Come to German PowerShell Forum!

    Mittwoch, 29. Mai 2013 08:32

Alle Antworten

  • Moin moin Ingo,

    was willst du denn mit Access machen?

    Wenn du direkt das COM Objekt nutzen möchtest hilft dir sicherlich folgender Link weiter:

    http://blogs.technet.com/b/heyscriptingguy/archive/2009/02/16/how-can-i-use-windows-powershell-to-create-an-office-access-database.aspx

    Gruß Malte

    Dienstag, 28. Mai 2013 13:52
  • Hallo Ingo!

    $ShellApp = New-Object -ComObject Shell.Application
    $Fenster = $ShellApp.Windows()

    Dies findet nur Explorer Fenster! Datei Explorer und Internet Explorer!

    Auf eine offene Access Applikation  zuzugreifen ist zwar nicht unmöglich aber doch sehr, sehr "speziell".
    Dies nennt man Late-Binding (spätes binden) und ist über COM nicht üblich!

    Wenn du eine Access Datenbank öffnen und steuern möchtest dann macht man das so:

    $Access = New-Object -ComObject Access.Application
    $Access.Visible = $True
    $Access.OpenCurrentDataBase('X:\MDB\Entw2010\Kabelueberwachung\Kabelueberwachung.accdb')
    # diese Befehl zeigt dir an was du mit dem Accesss Objekt machen kannst
    $Access | Get-Member

    Du kannst mit den Get-Process Cmdlet überprüfen ob schon einen MSAccess läuft und wie der Titel der Applikation ist:

    Get-Process -Name MSAccess | Select-Object MainWindowTitle

    Die Windows API Funktion AccessibleObjectFromWindow kann aus einem geöffneten Fenster wieder ein COM Objekt generieren, aber da habe sich schon ganz große Programmierer die Ohren gebrochen!
    http://msdn.microsoft.com/en-us/library/windows/desktop/dd317978%28v=vs.85%29.aspx

    Vorhandene Applikationen Fern-zusteuern ist auch Sicherheitstechnisch ein Problem und nicht unbedingt gewollt! Deshalb wird das von Microsoft auch nicht gefördert!


    Please click “Mark as Answer” if my post answers your question and click “Vote As Helpful” if my Post helps you.
    Bitte markiere hilfreiche Beiträge von mir als “Als Hilfreich bewerten” und Beiträge die deine Frage ganz oder teilweise beantwortet haben als “Als Antwort markieren”.
    My PowerShell Blog http://www.admin-source.info
    [string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '
    German ? Come to German PowerShell Forum!



    Mittwoch, 29. Mai 2013 05:19
  • >was willst du denn mit Access machen?

    Der User klickt in einer (nicht veränderbaren) Anwendung auf einen Link. Dieser soll meine Access-Anwendung öffnen und einen bestimmten Datensatz anspringen. Das ist kein Problem, solange die Access-DB geschlossen ist. Wenn sie aber geöffnet ist, muss ich den Befehl, zum gewünschten Datensatz zu gehen, an die laufende Anwendung übergeben.

    Das scheint aber wirklich schwierig zu sein. Der von Dir angebotene Link hilft da auch nicht weiter. Dort wird auch eine neue DB angelegt. Ich kann aber die gleiche DB auf einem Rechner nicht zweimal öffnen. Access macht das einfach nicht, es gibt auch keine Fehlermeldung.

    Ingo

    Mittwoch, 29. Mai 2013 07:46
  • Hallo Peter!

    Das funktioniert leider nicht. Wenn die DB schon geöffnet ist wird nur Access gestartet und die DB nicht noch einmal geöffnet.

    Habe gerade eine andere Idee. Ich habe ja Zugriff auf den laufenden Access-Prozess

    $proc = Get-Process | Where-Object {$_.ProcessName -eq "MSACCESS"}

    Kann man den Prozess beenden? Das wäre zwar keine elegante Lösung, aber das könnte ja funktionieren. Das man damit versehentlich eine falsche Datenbank abschießt ist auf dem sehr speziellen Kundenrechner nicht zu befürchten.

    Ingo

    Mittwoch, 29. Mai 2013 07:50
  • Hallo Ingo!

    Da Where-Object nicht das schnellste ist, sollte man in der PowerShell immer die Filter der Cmdlets benutzen bevor man zu Where-object greift!
    Immer so weit rechts wie möglich Filtern!

    Get-Process –Name 'MSAccess'

    Ich hatte dir schon den Hinweis mit dem MainWindowTitle gegeben.
    Anhand des MainWindowTitle des Prozesses, kannst du feststellen ob du den richtigen Prozess vor dir hast!

    Prozesse einfach Killen ist nicht sehr elegant! Ebenso gehen ungesicherte Daten verloren!
    Ich würde den User mit einem Hinweisfenster bitten Access zu schließen!
    Dann kann er nochmal auf deinen Link klicken um die DB neu zu öffnen!

    Alternativ kannst du Access Ordentlich schließen!
    Die CloseMainWindow() Methode von dem Prozess Objekt, hat dieselbe Wirkung, als wenn der User die App von selbst schließt.
    Es wird nach dem abspeichern gefragt!
    Dies ist nicht so Brutal!

    Get-Process –Name 'MSAccess' | ForEach-Object {
        If($_.MainWindowTitle –like "* Kabelueberwachung*") {
            # mach was hier
            # Poupfenster oder $_. CloseMainWindow()
        }
    }


    Please click “Mark as Answer” if my post answers your question and click “Vote As Helpful” if my Post helps you.
    Bitte markiere hilfreiche Beiträge von mir als “Als Hilfreich bewerten” und Beiträge die deine Frage ganz oder teilweise beantwortet haben als “Als Antwort markieren”.
    My PowerShell Blog http://www.admin-source.info
    [string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '
    German ? Come to German PowerShell Forum!

    Mittwoch, 29. Mai 2013 08:32
  • Hallo Peter!

    So funktioniert es, wenn auch nicht so, wie ich mir das mal vorgestellt hatte:

    $proc = Get-Process | Where-Object {$_.ProcessName -eq "MSACCESS"}

    if ($proc -imatch "MSACCESS")
        {
        $proc.CloseMainWindow()
        }
    & "C:\Program Files\Microsoft Office\Office14\msaccess.exe" X:\MDB\Entw2010\Kabelueberwachung\Kabelueberwachung.accdb /cmd "Cmd=K_S|IDX=11"

    Da es in meinem Fall eher unwahrscheinlich ist, dass Access schon läuft, reicht das aus.

    Vielen Dank noch Mal!

    Ingo

    Mittwoch, 29. Mai 2013 13:31