thorsten-rehm
Goto Top

PowerShell Skript Frage

Hallo!

Die ich gerade erst angefangen habe mich mit der PowerShell auseinander zusetzen, wollte ich zuerst eine "alte" BATCH Datei migrieren.
Das Batch-Skript ist einfach aufgebaut und beendet bestimmte Dienste und Prozesse:

devcon disable "USB\Vid_0846&Pid_4240&Rev_1040"  
net stop "DIENSTNAME1"  
net stop "DIENSTNAME2"  
net stop "DIENSTNAME3"  
taskkill /S HOST /F /IM prozess1.exe /T
taskkill /S HOST /F /IM prozess2.exe /T
taskkill /S HOST /F /IM prozess3.exe /T

Der devcon Befehl ist eine eigenständige Datei bzw. ein Tool von Microsoft mit dem Netzwerkschnittstellen de- und aktivieren kann.
Jetzt möchte ich das Ganze, wie schon erwähnt, mit der PowerShell verwirklichen. Das sieht bisher so aus:

stop-service -force DIENSTNAME1,DIENSTNAME2,DIENSTNAME3
stop-process -name prozess1,prozess2,prozess3

Funktioniert. Aber wie kann ich die Netzwerkschnittstelle, in meinem Fall ein USB WLAN Stick, deaktivieren?

Und vielleicht noch ein anderer Ansatz für das Beenden der Dienste und Prozesse:
Von z.B. 20 Diensten, gebe ich im Skript an, dass er 15 beenden soll. Geht es eigentlich auch umgekehrt,
also das ich im Skript angebe, dass er alle 20 beendet bis auf DIENST1, DIENST2 usw... (also 5 Stück)

thx im Voraus.

Content-ID: 87083

Url: https://administrator.de/contentid/87083

Ausgedruckt am: 25.11.2024 um 06:11 Uhr

TuXHunt3R
TuXHunt3R 06.05.2008 um 20:22:48 Uhr
Goto Top
Hallo thorsten-rehm

Du kannst in PowerShell alle Exe-Files genau wie in einer Batch gebrauchen. Die devcon.exe kannst du also ohne Probleme weiterverwenden....


Allerdings verstehe ich, dass wenn man schon die mächtige PowerShell zur Verfügung hat, diese auch nutzen will und nicht mehr auf externe Tools angewiesen sein will.

Ich probiere mal ein paar Sachen aus, ich melde mich wieder....
filippg
filippg 06.05.2008 um 20:24:11 Uhr
Goto Top
Hallo,

da devcon kein in die cmd integrierte Befehl ist, sondern in Programm kannst du es aus der Powershell genauso aufrufen wie aus der cmd auch.
Ein "Beende alles bis auf" gibt es erstmal nicht. Was man aber machen kann ist, sich eine Liste aller Dienste liefern lassen, dann über diese iterieren und für alle, deren Name nicht in einer Liste ist beenden.
Grob:
$servicesLetLive = "Svc1;svc2;svc3;"  
$services = get-service
foreach($service in $services){
	if(!$servicesLetLive.Contains($service.DisplayName+";"){  
		$service | restart-service
	}
}

Gruß

Filipp
TuXHunt3R
TuXHunt3R 06.05.2008 um 21:13:38 Uhr
Goto Top
Hallo thorsten-rehm

Folgendes habe ich gefunden:

Gemäss diesem Link (http://www.vistax64.com/powershell/27830-enable-disable-network-connect ..) funktioniert dieses Script:

$yourDeviceID = <DeviceID deiner Netzwerkkarte>

$YourNIC = Get-WmiObject win32_networkadapter | where {$_.DeviceId -eq $yourDeviceID}

$YourNIC.disable()

Die folgende Zeile muss du anpassen:
$yourDeviceID = <DeviceID deiner Netzwerkkarte>

Statt <DeviceID deiner Netzwerkkarte> fügst du die DeviceID deiner Netwerkkarte ein. Diese findest du mit dem folgenden Befehl in der PowerShell heraus:
get-wmiobject win32_networkadapter | select-object Name, MACAddress, DeviceID | format-table
Dieser Befehl listet dir alle Netzwerkadapter samt MAC-Adresse und DeviceID heraus. Du musst nur noch die richtige heraussuchen.

Zum Script selber:
Ich selbst habe es nicht getestet, kann dir also keine Garantie gegeben.
Ich wäre also auch froh um ein Feedback, ob es geklappt hat.
thorsten-rehm
thorsten-rehm 06.05.2008 um 22:57:27 Uhr
Goto Top
Wunderbar. Ich teste es morgen gleich mal aus. Sehr schön. Danke schonmal.
thorsten-rehm
thorsten-rehm 07.05.2008 um 20:09:27 Uhr
Goto Top
Geht leider nicht.
So sieht mein Skript aus:

$yourDeviceID = 10
$YourNIC = Get-WmiObject win32_networkadapter | where {$_.DeviceId -eq $yourDeviceID}
$YourNIC.disable()

So lautet die Meldung:
PS C:\temp\powershell> .\network-disable
Method invocation failed because
[System.Management.ManagementObject#root\cimv2\Win32_NetworkAdapter]
doesn't contain a  method named 'disable'.  
At C:\temp\powershell\network-disable.ps1:3 char:17
+ $YourNIC.disable <<<< ()
TuXHunt3R
TuXHunt3R 07.05.2008 um 20:38:25 Uhr
Goto Top
Tja, dann kann man wohl definitiv nicht per WMI einen NIC disablen. Schade.....


Naja, dann würde ich wieder zur devcon.exe greifen, um den NIC zu disablen.

Ich hab irgendwo gelesen, dass es ein .NET-Objekt gibt, mit dem man einen NIC ebenfalls disablen kann. Hab allerdings kein Codebeispiel gesehen und der Verfasser des Forumeintrags war sich auch nicht sicher.....

Spar dir den Aufwand und greif wieder zur devcon.exe.
thorsten-rehm
thorsten-rehm 07.05.2008 um 20:41:47 Uhr
Goto Top
Alles klar. Vielen Dank aber.
Ich denke das ich die nächsten Wochen noch einige Fragen haben werde. Sehr schöne Sache, die PowerShell ;)

Zu meinem Ursprungsskript im 1. Beitrag noch ein Verbesserungsvorschlag oder so ok?
thorsten-rehm
thorsten-rehm 07.05.2008 um 21:01:38 Uhr
Goto Top
Ähm, wie füge ich devcon am Besten ein?
So wie im alten Batch Skript geht es ja nicht direkt. Mit Pfadangabe habe ich es hinbekommen.
Also:
c:\temp\powershell\devcon disable "USB\Vid_0846&Pid_4240&Rev_1040"  
stop-service usw...

Aber da gibt es doch bestimmt eine bessere Lösung!?
TuXHunt3R
TuXHunt3R 07.05.2008 um 22:38:40 Uhr
Goto Top
Kopier die Devcon.exe in einen Ordner, die in der Path-Variable drin ist, z.B. C:\Windows

Dann kannst du die Befehlszeile wie in der Batch setzen:
devcon disable "USB\Vid_0846&Pid_4240&Rev_1040"  

Die den Inhalt der Path-Variable kannst du folgendermassen abrufen (in der PowerShell):
write-host $env:path
Die einzelnen Pfade sind dort mit Semikolons getrennt abgelegt.
TuXHunt3R
TuXHunt3R 07.05.2008 um 22:40:06 Uhr
Goto Top
Zu meinem Ursprungsskript im 1. Beitrag noch ein Verbesserungsvorschlag oder so ok?

Nein, eigentlich nicht......
thorsten-rehm
thorsten-rehm 08.05.2008 um 19:53:24 Uhr
Goto Top
Jetzt habe ich 2 Skripts:

stop
devcon disable "USB\Vid_0846&Pid_4240&Rev_1040"  
stop-service -force DIENST1,DIENST2,DIENST3
stop-process -name PROZESS1,PROZESS2,PROZESS3

start (startet wieder die Netzwerkschnittstelle und macht nen Reboot)
devcon enable "USB\Vid_0846&Pid_4240&Rev_1040"  
shutdown -r -t 02 -f

Jetzt ist die Frage, ob ich daraus 1 Skript machen kann, in dem ich mit dem IF Befehl arbeite.
So stelle ich mir das vor:

WENN Netzwerkschnittstelle aktiv, dann "stop". WENN Netzwerkschnittstelle inaktiv, dann überspringe "stop" und gehe zu "start".
Geht das mit goto oder so?
TuXHunt3R
TuXHunt3R 08.05.2008 um 21:07:18 Uhr
Goto Top
Gibt die devcon.exe Errorlevel aus (in der Doku nachschauen)? Wenn ja, kannst du mit einer if- oder einer switch-Abfrage die Variable "$Lastexitcode" auswerten und dann je nach Ergebnis andere Befehle ausführen. Das Ganze sieht dann in etwa so aus:

devcon .............
if ($lastexitcode -eq "1") {  
Mache dies....

} else {
Mache das....

}

Geht das mit goto oder so?
GOTO ist in jeder strukturierten Programmiersprache, also auch in der PowerShell Script Language, verpönt. In der PowerShell gibt es meines Wissens auch kein GOTO, braucht es auch nicht.
thorsten-rehm
thorsten-rehm 10.05.2008 um 15:59:07 Uhr
Goto Top
Ich komme gerade nicht voran. Ich versuche das Obige umzusetzen, aber beim Aufruf des Skripts nimmt er immer den Befehl unter else. Jetzt kann man ja mit devcon den Status abfragen und da habe ich mir folgendes ausgedacht:

$status = devcon status "USB\Vid_0846&Pid_4240&Rev_1040"  

devcon disable "USB\Vid_0846&Pid_4240&Rev_1040"  
if ($status -like "disabled") {  
stop-process -name taskmgr

} else {
devcon enable "USB\Vid_0846&Pid_4240&Rev_1040"  

}

Aber auch hier versage ich leider. Er nimmt den Befehl unter else.
Eine Devcon Status Meldung sieht so aus

USB\VID_0846&PID_4240\3887-0000
    Name: NETGEAR WG111 802.11g Wireless USB2.0 Adapter
    Device is disabled.
1 matching device(s) found.

bzw.

USB\VID_0846&PID_4240\3887-0000
    Name: NETGEAR WG111 802.11g Wireless USB2.0 Adapter
    Driver is running.
1 matching device(s) found.

Device is ... ist also die einzige Unterscheidung. Wie kann ich dem Skript das begreiflich machen?
filippg
filippg 10.05.2008 um 20:20:28 Uhr
Goto Top
if ($status -like "disabled") {
Du solltest dir die Doku zu -like nochmal ansehen. Du hast die Wildcards vergessen, es müsste "*disabled*" heißen.

Gruß

Filipp
thorsten-rehm
thorsten-rehm 10.05.2008 um 21:04:10 Uhr
Goto Top
Ok, danke für den Hinweis. Ich dachte das er bei "like" grundsätzlich den nachfolgenden Begriff als Wildcard Suche einbindet.

So sieht es jetzt aus:

devcon disable "USB\Vid_0846&Pid_4240&Rev_1040"  
$status = devcon status "USB\Vid_0846&Pid_4240&Rev_1040"  
if ($status -like "*disabled*") {  
stop-process -name taskmgr

} else {
devcon enable "USB\Vid_0846&Pid_4240&Rev_1040"  

}

Klappt bis auf den else Befehl. Also wenn die Netzwerkschnittstelle aktiviert ist, arbeitet er brav "stop-process" ab. Beim nachfolgenden Aufruf des Skripts, also wenn die Netzwerkschnittstelle deaktiviert ist, will er aber wieder den Prozess stoppen. Er springt nicht zum Punkt "else" über. Was übersehe ich da?
filippg
filippg 10.05.2008 um 23:14:44 Uhr
Goto Top
Hallo,

einer von uns beiden hat da gerade einen kleinen Hänger.
So wie ich das sehe, sorgt die erste Zeile immer dafür, dass die Karte deaktiviert wird (und da ist kein "if" davor). Folglich gibt die Prüfung im if auch immer true.

Gruß

Filipp

edit: außerdem prüft die Schleife, ob der Adapter abgeschaltet ist. Wenn er es nicht ist (also an) wird der else-Zweig ausgeführt, und der Adapter wird angeschaltet.
Einer von uns beiden muss das nochmal genau anschauen
thorsten-rehm
thorsten-rehm 11.05.2008 um 09:44:21 Uhr
Goto Top
edit: außerdem prüft die
Schleife, ob der Adapter abgeschaltet ist.
Wenn er es nicht ist (also an) wird der
else-Zweig ausgeführt, und der Adapter
wird angeschaltet.

Genau das passiert leider nicht.
Ich möchte einfach das hier erreichen:

- Deaktivieren der Netzwerkschnittstelle
- Ausführen von bestimmten Befehlen (wie Prozesse beenden, Dienste stoppen)

Wenn ich das Skript jetzt wieder aufrufe, soll es merken, dass die Schnittstelle deaktiviert ist und etwas anderes ausgeführt werden soll. In meinem Fall:
- Karte aktivieren
- Neustart des PCs

Er springt bei einer deaktivierten Netzwerkschnittstelle nicht zum else Befehl was mich verwundert, da ja alles korrekt aussieht.
Im Endeffekt möchte ich 2 Skripts in einem Skript haben (s. weiter oben).
Biber
Biber 11.05.2008 um 10:46:37 Uhr
Goto Top
Moin thorsten-rehm,
was mich verwundert, da ja alles korrekt aussieht.
ähmm...
Magst Du nochmal kurz (zur Sensibilisierung) filipps letzten Kommentar lesen und danach bitte noch einmal, was Du als jetzigen Zustand Deines Zustands bezeichnet hast?

Sonst übersetze ich mal in Pseudocode:
devcon disable "USB\Vid_0846&Pid_4240&Rev_1040"  
$status = devcon status "USB\Vid_0846&Pid_4240&Rev_1040"  
if ($status -like "*disabled*") {  
stop-process -name taskmgr

} else {
devcon enable "USB\Vid_0846&Pid_4240&Rev_1040"  

}

Klemm mit Devcon das US-Geraffel ab
Frag den Status vom USB-Geraffel ab
Wenn Status so wie *abgeklemmt*
     Hau-Wech einen Prozess
wenn nich so wie *abgeklemmt*
     Klemm sicherheitshalber nochmal mit DevCon das USB-Geraffel wieder an
      /* aber starte es erstmal noch nicht */
Ende vons Wenn

Was filipp andeutete war, das der PowerShell-Schnipsel eventuell works as designed.
Und man/frau es deshalb (diesmal) nicht M$ anlasten darf.

Grüße
Biber
thorsten-rehm
thorsten-rehm 11.05.2008 um 15:00:42 Uhr
Goto Top
Also ich steh jetzt auf dem Schlauch. Sorry ;)

Klemm sicherheitshalber nochmal mit DevCon das USB-Geraffel wieder an
/* aber starte es erstmal noch nicht */

Warum: "aber starte es erstmal noch nicht" ?
Das raff ich jetzt überhaupt nicht.

Wie muss denn der if / else Befehl aussehen, so dass es so läuft wie ich gerne hätte? Das ist ja der Punkt wo ich gerade nicht weiter weiß.
filippg
filippg 11.05.2008 um 15:15:14 Uhr
Goto Top
Also nochmal:

1: devcon disable "USB\Vid_0846&Pid_4240&Rev_1040"      Als erstes deaktivierst du das Gerät bei jedem Aufruf des Skriptes  
2: $status = devcon status "USB\Vid_0846&Pid_4240&Rev_1040"  
3: f ($status -like "*disabled*") {      Diese Abfrage wird immer "true" ergeben, weil du das Gerät in Zeile 1 ja deaktiviert hast.  
4:    stop-process -name taskmgr
5: } else {    Wird nie erreicht werden (Abfrage in 3 immer true wege 1, also niemals ins else.
6:   devcon enable "USB\Vid_0846&Pid_4240&Rev_1040"  
7:}

Uns selbst, wenn du mal in die else-Schleife kommen solltest: else bedeutet, das Gerät ist enabled. Warum schaltest du es dann in Zeile 6 gleich nochmal an?
filippg
filippg 11.05.2008 um 15:21:44 Uhr
Goto Top
Okay, und bevor wir da noch ewig drüber diskutieren, du willst wohl etwas wie:

$status = devcon status "USB\Vid_0846&Pid_4240&Rev_1040"  
if ($status -like "*disabled*") {    #Das Gerät is mometan aus -> anschalten  
      devcon enable "USB\Vid_0846&Pid_4240&Rev_1040"  
} else {                                        #Das Gerät ist an -> ausschalten
      devcon disable "USB\Vid_0846&Pid_4240&Rev_1040"  
}

Deaktiviert die Netzwerkkarte, wenn sie aktiviert ist, und aktiviert sie, wenn sie deaktiviert ist. Das war, soweit ich das verstanden habe, das was du wolltest. Das Anhalten der entsprechenden Dienste musst du an der entsprechenden Stelle hinzufügen.
Solltest du das ganze jetzt nicht verstehen: Vergiss es kurz, mach etwas anderes, dann lies es dir nochmal genau durch und fange von vorne an.

Gruß

Filipp
Biber
Biber 11.05.2008 um 15:34:04 Uhr
Goto Top
Moin thorsten-rehm,

mit Powershell kenn ich mich ja nun wirklich nicht aus, aber aus anderen Skripting-Versuchen kann ich folgende Golden Rule weitergeben.
Wenn Du vier Tage lang auf denselben Codeschnipsel geschaut hast und hast ihn nicht zum Fliegen gebracht:
  • Druck den gesamten Code zweimal aus. Lösche danach den Quellcode und überschreibe alles 12x mit hex(FF).
  • Ruf eine dieser blutjungen rothaarigen Praktikantinnen an und lade sie zu Dir nach Hause zum Candlelight-Dinner ein
  • Konzentrier Dich am Herd auf die Menübereitung und nicht auf alternative IF-ELSE-Konstrukte
  • Benutze die Ausdrucke dazu, stilvoll ein paar Kerzen anzuzünden und öffne eine Flasche von dem GUTEN Dornfelder. Nicht den für Kollegen.
  • Macht Euch einen netten Abend.
  • Nach dem Frühstück schreibst Du den Code neu.
  • Und fängst dabei mit Pseudocode an.

/* Pseudocode */
Frag den Status vom USB-Geraffel ab

Wenn Status so wie *ANgeklemmt*
     Hau-Wech einen Prozess (den, der bei Neustart an ANgeklemmt gestartet wird)
     Klemm mit Devcon das US-Geraffel AB
wenn nich so wie *ANgeklemmt*
    /* ...dann isses wohl ABgeklemmt, oder? */
     Klemm mit Devcon das US-Geraffel AN
      /* starte es ODER mach einen Reboot, bei dem es automatisch gestartet wird */
Ende vons Wenn

Grüße
Biber
[Edit] Moin filipp, ich sehe gerade, Du bist exakt zu dem gleichen Lösungsansatz gekommen...*g
Beim Coden in Powershell bin ich offensichtlich noch zu langsam..[/Edit]
filippg
filippg 11.05.2008 um 15:46:24 Uhr
Goto Top
* Ruf eine dieser blutjungen rothaarigen
Praktikantinnen an und lade sie zu Dir nach
Hause zum Candlelight-Dinner ein
Gibt es solche bei euch wirklich? Ich dachte immer das wären nur Legenden, von anderen Administratoren erzählt um einen neidisch zu machen. Ich muss da mal mit dem Chef reden, er soll mit der Personalbteilung reden.

Filipp
Biber
Biber 11.05.2008 um 15:53:24 Uhr
Goto Top
@filipp
Ich dachte immer das wären nur Legenden,
Meinst Du jetzt die Flachzu-Legenden??
Brauchst nicht neidisch sein - einige wenige würde ich als Legenden bezeichen, wenn ich ins Schwärmen komme.
Die meisten sind einfach nur blutjung und rothaarig...*seufz*

Ach, es wird Frühling...
Biber
thorsten-rehm
thorsten-rehm 11.05.2008 um 19:02:14 Uhr
Goto Top
Ahhh. Ok, klar. Ich war wirklich auf dem Schlauch gestanden. Jetzt erkenne ich meinen Fehler. Das ist ja fast schon peinlich, dass mir das nicht eher aufgefallen ist ;)
Jetzt verstehe ich auch warum er nicht zu else springt.

So sieht jetzt mein funktionierendes Final Skript aus:

# Name: stop
# Erstellt am: 11.05.2008
# Letzte Änderung: -

# Ruft den Status der Netzwerkschnittstelle ab
$status = devcon status "USB\Vid_0846&Pid_4240&Rev_1040"  

# Wenn die Netzwerkschnittstelle deaktiviert ist, dann wird diese aktiviert und ein Reboot durchgeführt
if ($status -like "*disabled*") {  
devcon enable "USB\Vid_0846&Pid_4240&Rev_1040"  
shutdown -r -t 02 -f

# Wenn die Netzwerkschnittstelle aktiviert ist, dann wird diese deaktiviert und bestimmte Dienste und Prozesse beendet
} else {
devcon disable "USB\Vid_0846&Pid_4240&Rev_1040"  
stop-service -force DIENST1,DIENST2,DIENST3,
stop-process -name PROZESS1,PROZESS2,PROZESS3
}

Vielen Dank für die Hilfe und Unterstützung.

Bis zum nächsten Skript ;)
TuXHunt3R
TuXHunt3R 11.05.2008 um 21:28:21 Uhr
Goto Top
Bis zum nächsten Skript ;)

Bin wieder dabei, schick ne PN.